Fix feed entry id issues
This commit is contained in:
parent
44208470f8
commit
c89ee29d4d
12
.sqlx/query-241fab33b2e6ffcba26cb3bd668f2f601d0ee2f24f5e8612323b66e5a2d2cbe9.json
generated
Normal file
12
.sqlx/query-241fab33b2e6ffcba26cb3bd668f2f601d0ee2f24f5e8612323b66e5a2d2cbe9.json
generated
Normal file
@ -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"
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"db_name": "SQLite",
|
||||||
"query": "\n SELECT \n id as \"id!: String\",\n entry_id,\n title,\n published as \"published: Option<chrono::DateTime<Utc>>\",\n updated as \"updated: Option<chrono::DateTime<Utc>>\",\n summary,\n content,\n link,\n marked_read as \"marked_read: Option<chrono::DateTime<Utc>>\"\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<chrono::DateTime<Utc>>\",\n updated as \"updated: Option<chrono::DateTime<Utc>>\",\n summary,\n content,\n link,\n marked_read as \"marked_read: Option<chrono::DateTime<Utc>>\"\n FROM feed_entries \n WHERE feed_id = ?\n ORDER BY published DESC NULLS LAST\n LIMIT ?\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "entry_id",
|
"name": "local_id!: String",
|
||||||
"ordinal": 1,
|
"ordinal": 1,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
@ -64,5 +64,5 @@
|
|||||||
true
|
true
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "7698fc853218a67cf22338697be3b504220e8fbf845e32945273c7e5cd579152"
|
"hash": "2bbed6f20243ced25ac9359afefafb5ddffdff949250e0e4e35bf399fc0199fc"
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"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": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@ -16,5 +16,5 @@
|
|||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "ce12e0b02596a4045fb2cd91d566aa633109a65afcecc92564a785282e67e193"
|
"hash": "3744bfed27760e0d6029063116352c42d90a3e4a5ea924e241437ce312535cc1"
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"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": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
@ -8,5 +8,5 @@
|
|||||||
},
|
},
|
||||||
"nullable": []
|
"nullable": []
|
||||||
},
|
},
|
||||||
"hash": "3c8d358e534f35c6e59b1d94cf28175b5d9b60a662388dec1c20a79e298cac4f"
|
"hash": "6efd0a1292d597cce5ea84e4fada30035dd40d557f5c305ec7b5bb6b0788948c"
|
||||||
}
|
}
|
12
.sqlx/query-7cb047b30c2454689b447f4f2717b665d0094b645205e20390c6dec72fd15910.json
generated
Normal file
12
.sqlx/query-7cb047b30c2454689b447f4f2717b665d0094b645205e20390c6dec72fd15910.json
generated
Normal file
@ -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"
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "UPDATE feed_entries SET marked_read = ? WHERE id = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "ad2e09903009082ca746a9dc75cb04831b016d17cc7ce32fa86681431071fef6"
|
|
||||||
}
|
|
@ -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"
|
|
||||||
}
|
|
2
migrations/20240320000009_drop_entry_id.sql
Normal file
2
migrations/20240320000009_drop_entry_id.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-- Rename entry_id column to local_id
|
||||||
|
ALTER TABLE feed_entries RENAME COLUMN entry_id TO local_id;
|
42
src/poll.rs
42
src/poll.rs
@ -23,8 +23,11 @@ pub struct FeedPollResponse {
|
|||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(crate = "rocket::serde")]
|
#[serde(crate = "rocket::serde")]
|
||||||
struct Entry {
|
struct Entry {
|
||||||
id: Uuid,
|
/// id is the id from the feed, and is the primary key of entries
|
||||||
entry_id: String,
|
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,
|
title: String,
|
||||||
published: Option<DateTime<Utc>>,
|
published: Option<DateTime<Utc>>,
|
||||||
updated: Option<DateTime<Utc>>,
|
updated: Option<DateTime<Utc>>,
|
||||||
@ -74,11 +77,12 @@ async fn update_entry_db(
|
|||||||
let published = entry.published.map(|dt| dt.to_rfc3339());
|
let published = entry.published.map(|dt| dt.to_rfc3339());
|
||||||
let updated = entry.updated.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!(
|
let result = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO feed_entries (
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
ON CONFLICT (feed_id, id) DO UPDATE SET
|
ON CONFLICT (feed_id, id) DO UPDATE SET
|
||||||
title = excluded.title,
|
title = excluded.title,
|
||||||
@ -88,9 +92,9 @@ async fn update_entry_db(
|
|||||||
content = excluded.content,
|
content = excluded.content,
|
||||||
link = excluded.link
|
link = excluded.link
|
||||||
"#,
|
"#,
|
||||||
entry_id,
|
entry.id,
|
||||||
feed_id,
|
feed_id,
|
||||||
entry.entry_id,
|
local_id,
|
||||||
entry.title,
|
entry.title,
|
||||||
published,
|
published,
|
||||||
updated,
|
updated,
|
||||||
@ -126,7 +130,7 @@ async fn read_entries(feed_id: &str, db: &mut SqliteConnection) -> Result<Vec<En
|
|||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
id as "id!: String",
|
id as "id!: String",
|
||||||
entry_id,
|
local_id as "local_id!: String",
|
||||||
title,
|
title,
|
||||||
published as "published: Option<chrono::DateTime<Utc>>",
|
published as "published: Option<chrono::DateTime<Utc>>",
|
||||||
updated as "updated: Option<chrono::DateTime<Utc>>",
|
updated as "updated: Option<chrono::DateTime<Utc>>",
|
||||||
@ -158,8 +162,8 @@ async fn read_entries(feed_id: &str, db: &mut SqliteConnection) -> Result<Vec<En
|
|||||||
.and_then(|s| serde::json::from_str(s).ok());
|
.and_then(|s| serde::json::from_str(s).ok());
|
||||||
|
|
||||||
Ok(Entry {
|
Ok(Entry {
|
||||||
id: Uuid::parse_str(&row.id).map_err(|_| Status::InternalServerError)?,
|
id: row.id.clone(),
|
||||||
entry_id: row.entry_id.clone(),
|
local_id: Uuid::parse_str(&row.local_id).map_err(|_| Status::InternalServerError)?,
|
||||||
title: row.title.clone(),
|
title: row.title.clone(),
|
||||||
published: row.published.flatten(),
|
published: row.published.flatten(),
|
||||||
updated: row.updated.flatten(),
|
updated: row.updated.flatten(),
|
||||||
@ -187,8 +191,8 @@ async fn fetch_new_entries(url: &Url) -> Result<Vec<Entry>, Status> {
|
|||||||
.entries
|
.entries
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|feed_entry| Entry {
|
.map(|feed_entry| Entry {
|
||||||
id: Uuid::new_v4(),
|
id: feed_entry.id,
|
||||||
entry_id: feed_entry.id,
|
local_id: Uuid::new_v4(),
|
||||||
title: get(feed_entry.title, "title"),
|
title: get(feed_entry.title, "title"),
|
||||||
published: feed_entry.published,
|
published: feed_entry.published,
|
||||||
updated: feed_entry.updated,
|
updated: feed_entry.updated,
|
||||||
@ -242,10 +246,10 @@ pub async fn poll_feed(
|
|||||||
Ok(Json(FeedPollResponse { count, entries }))
|
Ok(Json(FeedPollResponse { count, entries }))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[patch("/entries/<entry_id>/state", data = "<state>")]
|
#[patch("/entries/<local_id>/state", data = "<state>")]
|
||||||
pub async fn update_entry_state(
|
pub async fn update_entry_state(
|
||||||
mut db: Connection<Db>,
|
mut db: Connection<Db>,
|
||||||
entry_id: &str,
|
local_id: &str,
|
||||||
user: AuthenticatedUser,
|
user: AuthenticatedUser,
|
||||||
state: Json<EntryStateUpdate>,
|
state: Json<EntryStateUpdate>,
|
||||||
) -> Result<Status, Status> {
|
) -> Result<Status, Status> {
|
||||||
@ -257,9 +261,9 @@ pub async fn update_entry_state(
|
|||||||
r#"
|
r#"
|
||||||
SELECT 1 as found FROM feed_entries e
|
SELECT 1 as found FROM feed_entries e
|
||||||
JOIN feeds f ON e.feed_id = f.feed_id
|
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,
|
user_id,
|
||||||
)
|
)
|
||||||
.fetch_optional(&mut **db)
|
.fetch_optional(&mut **db)
|
||||||
@ -278,16 +282,16 @@ pub async fn update_entry_state(
|
|||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
let result = if read {
|
let result = if read {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"UPDATE feed_entries SET marked_read = ? WHERE id = ?",
|
"UPDATE feed_entries SET marked_read = ? WHERE local_id = ?",
|
||||||
now,
|
now,
|
||||||
entry_id
|
local_id
|
||||||
)
|
)
|
||||||
.execute(&mut **db)
|
.execute(&mut **db)
|
||||||
.await
|
.await
|
||||||
} else {
|
} else {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"UPDATE feed_entries SET marked_read = NULL WHERE id = ?",
|
"UPDATE feed_entries SET marked_read = NULL WHERE local_id = ?",
|
||||||
entry_id
|
local_id
|
||||||
)
|
)
|
||||||
.execute(&mut **db)
|
.execute(&mut **db)
|
||||||
.await
|
.await
|
||||||
|
@ -57,7 +57,7 @@ function renderFeedEntries(entries) {
|
|||||||
: '<i class="fa-regular fa-square"></i>';
|
: '<i class="fa-regular fa-square"></i>';
|
||||||
readToggle.onclick = async () => {
|
readToggle.onclick = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/entries/${entry.id}/state`, {
|
const response = await fetch(`/entries/${entry.local_id}/state`, {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -90,7 +90,7 @@ function renderFeedEntries(entries) {
|
|||||||
titleLink.onclick = () => {
|
titleLink.onclick = () => {
|
||||||
if (!entry.marked_read) {
|
if (!entry.marked_read) {
|
||||||
// Mark as read in the background, don't wait for it
|
// Mark as read in the background, don't wait for it
|
||||||
fetch(`/entries/${entry.id}/state`, {
|
fetch(`/entries/${entry.local_id}/state`, {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
Loading…
Reference in New Issue
Block a user