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

76 lines
3.2 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: sqlite-fix-watcher-death-subscribe
name: Dead-watcher subscribe hang + initial-stat self-kill (review 004 items 2+3)
status: pending
depends_on: []
scope: moderate
risk: medium
impact: component
level: implementation
tags: [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