Skip to content

Split Pub/Sub SDK into core and server gems - #453

Draft
umair-ably wants to merge 3 commits into
integration/v2from
pubsub-split/restructure
Draft

Split Pub/Sub SDK into core and server gems#453
umair-ably wants to merge 3 commits into
integration/v2from
pubsub-split/restructure

Conversation

@umair-ably

@umair-ably umair-ably commented Sep 1, 2026

Copy link
Copy Markdown

Implements the PubSub package split (PDR-091b) for the Ruby SDK, mirroring ably/ably-js#2293.

  • New public package: ably-pubsub-server (server/), allowing Pub/Sub connections to explicitly declare they are server-side for realtime classification and MAU billing. Ruby is a server-only SDK under PDR-091b2, so there is no device gem. Factory functions are the only recommended entry points:
    • Ably::PubSub::Server.create_http_client(...)
    • Ably::PubSub::Server.create_realtime_client(...)
  • Shared core: the implementation moves to ably-pubsub-core (core/), for internal/shared usage and not intended as a public API. The ably-common submodule moves with it.
  • Agent stamping: the factories append the versionless side-declaring agent entry ably-pubsub-server (a pure flag, matching its Register the cross-SDK per-side Pub/Sub agents ably-common#361 registration — the ably-ruby/x.y.z entry beside it carries the version) via a new additive :agents client option. Caller entries are preserved; the side entry wins a collision on its own identifier. The -server suffix is what MAU classification reads, so specs assert it loudly.
  • Lockstep versioning: core and server are both at 2.0.0, with the server gem pinning core to the exact version.
  • The old ably gemspec is removed: the ably gem enters its 1-year maintenance window from a maintenance branch, not from here.

Unit suite green (1250 examples), sandbox acceptance smoke-tested, both gems build.

🤖 Generated with Claude Code

Implements the PubSub package split (PDR-091b) for the Ruby SDK:

- Move the implementation into core/ as the ably-pubsub-core gem, an
  internal package that only Ably packages depend on. The ably-common
  submodule moves with it.
- Add server/ as the ably-pubsub-server gem, whose factory functions
  are the only recommended entry points:
  Ably::PubSub::Server.create_http_client and .create_realtime_client.
  Ruby is a server-only SDK under PDR-091b2, so there is no device gem.
- The factories stamp the side-declaring agent entry
  ably-pubsub-server/<version> via a new additive :agents client
  option; the caller's own agent entries are preserved and the side
  entry wins a collision on its own identifier. The -server suffix is
  what MAU classification reads, so specs assert it loudly.
- Core and server are versioned in lockstep at 2.0.0, with the server
  gem pinning the core dependency to the exact version.
- The old ably gemspec is removed; the ably gem is maintained from a
  maintenance branch per the 1-year support window, not from here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@paddybyers

Copy link
Copy Markdown
Member

Given that there's no device variant, why move everything into core ?

Ruby 3.3.11 and similar patch versions no longer match the previous
single-digit \d.\d.\d pattern, which made this spec fail on current
CI runners regardless of this branch's changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@umair-ably

Copy link
Copy Markdown
Author

CI triage:

  • Fixed: connection_spec.rb agent-param spec used a single-digit version regex (\d.\d.\d), which current runner Rubies (e.g. 3.3.11) no longer match. Pre-existing brittleness, exposed on the 3.2/3.3 jobs.
  • Pre-existing, not this branch: spec/acceptance/rest/presence_spec.rb:95 and :110 (presence GET filtered by client_id/connection_id) fail identically on main against sandbox — verified locally on a clean main worktree. Sandbox appears to no longer filter presence GET by those params; this needs investigating separately from this PR.

Everything else in the matrix is green (all unit jobs pass on every Ruby/protocol combination).

🤖 Generated with Claude Code

@umair-ably

Copy link
Copy Markdown
Author

Given that there's no device variant, why move everything into core ?

@paddybyers https://ably.atlassian.net/wiki/spaces/product/pages/5348425729/PDR-091b2+Per-SDK+rollout+plan+v2#Support-window-for-existing-packages implies there's always a new core?

my own pov... I think the symmetry between packages is a good enough reason to keep as is, also create_http_client literally just calls the old Ably::Rest::Client.new under the hood. This old constructor needs to live somewhere, and keeping it in the same server package defeats the purpose of the new package obfuscating the old constructors (and preventing them from leaking in the public api)

umair-ably added a commit to ably/ably-common that referenced this pull request Sep 1, 2026
PDR-091b splits every Pub/Sub SDK into per-side packages whose
factories stamp a side-declaring agent entry so that MAU
classification never has to guess which side a connection is on. The
identifiers are shared across languages: ably/ably-js#2293,
ably/ably-java#1233 and ably/ably-ruby#453 all stamp the same
ably-pubsub-device / ably-pubsub-server strings, each with its own
package version, alongside the SDK's own agent entry.

Register both identifiers so the realtime system classifies them as
known agents rather than by their -device/-server suffix alone. Names
are language-neutral because the identifiers are.

The schema requires a single source repository for wrapper-type
agents, but these are the registry's first multi-repo identifiers;
ably-js is given as the first publisher, with the caveat noted in the
PR that fetch-agent-releases will attribute all stamped versions to
ably-js releases until the schema can express multiple sources.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
umair-ably added a commit to ably/ably-common that referenced this pull request Sep 2, 2026
PDR-091b splits every Pub/Sub SDK into per-side packages whose
factories stamp a side-declaring agent entry so that MAU
classification never has to guess which side a connection is on. The
identifiers are shared across languages: ably/ably-js#2293,
ably/ably-java#1233 and ably/ably-ruby#453 all stamp the same
ably-pubsub-device / ably-pubsub-server strings, alongside the SDK's
own versioned agent entry.

The entries are versionless, like browser: under lockstep versioning a
side-flag version would always duplicate the SDK entry beside it, and
across SDKs a bare ably-pubsub-device/1.2.3 cannot say 1.2.3 of what.
Version-of-what stays the SDK entry's job; the side entry is a pure
flag. They carry no source or product for the same reason browser
carries none: they are emitted by many repos and attribute no package.

Register both so the realtime system classifies them as known agents
rather than by their -device/-server suffix alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Matches the entry's registration in the ably-common agents registry
(ably/ably-common#361): the side entry is a pure flag, like browser.
Under lockstep versioning a version on the flag always duplicates the
ably-ruby entry beside it, which keeps carrying identity, version and
support status. Wire shape:

  ably-ruby/2.0.0 ruby/3.3.0 ably-pubsub-server

Co-Authored-By: Claude Fable 5 <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.

2 participants