Skip to content

couch: failed tombstones are fire-once - port memory-core 0.3.1 deletion reconciliation #84

Description

@vreshch

Gap

CouchSync.removeFile in src/couch/couch-sync.ts is fire-once: unlike pushFileLive (which self-enqueues into the pending queue on failure), a tombstone that fails (network down, 401 mid-outage) is silently lost. pushAll/syncNow only reconcile existing files, so the couch doc survives, the deletion never propagates to other devices, and the deleted note can resurrect on a later pull.

Fix shipped upstream (port candidate)

@agentage/memory-core@0.3.1 (agentage/memory-core#17) closed this in its port of these modules:

  • CouchSyncState gains deletions?: string[]; failed removeFile enqueues; flushPending retries both kinds; old-shape persisted state loads fine.
  • Deletion reconciliation in pushAll: rev cache is the oracle - path in the rev cache but absent on disk = local deletion -> tombstone + drop rev; no rev-cache entry = new remote content (pull writes it).
  • 409 policy: DELETE 409 or advanced content-rev = conflict -> drop the pending deletion + rev, let the next pull re-deliver the newer remote version (edit wins over stale delete; never force-delete with the fresh rev).
  • Bonus: syncNow() now catches pull errors like tick() (returns {pushed, pulled, error?}).

Either port the diff or switch the plugin to consume the shared module from @agentage/memory-core (it now exports CouchSync behind injected FileStore/persistence/fetch seams designed to fit plugin adapters).

Tests to carry over: delete durability (fail then land), phantom-delete guard on pull-applied deletes, tombstone-409 restore, old-state-shape load.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions