Repository navigation
fix(projects): sweep only retired Project prefixes - #9021
Merged
Merged
Conversation
Retirement no longer arms the bucket-wide Project storage inventory, which deleted every project/<id>/ prefix without a row in this database. The database is not the authority for a bucket another deployment shares or for a bucket that outlives a point-in-time restore, so the inventory could permanently delete live Project files. The reconcile event stays registered with a no-op handler so rows already armed drain to completed, and the processor no longer revives dead-lettered inventory rows. Per-project immediate and post-TTL sweeps are unchanged. The Azure prefix listing no longer includes uncommitted blobs: deleteIfExists cannot remove them, so a page of them kept the sweep continuing until Azure garbage-collected the blocks.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
|
This was referenced Oct 14, 2026
Merged
This branch was previously deployed
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.
Summary
Follow-up to #8609. The Project storage inventory (
project-file.storage.reconcile) listed theproject/prefix in the bucket and deleted everyproject/<id>/whose id was not a row in this database. The database is not the authority for the bucket: after a point-in-time restore the next sweep would permanently delete every Project created after the restore point, and two deployments sharing a bucket would delete each other's Project files. It was armed in production by account deletion and revived on every outbox tick.completedwithout touching storage.includeUncommitedBlobs:deleteIfExistscannot delete uncommitted-only blobs, so a page of them made a prefix sweep loop until Azure GC.Residual: a background write that lands under
project/<id>/after the delayed sweep now orphans bytes instead of being found by the inventory. Covering that safely needs an ownership-safe signal (a tombstone table), not a bucket-vs-database diff.Type of Change
Testing
private-purge.integration.ts: retirement batches no longer arm the inventory, and an already-armed row completes while an unownedproject/<id>/object survives (fails on the old code, which swept it). Full validation in CI.Checklist