DeleteBucket: retired segments' space registrations are unenumerable; needs a space-scoped bulk release #76
Description
Problem
Deleting a bucket requires its Forge space to be empty: hilt's /s3/bucket/delete checks
SpaceEmpty (a /space/blob/list against sprue) and refuses while any registration remains.
Since #68, DeleteBucket releases the blobs its catalog segments registered — each shipped
segment's CAR and sharded-dag-index — by enumerating the bucket's segment rows and invoking
/space/blob/remove per digest.
That enumeration only covers registrations the rows still describe. Retention prunes segment
rows past the Retain window (default 6) after retiring their local CARs, and retiring is
local-only by design: the network copy is the durable read tier, so the CAR and index stay
registered in the space with no remaining record on ingot's side. Consequences:
- A long-lived bucket with more than
Retainshipped catalog segments cannot be fully
released by ingot at deletion —DeleteBucketreturnsBucketNotEmptyeven though the
bucket holds no objects. - Registrations leaked by past best-effort release failures (
releaseBlobslogs and moves on)
are equally invisible to the enumeration. - Even with complete records, the per-digest
/blob/removeloop is one RPC per blob and will
not scale to old buckets.
Raised in review: #68 (comment)
Proposal
Replace per-blob enumeration with a space-scoped teardown at bucket deletion, on the
service side — either shape works:
- sprue: a bulk
/space/blob/remove(remove-all, or paginated remove-by-list) that
deregisters every blob in the space and forwards the releases to the holding providers; or - hilt:
/s3/bucket/deletetears the space down itself when it knows the bucket is being
deleted (it already owns the space lifecycle and theSpaceEmptycheck), instead of
refusing on a non-empty space.
Either way ingot's DeleteBucket drops the enumerate-and-release pass (keeping the quiesce,
which is still needed so an in-flight ship cannot re-register after teardown), and a space
wipe also sweeps historic leaks that no local record describes.
Cross-repo: the mechanism lands in sprue or hilt; this issue tracks the ingot side and the
overall shape.
🤖 Generated with Claude Code
Activity