Contract-suite queue-depth rows (task suite-queue-depth-rows): the job-handle validity predicate row (in-window heartbeat/ack landing, late-heartbeat/post-lapse-ack/retry/fail refusals past a 1 s stamp with the row untouched, ack_batch per-id predicate live-1/lapsed-0/nonexistent-0, fail(None)→"failed" and retry-at-budget→"max attempts exceeded"), the ADR-010 depth row (reclaim consumes an attempt with claimed_at/deadline refreshed and the original holder refusing, reclaim-exhaustion dead-lettering with the pre-claim sweep — get_job-visible "max attempts exceeded"+died_at, cancel unconditional delete with the not-an-interrupt refusal shape plus pending/dead/missing arms), and the no-stranded-rows sweep row (both states move with "expired", unexpired/never-expiring untouched, retention TTL enforcing with the moved+deleted sum, None=forever) — each version-stamped per the suite convention (ADR-010 §1–§5, ADR-019 §3, ADR-008 §5), wired into both engines' suite targets (SQLite tokio tests, pg harness_row!s). M-1's retention-failure pin dispositioned engine-side per the task's honest call: the storage-level DELETE failure is not injectable through the contract surface, so it lands in the SQLite substrate's trigger seam (sweep_rolls_back_the_retention_half_with_the_move — the move half rolls back with the retention half), with the pg twin verified structurally (both halves inside in_tx's frame) and the disposition recorded in the task Notes. Verified: sqlite suite 13/13, pg suite 13/13 vs harness twice (postgres/poc@:15432), substrate sweep-rollback tests 4/4, workspace build/test green, clippy -D warnings, fmt clean

This commit is contained in:
glm-5.3-flash committed 2026-10-10 05:50:26 +00:00
1 parent 250511d480
commit 5c9ae6a7fc
6 files changed
+746 -15

No files matched your search

@@ -795,6 +795,14 @@ mod queue_tests {
.unwrap();
}
fn block_dead_deletes(conn: &Connection) {
conn.execute_batch(
"CREATE TRIGGER test_block_dead_delete BEFORE DELETE ON __alkstore_dead
BEGIN SELECT RAISE(ABORT, 'dead delete blocked'); END",
)
.unwrap();
}
fn undecodable_pending_job(conn: &Connection) -> i64 {
let id = put(conn, "emails", "{}", now_unix(conn).unwrap(), 0, 3, None);
conn.execute(
@@ -1532,6 +1540,69 @@ mod queue_tests {
assert!(conn.is_autocommit());
}
// The M-1 follow-up (the waves-1–2 general review's §4 suggested add,
// task suite-queue-depth-rows): the retention half's rollback. The
// retention DELETE runs inside the same savepoint as the move half —
// a failure in it rolls the live→dead move back too (no effects
// partially applied by an Err sweep). Not injectable through the
// contract surface (storage-level failure, no fault seam) — pinned
// here at the substrate seam with a trigger-raised ABORT.
#[test]
fn sweep_rolls_back_the_retention_half_with_the_move() {
let conn = db();
let now: i64 = now_unix(&conn).unwrap();
let aged = enqueue(
&conn,
"q",
"{}",
now,
0,
Some(now - 1),
Stamps {
max_attempts: 5,
visibility_timeout_s: 300,
backoff_base_s: 5,
dead_letter_retention_s: Some(60),
},
)
.unwrap();
assert_eq!(sweep_expired(&conn, "q", EXPIRED).unwrap(), 1);
let aged_out = now - 61;
conn.execute_batch(&format!(
"UPDATE __alkstore_dead SET died_at = {aged_out} WHERE id = {aged}"
))
.unwrap();
let fresh = put(&conn, "q", "{}", now, 0, 5, Some(now - 1));
block_dead_deletes(&conn);
let err = sweep_expired(&conn, "q", EXPIRED)
.expect_err("the failing retention DELETE must reach the caller");
assert!(
err.to_string().contains("dead delete blocked"),
"got: {err}"
);
assert_eq!(
(live_count(&conn, fresh), dead_count(&conn, fresh)),
(1, 0),
"the move half rolled back with the retention half"
);
assert_eq!(
dead_count(&conn, aged),
1,
"the retention DELETE rolled back with it"
);
assert!(conn.is_autocommit());
conn.execute_batch("DROP TRIGGER test_block_dead_delete")
.unwrap();
assert_eq!(
sweep_expired(&conn, "q", EXPIRED).unwrap(),
2,
"unblocked, both halves land: one moved + one retention-deleted"
);
assert_eq!((live_count(&conn, fresh), dead_count(&conn, aged)), (0, 0));
}
// ---------------- no-stranded-rows property ----------------
#[test]