Skip to content

feat(pubsub): sharded Pub/Sub for cluster mode - #317

Draft
Aryex wants to merge 2 commits into
alexl/pubsub-part3-advanced-subsfrom
alexl/pubsub-part4-cluster
Draft

Aryex wants to merge 2 commits into
alexl/pubsub-part3-advanced-subsfrom
alexl/pubsub-part4-cluster

Conversation

@Aryex

@Aryex Aryex commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds sharded (cluster-mode) Pub/Sub — Part 4 of the Pub/Sub implementation. This exposes the SPUBLISH / SSUBSCRIBE / SUNSUBSCRIBE family so cluster clients can publish and subscribe on shard channels, plus a connect-time sharded: subscription option. Sharded messages are routed by the channel's slot, matching the other GLIDE clients.

Stacked PR. This targets alexl/pubsub-part3-advanced-subs (Part 3, #316), not main. It must be retargeted to main once Part 3 merges. The diff shown against main will include Part 3's commits until then.

Issue link

Sub task of #135 Pub/Sub Support — Part 4 of the implementation plan.

Changes

Before, the sharded verbs were documented stubs raising NotImplementedError and publish refused sharded: true. After:

  • publish(message, channel, sharded: true) dispatches SPUBLISH (wire order <channel> <message>, Ruby signature (message, channel)). Left deliberately un-guarded and batchable — it works inside pipelined/multi, and glide-core rejects it in standalone.
  • ssubscribe(*channels, timeout_ms:) / sunsubscribe(*channels, timeout_ms:) (blocking) and ssubscribe_lazy(*channels) / sunsubscribe_lazy(*channels) (non-blocking). Same empty-list asymmetry as the exact verbs: ssubscribe/ssubscribe_lazy reject an empty list, sunsubscribe/sunsubscribe_lazy with no args target all sharded channels.
  • Connect-time pubsub: { subscriptions: { sharded: [...] } }.
  • New Valkey#cluster_mode? predicate.

Cluster-mode enforcement (the one design decision): the four subscribe verbs and the connect-time sharded config are cluster-only and raise ArgumentError in standalone. The guard is a private validate_cluster_mode! reading cluster_mode? as a method — mirroring how validate_resp3! reads protocol, keeping the mixin decoupled from client ivars. publish(sharded: true) is intentionally not guarded, so it stays batchable in a pipeline (a cluster_mode? call there would break the batch); the core decides.

Limitations

  • Sharded Pub/Sub requires cluster_mode: true and Valkey 7.0.0+.
  • pubsub_shardchannels / pubsub_shardnumsub / get_subscriptions introspection is Part 5, not here.

Testing

  • bundle exec rubocop — clean (126 files, no offenses).
  • bundle exec rake test:unit — 417 tests, 0 failures (added ~30 sharded unit tests covering request type, arg order, to_s coercion, timeout parsing, the RESP3 sweep, empty-list rules, the cluster-mode guard, and publish(sharded:) batchability).
  • bundle exec rake test:standalone — sharded delivery tests skip; the standalone rejection tests (verbs + config) pass.
  • bundle exec rake test:cluster — all 9 sharded integration tests pass, including a cross-slot routing test (distinct hash tags, proving SPUBLISH routes by channel not subscriber node) and a batchable-pipeline test.

Pre-existing, unrelated cluster-suite failures were observed and are not from this change (no Pub/Sub tests among them): the lib_name/client_info_tag validation family (#246, stale native lib), TLS errors (TLS_CERT_DIR unset), and a flaky cluster_bumpepoch epoch-state assertion.

Checklist

  • This Pull Request is related to an issue.
  • Commit message describe your changes
  • Commits are signed off (git commit -s) per the DCO.
  • Tests are added or updated.
  • CHANGELOG.md and documentation files are updated.
  • Linters have been run (bundle exec rubocop) and pass.
  • Destination branch is correct - main. (Stacked on alexl/pubsub-part3-advanced-subs; retarget to main after Part 3 merges.)

Aryex added a commit that referenced this pull request Sep 15, 2026
Signed-off-by: Alex Le <alex.le@improving.com>
@Aryex
Aryex added this pull request to stack #313 September 15, 2026 16:03
Implement the sharded (cluster-mode) Pub/Sub verbs from Part 4 of the
Pub/Sub plan (issue #135):

- publish(message, channel, sharded: true) -> SPUBLISH; stays batchable
  inside pipelined/multi
- ssubscribe / sunsubscribe (blocking) and ssubscribe_lazy /
  sunsubscribe_lazy (non-blocking)
- connect-time pubsub: { subscriptions: { sharded: [...] } }

The four sharded subscribe verbs and the sharded connection config are
cluster-only and raise ArgumentError in standalone. publish(sharded: true)
is left un-guarded so it stays batchable; glide-core rejects it in
standalone. Adds the Valkey#cluster_mode? predicate, read as a method by
the command mixin the same way validate_resp3! reads protocol.

Signed-off-by: Alex Le <alex.le@improving.com>
Signed-off-by: Alex Le <alex.le@improving.com>
@Aryex
Aryex force-pushed the alexl/pubsub-part4-cluster branch from 8a68a4d to e334081 Compare September 15, 2026 21:22
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.

1 participant