feat(watcher): prune projects whose root stays missing (ENOENT-only, grace window)#817
Open
DeusData wants to merge 2 commits into
Open
feat(watcher): prune projects whose root stays missing (ENOENT-only, grace window)#817DeusData wants to merge 2 commits into
DeusData wants to merge 2 commits into
Conversation
…grace window) Distilled from #738: the watcher now prunes a watched project whose root directory has genuinely disappeared - deleting the cached DB (+wal/shm, validated name, cache-dir-only paths) and removing the watch entry - so vanished worktrees stop being watched forever (#286). Hardened beyond the original PR to remove a data-loss hazard (the cached DB can hold user-authored data such as the ADR, unrecoverable once deleted): - Only ENOENT/ENOTDIR stat failures count as missing. Any other failure (EACCES, EIO, transient mounts, macOS TCC revocation) resets the streak and logs watcher.root_stat_error with the errno; Windows (mingw/UCRT) maps not-found to ENOENT so the check holds there. - Pruning requires BOTH >=3 consecutive missing polls AND a sustained- absence grace window since the streak's first miss (default 600s, override via CBM_WATCHER_PRUNE_GRACE_S), tracked with monotonic cbm_now_ms. - Root reappearance resets streak + timestamp (watcher.root_restored). - The pruned entry is released via the deferred-free list poll_once drains (one freeing model shared with cbm_watcher_unwatch). Limitation: only currently-watched projects are pruned; stale DBs left by older sessions are out of scope. Co-authored-by: pcristin <xxxokzxxx@protonmail.com> Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(watcher): prune projects whose root stays missing (ENOENT-only, grace window)
What does this PR do?
Implements the stale-root cleanup from #286: the watcher now prunes a watched
project whose root directory has genuinely disappeared — the cached project DB
(
<name>.dbplus-wal/-shm) is deleted and the watch entry removed — sovanished worktrees stop being watched (and re-stat'ed) forever.
Distilled from #738 (thanks @pcristin), with safety hardening on top of the
original mechanism. The cached DB can hold user-authored data (e.g. the
project ADR) that is unrecoverable once deleted, so pruning is deliberately
conservative:
stat()fails withENOENT/ENOTDIR(or the root exists but is no longera directory). Any other failure —
EACCES,EIO, a transient networkmount, macOS TCC permission revocation — resets the streak and is logged
distinctly as
watcher.root_stat_error errno=..., never counting towarddeletion. Windows (mingw/UCRT) maps
ERROR_FILE_NOT_FOUND/ERROR_PATH_NOT_FOUNDtoENOENT, so the same check holds there (sameconvention as
find_deleted_filesinpipeline_incremental.c).consecutive missing polls AND at least
CBM_WATCHER_PRUNE_GRACE_Sseconds(default 600 = 10 minutes, env-overridable) elapsed since the streak's
first missing observation (tracked via monotonic
cbm_now_ms()).first-miss timestamp reset (
watcher.root_restored); a fresh uninterruptedstreak is required to prune.
list introduced in fix: unwatch deleted projects to prevent zombie reindex #537 for
cbm_watcher_unwatch(drained by the nextpoll_once), keeping one consistent freeing model for poll snapshots.DB deletion goes through
cbm_validate_project_nameand builds paths onlyinside
cbm_resolve_cache_dir().Tests
watcher_prunes_sustained_missing_root— positive prune path (grace 0sisolates the streak threshold): misses 1–2 keep project + DB, miss 3 prunes
the watch entry and deletes db/-wal/-shm. Red-first verified: on
origin/mainthis fails (nothing prunes); green with the fix.watcher_grace_window_blocks_prune— 4 fast missing polls with a 600swindow: streak threshold reached, time gate not → NOT pruned, DB intact.
watcher_root_restore_resets_prune_streak— 2 misses, root restored,2 misses again → not pruned (streak restarted); 3rd miss of the new streak
prunes. Red-first verified on
origin/main.watcher_root_missing_errno_classification— unit test of the errnoclassifier with injected values (
ENOENT/ENOTDIR→ missing;0,EACCES,EIO,EINVAL,ENAMETOOLONG→ not). A realEACCEScannot besimulated portably (root on CI, Windows ACLs), hence the injected-errno
unit test on the factored classifier.
Known limitation (honest residual of #286)
Only currently-watched projects are pruned. Stale cached DBs left behind
by older sessions (projects never watched in this server's lifetime) are out
of scope for this change.
Validation
make -f Makefile.cbm cbm—-Werrorcleanmake -f Makefile.cbm lint-ci— clean./build/c/test-runner watcher— 58 passed, 0 failed (ASan/UBSan runner)Closes #286.