Feeds + polling work

This commit is contained in:
Greg Shuflin 2025-02-04 14:05:35 -08:00
parent b4028fa08f
commit c756e206e4
2 changed files with 60 additions and 3 deletions

View File

@ -31,7 +31,7 @@ impl Feed {
url,
user_id,
added_time: now,
last_checked_time: now,
last_checked_time: chrono::DateTime::UNIX_EPOCH,
categorization: Vec::new(),
}
}

View File

@ -4,8 +4,9 @@ use chrono::{DateTime, Utc};
use feed_rs::model::Text;
use rocket::http::Status;
use rocket::serde::uuid::Uuid;
use rocket::serde::{json::Json, Serialize};
use rocket::serde::{self, json::Json, Serialize};
use rocket_db_pools::Connection;
use sqlx::Acquire;
#[derive(Debug, Serialize)]
#[serde(crate = "rocket::serde")]
@ -57,7 +58,7 @@ pub async fn poll_feed(
.unwrap_or(format!("<no {name}>"))
}
let entries = feed_data
let entries: Vec<Entry> = feed_data
.entries
.into_iter()
.map(|feed_entry| Entry {
@ -71,5 +72,61 @@ pub async fn poll_feed(
})
.collect();
// Start a transaction for batch update
let mut tx = db.begin().await.map_err(|e| {
eprintln!("Failed to start transaction: {}", e);
Status::InternalServerError
})?;
let now = Utc::now().to_rfc3339();
for entry in &entries {
let content_json = if let Some(content) = &entry.content {
serde::json::to_string(content).ok()
} else {
None
};
let result = sqlx::query(
r#"
INSERT INTO feed_entries (
id, feed_id, title, published, updated, summary, content, link, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (feed_id, id) DO UPDATE SET
title = excluded.title,
published = excluded.published,
updated = excluded.updated,
summary = excluded.summary,
content = excluded.content,
link = excluded.link
"#
)
.bind(&entry.id)
.bind(&feed_id)
.bind(&entry.title)
.bind(entry.published.map(|dt| dt.to_rfc3339()))
.bind(entry.updated.map(|dt| dt.to_rfc3339()))
.bind(&entry.summary)
.bind(content_json)
.bind(&entry.link)
.bind(&now)
.execute(&mut *tx)
.await;
if let Err(e) = result {
eprintln!("Failed to save feed entry: {}", e);
tx.rollback().await.map_err(|e| {
eprintln!("Failed to rollback transaction: {}", e);
Status::InternalServerError
})?;
return Err(Status::InternalServerError);
}
}
// Commit the transaction
tx.commit().await.map_err(|e| {
eprintln!("Failed to commit transaction: {}", e);
Status::InternalServerError
})?;
Ok(Json(FeedPollResponse { count, entries }))
}