Repository navigation
Fixes #3982 - #3985
Fixes #3982#3985
Conversation
Two owners of one project share a hook data root. A late retirement of the older owner must not stop the newer owner's consumer, and a reopen must take over replay from an owner still retiring. Both fail on master (#3982).
Retiring an owner stopped whichever consumer held its hook data root, and a reopen that registered while the retiring owner's graph was alive was refused, so the older graph's release left the project without replay. The newest owner now takes the data root over, retirement stops only the consumer its graph owns, and spool detach clears only the wake it attached. Daemon shutdown and project deletion still stop any owner. Fixes #3982.
|
| spool_watch::attach_consumer(&data_root, &project_root, Arc::clone(&wake)); | ||
| let task_wake = Arc::clone(&wake); |
There was a problem hiding this comment.
🟡 Spool wakes target an aborted consumer
When registrations overlap, register_hook_v2_replay_consumer can attach the displaced owner's wake after the new owner's wake. The displaced task is aborted, so new records wait for the live consumer's 30-second sweep.
Learn more
The registry insertion determines which graph owns the data root, but attaching its filesystem wake happens afterward. Another registration can replace the first registry entry and attach its wake before the first registration reaches the watch. The first then overwrites the second wake; its task is aborted when it tries to save its handle, so the watcher keeps notifying a task that cannot drain records. The live task still polls on the replay interval, so the result is delayed delivery rather than permanent loss.
Example: Registration A inserts its entry and pauses. Registration B replaces it and attaches wake B. A attaches wake A, then aborts its own task because its entry is gone. An appended record wakes A instead of B and waits until B's next interval sweep.
Recommended fix: Serialize registry ownership changes with wake attachment, or conditionally attach a wake only when its registration still owns the data root. Ensure that a displaced registration cannot overwrite the active watch target after its registry entry has been replaced.
Was this helpful? React with 👍 or 👎 to provide feedback.
Fixes #3982.
A project's Hook V2 replay consumer is registered per hook data root. Two owners of one project share that root, for example a reopened route and the retiring owner it replaces. Two defects let the older owner strand the newer one:
shutdown_hook_v2_replay_consumer(data_root), which removed, aborted and detached whichever consumer held the root, including a newer owner's.Change
register_hook_v2_replay_consumer: the newest graph for a data root takes it over and aborts the displaced task. Registering the same live graph twice still returnsfalse.Arc<Notify>). The consumer task's exit path andspool_watch::detach_consumeract only on the registration or wake they own.retire_hook_v2_replay_consumer(data_root, owner)stops the consumer only whenowner's graph owns it. Capacity retirement, unserved-owner retirement and remote recovery now call it.shutdown_hook_v2_replay_consumer(data_root)still stops any owner. Its remaining callers are daemon shutdown and remote project deletion, which end every owner of the root.Verification
Both new tests in
hook_v2_replay_consumer::testsfail on master and pass with the fix:a_late_retirement_leaves_the_newer_owners_replay_consumer_running: on master it fails with "the newer owner must own the data root's running replay consumer".a_reopen_takes_over_replay_from_an_owner_still_retiring: on master it fails with "the reopened owner's registration must be accepted".Gates: clippy
--config=clippy //crates/tracedecay/...,//crates/tracedecay:rustfmt_check_2024,//crates/tracedecay:unit_testand//crates/tracedecay:daemon_suiteall pass.twelve_project_journey_retires_idle_owners_without_empty_graphspassed 20/20 runs (20 jobs pinned to 4 cores) on master, on #3981's head and on this branch. The original flake did not reproduce locally.