feat(inbound): listen for backend-pushed channel.joined/left events #2

Merged
hzhang merged 1 commits from feat/inbound-listen-push-events into main 2026-05-21 07:12:52 +00:00
Contributor

Companion to nav/Fabric.Backend.Guild#. Before: only the 60s polling resync (introduced in #1) learned about new channels. Now the backend pushes membership changes directly.

Changes

  • socket.on('channel.joined', evt)socket.emit('join_channel', ...) + add to local joined set
  • socket.on('channel.left', evt)socket.emit('leave_channel', ...) + remove

Both handlers idempotent (skip if already in/out of joined). Polling resync stays as a safety net for missed pushes (socket drops between emit and reconnect, partial server failures). Older backends without emitToUser simply never fire these events — nothing breaks, polling carries the load as before.

Sim verification

channel.joined push: 222ms end-to-end
channel.left push: 465ms end-to-end

🤖 Generated with Claude Code

Companion to nav/Fabric.Backend.Guild#<TBD>. Before: only the 60s polling resync (introduced in #1) learned about new channels. Now the backend pushes membership changes directly. ## Changes - `socket.on('channel.joined', evt)` → `socket.emit('join_channel', ...)` + add to local `joined` set - `socket.on('channel.left', evt)` → `socket.emit('leave_channel', ...)` + remove Both handlers idempotent (skip if already in/out of `joined`). Polling resync stays as a safety net for missed pushes (socket drops between emit and reconnect, partial server failures). Older backends without `emitToUser` simply never fire these events — nothing breaks, polling carries the load as before. ## Sim verification channel.joined push: 222ms end-to-end channel.left push: 465ms end-to-end 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hzhang added 1 commit 2026-05-21 07:12:45 +00:00
Companion to nav/Fabric.Backend.Guild#<TBD> which adds the server-side
emitToUser broadcast on channel membership changes. Before, the inbound
only learned about new channels via the 60s polling resync (worst-case
60s lag). Now the backend tells us directly so sub/unsub is realtime.

socket.on('channel.joined', evt) → join the socket.io room for evt.channelId
                                    and add to the local 'joined' set.
socket.on('channel.left',   evt) → leave + remove from 'joined'.

Both events are idempotent (`if (joined.has(id))` / `if (!joined.has(id))`)
so duplicate emits from server are safe. Polling resync still runs every
60s as a safety net for transient socket drops between emit and
reconnect, partial server failures, etc.

When backend lacks this support (older deployments), nothing breaks —
the event simply never fires and polling carries the load as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hzhang merged commit 2ec97eceda into main 2026-05-21 07:12:52 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: nav/Fabric.OpenclawPlugin#2