Skip to content

[FTF-198] Send close code on react-web-cli panel unmount#128

Open
denissellu wants to merge 2 commits intomainfrom
FTF-198-send-close-code-on-unmount
Open

[FTF-198] Send close code on react-web-cli panel unmount#128
denissellu wants to merge 2 commits intomainfrom
FTF-198-send-close-code-on-unmount

Conversation

@denissellu
Copy link
Member

@denissellu denissellu commented Jan 9, 2026

See FTF-198 This PR ensures the terminal component signals session closure correctly over WebSocket, while preserving session resume on navigation/reload.

Companion server PR: https://github.com/ably/cli-terminal-server/pull/105


Problem

The original implementation sent close code 4001 on every component unmount. This told the server to immediately destroy the session — but unmount also fires on page navigation and reloads, which broke resumeOnReload behavior.

Solution

  • Unmount now calls close() with no special code, so the server's grace period applies and the session remains resumable.
  • terminateSession() — a new method exposed on the AblyCliTerminalHandle ref — sends close(4001, "user-closed-panel") for immediate server cleanup. The parent should call this before unmounting when the user explicitly closes the panel.

Changes

File What changed
AblyCliTerminal.tsx Unmount uses normal close(); added terminateSession() on the imperative handle for explicit 4001 close
AblyCliTerminal.test.tsx Tests for: normal close on unmount, skip close when already closing, terminateSession() sends 4001

Usage

const terminalRef = useRef<AblyCliTerminalHandle>(null);

// When user clicks "close panel":
terminalRef.current?.terminateSession();
// Then unmount the component

Note

Low Risk
Small, isolated change to WebSocket close semantics plus unit tests; main risk is behavioral expectations around when sessions should be terminated vs resumable.

Overview
Preserves resumeOnReload by changing AblyCliTerminal unmount cleanup to perform a normal WebSocket.close() (no 4001), so the server can apply its resume grace period.

Adds an imperative terminateSession() method on AblyCliTerminalHandle that explicitly closes primary/secondary sockets with close(4001, "user-closed-panel") for immediate server-side session cleanup, and introduces tests covering unmount close behavior, skipping close when already CLOSING, and terminateSession() sending 4001.

Written by Cursor Bugbot for commit 1caa265. This will update automatically on new commits. Configure here.

@vercel
Copy link

vercel bot commented Jan 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cli-web-cli Ready Ready Preview, Comment Feb 18, 2026 7:21pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

Walkthrough

Modifies AblyCliTerminal component to close WebSocket connections with code 4001 and reason "user-closed-panel" when unmounting, signaling intentional shutdown to enable server session cleanup. Adds test coverage for unmount cleanup behavior.

Changes

Cohort / File(s) Change Summary
WebSocket close signal on unmount
packages/react-web-cli/src/AblyCliTerminal.tsx
Updated WebSocket close call on component unmount to pass close code 4001 with reason "user-closed-panel" instead of plain close, with explanatory comment for server cleanup intent
Unmount cleanup test suite
packages/react-web-cli/src/AblyCliTerminal.test.tsx
Added new "Unmount cleanup" test suite with two test cases: one verifying WebSocket closes with code 4001 and reason when unmounted, another verifying no close call when socket already in CLOSING state

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 When panels close and time to part,
A code four-zero-zero-one at heart,
"User-closed-panel" rings so clear,
Sessions end without a tear! 🌙✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: sending a close code when the react-web-cli panel unmounts.
Linked Issues check ✅ Passed Changes implement the core requirement to terminate terminal sessions on panel unmount by closing WebSocket with code 4001 and reason 'user-closed-panel'.
Out of Scope Changes check ✅ Passed All changes are directly related to the issue objective of terminating sessions on panel close; no out-of-scope modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch FTF-198-send-close-code-on-unmount

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/react-web-cli/src/AblyCliTerminal.tsx (1)

3556-3564: Add close code and reason to secondary WebSocket cleanup for consistency.

The secondary WebSocket at line 3563 closes without an explicit close code, defaulting to 1000, while the primary socket uses close code 4001 with reason "user-closed-panel" at line 2425. This inconsistency should be addressed.

Consider updating line 3563 to use an explicit close code and reason string (e.g., close(1000, "user-closed-panel") or close(4001, "user-closed-panel")) to match the pattern established for primary socket cleanup. This ensures both sockets signal their closure to the server in the same manner.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9b37916 and f7a6f37.

📒 Files selected for processing (2)
  • packages/react-web-cli/src/AblyCliTerminal.test.tsx
  • packages/react-web-cli/src/AblyCliTerminal.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/Development.mdc)

**/*.{ts,tsx}: Use TypeScript and follow best practice naming conventions
ESLint is used to ensure all code adheres best practices; ensure you check that all code passes the linter before concluding your work.

Files:

  • packages/react-web-cli/src/AblyCliTerminal.tsx
  • packages/react-web-cli/src/AblyCliTerminal.test.tsx
🧬 Code graph analysis (2)
packages/react-web-cli/src/AblyCliTerminal.tsx (1)
packages/react-web-cli/src/terminal-shared.ts (1)
  • debugLog (311-315)
packages/react-web-cli/src/AblyCliTerminal.test.tsx (1)
packages/react-web-cli/src/AblyCliTerminal.tsx (1)
  • AblyCliTerminal (3838-3841)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: auth-tests
  • GitHub Check: session-tests
  • GitHub Check: ui-tests
  • GitHub Check: Cursor Bugbot
  • GitHub Check: e2e-cli
🔇 Additional comments (2)
packages/react-web-cli/src/AblyCliTerminal.tsx (1)

2418-2426: LGTM - Clear intent and proper cleanup.

The unmount logic correctly closes the WebSocket with code 4001 to signal intentional closure, and the guard condition properly checks for sockets that are still active (CONNECTING or OPEN states). The inline comment clearly documents the server-side cleanup behavior.

packages/react-web-cli/src/AblyCliTerminal.test.tsx (1)

2471-2514: LGTM - Comprehensive test coverage for unmount cleanup.

The test suite appropriately covers both the standard unmount case (socket open → close with 4001) and the edge case where the socket is already closing. The test structure is clear and the assertions directly verify the implementation's behavior.

// This tells the server to cleanup immediately (no grace period)
debugLog("[AblyCLITerminal] Closing WebSocket on unmount.");
socketReference.current.close();
socketReference.current.close(4001, "user-closed-panel");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the intention here is that if we send 4001 to the terminal server, it just should just remove the session immediately, rather than wait for natural timeout. This is fine in principle for when a user explicitly clicks something, but doing this here would force the close on any unmount, which could happen between pages? We certainly don't want to limit navigation options to just non-reloading.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

…t graceful

Unmount uses a normal close() so the server grace period preserves
session resumability on navigation/reload. A new terminateSession()
method on the AblyCliTerminalHandle ref sends close(4001,
"user-closed-panel") for immediate server cleanup when the user
explicitly closes the panel.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments