Skip to content

feat: delete Room — purge transfers + kick participants (#92) - #94

Merged
izolyte merged 2 commits into
mainfrom
feat/92-delete-room
Jul 19, 2026
Merged

feat: delete Room — purge transfers + kick participants (#92)#94
izolyte merged 2 commits into
mainfrom
feat/92-delete-room

Conversation

@izolyte

@izolyte izolyte commented Jul 19, 2026

Copy link
Copy Markdown
Owner

What

The Sender had no way to end a Room on demand — Rooms only died lazily at expiry via the sweeper. This adds a Sender-only teardown that purges everything and evicts every Participant.

Changes

  • Socket close: a room:close message, authorised off the Sender's own connection (same auth boundary as sendText). The gateway purges the Room, broadcasts room:closed, then disconnects every other socket — the initiator stays connected long enough to get the ack and navigates away itself.
  • Shared purge: extracted the object-purge + deleteByRoomId out of ExpirySweeperService.expireRoom into RoomService.purgeRoomContents; both on-demand close and the sweeper use the exact same path.
  • Status: RoomService.close flips the Room to CLOSED after purging. CLOSED is already non-joinable via isExpired, so join rejects it for free.
  • Cascade: purge drops MinIO objects + Transfer/FilePayload/TextPayload/Delivery rows.
  • FE: the Sender gets a destructive Delete Room control (edge of the view, inline two-step confirm), which closes the Room and navigates home. A kicked Receiver lands on a Room closed notice.

Tests

  • Gateway: Sender close purges + notifies + kicks; a Receiver's close is rejected and purges nothing; a failed purge surfaces an error and keeps the Room.
  • Service: close purges objects + rows and flips to CLOSED; a storage failure leaves the Room ACTIVE.
  • FE: closeRoom emits + resolves the ack; room:closed latches closed; Sender delete flow emits room:close only after confirm; Receiver sees the closed notice; Receiver has no delete control.
  • Full API (243) + web room (240) suites green; lint + typecheck clean.

Depends on

Stacked on #93 (Text/Link persistence) — the purge cascade needs the TextPayload table. Based on that branch; will retarget to main once #93 merges.

Closes #92

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@izolyte, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 24 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cc3e6f3b-81ae-4343-8d03-e97e91ce8d90

📥 Commits

Reviewing files that changed from the base of the PR and between 1e7c2d2 and 80f2b52.

📒 Files selected for processing (18)
  • apps/api/src/domain/room/room.errors.ts
  • apps/api/src/room/room-events.ts
  • apps/api/src/room/room.gateway.spec.ts
  • apps/api/src/room/room.gateway.ts
  • apps/api/src/room/room.module.ts
  • apps/api/src/room/room.service.spec.ts
  • apps/api/src/room/room.service.ts
  • apps/api/src/sweeper/expiry-sweeper.service.spec.ts
  • apps/api/src/sweeper/expiry-sweeper.service.ts
  • apps/api/src/sweeper/sweeper.module.ts
  • apps/api/src/trpc/routers/room.router.ts
  • apps/web/src/features/room/components/DeleteRoomControl.tsx
  • apps/web/src/features/room/components/RoomShareView.spec.tsx
  • apps/web/src/features/room/components/RoomShareView.tsx
  • apps/web/src/features/room/constants/room-events.ts
  • apps/web/src/features/room/hooks/useRoomSocket.spec.tsx
  • apps/web/src/features/room/hooks/useRoomSocket.ts
  • apps/web/test/app/vocabulary.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/92-delete-room

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@izolyte izolyte added this to the Phase 2 milestone Jul 19, 2026
@izolyte

izolyte commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 27 minutes.

izolyte added a commit that referenced this pull request Jul 19, 2026
Review follow-up on #94.

- closeRoom refuses to emit on a disconnected/lost socket (the emit would
  buffer and its ack never fire, spinning the delete button forever) and
  backstops the ack with a timeout
- join distinguishes a deliberately-closed Room (RoomClosedError) from a
  lapsed one, mapped to NOT_FOUND like the others
- tests: closeRoom fails fast when disconnected; the initiating Sender stays
  connected after close; join rejects a CLOSED Room
izolyte added a commit that referenced this pull request Jul 19, 2026
Review follow-up on #94.

- closeRoom refuses to emit on a disconnected/lost socket (the emit would
  buffer and its ack never fire, spinning the delete button forever) and
  backstops the ack with a timeout
- join distinguishes a deliberately-closed Room (RoomClosedError) from a
  lapsed one, mapped to NOT_FOUND like the others
- tests: closeRoom fails fast when disconnected; the initiating Sender stays
  connected after close; join rejects a CLOSED Room
@izolyte
izolyte force-pushed the feat/92-delete-room branch from 938bc09 to f28bd68 Compare July 19, 2026 19:45
izolyte added a commit that referenced this pull request Jul 19, 2026
Review follow-up on #94.

- closeRoom refuses to emit on a disconnected/lost socket (the emit would
  buffer and its ack never fire, spinning the delete button forever) and
  backstops the ack with a timeout
- join distinguishes a deliberately-closed Room (RoomClosedError) from a
  lapsed one, mapped to NOT_FOUND like the others
- tests: closeRoom fails fast when disconnected; the initiating Sender stays
  connected after close; join rejects a CLOSED Room
@izolyte
izolyte force-pushed the feat/92-delete-room branch from f28bd68 to 634fad4 Compare July 19, 2026 20:03
Base automatically changed from feat/91-persist-text-link to main July 19, 2026 20:05
izolyte added 2 commits July 20, 2026 03:05
The Sender had no way to end a Room; it only died lazily at expiry. Adds
a Sender-only teardown that removes everything and evicts everyone.

- room:close socket message, guarded to the Sender's connection; the gateway
  purges the Room, notifies with room:closed, then disconnects the rest
- RoomService.close flips the Room to CLOSED (already non-joinable via
  isExpired) after purging; purge logic is shared with the expiry sweeper
- purge cascades objects + Transfer/FilePayload/TextPayload/Delivery rows
- FE: Sender gets a destructive Delete Room control with an inline confirm,
  then navigates home; a kicked Receiver lands on a Room closed notice
Review follow-up on #94.

- closeRoom refuses to emit on a disconnected/lost socket (the emit would
  buffer and its ack never fire, spinning the delete button forever) and
  backstops the ack with a timeout
- join distinguishes a deliberately-closed Room (RoomClosedError) from a
  lapsed one, mapped to NOT_FOUND like the others
- tests: closeRoom fails fast when disconnected; the initiating Sender stays
  connected after close; join rejects a CLOSED Room
@izolyte
izolyte force-pushed the feat/92-delete-room branch from 634fad4 to 80f2b52 Compare July 19, 2026 20:06
@izolyte
izolyte merged commit b7ca3c3 into main Jul 19, 2026
6 checks passed
@izolyte
izolyte deleted the feat/92-delete-room branch July 19, 2026 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: delete Room — purge transfers + kick participants

1 participant