Skip to content

ably: make Channels.Release return an error unless the channel is detached (RTS4c-e) - #717

Merged
SimonWoolf merged 1 commit into
integration/v2from
release-throw-unless-detached
Oct 9, 2026
Merged

SimonWoolf merged 1 commit into
integration/v2from
release-throw-unless-detached

Conversation

@SimonWoolf

@SimonWoolf SimonWoolf commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

Implements RTS4c–e from spec 6.3.0 (ably/specification#557) for the next major version.

Breaking change. RealtimeChannels.Release is now Release(name string) error:

  • If no channel with that name exists, it returns nil (RTS4c).
  • If the channel is INITIALIZED, DETACHED or FAILED, it is removed from the collection before Release returns (RTS4d).
  • Otherwise it returns an *ably.ErrorInfo with code 90011 (ably.ErrChannelReleaseInvalidState) and statusCode 400, and the channel and collection are left unchanged (RTS4e). It no longer detaches the channel for you.
  • Because it no longer blocks on a detach, it no longer takes a context.Context.

Why: under the old behaviour the channel stayed in the collection while the detach was in flight. A Get for the same name in that window returned the channel that was about to be removed, which then received no further messages. Releasing a FAILED channel also failed, since detaching a FAILED channel is an error.

Migration: detach and wait before releasing.

if err := channel.Detach(ctx); err != nil {
    return err
}
if err := client.Channels.Release(channel.Name); err != nil {
    return err
}

90011 is registered in ably/ably-common#367, but the common submodule pin isn't bumped here, because scripts/errors can't parse the current errors.json format. The constant is added by hand to error_names.go.

The current-major deprecation is in #716. Reference ably-js PRs: ably/ably-pubsub-js#2322 (deprecation) and ably/ably-pubsub-js#2323 (next major).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Behavior Changes
    • Releasing a channel now succeeds only when it is initialized, detached, or failed. Channels in other states remain in the collection and return an error with status 400.
    • Detach an attached channel before releasing it. Releasing a channel that does not exist returns no error.

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7f9bbe17-3faf-415a-b91e-b0a6b0a510c0

📥 Commits

Reviewing files that changed from the base of the PR and between 24bd01a and 1c4eaf0.


📒 Files selected for processing (5)
  • ably/error_names.go
  • ably/realtime_channel.go
  • ably/realtime_channel_integration_test.go
  • ably/realtime_channel_internal_test.go
  • ably/state.go

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.



Walkthrough

RealtimeChannels.Release no longer accepts a context or detaches channels. It removes existing channels only in INITIALIZED, DETACHED, or FAILED states. For other states, it returns error code 90011 with status 400.

Changes

Realtime channel release

Layer / File(s) Summary
Define releasable states
ably/error_names.go, ably/state.go
Adds error code 90011 and a state check that allows release in INITIALIZED, DETACHED, and FAILED states.
Validate and remove channels
ably/realtime_channel.go, ably/realtime_channel_integration_test.go, ably/realtime_channel_internal_test.go
Updates Release to reject non-releasable states without removing the channel. Tests cover missing channels, releasable states, rejected states, and explicit detachment before release.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Suggested reviewers: ttypic, lmars

Merge Risk: ⚪ Minimal · up to 1c4ea

Release now rejects channels that are not detached, as intended for the breaking API change. No concrete defects remain. Releasing a channel from its detached event handler does not deadlock.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the main change to Channels.Release and the invalid-state behavior. It is concise and directly related to the pull request, although it does not mention the additional rel…
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.


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR


  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

A rabbit checks each channel’s state
And waits until the time is right
The detached ones can hop away
The others stay, unchanged in place
A code nine-zero-zero-one-one marks the gate
Then carrots celebrate the night

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

@ttypic ttypic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

…ached (RTS4c-e)

Spec 6.3.0 replaces RTS4a with RTS4c-e. Release previously detached the
channel and removed it once the detach completed, so a Get for the same
name in that window returned the channel that was about to be removed,
which then received no further messages. It also failed to release a
FAILED channel, since detaching one is an error (RTL5b).

Release now removes a channel in the INITIALIZED, DETACHED or FAILED
state immediately, and for any other state returns an ErrorInfo with
code 90011 and statusCode 400 without changing the channel or the
collection. As it no longer blocks, it no longer takes a context.

This is a breaking change: callers must call RealtimeChannel.Detach and
wait for it to return before calling Channels.Release(name).

ErrChannelReleaseInvalidState is added by hand to error_names.go. 90011
is registered in ably-common, but the common pin is not bumped: the
errors.go generator cannot parse the current errors.json format.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SimonWoolf
SimonWoolf force-pushed the release-throw-unless-detached branch from e5a6dfc to 1c4eaf0 Compare October 9, 2026 16:06
@SimonWoolf
SimonWoolf merged commit aa5a21b into integration/v2 Oct 9, 2026
8 checks passed
@SimonWoolf
SimonWoolf deleted the release-throw-unless-detached branch October 9, 2026 16:15

This branch was successfully deployed

1 active deployment
staging/pull/717/godoc — 1c4eaf01 Deployed Oct 9, 2026 by github-actions[bot]
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.

2 participants