glm-5.3-flash 029f885aa1 general review 004 (pre-release, whole workspace): one HIGH slot-poisoning fix, two contract-observable divergence fixes, robustness + doc corrections — all gates re-run green
- sqlite scheduler tick: a failed COMMIT (or ROLLBACK) left the connection
  released with a stuck-open transaction, wedging the writer slot forever —
  the one commit site missing the drop-+-reopen-replenish arm; tick now
  takes the conn by value with a poisoned disposition (drop + replenish),
  the commit-fault seam reaches the tick, and
  failed_tick_commit_replenishes_the_writer_slot pins the arm
- pg save_offset_tx stored GREATEST($3,0) where the wave-8 gate's
  negative-seed fix (raw seed, ADR-023 §2 2026-10-11 annotation) covered
  only the auto-commit form; mem's merged in-tx read clamped a staged
  negative seed against a phantom zero; both fixed and the tx-form
  totality pinned by a new stamped suite leg (in_tx_reads_see_own_writes)
  green on all three columns vs the live harness server
- pg: a failed forwarder register leaked the channel refcount forever
  (no receiver to drop it) — listen/spawn_bridge now unregister on the
  register error, mirroring the subscribe-failure arm; register doc
  corrected to put the failure disposition at the call site
- pg forwarder: nine poisoned-mutex expect() panics converted to the
  mem crate's into_inner recovery idiom (no-expect-outside-tests rule)
- core encode_payload: a deeply-nested Value aborted the process in
  serde_json's unguarded serializer recursion and the fuzz pin blessed
  storing bytes no decoder could read back; encode now rejects nesting
  past 127 containers (the empirically-verified decode limit) with typed
  Codec — decode-aligned boundary pins added to the fuzz invariant and
  value_type_tests, applied pre-publish within the open class-1 window
- scheduler sleep deadlines: Instant + Duration overflow caps (MAX_SLEEP_S,
  tick-and-resleep) on all three engines for far-future boundaries;
  sqlite tick claim stamp now saturating_add
- docs read true again: Error::Closed scope (stream try_recv arm),
  validation whitespace wording, sqlite lib.rs phantom durability knobs,
  pg lock.rs honest autocommit wording, mem tx/stream merge + wake-
  granularity wording; wakes.rs stale allow(dead_code) removed
- tests: value_type_tests exercised its own map_err instead of the
  function under test (fixed); unwrap_or_default reference encodes
  panic with cause
- docs/reviews/004-pre-release-general-review.md records nine fixed +
  sixteen parked findings (sqlite seam panic-safety armor, watcher
  post-death-subscribe hang + initial-stat self-kill, pg forwarder
  TOCTOU/hang/diagnosability, pg BIGINT server-side stamp overflow, mem
  growth/outbox notes, pg identifier-truncation doc note, smaller) and
  two false positives caught on verification; implementation.md
  review-rounds entry + core-contract backlog rows updated
- gates: build, workspace tests (sqlite 194, core 27, suite legs new),
  full live pg column 127+25+9, clippy -D warnings, fmt, fuzz replay
  6/6, wasm32 check, doc gate -D warnings — all green
