From c89ee29d4da7b4e1b83c37e00e7ff692c306ffea Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Wed, 5 Feb 2025 02:31:29 -0800 Subject: [PATCH] Fix feed entry id issues --- ...f2f601d0ee2f24f5e8612323b66e5a2d2cbe9.json | 12 ++++++ ...fb5ddffdff949250e0e4e35bf399fc0199fc.json} | 6 +-- ...2c42d90a3e4a5ea924e241437ce312535cc1.json} | 4 +- ...30035dd40d557f5c305ec7b5bb6b0788948c.json} | 4 +- ...7b665d0094b645205e20390c6dec72fd15910.json | 12 ++++++ ...b04831b016d17cc7ce32fa86681431071fef6.json | 12 ------ ...8f76fea57c4c815981673c92e709b17b9204b.json | 12 ------ migrations/20240320000009_drop_entry_id.sql | 2 + src/poll.rs | 42 ++++++++++--------- static/js/app.js | 4 +- 10 files changed, 58 insertions(+), 52 deletions(-) create mode 100644 .sqlx/query-241fab33b2e6ffcba26cb3bd668f2f601d0ee2f24f5e8612323b66e5a2d2cbe9.json rename .sqlx/{query-7698fc853218a67cf22338697be3b504220e8fbf845e32945273c7e5cd579152.json => query-2bbed6f20243ced25ac9359afefafb5ddffdff949250e0e4e35bf399fc0199fc.json} (67%) rename .sqlx/{query-ce12e0b02596a4045fb2cd91d566aa633109a65afcecc92564a785282e67e193.json => query-3744bfed27760e0d6029063116352c42d90a3e4a5ea924e241437ce312535cc1.json} (62%) rename .sqlx/{query-3c8d358e534f35c6e59b1d94cf28175b5d9b60a662388dec1c20a79e298cac4f.json => query-6efd0a1292d597cce5ea84e4fada30035dd40d557f5c305ec7b5bb6b0788948c.json} (81%) create mode 100644 .sqlx/query-7cb047b30c2454689b447f4f2717b665d0094b645205e20390c6dec72fd15910.json delete mode 100644 .sqlx/query-ad2e09903009082ca746a9dc75cb04831b016d17cc7ce32fa86681431071fef6.json delete mode 100644 .sqlx/query-c64e0927e594985ee8d2be7190c8f76fea57c4c815981673c92e709b17b9204b.json create mode 100644 migrations/20240320000009_drop_entry_id.sql diff --git a/.sqlx/query-241fab33b2e6ffcba26cb3bd668f2f601d0ee2f24f5e8612323b66e5a2d2cbe9.json b/.sqlx/query-241fab33b2e6ffcba26cb3bd668f2f601d0ee2f24f5e8612323b66e5a2d2cbe9.json new file mode 100644 index 0000000..c32c55e --- /dev/null +++ b/.sqlx/query-241fab33b2e6ffcba26cb3bd668f2f601d0ee2f24f5e8612323b66e5a2d2cbe9.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "UPDATE feed_entries SET marked_read = NULL WHERE local_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "241fab33b2e6ffcba26cb3bd668f2f601d0ee2f24f5e8612323b66e5a2d2cbe9" +} diff --git a/.sqlx/query-7698fc853218a67cf22338697be3b504220e8fbf845e32945273c7e5cd579152.json b/.sqlx/query-2bbed6f20243ced25ac9359afefafb5ddffdff949250e0e4e35bf399fc0199fc.json similarity index 67% rename from .sqlx/query-7698fc853218a67cf22338697be3b504220e8fbf845e32945273c7e5cd579152.json rename to .sqlx/query-2bbed6f20243ced25ac9359afefafb5ddffdff949250e0e4e35bf399fc0199fc.json index f15771a..dfa7992 100644 --- a/.sqlx/query-7698fc853218a67cf22338697be3b504220e8fbf845e32945273c7e5cd579152.json +++ b/.sqlx/query-2bbed6f20243ced25ac9359afefafb5ddffdff949250e0e4e35bf399fc0199fc.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "\n SELECT \n id as \"id!: String\",\n entry_id,\n title,\n published as \"published: Option>\",\n updated as \"updated: Option>\",\n summary,\n content,\n link,\n marked_read as \"marked_read: Option>\"\n FROM feed_entries \n WHERE feed_id = ?\n ORDER BY published DESC NULLS LAST\n LIMIT ?\n ", + "query": "\n SELECT \n id as \"id!: String\",\n local_id as \"local_id!: String\",\n title,\n published as \"published: Option>\",\n updated as \"updated: Option>\",\n summary,\n content,\n link,\n marked_read as \"marked_read: Option>\"\n FROM feed_entries \n WHERE feed_id = ?\n ORDER BY published DESC NULLS LAST\n LIMIT ?\n ", "describe": { "columns": [ { @@ -9,7 +9,7 @@ "type_info": "Text" }, { - "name": "entry_id", + "name": "local_id!: String", "ordinal": 1, "type_info": "Text" }, @@ -64,5 +64,5 @@ true ] }, - "hash": "7698fc853218a67cf22338697be3b504220e8fbf845e32945273c7e5cd579152" + "hash": "2bbed6f20243ced25ac9359afefafb5ddffdff949250e0e4e35bf399fc0199fc" } diff --git a/.sqlx/query-ce12e0b02596a4045fb2cd91d566aa633109a65afcecc92564a785282e67e193.json b/.sqlx/query-3744bfed27760e0d6029063116352c42d90a3e4a5ea924e241437ce312535cc1.json similarity index 62% rename from .sqlx/query-ce12e0b02596a4045fb2cd91d566aa633109a65afcecc92564a785282e67e193.json rename to .sqlx/query-3744bfed27760e0d6029063116352c42d90a3e4a5ea924e241437ce312535cc1.json index eb53bf4..0b756c6 100644 --- a/.sqlx/query-ce12e0b02596a4045fb2cd91d566aa633109a65afcecc92564a785282e67e193.json +++ b/.sqlx/query-3744bfed27760e0d6029063116352c42d90a3e4a5ea924e241437ce312535cc1.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "\n SELECT 1 as found FROM feed_entries e\n JOIN feeds f ON e.feed_id = f.feed_id\n WHERE e.id = ? AND f.user_id = ?\n ", + "query": "\n SELECT 1 as found FROM feed_entries e\n JOIN feeds f ON e.feed_id = f.feed_id\n WHERE e.local_id = ? AND f.user_id = ?\n ", "describe": { "columns": [ { @@ -16,5 +16,5 @@ false ] }, - "hash": "ce12e0b02596a4045fb2cd91d566aa633109a65afcecc92564a785282e67e193" + "hash": "3744bfed27760e0d6029063116352c42d90a3e4a5ea924e241437ce312535cc1" } diff --git a/.sqlx/query-3c8d358e534f35c6e59b1d94cf28175b5d9b60a662388dec1c20a79e298cac4f.json b/.sqlx/query-6efd0a1292d597cce5ea84e4fada30035dd40d557f5c305ec7b5bb6b0788948c.json similarity index 81% rename from .sqlx/query-3c8d358e534f35c6e59b1d94cf28175b5d9b60a662388dec1c20a79e298cac4f.json rename to .sqlx/query-6efd0a1292d597cce5ea84e4fada30035dd40d557f5c305ec7b5bb6b0788948c.json index 9759c8f..28db479 100644 --- a/.sqlx/query-3c8d358e534f35c6e59b1d94cf28175b5d9b60a662388dec1c20a79e298cac4f.json +++ b/.sqlx/query-6efd0a1292d597cce5ea84e4fada30035dd40d557f5c305ec7b5bb6b0788948c.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "\n INSERT INTO feed_entries (\n id, feed_id, entry_id, title, published, updated, summary, content, link, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (feed_id, id) DO UPDATE SET\n title = excluded.title,\n published = excluded.published,\n updated = excluded.updated,\n summary = excluded.summary,\n content = excluded.content,\n link = excluded.link\n ", + "query": "\n INSERT INTO feed_entries (\n id, feed_id, local_id, title, published, updated, summary, content, link, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (feed_id, id) DO UPDATE SET\n title = excluded.title,\n published = excluded.published,\n updated = excluded.updated,\n summary = excluded.summary,\n content = excluded.content,\n link = excluded.link\n ", "describe": { "columns": [], "parameters": { @@ -8,5 +8,5 @@ }, "nullable": [] }, - "hash": "3c8d358e534f35c6e59b1d94cf28175b5d9b60a662388dec1c20a79e298cac4f" + "hash": "6efd0a1292d597cce5ea84e4fada30035dd40d557f5c305ec7b5bb6b0788948c" } diff --git a/.sqlx/query-7cb047b30c2454689b447f4f2717b665d0094b645205e20390c6dec72fd15910.json b/.sqlx/query-7cb047b30c2454689b447f4f2717b665d0094b645205e20390c6dec72fd15910.json new file mode 100644 index 0000000..988fd98 --- /dev/null +++ b/.sqlx/query-7cb047b30c2454689b447f4f2717b665d0094b645205e20390c6dec72fd15910.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "UPDATE feed_entries SET marked_read = ? WHERE local_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "7cb047b30c2454689b447f4f2717b665d0094b645205e20390c6dec72fd15910" +} diff --git a/.sqlx/query-ad2e09903009082ca746a9dc75cb04831b016d17cc7ce32fa86681431071fef6.json b/.sqlx/query-ad2e09903009082ca746a9dc75cb04831b016d17cc7ce32fa86681431071fef6.json deleted file mode 100644 index 6d85b84..0000000 --- a/.sqlx/query-ad2e09903009082ca746a9dc75cb04831b016d17cc7ce32fa86681431071fef6.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE feed_entries SET marked_read = ? WHERE id = ?", - "describe": { - "columns": [], - "parameters": { - "Right": 2 - }, - "nullable": [] - }, - "hash": "ad2e09903009082ca746a9dc75cb04831b016d17cc7ce32fa86681431071fef6" -} diff --git a/.sqlx/query-c64e0927e594985ee8d2be7190c8f76fea57c4c815981673c92e709b17b9204b.json b/.sqlx/query-c64e0927e594985ee8d2be7190c8f76fea57c4c815981673c92e709b17b9204b.json deleted file mode 100644 index e9c65a8..0000000 --- a/.sqlx/query-c64e0927e594985ee8d2be7190c8f76fea57c4c815981673c92e709b17b9204b.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE feed_entries SET marked_read = NULL WHERE id = ?", - "describe": { - "columns": [], - "parameters": { - "Right": 1 - }, - "nullable": [] - }, - "hash": "c64e0927e594985ee8d2be7190c8f76fea57c4c815981673c92e709b17b9204b" -} diff --git a/migrations/20240320000009_drop_entry_id.sql b/migrations/20240320000009_drop_entry_id.sql new file mode 100644 index 0000000..514e895 --- /dev/null +++ b/migrations/20240320000009_drop_entry_id.sql @@ -0,0 +1,2 @@ +-- Rename entry_id column to local_id +ALTER TABLE feed_entries RENAME COLUMN entry_id TO local_id; \ No newline at end of file diff --git a/src/poll.rs b/src/poll.rs index 6274d95..6f6585b 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -23,8 +23,11 @@ pub struct FeedPollResponse { #[derive(Debug, Serialize)] #[serde(crate = "rocket::serde")] struct Entry { - id: Uuid, - entry_id: String, + /// id is the id from the feed, and is the primary key of entries + id: String, + /// local_id is a UUID generated locally. it is used because we don't have control over the + /// exact format of the id from the feed entry + local_id: Uuid, title: String, published: Option>, updated: Option>, @@ -74,11 +77,12 @@ async fn update_entry_db( let published = entry.published.map(|dt| dt.to_rfc3339()); let updated = entry.updated.map(|dt| dt.to_rfc3339()); - let entry_id = entry.id.to_string(); + let local_id = entry.local_id.to_string(); + let result = sqlx::query!( r#" INSERT INTO feed_entries ( - id, feed_id, entry_id, title, published, updated, summary, content, link, created_at + id, feed_id, local_id, title, published, updated, summary, content, link, created_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT (feed_id, id) DO UPDATE SET title = excluded.title, @@ -88,9 +92,9 @@ async fn update_entry_db( content = excluded.content, link = excluded.link "#, - entry_id, + entry.id, feed_id, - entry.entry_id, + local_id, entry.title, published, updated, @@ -126,7 +130,7 @@ async fn read_entries(feed_id: &str, db: &mut SqliteConnection) -> Result>", updated as "updated: Option>", @@ -158,8 +162,8 @@ async fn read_entries(feed_id: &str, db: &mut SqliteConnection) -> Result Result, Status> { .entries .into_iter() .map(|feed_entry| Entry { - id: Uuid::new_v4(), - entry_id: feed_entry.id, + id: feed_entry.id, + local_id: Uuid::new_v4(), title: get(feed_entry.title, "title"), published: feed_entry.published, updated: feed_entry.updated, @@ -242,10 +246,10 @@ pub async fn poll_feed( Ok(Json(FeedPollResponse { count, entries })) } -#[patch("/entries//state", data = "")] +#[patch("/entries//state", data = "")] pub async fn update_entry_state( mut db: Connection, - entry_id: &str, + local_id: &str, user: AuthenticatedUser, state: Json, ) -> Result { @@ -257,9 +261,9 @@ pub async fn update_entry_state( r#" SELECT 1 as found FROM feed_entries e JOIN feeds f ON e.feed_id = f.feed_id - WHERE e.id = ? AND f.user_id = ? + WHERE e.local_id = ? AND f.user_id = ? "#, - entry_id, + local_id, user_id, ) .fetch_optional(&mut **db) @@ -278,16 +282,16 @@ pub async fn update_entry_state( let now = Utc::now(); let result = if read { sqlx::query!( - "UPDATE feed_entries SET marked_read = ? WHERE id = ?", + "UPDATE feed_entries SET marked_read = ? WHERE local_id = ?", now, - entry_id + local_id ) .execute(&mut **db) .await } else { sqlx::query!( - "UPDATE feed_entries SET marked_read = NULL WHERE id = ?", - entry_id + "UPDATE feed_entries SET marked_read = NULL WHERE local_id = ?", + local_id ) .execute(&mut **db) .await diff --git a/static/js/app.js b/static/js/app.js index 96e89b6..c4cd764 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -57,7 +57,7 @@ function renderFeedEntries(entries) { : ''; readToggle.onclick = async () => { try { - const response = await fetch(`/entries/${entry.id}/state`, { + const response = await fetch(`/entries/${entry.local_id}/state`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', @@ -90,7 +90,7 @@ function renderFeedEntries(entries) { titleLink.onclick = () => { if (!entry.marked_read) { // Mark as read in the background, don't wait for it - fetch(`/entries/${entry.id}/state`, { + fetch(`/entries/${entry.local_id}/state`, { method: 'PATCH', headers: { 'Content-Type': 'application/json',