use sqlx::SqlitePool;
use super::{PurgeReport, RetentionPolicy, terminal_state_labels};
pub async fn purge(
pool: &SqlitePool,
table: &'static str,
orphan_sweeps: &[&'static str],
key_sweep: &'static str,
policy: &RetentionPolicy,
) -> Result<PurgeReport, sqlx::Error> {
let labels = terminal_state_labels();
let cutoff = format!("-{} seconds", policy.terminal_max_age.as_secs());
let batch = i64::from(policy.effective_batch_size());
let delete_sql = format!(
"DELETE FROM {table} WHERE rowid IN ( \
SELECT rowid FROM {table} \
WHERE state IN (?1, ?2, ?3, ?4) \
AND updated_at < strftime('%Y-%m-%d %H:%M:%f', 'now', ?5) \
LIMIT ?6 \
)"
);
let mut report = PurgeReport::default();
loop {
if policy.max_batches.is_some_and(|max| report.batches >= max) {
report.complete = false;
break;
}
let mut query = sqlx::query(&delete_sql);
for label in &labels {
query = query.bind(label);
}
let deleted = query
.bind(&cutoff)
.bind(batch)
.execute(pool)
.await?
.rows_affected();
if deleted == 0 {
report.complete = true;
break;
}
report.tasks_deleted += deleted;
report.batches += 1;
}
for sweep in orphan_sweeps {
loop {
if policy.max_batches.is_some_and(|max| report.batches >= max) {
report.complete = false;
return Ok(report);
}
let deleted = sqlx::query(sweep)
.bind(batch)
.execute(pool)
.await?
.rows_affected();
if deleted == 0 {
break;
}
report.orphan_rows_deleted += deleted;
report.batches += 1;
}
}
expire_keys(pool, key_sweep, policy, batch, &mut report).await?;
Ok(report)
}
async fn expire_keys(
pool: &SqlitePool,
key_sweep: &'static str,
policy: &RetentionPolicy,
batch: i64,
report: &mut PurgeReport,
) -> Result<(), sqlx::Error> {
let Some(max_age) = policy.effective_idempotency_key_max_age() else {
return Ok(());
};
let cutoff = format!("-{} seconds", max_age.as_secs());
loop {
if policy.max_batches.is_some_and(|max| report.batches >= max) {
report.complete = false;
return Ok(());
}
let deleted = sqlx::query(key_sweep)
.bind(&cutoff)
.bind(batch)
.execute(pool)
.await?
.rows_affected();
if deleted == 0 {
return Ok(());
}
report.idempotency_keys_deleted += deleted;
report.batches += 1;
}
}