Core trait surface: Store, TxHandle, mechanism handles, receivers, with_tx (ADR-007 §with_tx, ADR-008 §1–§3/§8, ADR-009 §1/§6, ADR-014, ADR-015 §2, ADR-019 §1–§6, ADR-021 §1/§4/§5)

This commit is contained in:
glm-5.3-flash committed 2026-10-07 15:50:02 +00:00
1 parent 92615f7b7d
commit eefee9ec1d
17 files changed
+1204 -8

No files matched your search

+73 -8
View File
@@ -1,7 +1,7 @@
---
id: core-trait-surface
name: Core trait surface (Store, TxHandle, mechanism handles, receivers)
status: pending
status: completed
depends_on: [core-value-types]
scope: moderate
risk: medium
@@ -87,17 +87,17 @@ drop=rollback, no-claim_tx absence rationale).
## Acceptance Criteria
- [ ] Every trait above with the exact pinned method sets and
- [x] Every trait above with the exact pinned method sets and
signatures; compiles as object-safe (`Box<dyn ...>` everywhere
the contract says)
- [ ] `with_tx` provided method present with the pinned signature
- [ ] A compile-probe test constructs `Box<dyn TxHandle>`,
- [x] `with_tx` provided method present with the pinned signature
- [x] A compile-probe test constructs `Box<dyn TxHandle>`,
`Box<dyn Queue>`, etc. from a trivial local impl, proving object
safety of the whole surface
- [ ] Trait docs state: entry-point validation obligation, drop =
- [x] Trait docs state: entry-point validation obligation, drop =
rollback, the uniform handle-op validity predicate reference,
heartbeat's absolute-reset semantics, no `claim_tx` rationale
- [ ] `cargo test -p alkstore`, clippy `-D warnings`, fmt clean
- [x] `cargo test -p alkstore`, clippy `-D warnings`, fmt clean
## References
@@ -110,8 +110,73 @@ drop=rollback, no-claim_tx absence rationale).
## Notes
> To be filled by implementation agent
- **Async posture**: the "desugared boxed-future form" (ADR-008 §2) is
realized as a named alias, `BoxedFuture<'a, T> =
Pin<Box<dyn Future<Output = T> + Send + 'a>>` in
`src/future.rs` — no `async_trait` macro, no core dependency beyond
the pinned posture (Send bounds the futures: `begin_tx` returns
`Box<dyn TxHandle + Send>`, so its futures must be equally
portable). Sync methods (`try_recv`/`save_offset`/`offset` on
receivers, `job(&self)`, `name(&self)`) stay sync as pinned.
- **`with_tx` dyn encoding**: the pinned signature is
non-generic — a `Store` trait object must stay object-safe — so the
generic-`F` form does not compile on the trait; the pinned
`FnOnce(&mut dyn TxHandle) -> BoxedFuture<Result<()>>` shape crosses
dyn-encoded as `Box<dyn FnOnce ...>`, aliased `WithTxClosure<'a>`
(re-exported) to keep the complex type out of signatures. Values
return through captured state; the provided default body commits on
`Ok`, drops (rolls back) on `Err`.
- **Delivery callable encoding** (ADR-019 §5's implementer's choice):
the named one-method trait object — `trait Delivery { fn
deliver(&mut self, Box<dyn JobHandle>) -> BoxedFuture<Result<()>>;
}` — with `run_once(worker_id, delivery: &mut dyn Delivery)`.
`&mut dyn FnMut` cannot return boxed futures of borrowed data under
object safety, so the named-trait form is the workable answer; the
engine acks on the closure's `Ok` and retries on its `Err`.
- **Fallibility**: the ADR sketches elide `Result<>` for brevity
(ADR-008 §2's note: every fallible op returns the §5 taxonomy);
entry points validating names must err, so constructors
(`stream`/`queue`/`outbox`/`listen`) are `Result`-returning as is
`notify` (PayloadTooLarge); `begin_tx` returns `Result` (SQLite
writer-slot acquisition can fail); no-claim and no-lock outcomes
stay values (`Option`), handle-op outcomes stay `bool`s per
ADR-008 §5's act-differently rule.
- **Scheduler error variants** (`InvalidSpec { spec }`,
`LeadershipLost` — ADR-009 §6) joined `Error` here per
`core-errors-and-validation`'s note (exactly-six list was that
task's scope; their signatures pin in this task). Unit-tested.
- **`tokio` added as a *dev*-dependency only** (test to drive the
boxed-future probes) — runtime deps remain exactly
serde/serde_json/thiserror (ADR-020 §4, ADR-001: no driver deps in
core).
- `Wake`'s `#[non_exhaustive]` prevented the probe's struct-literal
construction — the probe re-exports or constructs nothing of the
read types beyond the existing value-type tests; trait-object
construction is the probe's whole point.
- Every trait doc carries the pinned semantics text: entry-point
validation obligations (Store; TxHandle's own mirror — name-bearing
`*_tx` methods validate like their auto-commit counterparts),
drop=rollback (TxHandle), no-`claim_tx` rationale (Queue), the
uniform validity predicate + absolute-reset heartbeat (JobHandle),
monotone saves (StreamHandle/EventReceiver), terminal-close arms
and the deliberate no-`recv_timeout` absence (receivers).
## Summary
> To be filled on completion
The core trait surface — contract v1 in code — is implemented and
re-exported from `alkstore/src/lib.rs`: `BoxedFuture` +
`TxHandle` (the eleven pinned methods incl. ADR-021 §1's four tx
reads, `commit(self: Box<Self>)`, drop=rollback docs);
`Store` (the pinned method set + the `with_tx` provided method in the
pinned dyn-encoded signature, with commit/rollback dispositions —
unit-tested); mechanism handles `Queue`/`JobHandle`/`StreamHandle`/
`Outbox` (+ `Delivery`)/`Lock` with the exact ADR-019 §1/§3/§5 method
sets; receivers `WakeReceiver` (timeout expiry = `Ok(None)`; `Err` =
Database/Closed only) and `EventReceiver` (no `recv_timeout`,
deliberate); `Error::InvalidSpec`/`LeadershipLost` added (ADR-009
§6). Object-safety compile probes construct every trait object from
trivial local impls (`trait_objects_construct`), and the `with_tx`
dispositions run against a probe store (`with_tx_commit_and_
rollback_dispositions`) — 23 tests green; `cargo test -p alkstore`,
workspace `cargo build`, clippy `-D warnings` (workspace), and
`cargo fmt --check` all clean.