Skip to content

Move resumability decisions from the client to the server (spec 6.1.0)#2273

Open
SimonWoolf wants to merge 4 commits into
mainfrom
spec-6.1.0-server-resumability
Open

Move resumability decisions from the client to the server (spec 6.1.0)#2273
SimonWoolf wants to merge 4 commits into
mainfrom
spec-6.1.0-server-resumability

Conversation

@SimonWoolf

@SimonWoolf SimonWoolf commented Jul 22, 2026

Copy link
Copy Markdown
Member

Implements specification version 6.1.0 (spec commit 2a0a0006, ably/specification#488).

The client no longer decides whether continuity can be preserved on reconnection. It always attempts to resume and lets the server make the authoritative decision (surfaced via the resumed flag on the subsequent attached/connection state change).

Behaviour changes

  • RTN8d/RTN9dConnection#id and Connection#key are now cleared only in the terminal states (CLOSED, CLOSING, FAILED); they are retained through SUSPENDED.
  • RTN15g removed / RTN14h — dropped checkConnectionStateFreshness(). The client no longer discards connection state based on how long it has been disconnected, so reconnection (including out of SUSPENDED) always attempts a resume.
  • RTL15b2 — a channel's channelSerial is retained through SUSPENDED (cleared only on DETACHED/FAILED), so the subsequent ATTACH carries it (RTL4c1) for the server's continuity decision.
  • RTL4j removed / TR3f — the library no longer sets the (now deprecated) ATTACH_RESUME flag; the _attachResume tracking is removed. The flag constant is retained in the protocol definitions.

Also updates the SUSPENDED/DISCONNECTED docstrings in ably.d.ts, and drops the now-unused ConnectionManager#lastActivity mirror (the transport keeps its own copy for the idle timer).

Tests

Reworked or removed the tests that asserted the pre-6.1.0 behaviour, and added positive coverage for the new behaviour (id/key and channelSerial retained through SUSPENDED, reconnects still carrying the resume param after the TTL, ATTACH_RESUME not set, createRecoveryKey returning a key in SUSPENDED).

Follow-up in the spec repo

A companion PR is needed in ably/specification to bring the shared UTS .md test-spec sources in line with 6.1.0 — spec PR #488 updated features.md/api-docstrings.md but not the UTS sources. That PR should also fix RTN16g2, which still says createRecoveryKey() returns Null in SUSPENDED; since connectionKey is now retained there, this implementation returns a valid recovery key in SUSPENDED instead.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • Improved realtime reconnection behavior after extended disconnections by preserving connection/channel continuity details during the suspended period.
    • Reconnect attempts while suspended now continue to use resume mode (instead of starting fresh).
    • Updated channel reattachment so continuity information is retained across temporary suspension.
  • Documentation
    • Clarified enum state descriptions for connection/channel suspension, reconnection timing/queue handling, and continuity semantics.

SimonWoolf and others added 3 commits July 22, 2026 18:57
Implements specification version 6.1.0 (spec commit 2a0a0006).

The client no longer decides whether continuity can be preserved on
reconnection. It always attempts to resume and lets the server make the
authoritative decision (surfaced via the `resumed` flag).

- RTN8d/RTN9d: retain Connection#id and Connection#key through the
  SUSPENDED state; only clear them in the terminal states (CLOSED,
  CLOSING, FAILED).
- RTN15g removed / RTN14h: drop checkConnectionStateFreshness(). The
  client no longer discards connection state based on how long it has
  been disconnected, so reconnection always attempts a resume.
- RTL15b2: retain a channel's channelSerial through SUSPENDED (clear it
  only on DETACHED/FAILED), so the subsequent ATTACH carries it for the
  server's continuity decision.
- RTL4j removed / TR3f: stop setting the (now deprecated) ATTACH_RESUME
  flag; remove the _attachResume tracking. The flag constant is retained
  in the protocol definitions.

Also drop the now-unused ConnectionManager#lastActivity mirror (the
transport keeps its own copy for the idle timer).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework or remove the tests that asserted the pre-6.1.0 client behaviour,
matching the source changes for spec commit 2a0a0006:

- resume.test.js: replace no_resume_once_suspended and no_resume_last_activity
  (RTN15g) with resume_after_suspended (RTN14h), which checks the client still
  attempts a resume after being suspended.
- connection.test.js: remove stale_connection_resets_msgSerial_and_sendAttempted,
  which exercised the now-deleted checkConnectionStateFreshness path.
- UTS connection_id_key: RTN8c/RTN9c "id/key null in SUSPENDED" becomes
  RTN8d/RTN9d "id/key retained in SUSPENDED" (now connects first, then suspends).
- UTS channel_properties: RTL15b1 "channelSerial cleared on suspended" becomes
  RTL15b2 "channelSerial retained in suspended"; the detach/failed cases are
  relabelled RTL15b2.
- UTS channel_attach: RTL4j "ATTACH_RESUME flag on reattach" becomes
  "ATTACH_RESUME flag not set on reattach".
- private_api_recorder: drop the now-unused connectionManager.lastActivity entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two more UTS unit tests asserted the pre-6.1.0 behaviour:

