Separate logic out
This commit is contained in:
parent
2fd1ade3ee
commit
480d686b1c
74
src/poll.rs
74
src/poll.rs
@ -7,6 +7,7 @@ use rocket::serde::uuid::Uuid;
|
|||||||
use rocket::serde::{self, json::Json, Serialize};
|
use rocket::serde::{self, json::Json, Serialize};
|
||||||
use rocket_db_pools::Connection;
|
use rocket_db_pools::Connection;
|
||||||
use sqlx::{Acquire, SqliteConnection};
|
use sqlx::{Acquire, SqliteConnection};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
const POLLING_INTERVAL: Duration = Duration::minutes(20);
|
const POLLING_INTERVAL: Duration = Duration::minutes(20);
|
||||||
|
|
||||||
@ -29,7 +30,11 @@ struct Entry {
|
|||||||
link: Option<String>,
|
link: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_entry_db(entries: &Vec<Entry>, feed_id: &str, db: &mut SqliteConnection) -> Result<(), Status> {
|
async fn update_entry_db(
|
||||||
|
entries: &Vec<Entry>,
|
||||||
|
feed_id: &str,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<(), Status> {
|
||||||
// Start a transaction for batch update
|
// Start a transaction for batch update
|
||||||
let mut tx = db.begin().await.map_err(|e| {
|
let mut tx = db.begin().await.map_err(|e| {
|
||||||
eprintln!("Failed to start transaction: {}", e);
|
eprintln!("Failed to start transaction: {}", e);
|
||||||
@ -89,38 +94,9 @@ async fn update_entry_db(entries: &Vec<Entry>, feed_id: &str, db: &mut SqliteCon
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/poll/<feed_id>")]
|
/// Perform the request to fetch from the remote feed url
|
||||||
pub async fn poll_feed(
|
async fn fetch_new_entries(url: &Url) -> Result<Vec<Entry>, Status> {
|
||||||
mut db: Connection<Db>,
|
|
||||||
feed_id: Uuid,
|
|
||||||
user: AuthenticatedUser,
|
|
||||||
) -> Result<Json<FeedPollResponse>, 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<chrono::Utc>" 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)?;
|
|
||||||
|
|
||||||
let feed_data = fetch_feed(&url).await.map_err(|_| Status::BadGateway)?;
|
let feed_data = fetch_feed(&url).await.map_err(|_| Status::BadGateway)?;
|
||||||
let count = feed_data.entries.len();
|
|
||||||
|
|
||||||
fn get(item: Option<Text>, name: &'static str) -> String {
|
fn get(item: Option<Text>, name: &'static str) -> String {
|
||||||
item.map(|t| t.content.to_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()),
|
link: feed_entry.links.first().map(|l| l.href.clone()),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
Ok(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/poll/<feed_id>")]
|
||||||
|
pub async fn poll_feed(
|
||||||
|
mut db: Connection<Db>,
|
||||||
|
feed_id: Uuid,
|
||||||
|
user: AuthenticatedUser,
|
||||||
|
) -> Result<Json<FeedPollResponse>, 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<chrono::Utc>" 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?;
|
update_entry_db(&entries, &feed_id, &mut db).await?;
|
||||||
|
|
||||||
Ok(Json(FeedPollResponse { count, entries }))
|
Ok(Json(FeedPollResponse { count, entries }))
|
||||||
|
Loading…
Reference in New Issue
Block a user