Skip to content

scanOfflineChanges only handles adds/modifies — missing files on disk are never tombstoned in CouchDB #59

Description

@pike00

Summary

PeerStorage.scanOfflineChanges() walks the filesystem and uploads new or modified files, but it never tombstones CouchDB documents whose corresponding files are missing on disk. If a file is deleted while the bridge is down, the CouchDB document persists forever — the deletion is never propagated.

Current behavior

  • Offline scan: walks disk, uploads new/changed files. Deletions are invisible (the walk only sees what exists).
  • Live watch: catches deletions via dispatchDeleted(), but only for events that happen while the watcher is running.

Proposed fix

After the offline scan walk completes, iterate all CouchDB documents and tombstone those whose paths are absent on disk. This requires:

  1. A promise-based gate on PeerStorage so the Hub knows when the offline walk finished (waitOfflineScanComplete()).
  2. A reconcileDiskDeletions() method on Hub that iterates CouchDB docs, checks disk existence via Deno.stat(), and tombstones missing ones via DirectFileManipulator.delete().
  3. Integration into Hub.start() so it runs automatically after an offline scan (no-op when scanOfflineChanges is false).

The reconcile pass respects excludePrefixes (if that config option is added — see related feature request) and logs a summary of scanned/deleted/failed paths.

Design notes

  • The reconcile runs only when scanOfflineChanges is true, so steady-state operation is unaffected.
  • It uses DirectFileManipulator directly (not PeerCouchDB) to avoid the isRepeating dedup gate, which is unnecessary for a one-shot reconcile.
  • The PeerStorage.start() method is changed from await p.start() to void p.start() in the Hub (Deno watchFs never returns; chokidar returns after setup), with the reconcile gated on the new completion promise.

Impact

Without this, any file deleted while the bridge is down leaves a zombie document in CouchDB. On restart, the document is never cleaned up, and other clients never learn of the deletion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions