Relationships
#2329 s3/gcs-datastore: clean up data left behind by deletes that silently no-opped before the swamp-club#2249 fix
Opened by hammz · 9/21/2026
Summary
Follow-up cleanup for swamp-club#2249, against @swamp/s3-datastore and
@swamp/gcs-datastore. That issue fixes the shard-key derivation so data
deletes correctly remove their objects going forward. It does not repair
state already written by the broken code, and there are two distinct kinds
of leftover.
1. Orphaned latest pointers (all model types). A deleted data item
leaves <dataName>/latest in the bucket, indexed under the wrong shard.
Low impact: core ignores a latest whose version directory is missing, so
data get stays not-found, and the next write to the same data name
overwrites and correctly re-indexes the pointer. It persists only for data
names deleted and never recreated.
2. Data items that were never deleted at all (model types with 3+ type
segments, e.g. aws/ec2/vpc). This is the one worth acting on. The
scoped delete derived a partition key absent from _meta.json, read an
empty index, and deleted nothing — while reporting success. Verified
against the in-memory mock: after the delete, the bucket still holds
1/raw, 1/metadata.yaml and latest, and a fresh reader hydrates all
three with the raw content intact and readable.
Why the 2249 fix does not cover it
Nothing re-examines state nobody touches. For case 1, _meta.json prunes
a partition only when its shard goes empty, and pullChangeds bulk-diff
prunes an index entry only when its object is gone from the bucket — the
orphan object is still there. For case 2 the state is not even
inconsistent: bucket and index agree the item exists. The only thing that
would clear it is re-running the delete, which the user already ran and
was told succeeded.
Impact, stated honestly
Nothing stops working. There is no availability or read-correctness
problem, and the drift does not compound — a recreated-then-deleted name
self-heals via the bulk-diff prune. The verifier in this repo never reads
the index (HeadBucket plus a conditional-write probe), and there is no
compaction tooling here, so the "breaks verifier/compaction" concern
raised in 2249 does not apply to this repo.
The real point is semantic: users who ran swamp data delete on an
affected model and saw it succeed still have that data in their bucket,
and nothing will tell them.
Suggested work
- A reconcile pass that walks the bucket against the assembled index and
reports data-name subtrees whose deletion never completed, plus
latestpointers whose version directories are absent. - Report-only first. Removal should be opt-in — this deletes user data, and the population is exactly the set of items where a previous delete already misbehaved.
- Applies to both extensions; the sync implementations are duplicated and carried the identical defect.
Related
- swamp-club#2249 — the root-cause fix (shard-key derivation)
Open
No activity in this phase yet.
Sign in to post a ripple.