2026-10-11 09:25:59 +00:00
mem engine integration — the suite's third column lands, born pinned: StoreFactory implemented for the mem engine (alkstore-mem/tests/contract_suite.rs — a fresh MemStore::new() per open, teardown = drop, unit-struct factory with no external backing) and all 25 rows wired under the current-thread flavor (every test explicitly flavor = "current_thread" — the no-spawn_blocking posture proven by the flavor the column runs under, grep re-verified clean): the 24 engine-shared mechanism rows + mem's new PayloadTooLarge non-occurrence arm row (payload_too_large_never_produced_on_mem — properties.rs, stamped ADR-016 §5 + ADR-024 §3, just-past-2-MiB payload, exported from the suite lib; the SQLite/pg rows untouched — a suite-side class-4 addition, recorded in the task Notes). Column green first run (13 s), zero red rows — no mem defects, no row wobbles, no class-1 escalation owed. Full-surface wiring + crate posture/wasm-identity docs verified as landed by the seam/foundations tasks — zero production code changed. engine-mem.md frontmatter: draft → implementation-complete (stable flip stays with the review gate). Task file: status completed, 6 acceptance boxes ticked, Notes (incl. the wasm on-target scope-out's named collapse condition: a wasm-bindgen-test adapter crate, deliberately not an OQ) + Summary filled. Verified: cargo build; workspace cargo test green (core 25, suite harness 3, mem 100 lib + 25 suite, sqlite 191 + 25, pg 124 + 25 + 9); clippy --all-targets -D warnings clean; cargo fmt --check clean; cargo check --target wasm32-unknown-unknown -p alkstore-mem clean
2026-10-10 12:40:26 +00:00

alkstore

One reactive store interface — durable notify/subscribe signals, streams with per-consumer offsets, durable queues with the transactional enqueue property, named locks, a scheduler, and an outbox helper — over SQLite, Postgres, and the in-process mem engine. Each engine uses its own native machinery underneath (SQLite: the forked honker watcher design; Postgres: pg_notify/LISTEN and the pg-boss schema family; mem: guarded in-process state, ephemeral by design).

alkstore is the substrate, made once: the answer to "how does a change in the database become visible to other processes/connections?" that downstream stores don't re-derive.

The interface

One unified trait surface (alkstore::Store), seven mechanisms:

  • notify / listen — durable publish/subscribe signals with transactional wake discipline (wake on commit, opaque wake → re-read).
  • streams — append-only logs with per-consumer offsets, carried metadata, and consumer-invoked trim_to.
  • queues — visibility-timeout claim discipline, backoff, dead-lettering, and an opt-in retention sweep; enqueue is available inside the transaction seam (the outbox pattern).
  • named locks — TTL-based lease locks with renewal and expiry reclaim.
  • outbox helper — transactional enqueue-on-commit (outbox_enqueue_tx) with a run_once delivery driver.
  • scheduler — @every-interval schedules that enqueue onto a queue, with bounded catch-up and leadership discipline (multi-process safe).
  • transaction seam — with_tx and caller-held TxHandle methods; drop of the handle rolls back.

Crate family

Downstream consumers depend on alkstore (core) plus exactly one engine crate. Engine identity is compile-time: the engine crate your binary depends on is the deployment statement — there is no runtime capability surface (ADR-016).

Crate Role Engine posture
alkstore the contract artifact: unified trait surface, value types, error model (no driver dependencies) —
alkstore-sqlite SQLite engine (rusqlite over the in-tree forked honker substrate) single-host, file-backed — cross-process on one host is verified territory; NFS two-writers is not a supportable posture
alkstore-postgres Postgres engine (tokio-postgres + deadpool-postgres, hand-rolled LISTEN) multi-host native; v1 TLS is effectively unavailable (NoTls on every connection path) — network confidentiality comes from the deployment topology
alkstore-mem in-process engine, full contract v1 honest-ephemeral — no durability, single-process, never fleet-valid; loss on process exit is the documented posture; compiles clean on wasm32-unknown-unknown

The unified trait does not pretend SQLite is multi-host — the honest boundary lives in the compile-time engine identity plus the documented deployment matrix (host semantics, connection budgets, durability knobs, growth postures).

Usage

The mem engine is the zero-config example carrier — one call and no options:

use alkstore::{EnqueueOpts, JobState, QueueOpts, Store};
use alkstore_mem::MemStore;

let rt = tokio::runtime::Builder::new_current_thread().build()?;
let store = MemStore::new();

let queue = rt.block_on(store.queue("demo", QueueOpts::default()))?;
let job_id = rt.block_on(queue.enqueue(
    serde_json::json!("hello"),
    EnqueueOpts::default(),
))?;

let claimed = rt.block_on(queue.claim_one("worker-1"))?
    .expect("the enqueued job is claimable");
assert_eq!(claimed.job().id, job_id);
assert_eq!(claimed.job().state, JobState::Processing);

The surface is the same on every engine; only the constructor differs:

let store = alkstore_sqlite::open("store.db", SqliteOpts::default())?;      // single-host
let store = alkstore_postgres::open(&dsn, PgOpts::default()).await?;        // multi-host
let store = MemStore::new();                                                // in-process

Three engines, one pinned contract

The contract is pinned once, not per engine: the internal alkstore-contract-suite crate parameterizes the contract's property set over a store factory, and each engine crate runs the same suite rows against its own factory as part of its test target. Three engines, one pinned contract — the core contract is the spec of record (mechanisms, delivery guarantees, error taxonomy, naming / reserved namespace).

Documentation

License

Dual-licensed under MIT or Apache-2.0, matching the workspace license = "MIT OR Apache-2.0" field.

The SQLite engine carries a forked third-party substrate (honker) in-tree under its upstream dual license; its bundled license notice (alkstore-sqlite/src/substrate/LICENSE) is the preservation obligation's carrier and is not replaced by the root license files (ADR-018).

S
Description
No description provided
Readme
2.2 MiB
0 Stars 6 Watchers 0 Forks
Languages
Rust 99.4%
Python 0.5%