feat: relay over crossws pub/sub and upgrade to crossws 0.4 - #16
Open
benjamincanac wants to merge 2 commits into
Open
feat: relay over crossws pub/sub and upgrade to crossws 0.4#16benjamincanac wants to merge 2 commits into
benjamincanac wants to merge 2 commits into
Conversation
Replace the manual per-peer broadcast loop with crossws pub/sub (peer.subscribe on open, origin.publish to relay). This is the abstraction crossws sync backplanes extend, so cross-instance relay (e.g. Redis/Postgres via h3js/crossws#192) works transparently once configured on the adapter, with no changes here. Relay stays local to a single instance otherwise — documented as a known limitation. - chore(deps): upgrade crossws to ^0.4.6; switch CF playground to the unified `crossws/adapters/cloudflare` adapter and drop now-stale `@ts-expect-error`s. - fix(provider): initialize `ws` as `null` (not `undefined`) so the `ws === null` guards in connect()/setupWS() fire — the old default made the first connect() a silent no-op. - test: add a Vitest suite (server + provider) over real WebSockets on ephemeral ports, wired into `pnpm test`. - docs: add a "Multi-instance deployments" section covering the sync backplane and the message-vs-doc-state caveat.
benjamincanac
marked this pull request as ready for review
June 25, 2026 08:27
- Add a pkg-pr-new workflow that builds and publishes a continuous preview release on pushes to main and PRs, so reviewers can install the package straight from a commit/PR. - Run `pnpm vitest run` in the ci workflow now that a test suite exists (previously only lint + types + build ran).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the manual per-peer broadcast loop with crossws pub/sub (
peer.subscribeon open,origin.publishto relay updates & awareness). This is the abstraction crossws sync backplanes extend, so once a backplane is configured on the adapter, cross-instance relay (Redis/Postgres/etc.) works transparently with no changes toy-crossws. The oldfor (peer of peerIds) peer.send()loop bypassed crossws pub/sub entirely and could never benefit from a backplane.Also upgrades
crosswsto^0.4.6, fixes a provider connect bug, and adds a test suite.Changes
refactor(server)— relay doc + awareness updates over crossws pub/sub instead of a manual peer loop.publishexcludes the sender (verified in the node adapter), so each update goes to every other room subscriber.chore(deps)— upgradecrosswsto^0.4.6; switch the CF playground to the unifiedcrossws/adapters/cloudflareadapter (still wires up the Durable Object); drop now-unnecessary@ts-expect-errors.fix(provider)— initializewsasnullinstead ofundefined.connect()/setupWS()gate onws === null, so the oldundefineddefault made the firstconnect()a silent no-op.test— add a Vitest suite exercising the server (raw protocol clients: doc sync, CRDT merge, awareness both ways, awareness-cleared-on-disconnect) and the bundledWebsocketProvider(connect + sync), over real WebSockets on ephemeral ports. Wired intopnpm test.docs— add a "Multi-instance deployments" section.Scope / known limitation
This is correct for a single instance and Cloudflare (single Durable Object). It does not by itself make multi-instance (e.g. Vercel horizontal scaling) work:
0.4.6has no sync backplane yet — theverceladapter is the node adapter, sopublishis in-process only. Cross-instance relay needs #192.Y.Doc(used forwriteSyncStep1+ persistence). A client joining a "cold" instance can miss history that only lives on another instance — backplanes relay messages, not doc state.Both are documented in code comments and the README, framed as known limitations rather than something this PR claims to solve. Happy to align with the upcoming crossws/nitro sync engine.
Test plan
pnpm test— lint + types + Vitest (4 tests) ✅pnpm build --stub && pnpm play:node, open/tiptap/in two windows → live sync + cursors ✅