Files
alkstore/tasks/sqlite-fix-watcher-death-subscribe.md
T

3.2 KiB
Raw Blame History

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
sqlite-fix-watcher-death-subscribe Dead-watcher subscribe hang + initial-stat self-kill (review 004 items 2+3) pending
moderate medium component implementation
review-004-fixes
sqlite-engine
watcher

Description

Two bundled watcher-state defects in the SQLite engine, per docs/reviews/004-pre-release-general-review.md §"Findings recorded, not fixed" items 2 and 3 (the review says bundle them — both are watcher-state changes).

(a) Post-watcher-death subscribe hang (item 2). After the watcher thread exits (db-file replacement), subscribe() still enrolls new senders with no poller alive (substrate/watcher.rs:391-396): a listen() or stream subscribe() on the dead store parks forever, contradicting engine-sqlite.md's "on watcher death every subscriber closes" posture — which is enforced only for pre-death subscribers. Fix shape: a dead-store/dead-watcher sign that the new subscription paths consult — a state-machine change across store.rs/notify.rs/ stream.rs. New subscriptions on a dead store must fail closed (a typed error, the established failure vocabulary) rather than park.

(b) Initial-stat failure self-kill (item 3). An identity-stat failure at watcher start seeds (0, 0) (watcher.rs:164-170); the first successful later stat mismatches it and drives the death path, spuriously closing every subscriber on recovery from a transient stat hiccup. Rare, but the fix — an identity-unknown state instead of a false identity — is the same watcher-state family: the watcher treats identity as unknown until the first successful stat, and that first successful stat must not trigger the death path.

Test shapes: (a) kill the watcher (the db-file replacement seam or a cfg(test) death injection), then listen()/subscribe() — assert the typed failure, not a park; the pre-death subscribers' close-at- death pins stay green. (b) inject an initial stat failure, let the first successful stat land, assert the watcher survives and subscribers stay open.

Acceptance Criteria

  • Subscribing (listen or stream) after watcher death fails closed with a typed error instead of parking — pinned by test
  • Pre-death subscribers still close at watcher death — the existing pins green unchanged
  • An initial identity-stat failure no longer seeds a false identity: the first successful stat does not trigger the death path and subscribers stay open — pinned by injected-failure test
  • engine-sqlite.md's watcher-death posture text covers the new-subscriber arm (and the identity-unknown state if it changes observable behavior)
  • cargo test -p alkstore-sqlite, clippy -D warnings, fmt clean; workspace gates green server-less

References

  • docs/reviews/004-pre-release-general-review.md §"Findings recorded, not fixed" items 2–3 (the findings, the fix shapes, the bundling)
  • docs/architecture/engine-sqlite.md (the watcher-death posture)
  • alkstore-sqlite/src/substrate/watcher.rs (both sites), store.rs / notify.rs / stream.rs (the subscription paths)

Notes

To be filled by implementation agent

Summary

To be filled on completion