Skip to content

feat(backend): replace WebSocket payment updates with SSE - #869

Open
Bayovictor wants to merge 1 commit into
Abdulazeem-code:mainfrom
Bayovictor:feature/backend-sse-updates
Open

Bayovictor wants to merge 1 commit into
Abdulazeem-code:mainfrom
Bayovictor:feature/backend-sse-updates

Conversation

@Bayovictor

Copy link
Copy Markdown

Closes #730

What

Replaces the Socket.io/WebSocket realtime channel with plain-HTTP Server-Sent Events for one-way payment status updates: one socket plus one map entry per client instead of a WS upgrade, frame protocol and server-side ping bookkeeping.

  • stellar-payment-platform/src/sse/index.js — client registry keyed by payment topic, 25s keep-alive heartbeats, retry: hint, in-process emitPaymentUpdate, Redis publishPaymentUpdate for cross-process fan-out, and closeSse() drain used by graceful shutdown (keeps the legacy wire channel and accepts the old paymentIntentId field)
  • GET /api/v1/payments/:paymentId/events (src/routes/v1/sseRoutes.js) — emits connected, a snapshot of the last known status (so an EventSource reconnect converges immediately) and payment-update on every change; headers are flushed before any async work so connect-timeout/compression cannot buffer or abort the stream
  • SSE paths are exempt from the global token bucket and bounded instead by a dedicated per-IP stream limiter
  • horizonListener.js now publishes detected payments to Redis (the producer was imported but never called), so the pipeline is live end to end
  • Dropped socket.io and src/websocket; nginx gets a no-buffer/no-timeout proxy location for the stream; .env.example, EVENT_SOURCING.md and README.md updated
  • payment-dashboard/src/lib/paymentEvents.js wraps EventSource, so reconnection is handled natively by the browser (AC)
  • Fixed the broken lint-staged entry so dashboard files lint from the repo root

Acceptance criteria

  • SSE endpoints stream status updates to clients — GET /api/v1/payments/:paymentId/events
  • Reconnection logic handled natively by the EventSource API — payment-dashboard/src/lib/paymentEvents.js
  • Server resource consumption drops vs WS — Socket.io and src/websocket removed; per client cost is a single HTTP stream + map entry

Verification

  • npx jest tests/sse.test.js tests/horizon-listener.test.js — 28 passed (manager, route, Redis fan-out, shutdown, listener regression)
  • npx jest server.test.js — 67 passed
  • npx eslint on the touched files — 0 errors (2 pre-existing no-unused-vars warnings on horizonListener.js, present on main)

Related: #859

…-code#730)

Stream payment status updates over Server-Sent Events instead of Socket.io
so one-way updates cost a single socket plus a map entry per client instead
of a WebSocket upgrade, frame protocol and server-side ping bookkeeping.

- add src/sse: client registry per payment topic, 25s keep-alive heartbeats,
  `retry:` hint, in-process emitPaymentUpdate, Redis publishPaymentUpdate and
  a closeSse() drain used by graceful shutdown (keeps the old wire channel
  and accepts the legacy paymentIntentId field)
- add GET /payments/:paymentId/events emitting `connected`, a `snapshot` of
  the last known status (so EventSource reconnects converge immediately) and
  `payment-update` on every change; headers are flushed before async work so
  connect-timeout/compression cannot buffer or abort the stream
- exempt SSE paths from the global token bucket and bound stream opens with
  a dedicated per-IP limiter instead
- publish detected payments from horizonListener to Redis so the pipeline is
  live end to end (the old producer was imported but never called)
- drop socket.io and src/websocket; nginx gets a no-buffer/no-timeout proxy
  location for the stream; .env.example, EVENT_SOURCING.md and README updated
- add payment-dashboard/src/lib/paymentEvents.js wrapping EventSource (AC:
  reconnection handled natively by the EventSource API) and fix the broken
  lint-staged entry for dashboard files so staged files lint from repo root
- cover the manager, route, Redis fan-out and shutdown in tests/sse.test.js
  plus a regression test that the listener publishes status updates
@vercel

vercel Bot commented Oct 8, 2026

Copy link
Copy Markdown

@Bayovictor is attempting to deploy a commit to the Abdulazeem's projects Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
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.

Backend: Setup Server-Sent Events (SSE) for Lighter Status Updates

1 participant