Files
alkstore/tasks/suite-tx-commit-atomicity-rows.md
T

83 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: suite-tx-commit-atomicity-rows
name: Contract-suite rows — outbox/keyed-publish tx commit-atomicity + with_tx panic probe
status: pending
depends_on: []
scope: moderate
risk: low
impact: phase
level: implementation
tags: [wave-5, contract-suite, tx-seam]
---
## Description
Add the tx-seam commit-atomicity rows to
`alkstore-contract-suite/src/properties.rs` and wire them into both
engines' suite targets, discharging three backlog rows
(core-contract.md §Verification backlog): "`outbox_enqueue_tx`
commit-atomicity on both engines" (ADR-014), "`publish_with_key_tx`
commit-atomicity on both engines" (ADR-015 §2), and the N-5
`with_tx` panic-disposition probe (the waves-1–2 general review's
ordered wave-5 add — the panic path "can only be fully pinned once a
real engine's handle exists").
Rows to add:
- **`outbox_enqueue_tx_commit_atomicity`** — rollback drops the
backing-queue job row together with the business write (no ghost
job; `run_once` afterwards claims nothing); commit makes the job
claimable by `run_once` exactly when the business write commits
(drive a real delivery through the `Delivery` closure); the stamped
opts are the outbox's derived 60/5/5 set, `get_job`-visible and
identical on both engines (ADR-014 §1, ADR-010 §3a). The
reserved/empty outbox-name validation legs already pin in the
exemplar row — do not duplicate them.
- **`publish_with_key_tx_commit_atomicity`** — rollback drops the
keyed event row with the business write (no ghost event); commit
makes it visible to `read_since` (and a subscriber attach); the key
round-trips on the committed event. The empty-`Some`-key
`InvalidName` leg already pins in the exemplar — do not duplicate.
- **`with_tx_panicking_closure_rolls_back`** — a closure that panics
mid-flight ⇒ rollback with no residue (the uniform no-ghosts list:
job/event/notify/offset — ADR-021 §4's drop = rollback through the
panic path), and the store remains usable afterward (the SQLite
writer slot replenished — the wave-3 stranding fix's property, now
pinned at contract level). Mechanics hint: the panic crosses an
await inside `with_tx`'s own future, so drive it via
`tokio::spawn` + `JoinError::is_panic()` (a `catch_unwind` around an
async closure does not see the panic point); assert the panic
surfaced *and* the post-panic state. This is N-5's probe against
real engines for the first time — the SQLite handle-on-lease Drop
impl and the pg pooled-object discard arm must both survive it.
## Acceptance Criteria
- [ ] Three rows exist, version-stamped (ADR-014 §1, ADR-015 §2,
ADR-021 §4, ADR-007 as applicable)
- [ ] Rows wired into both engines' `contract_suite.rs` targets
- [ ] SQLite column green server-less; pg column green against the
harness server
- [ ] The panic probe passes on both engines (no writer-slot stranding,
no pooled-object leak) — if an engine fails here, that is a real
defect: stop, record, fix engine-side before completing the task
- [ ] `cargo test -p alkstore-sqlite -p alkstore-postgres` green
(pg rows skip cleanly server-less); clippy `-D warnings`; fmt clean
## References
- docs/architecture/core-contract.md §Verification backlog (outbox tx
commit-atomicity; keyed-publish tx commit-atomicity)
- docs/architecture/decisions/014-outbox-tx-enqueue.md §1
- docs/architecture/decisions/015-streams-depth.md §2
- docs/architecture/decisions/021-tx-reads-and-value-shape-fixes.md §4
- docs/reviews/001-waves-1-2-general-review.md (N-5)
- tasks/sqlite-engine-seam-tx.md (the Drop impl N-5's probe exercises)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion