feat(inbound): listen for backend-pushed channel.joined/left events
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>
This commit is contained in:
22
dist/fabric/src/inbound.js
vendored
22
dist/fabric/src/inbound.js
vendored
@@ -154,6 +154,28 @@ export class FabricInbound {
|
|||||||
joined.clear();
|
joined.clear();
|
||||||
void syncChannels('initial');
|
void syncChannels('initial');
|
||||||
});
|
});
|
||||||
|
// Push-based membership events from the backend (companion to
|
||||||
|
// Fabric.Backend.Guild's RealtimeGateway.emitToUser). When the
|
||||||
|
// server tells us this user was added to / removed from a
|
||||||
|
// channel, we sub/unsub the socket.io room immediately — no
|
||||||
|
// 60s wait for the polling resync. Polling remains as a safety
|
||||||
|
// net for missed events.
|
||||||
|
socket.on('channel.joined', (evt) => {
|
||||||
|
const id = evt?.channelId;
|
||||||
|
if (!id || joined.has(id))
|
||||||
|
return;
|
||||||
|
socket.emit('join_channel', { channelId: id });
|
||||||
|
joined.add(id);
|
||||||
|
this.log.info(`fabric: agent ${agentId} channel.joined push on ${g.nodeId}: ${id} (now ${joined.size})`);
|
||||||
|
});
|
||||||
|
socket.on('channel.left', (evt) => {
|
||||||
|
const id = evt?.channelId;
|
||||||
|
if (!id || !joined.has(id))
|
||||||
|
return;
|
||||||
|
socket.emit('leave_channel', { channelId: id });
|
||||||
|
joined.delete(id);
|
||||||
|
this.log.info(`fabric: agent ${agentId} channel.left push on ${g.nodeId}: ${id} (now ${joined.size})`);
|
||||||
|
});
|
||||||
const syncTimer = setInterval(() => void syncChannels('resync'), FabricInbound.CHANNEL_SYNC_INTERVAL_MS);
|
const syncTimer = setInterval(() => void syncChannels('resync'), FabricInbound.CHANNEL_SYNC_INTERVAL_MS);
|
||||||
this.channelSyncTimers.push(syncTimer);
|
this.channelSyncTimers.push(syncTimer);
|
||||||
socket.on('message.created', (m) => {
|
socket.on('message.created', (m) => {
|
||||||
|
|||||||
@@ -199,6 +199,26 @@ export class FabricInbound {
|
|||||||
joined.clear();
|
joined.clear();
|
||||||
void syncChannels('initial');
|
void syncChannels('initial');
|
||||||
});
|
});
|
||||||
|
// Push-based membership events from the backend (companion to
|
||||||
|
// Fabric.Backend.Guild's RealtimeGateway.emitToUser). When the
|
||||||
|
// server tells us this user was added to / removed from a
|
||||||
|
// channel, we sub/unsub the socket.io room immediately — no
|
||||||
|
// 60s wait for the polling resync. Polling remains as a safety
|
||||||
|
// net for missed events.
|
||||||
|
socket.on('channel.joined', (evt: { channelId?: string }) => {
|
||||||
|
const id = evt?.channelId;
|
||||||
|
if (!id || joined.has(id)) return;
|
||||||
|
socket.emit('join_channel', { channelId: id });
|
||||||
|
joined.add(id);
|
||||||
|
this.log.info(`fabric: agent ${agentId} channel.joined push on ${g.nodeId}: ${id} (now ${joined.size})`);
|
||||||
|
});
|
||||||
|
socket.on('channel.left', (evt: { channelId?: string }) => {
|
||||||
|
const id = evt?.channelId;
|
||||||
|
if (!id || !joined.has(id)) return;
|
||||||
|
socket.emit('leave_channel', { channelId: id });
|
||||||
|
joined.delete(id);
|
||||||
|
this.log.info(`fabric: agent ${agentId} channel.left push on ${g.nodeId}: ${id} (now ${joined.size})`);
|
||||||
|
});
|
||||||
const syncTimer = setInterval(
|
const syncTimer = setInterval(
|
||||||
() => void syncChannels('resync'),
|
() => void syncChannels('resync'),
|
||||||
FabricInbound.CHANNEL_SYNC_INTERVAL_MS,
|
FabricInbound.CHANNEL_SYNC_INTERVAL_MS,
|
||||||
|
|||||||
Reference in New Issue
Block a user