- connection_failures: RTN15g "no resume after connectionStateTtl expires"
  becomes RTN14h "reconnection still attempts resume after connectionStateTtl
  expires" — verifying every post-suspension reconnect carries the resume
  param with the original connectionKey.
- connection_recovery: RTN16g2 "createRecoveryKey returns null in SUSPENDED"
  becomes "returns a key in SUSPENDED" — since connectionKey is now retained
  through SUSPENDED (RTN8d/RTN9d) the connection remains recoverable there.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2bc1da66-0c22-4e67-be59-193652a4fe13

📥 Commits

Reviewing files that changed from the base of the PR and between 28b0a58 and 26ddf91.

📒 Files selected for processing (1)
  • test/uts/realtime/unit/connection/connection_recovery.test.ts

Walkthrough

Connection suspension now retains resume identifiers and retries with resume parameters. Channel suspension retains channelSerial without setting ATTACH_RESUME. Tests and TypeScript JSDoc are updated to describe and verify these semantics.

Changes

Resume continuity behavior

Layer / File(s) Summary
Connection suspension and resume lifecycle
src/common/lib/transport/..., src/common/lib/transport/transport.ts, test/realtime/..., test/uts/realtime/unit/connection/...
Connection freshness clearing is removed, connection identifiers remain in SUSPENDED, and reconnection tests verify continued resume attempts and recovery-key availability.
Channel serial and attach handling
src/common/lib/client/realtimechannel.ts, test/uts/realtime/unit/channels/...
channelSerial is retained through SUSPENDED, internal _attachResume handling is removed, and channel tests verify reattach and state-transition behavior.
State semantics documentation
ably.d.ts
Connection and channel state JSDoc describes suspended-state continuity, queued messages, and reconnection behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: paddybyers

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ConnectionManager
  participant Transport
  Client->>ConnectionManager: transition to SUSPENDED
  ConnectionManager->>Transport: reconnect with resume key
  Transport-->>ConnectionManager: connection result
  ConnectionManager-->>Client: connection state update
Loading

Poem

A rabbit hops through states anew,
Keeps keys and serials safely too.
Resume flags fade from channel flight,
Reconnects knock through suspended night.
“Hop on,” says Bun, “the tests now bloom!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main behavioral shift: resumability logic moves from client-side checks to server-side decisions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spec-6.1.0-server-resumability

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.

@github-actions
github-actions Bot temporarily deployed to staging/pull/2273/features July 22, 2026 18:42 Inactive
@github-actions
github-actions Bot temporarily deployed to staging/pull/2273/bundle-report July 22, 2026 18:42 Inactive
@github-actions
github-actions Bot temporarily deployed to staging/pull/2273/typedoc July 22, 2026 18:43 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/uts/realtime/unit/connection/connection_id_key.test.ts`:
- Around line 329-335: Update the RTN8d/RTN9d lifecycle comment to remove
CLOSING from the terminal-state list, stating that connection identifiers are
cleared only in CLOSED and FAILED while retained through CLOSING and SUSPENDED.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 241d9ab9-7e80-42af-bd02-41766b8fe093

📥 Commits

Reviewing files that changed from the base of the PR and between 9619f3d and 28b0a58.

📒 Files selected for processing (12)
  • ably.d.ts
  • src/common/lib/client/realtimechannel.ts
  • src/common/lib/transport/connectionmanager.ts
  • src/common/lib/transport/transport.ts
  • test/common/modules/private_api_recorder.js
  • test/realtime/connection.test.js
  • test/realtime/resume.test.js
  • test/uts/realtime/unit/channels/channel_attach.test.ts
  • test/uts/realtime/unit/channels/channel_properties.test.ts
  • test/uts/realtime/unit/connection/connection_failures.test.ts
  • test/uts/realtime/unit/connection/connection_id_key.test.ts
  • test/uts/realtime/unit/connection/connection_recovery.test.ts
💤 Files with no reviewable changes (2)
  • test/common/modules/private_api_recorder.js
  • test/realtime/connection.test.js

Comment on lines +329 to +335
* RTN8d, RTN9d - ID and key are retained in the SUSPENDED state
*
* As of specification version 6.1.0 (RTN8d/RTN9d, replacing RTN8c/RTN9c) the
* connection id and key are cleared only in the terminal states (CLOSED,
* CLOSING, FAILED). They are retained through SUSPENDED, since the client
* always attempts to resume on reconnecting and lets the server decide
* whether continuity can be preserved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove CLOSING from the terminal-state list.

closing is non-terminal; identifiers are cleared only on closed and failed. The current comment misstates the lifecycle contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/uts/realtime/unit/connection/connection_id_key.test.ts` around lines 329
- 335, Update the RTN8d/RTN9d lifecycle comment to remove CLOSING from the
terminal-state list, stating that connection identifiers are cleared only in
CLOSED and FAILED while retained through CLOSING and SUSPENDED.

The spec-side change introduces RTN16g3 (replacing RTN16g2) to say
createRecoveryKey() no longer returns null in SUSPENDED. Match the label
in the ably-js UTS test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant