fix(cleanup): keep shared chat files, sweep inline images by prefix, and make room refetches wait
Merged
WA
1d ago+1230+1230+0123456789012345678901234567890123456789-404-404-012345678901234567890123456789
Summary
Fixes from the v0.9.37 release review that apply to #9419 and #9427.
- Room deliveries wait for every room's refetch:
RoomChangedCallbackis now() => Promise<unknown>, so a callback that drops its invalidation no longer type-checks; the tables and workflows rooms return the invalidations they already made, so a burst no longer cancels and restarts their in-flight list refetches - Deployed-state hint follows the active version: only
loadDeployedWorkflowStatesets the hint, to the active version id, on every successful read; by-id reads of other versions no longer repoint it, so active reads stop re-fetching the state blob after an older version executes - Chat files another chat still references are kept: forks share message attachment keys (organization and message-only copilot attachments are never copied, and a failed blob copy keeps the source key), so cleanup now checks every collected chat-scoped key against the surviving chats' attachments in its scope, one query per scope, before deleting it
- Inline images are swept by their chat prefix: they have no row, so a transcript read could miss ones written later; a dedicated outbox event sweeps
chat-images/<chatId>/for every chat whose row is gone, paged, concurrent and resumable under the outbox deadline, on every delete path (hard delete, account and admin removal, retention jobs) - Malformed attachment keys are skipped instead of throwing out of the purge
- Events queued before this change are still accepted (legacy
organizationIdrefs and inline-image keys), with the legacy paths marked for removal once they drain sweepStoragePrefixmoves intolib/uploads/core/prefix-sweep.tsbeside the listing it pages
Type of Change
- Bug fix
Testing
- Regression tests for each fix, each failing on the previous code: tables room refetch not restarted by a second broadcast; deployed-state hint after a by-id read and after a rollback to a cached version; fork-referenced upload kept, unreferenced one deleted; inline images written after the cleanup read are purged while a surviving chat's prefix is untouched; numeric attachment key skipped; image sweep checkpoint resumes from the lowest unfinished chat; an id no image key can hold is skipped instead of failing the event
- Unit: 361 files across cleanup, mothership chat, uploads, project files, workflow persistence, outbox, auth and the workspace app; integration: 17 files against a fresh database and Redis
bun run lint,bun run check:audits(61),bun run type-check,check:test-types
Checklist
- Code follows project style guidelines
- Self-reviewed my changes
- Tests added/updated and passing (new tests pass the
test-auditauthoring gate) - No new warnings introduced
- I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)