fix(outbox): classify lease expiry from the database clock - #105
Conversation
Claim a pending integration-outbox row with a fencing token so two workers cannot deliver the same event. Expired leases recover to pending without transferring that fence, and unfenced attempts fail closed while the lease is live.
Look up integration_outbox_lease_presence_check in the current schema so a second isolated search_path can install its own presence check. Serialize shared-schema lease fixtures behind an advisory lock to stop parallel CREATE SCHEMA/table races.
Replace isolated Result `?` tails that Linux llvm-cov counted as uncovered, and add claim-classify plus leased-update database-failure tests so exclusive delivery recovery stays fail-closed.
A failed claim aborts the transaction, so expire and leased-attempt error arms never ran. Use one transaction per operation.
Claim validation treated expires_at == 0 as InvalidTimestamp, but CI branch coverage only saw claimed_at == 0. Prove the second operand and satisfy rustfmt on the fencing-integrity helper.
Claiming with a positive start and a zero expiry must fail closed, and lease tokens decoded from PostgreSQL reject negative values. Expire classify uses an explicit match so the SELECT error arm is covered.
…ative fence Zero-expiry already short-circuited the claim window. Claimed-at overflow, UPDATE failure, and a negative returned fencing token need independent fail-closed evidence.
Lease Display arms were only exercised by lib unit tests, so the integration-test instantiation stayed eight lines short. Also split the concurrency acceptance fixture so clippy pedantic limits pass.
A future caller observation can no longer steal a still-live exclusive outbox delivery lease. Expiry recovery now uses PostgreSQL clock_timestamp(), matching fenced attempt classification. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
seonghobae
left a comment
There was a problem hiding this comment.
Independent last-push review of exact head c2541b96 (opencode-agent merge of protected main). Required checks opencode-review, noema-review, and coverage-evidence are SUCCESS. Classify lease expiry from the database clock is ready to land.
|
Hourly loop: exact head |
Keep persist-backed session HTTP as Active PR #232. Cover command-table load, insert-sink, and replay-lookup Database arms from the library.
|
Hourly loop: exact head |
Retarget onto current protected main after #105/#84/#243/#244. Record shipped persist, narrative, credential, authorization, and outbox-lease evidence. Keep remaining persist and HTTP health Active PR. Keep main's recovery fixture that preserves the exact claim deadline. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Summary
Repair for #60 at
dbeea2be. Exclusive outbox delivery-lease recovery now classifies liveness from PostgreSQLclock_timestamp(), matching fenced attempt recording. A worker can no longer pass a futureobserved_at_unix_msand steal a still-live lease.This branch contains the #60 persist slice plus that fail-closed expire-clock fix. Prefer this head over #60 until #60 picks up the same change.
What changed
expire_outbox_delivery_leasecompareslease_expires_at_unix_msto the database clock, not the caller observation.future_caller_timestamp_cannot_expire_a_live_database_lease.integration_consumptionis recorded as protected-main after feat(integration): persist PostgreSQL inbox consumption distinct from receipt #58, not as Active PR feat(integration): persist PostgreSQL inbox consumption distinct from receipt #58.Test plan
cargo test --test postgres_outbox_delivery_lease_authority --test postgres_outbox_delivery_leaseagainst a real PostgreSQL databasecargo fmt --all -- --checkcargo clippy --locked --all-targets -- -D warningsNext operator action
Review this head for the expire-clock contract, then land it instead of #60 or cherry-pick
69d0fa5onto #60 before merge.