feat(api): purge S3 objects when an event is deleted - #52
Merged
Merged
Conversation
MehrshadFb
force-pushed
the
fix/photo-list-cursor
branch
from
September 6, 2026 13:49
deeac20 to
0d96d39
Compare
MehrshadFb
force-pushed
the
feat/event-delete-s3-purge
branch
from
September 6, 2026 13:49
a190d3a to
cfa73ed
Compare
MehrshadFb
force-pushed
the
fix/photo-list-cursor
branch
from
September 6, 2026 13:50
0d96d39 to
2248583
Compare
MehrshadFb
force-pushed
the
feat/event-delete-s3-purge
branch
from
September 6, 2026 13:50
cfa73ed to
721fe28
Compare
6 tasks
API unit-test coverage
Unit suite only; controllers are exercised by the e2e suite. |
9 tasks
MehrshadFb
force-pushed
the
feat/event-delete-s3-purge
branch
from
September 9, 2026 02:46
721fe28 to
e7f4296
Compare
MehrshadFb
force-pushed
the
feat/event-delete-s3-purge
branch
from
September 9, 2026 02:52
e7f4296 to
4ac0e76
Compare
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.
Stacked on #51; the diff here is only the purge change once that merges.
Summary
DELETE /events/:eventIdnow removes the S3 objects of every photo in the event.EventsService.deletereads thes3Keyof eachPhotorow and deletes the event in one transaction (the cascade drops the rows), then hands the keys toPhotoPurgeService.purgeObjects()after the commit.S3Service.deleteObjects(keys): S3DeleteObjectsin quiet mode, 1000 keys per request, returning per-key failures; a request that fails as a whole throws like the otherS3Servicemethods.PhotoPurgeServicein the photos module (exported;EventsModulenow importsPhotosModule). It is best effort by contract: it never throws, logsevent.photos.purgedatinfowith counts on success and aterrorwhen any key remains, and the request still returns 204.event.deletedaudit log gainsphotoCount.deleteObjectsbatching and error mapping,PhotoPurgeServiceoutcomes,EventsService.deleteordering (keys read before the cascade, purge after the transaction, no purge when the transaction fails), and events e2e withS3Servicestubbed.Why
Deleting an event cascaded the rows but never touched S3, so every photo in the event kept costing storage until the daily orphan reconciler ran. That reconciler is opt-in and off outside a deployed environment, so in practice the objects stayed for good. The rows go first on purpose: once they are gone no member can see a photo whose object is missing and the uploaders' quota is released immediately, and what is left at stake is only billing, which is exactly the failure the reconciler exists for.
Notes
DeleteObjectsis authorised by thes3:DeleteObjectaction the API user already has on the bucket objects.Test plan
npx jest --watchman=false(400 tests)npx jest --config ./test/jest-e2e.json --watchman=false(108 tests)npm run typechecknpm run format:checkand eslint on the changed filesnpm run openapi:generate(no diff)