Skip to content

fix(hub): deliver message-received events to all:true SSE connections#507

Merged
tiann merged 1 commit intotiann:mainfrom
GeT-LeFt:fix/sse-all-message-received
Apr 22, 2026
Merged

fix(hub): deliver message-received events to all:true SSE connections#507
tiann merged 1 commit intotiann:mainfrom
GeT-LeFt:fix/sse-all-message-received

Conversation

@GeT-LeFt
Copy link
Copy Markdown
Contributor

Summary

The message-received branch of shouldSend() in hub/src/sse/sseManager.ts checks only connection.sessionId === event.sessionId, ignoring the connection.all flag. As a result, any SSE connection subscribed with all: true silently never receives message-received events, even though every other event type below this branch honors connection.all.

Change

 if (event.type === 'message-received') {
-    return connection.sessionId === event.sessionId
+    return connection.all || connection.sessionId === event.sessionId
 }

One-line fix — the branch now behaves consistently with the rest of the dispatch logic further down in the same function.

Impact

Any feature that relies on an all:true SSE subscription to observe messages across sessions (cross-session unread indicators, global notification logic, etc.) starts working again. No behavioral change for session-scoped connections.

Closes #506

Test plan

  • Reviewed that other event branches in shouldSend() all honor connection.all, confirming this was an inconsistency rather than an intentional restriction
  • Verified no other usages of message-received event filtering exist in hub/

The message-received branch of shouldSend() in hub/src/sse/sseManager.ts
checks only connection.sessionId === event.sessionId, ignoring the
connection.all flag. As a result, any SSE connection subscribed with
all: true (to observe events across every session in the namespace)
silently never receives message-received events, even though every
other event type below this branch honors connection.all.

Closes tiann#506
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Minor] Missing regression test for the repaired all:true path — The routing change in hub/src/sse/sseManager.ts:159 looks correct, but hub/src/sse/sseManager.test.ts:6 still has no case asserting that a message-received event reaches an all: true subscription in the same namespace. That leaves this exact bug easy to reintroduce unnoticed.
    Suggested fix:
    it('delivers message-received events to all subscriptions in the same namespace', () => {
        const manager = new SSEManager(0, new VisibilityTracker())
        const received: SyncEvent[] = []
    
        manager.subscribe({
            id: 'all',
            namespace: 'alpha',
            all: true,
            send: (event) => {
                received.push(event)
            },
            sendHeartbeat: () => {}
        })
    
        manager.broadcast({
            type: 'message-received',
            namespace: 'alpha',
            sessionId: 'session-1',
            message: {
                id: 'message-1',
                seq: 1,
                localId: null,
                createdAt: 0,
                content: {
                    type: 'event',
                    data: { type: 'ready' }
                }
            }
        })
    
        expect(received).toHaveLength(1)
    })

Summary
Review mode: initial. 1 minor issue found: the fix is reasonable, but the repaired all:true delivery path is still untested.

Testing
Not run (bun not available in this runner)
HAPI Bot

Comment thread hub/src/sse/sseManager.ts

if (event.type === 'message-received') {
return connection.sessionId === event.sessionId
return connection.all || connection.sessionId === event.sessionId
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MINOR] This branch fix looks right, but there is still no regression test covering message-received delivery for an all: true SSE subscription. The current suite in hub/src/sse/sseManager.test.ts exercises other routing paths only, so this exact bug can slip back unnoticed.

Suggested fix:

it('delivers message-received events to all subscriptions in the same namespace', () => {
    const manager = new SSEManager(0, new VisibilityTracker())
    const received: SyncEvent[] = []

    manager.subscribe({
        id: 'all',
        namespace: 'alpha',
        all: true,
        send: (event) => {
            received.push(event)
        },
        sendHeartbeat: () => {}
    })

    manager.broadcast({
        type: 'message-received',
        namespace: 'alpha',
        sessionId: 'session-1',
        message: {
            id: 'message-1',
            seq: 1,
            localId: null,
            createdAt: 0,
            content: {
                type: 'event',
                data: { type: 'ready' }
            }
        }
    })

    expect(received).toHaveLength(1)
})

@tiann tiann merged commit 1f994e5 into tiann:main Apr 22, 2026
2 checks passed
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.

[Bug] SSE message-received events not delivered to all:true connections

2 participants