From 480d686b1c49f46722ff82df1c8c2dccdd6d5ab4 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Tue, 4 Feb 2025 15:51:55 -0800 Subject: [PATCH] Separate logic out --- src/poll.rs | 74 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/poll.rs b/src/poll.rs index c3c1600..89c8fb0 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -7,6 +7,7 @@ use rocket::serde::uuid::Uuid; use rocket::serde::{self, json::Json, Serialize}; use rocket_db_pools::Connection; use sqlx::{Acquire, SqliteConnection}; +use url::Url; const POLLING_INTERVAL: Duration = Duration::minutes(20); @@ -29,7 +30,11 @@ struct Entry { link: Option, } -async fn update_entry_db(entries: &Vec, feed_id: &str, db: &mut SqliteConnection) -> Result<(), Status> { +async fn update_entry_db( + entries: &Vec, + feed_id: &str, + db: &mut SqliteConnection, +) -> Result<(), Status> { // Start a transaction for batch update let mut tx = db.begin().await.map_err(|e| { eprintln!("Failed to start transaction: {}", e); @@ -89,38 +94,9 @@ async fn update_entry_db(entries: &Vec, feed_id: &str, db: &mut SqliteCon Ok(()) } -#[post("/poll/")] -pub async fn poll_feed( - mut db: Connection, - feed_id: Uuid, - user: AuthenticatedUser, -) -> Result, Status> { - let feed_id = feed_id.to_string(); - let user_id = user.user_id.to_string(); - // Get the feed URL from the database, ensuring it belongs to the authenticated user - let feed = sqlx::query!( - r#"SELECT url, last_checked_time as "last_checked_time: chrono::DateTime" FROM feeds WHERE feed_id = ? AND user_id = ?"#, - feed_id, - user_id - ) - .fetch_optional(&mut **db) - .await - .map_err(|_| Status::InternalServerError)? - .ok_or(Status::NotFound)?; - - let now = Utc::now(); - if now - feed.last_checked_time < POLLING_INTERVAL { - println!( - "Feed {} was checked recently at {}", - feed_id, feed.last_checked_time - ); - } - - // Parse the URL - let url = url::Url::parse(&feed.url).map_err(|_| Status::InternalServerError)?; - +/// Perform the request to fetch from the remote feed url +async fn fetch_new_entries(url: &Url) -> Result, Status> { let feed_data = fetch_feed(&url).await.map_err(|_| Status::BadGateway)?; - let count = feed_data.entries.len(); fn get(item: Option, name: &'static str) -> String { item.map(|t| t.content.to_string()) @@ -140,7 +116,41 @@ pub async fn poll_feed( link: feed_entry.links.first().map(|l| l.href.clone()), }) .collect(); + Ok(entries) +} +#[post("/poll/")] +pub async fn poll_feed( + mut db: Connection, + feed_id: Uuid, + user: AuthenticatedUser, +) -> Result, Status> { + let feed_id = feed_id.to_string(); + let user_id = user.user_id.to_string(); + + // Get the feed URL from the database, ensuring it belongs to the authenticated user + let feed = sqlx::query!( + r#"SELECT url, last_checked_time as "last_checked_time: chrono::DateTime" FROM feeds WHERE feed_id = ? AND user_id = ?"#, + feed_id, + user_id + ) + .fetch_optional(&mut **db) + .await + .map_err(|_| Status::InternalServerError)? + .ok_or(Status::NotFound)?; + + let url = url::Url::parse(&feed.url).map_err(|_| Status::InternalServerError)?; + + let now = Utc::now(); + if now - feed.last_checked_time < POLLING_INTERVAL { + println!( + "Feed {} was checked recently at {}", + feed_id, feed.last_checked_time + ); + } + + let entries = fetch_new_entries(&url).await?; + let count = entries.len(); update_entry_db(&entries, &feed_id, &mut db).await?; Ok(Json(FeedPollResponse { count, entries }))