SeaORM: items and read state
The item list, its counts, filters, sorts and search, positions, pins and mark-all-read move to SeaORM, as SQL written for both databases: - Parameters are gathered as the SQL is written (Args), so only what a statement uses is bound. rusqlite needed every one mentioned, hence the old `?1 IS NULL` and `?2 = ''`; Postgres refuses a parameter it cannot type. - Yes/no columns are tested as booleans (NOT coalesce(s.read, false)) and written as true, not 1; SQLite reads true and false as 1 and 0. - The last tiebreak of the sort is the guid, not SQLite's rowid, which Postgres lacks. Only items with the same date change places. - set_position names entry_state.duration beside excluded.duration. - The status callback on the control socket returns a future, as the counts are now a query. Checked on a copy of production against the live server: 42 of 48 lists identical; the other six differ only in how ties fall, or because the test daemon cleared paths to files this machine does not have. Run on the same file, every filter's count matches the old SQL exactly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
11
src/main.rs
11
src/main.rs
@@ -340,7 +340,7 @@ async fn run(ctx: &Arc<Ctx>, cmd: Cmd) -> Result<()> {
|
||||
Cmd::Reap { dry_run } => reap(ctx, dry_run, true),
|
||||
Cmd::Download { enclosure } => download_one(ctx, enclosure).await,
|
||||
Cmd::Status => {
|
||||
ctx.out.emit(status(ctx));
|
||||
ctx.out.emit(status(ctx).await);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -348,8 +348,8 @@ async fn run(ctx: &Arc<Ctx>, cmd: Cmd) -> Result<()> {
|
||||
|
||||
/// The counts `ipx status` prints. A running daemon's socket answers with this directly rather
|
||||
/// than through the job queue.
|
||||
fn status(ctx: &Ctx) -> Event {
|
||||
match ctx.db.counts() {
|
||||
async fn status(ctx: &Ctx) -> Event {
|
||||
match ctx.db.counts().await {
|
||||
Ok((pending, downloaded)) => {
|
||||
let feeds = subscriptions(ctx).map(|s| s.len()).unwrap_or(0);
|
||||
Event::Status { feeds, pending, downloaded }
|
||||
@@ -420,7 +420,10 @@ async fn daemon(
|
||||
// status is answered by the socket itself; everything else waits its turn in the queue.
|
||||
let answer: ipc::StatusFn = {
|
||||
let ctx = ctx.clone();
|
||||
Arc::new(move || status(&ctx))
|
||||
Arc::new(move || {
|
||||
let ctx = ctx.clone();
|
||||
Box::pin(async move { status(&ctx).await })
|
||||
})
|
||||
};
|
||||
let server = tokio::spawn(ipc::serve(socket.clone(), events.clone(), tx_cmd, answer));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user