SeaORM: enclosures, downloads and the reaper
Twelve enclosure functions move to SeaORM: recording, the download queue, marking done or failed, requeueing, and what the reaper may delete. INSERT OR IGNORE becomes ON CONFLICT DO NOTHING; the reaper's read verdict is true or false rather than 1 or 0, which Postgres would type as a 32-bit integer and refuse to read as an i64; `read = 1` and `flagged = 1` test the booleans themselves. retention::run and its callers (reap, rm, retire_group, retire_stranded) become async. The reaper deletes files, so it was checked on a copy of production against the old SQL on the same file: all 2,195 candidates, identical and in the same order. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
16
src/web.rs
16
src/web.rs
@@ -1422,7 +1422,7 @@ async fn remove_feed(
|
||||
}
|
||||
cfg.save(&state.config_path)?;
|
||||
state.ctx.reload_cfg(&state.config_path)?;
|
||||
crate::retire_group(&state.ctx, &id)?;
|
||||
crate::retire_group(&state.ctx, &id).await?;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
@@ -1458,12 +1458,12 @@ async fn download_now(
|
||||
let enc = state
|
||||
.ctx
|
||||
.db
|
||||
.enclosure(id)?
|
||||
.enclosure(id).await?
|
||||
.ok_or_else(|| anyhow::anyhow!("no enclosure {id}"))?;
|
||||
if enc.path.is_some() {
|
||||
return Ok(StatusCode::NO_CONTENT); // Already here.
|
||||
}
|
||||
state.ctx.db.requeue(id)?;
|
||||
state.ctx.db.requeue(id).await?;
|
||||
state
|
||||
.cmds
|
||||
.send(Command::Download { enclosure: id })
|
||||
@@ -1487,7 +1487,7 @@ async fn delete_file(
|
||||
let enc = state
|
||||
.ctx
|
||||
.db
|
||||
.enclosure(id)?
|
||||
.enclosure(id).await?
|
||||
.ok_or_else(|| anyhow::anyhow!("no enclosure {id}"))?;
|
||||
|
||||
// There is one copy of the file: deleting it deletes everyone's. Say so before doing
|
||||
@@ -1519,7 +1519,7 @@ async fn delete_file(
|
||||
return Err(e.into());
|
||||
}
|
||||
// The row survives as 'reaped', which is what stops the next scan re-downloading it.
|
||||
state.ctx.db.mark_reaped(id)?;
|
||||
state.ctx.db.mark_reaped(id).await?;
|
||||
state.events.send(Event::Reaped {
|
||||
path: enc.path.unwrap_or_default(),
|
||||
bytes: enc.length.unwrap_or(0).max(0) as u64,
|
||||
@@ -1573,7 +1573,7 @@ async fn media(
|
||||
Path(id): Path<i64>,
|
||||
req: Request,
|
||||
) -> Response {
|
||||
let Ok(Some(enc)) = state.ctx.db.enclosure(id) else {
|
||||
let Ok(Some(enc)) = state.ctx.db.enclosure(id).await else {
|
||||
return (StatusCode::NOT_FOUND, "no such enclosure").into_response();
|
||||
};
|
||||
let Some(path) = enc.path else {
|
||||
@@ -1648,9 +1648,9 @@ async fn download_latest(
|
||||
Path(id): Path<String>,
|
||||
Json(body): Json<HowMany>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
let ids = state.ctx.db.undownloaded(&id, body.count.clamp(1, 100))?;
|
||||
let ids = state.ctx.db.undownloaded(&id, body.count.clamp(1, 100)).await?;
|
||||
for enc in &ids {
|
||||
state.ctx.db.requeue(*enc)?;
|
||||
state.ctx.db.requeue(*enc).await?;
|
||||
state
|
||||
.cmds
|
||||
.send(Command::Download { enclosure: *enc })
|
||||
|
||||
Reference in New Issue
Block a user