pull that resource intensive thing to another thread

This commit is contained in:
lda committed 2025-05-22 02:32:33 +07:00
1 parent b0cb29d911
commit 02d76d31ea
3 files changed
+84 -52

No files matched your search

+37
View File
@@ -0,0 +1,37 @@
// type calparseerrtype = <Calendar as std::str::FromStr>::Err; // String
#[allow(nonstandard_style)]
#[derive(Debug)]
pub enum asspullError {
calparse(String), // type calparseerrtype
regexnew(fancy_regex::Error),
}
// impl From<calparseerrtype> for asspullError {
// fn from(value: calparseerrtype) -> Self {
// asspullError::calparse(value)
// }
// }
impl From<String> for asspullError {
fn from(value: String) -> Self {
asspullError::calparse(value)
}
}
impl From<fancy_regex::Error> for asspullError {
fn from(value: fancy_regex::Error) -> Self {
asspullError::regexnew(value)
}
}
impl std::fmt::Display for asspullError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
asspullError::calparse(i) => std::fmt::Display::fmt(i, f),
asspullError::regexnew(i) => std::fmt::Display::fmt(i, f),
}
}
}
impl std::error::Error for asspullError {}
+2
View File
@@ -1,3 +1,5 @@
#![allow(dead_code)]
use tokio::time::Instant;
pub struct LdaTimer<'s>{timer: Instant, message: &'s str}
+45 -52
View File
@@ -6,7 +6,7 @@ use chrono::{NaiveDate, TimeDelta};
use fancy_regex::Regex;
use icalendar::{Calendar, CalendarComponent, Component};
use reqwest::Client;
mod funny_timer;
// use regex::Regex;
const ICS_URL: &str = "https://calendar.google.com/calendar/ical/i7p4ol56gi8sqe0dq7uc3m0o4c%40group.calendar.google.com/public/basic.ics";
@@ -17,26 +17,23 @@ async fn filtered_ics(
now: web::Data<NaiveDate>,
query: web::Query<HashMap<String, String>>,
) -> impl Responder {
let cumah = funny_timer::LdaTimer::new("total time idfk");
println!(
"got hit from {}, path is obviously {}",
req.peer_addr()
.map(|s| s.to_string())
.unwrap_or("deadass dont know".into()),
.unwrap_or_else(|| "deadass dont know".into()),
req.path()
);
let now: NaiveDate = **now;
let now = **now;
let client = Client::new();
let ics_url = query.get("url").map_or(ICS_URL, String::as_str);
let timer = tokio::time::Instant::now();
// Fetch the .ics content
let response = match client.get(ics_url).send().await {
Ok(resp) => resp,
Err(e) => return HttpResponse::BadGateway().body(format!("Failed to fetch ICS file: {e}")),
};
println!("got a response in {:?}", timer.elapsed());
cumah.ping("function time after response");
let body = match response.text().await {
Ok(text) => text,
@@ -45,53 +42,46 @@ async fn filtered_ics(
.body(format!("Failed to read response body: {e}"));
}
};
println!("with reading file: {:?}", timer.elapsed());
cumah.ping("function time after reading");
let timer = tokio::time::Instant::now();
// Parse the .ics content
let calendar = match body.parse::<Calendar>() {
Ok(cal) => cal,
Err(e) => {
return HttpResponse::InternalServerError()
.body(format!("Failed to parse ICS file: {e}"));
// Compile regex
let regex_rules = match query.get("regex") {
Some(rule) => match Regex::new(rule) {
Ok(reg_mc) => Some(reg_mc),
Err(e) => return HttpResponse::BadRequest().body(format!("Invalid regex rule: {e}")),
},
None => None,
};
// Do the CPU-heavy stuff on another thread
let block_task = tokio::task::spawn_blocking(move || -> Result<String, String> {
let calendar = body.parse::<Calendar>()?;
let start_date = now - TimeDelta::days(365);
let end_date = now + TimeDelta::days(365);
let filtered_events =
filter_events_by_date_and_regex(calendar, regex_rules, start_date, end_date);
let filtered_calendar = Calendar {
components: filtered_events,
..Default::default()
};
Ok(filtered_calendar.to_string())
});
// Await the result of the blocking task
match block_task.await {
Ok(Ok(ics_output)) => HttpResponse::Ok()
.content_type("text/calendar")
.body(ics_output),
Ok(Err(e)) => {
HttpResponse::InternalServerError().body(format!("Failed to process ICS file: {e}"))
}
};
println!("parsing took {:?}", timer.elapsed());
cumah.ping("function time after parsing");
let start_date = now - TimeDelta::days(365);
let end_date = now + TimeDelta::days(365);
let regex_rules = query
.get("regex")
.and_then(|r| Regex::new(r).inspect_err(|e| eprintln!("{e}")).ok()); // silently discard a faulty regex
// or
// let include = query.get("").map(|c|c.split(",")); // ?
// let exclude = query.get("").map(|c|c.split(",")); // ?
// Filter events by summary and date range
let timer = tokio::time::Instant::now();
let filtered_events =
filter_events_by_date_and_regex(calendar, regex_rules, start_date, end_date);
println!("filtering took {:?}", timer.elapsed());
cumah.ping("function time after filtering");
// Create a new calendar with filtered events
let filtered_calendar = Calendar {
components: filtered_events,
..Default::default()
};
cumah.ping("hi");
// Serialize the filtered calendar
let timer = tokio::time::Instant::now();
let ics_output = filtered_calendar.to_string();
println!("string building took {:?}", timer.elapsed());
cumah.ping("function time after building the string");
HttpResponse::Ok()
.content_type("text/calendar")
.body(ics_output)
Err(join_err) => {
HttpResponse::InternalServerError().body(format!("Blocking thread failed: {join_err}"))
}
}
}
fn filter_events_by_date_and_regex(
@@ -153,3 +143,6 @@ async fn main() -> std::io::Result<()> {
.run()
.await
}
mod asspull;
mod funny_timer;