Skip to content

Closes issue #17 Add SSE heartbeat and stale-client cleanup strategy#52

Open
Kingajong wants to merge 4 commits into
Flamki:masterfrom
Kingajong:master
Open

Closes issue #17 Add SSE heartbeat and stale-client cleanup strategy#52
Kingajong wants to merge 4 commits into
Flamki:masterfrom
Kingajong:master

Conversation

@Kingajong

@Kingajong Kingajong commented May 26, 2026

Copy link
Copy Markdown

CLOSES #17

  • SSE clients were tracked as bare response objects without heartbeat or backpressure handling, which can allow stale/disconnected clients to accumulate in memory over long runs.

  • The dashboard needs to reconnect cleanly after transient network blips and avoid unbounded memory growth from dead EventSource connections.

  • Replace the plain array with a keyed Map of clients and add writeSse(clientId, event) and removeClient(clientId) helpers to manage lifecycle and writes.

  • Guard all SSE writes with try/catch, observe res.write() return values, and attach a drain listener to handle per-client backpressure.

  • Emit a heartbeat event every 30s and evict clients that have not accepted writes for more than 90s to remove stale connections.

  • Update the /api/events handler to assign per-client IDs, send the initial connected event via the guarded writer, and clean up on both close and error events.

  • Ran node --check src/server.js which completed successfully.

  • No new automated tests were added in this change.


Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability of real-time event streaming with automatic cleanup of stale connections and better handling of slow/blocked clients.
  • Improvements

    • Connections now receive periodic heartbeat events and an initial "connected" event for faster recovery and session liveness.
    • Readiness/status reporting updated to more accurately reflect external service availability.

Kingajong added 2 commits May 26, 2026 19:58
…e-client-cleanup

Add SSE heartbeat and stale-client cleanup for event stream
@vercel

vercel Bot commented May 26, 2026

Copy link
Copy Markdown

@Kingajong is attempting to deploy a commit to the flamki's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d86143ca-70fb-4791-965d-35b0b51de631

📥 Commits

Reviewing files that changed from the base of the PR and between d105915 and 611e85a.

📒 Files selected for processing (1)
  • src/server.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/server.js

📝 Walkthrough

Walkthrough

Refactors SSE to track clients in a per-connection Map with per-client lastWriteAt, centralizes writes via writeSse (handles backpressure/errors), sends periodic heartbeat events, prunes stale clients, and updates x402 readiness logic; /api/events now registers and cleans up clients by clientId.

Changes

SSE Client Tracking and Readiness Update

Layer / File(s) Summary
SSE state management, helpers, and heartbeat
src/server.js
Replaced sseClients array with a Map keyed by client IDs storing { res, lastWriteAt }. Added HEARTBEAT_INTERVAL_MS and STALE_CLIENT_THRESHOLD_MS, removeClient and writeSse helpers with drain handling and error cleanup, updated broadcast to iterate the Map, and added a heartbeat interval that sends ping events and prunes stale clients.
Readiness payload x402 logic
src/server.js
Updated buildReadinessPayload so x402.ready depends on x402MiddlewareReady and config.facilitatorUrl, and adjusted associated description text branches.
/api/events endpoint wiring
src/server.js
Updated /api/events to generate a unique clientId, register the client in the Map with lastWriteAt, emit an initial connected event via writeSse, and attach close/error handlers that remove the client from the Map.
sequenceDiagram
  participant Client
  participant Server
  participant sseClientsMap
  participant writeSse

  Client->>Server: GET /api/events (open SSE)
  Server->>sseClientsMap: create clientId, store {res, lastWriteAt}
  Server->>writeSse: send "connected" event
  Note over Server,writeSse: heartbeat interval iterates sseClientsMap
  Server->>writeSse: send "heartbeat" to clients
  writeSse-->>sseClientsMap: update lastWriteAt or remove stale/error clients
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #17: Implements per-client SSE tracking, heartbeat mechanism, backpressure-aware writes, and stale-client cleanup.

Poem

🐰 I hopped into streams with a tidy map,
I tapped each friend with a steady beat,
When silence lingered, I cleaned the gap,
Backpressure calmed, connections kept neat,
A tiny heartbeat keeps the flow sweet.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title directly references issue #17 and accurately summarizes the main changes: adding SSE heartbeat and implementing a stale-client cleanup strategy.
Description check ✅ Passed The pull request description covers the problem statement, proposed solution, implementation details, and validation steps. It follows the template structure with summary and validation sections, though the formal checklist boxes are not explicitly marked.
Linked Issues check ✅ Passed The code changes implement all requirements from issue #17: periodic heartbeat events (30s intervals), stale client eviction (90s threshold), error handling with try/catch, backpressure handling via drain listeners, and per-client lifecycle management.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the SSE client management refactor. The x402 readiness calculation update appears to be a necessary adjustment to the readiness payload construction alongside the client map migration, remaining within scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch master

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/server.js`:
- Around line 29-34: The removeClient function should guard against calling
client.res.end() on an already-destroyed stream to avoid exceptions; update
removeClient (referencing sseClients, client, and client.res.end) to first
remove the client from sseClients, then check the response stream state (e.g.,
writableEnded/writableFinished/destroyed) and call client.res.end() only if it
is safe, and wrap the end() call in a try/catch to swallow and log any errors so
cleanup still completes even if the socket is already closed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f70e18f-cbf6-4767-b935-f8cdcd23a1d1

📥 Commits

Reviewing files that changed from the base of the PR and between b32a416 and d105915.

📒 Files selected for processing (1)
  • src/server.js

Comment thread src/server.js
@Flamki

Flamki commented May 27, 2026

Copy link
Copy Markdown
Owner

@Kingajong fix this potential issue

@drips-wave

drips-wave Bot commented May 27, 2026

Copy link
Copy Markdown

@Kingajong Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Flamki

Flamki commented May 29, 2026

Copy link
Copy Markdown
Owner

@Kingajong kindly resolve this confict

@Kingajong

Copy link
Copy Markdown
Author

@Flamki Good Day Sir i am still waiting for your approval

@Flamki

Flamki commented Jun 3, 2026

Copy link
Copy Markdown
Owner

@Kingajong kindly resolve this confict

       version to expose component-level readiness
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.

Add SSE heartbeat and stale-client cleanup strategy

2 participants