feat: add Server-Sent Events endpoint - #279
Merged
Merged
Conversation
|
@code-with-flex 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! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Implements a Server-Sent Events endpoint at
GET /api/events/claimsthat pushes real-time claim status updates to connected frontend clients. The internal event bus uses Redis pub/sub so every backend instance participates in fan-out, making this horizontally scalable without a centralised broker process. Connections are tracked in a registry that enforces a configurable max connection limit and drains gracefully on SIGTERM.Related Issue
Closes #202
Changes Made
events/claim-events.service.ts— Manages dedicated Redis subscriber and publisher connections (separate from the sharedRedisServicepool, as pub/sub mode blocks a connection). Exposespublish()for the indexer to call after each Prisma transaction commits. Handles malformed messages and Redis unavailability silently (fail open) so SSE outages do not affect indexer operation.events/sse-connection.registry.ts— Tracks all activeSubject-backed SSE connections. EnforcesSSE_MAX_CONNECTIONS(default 500) via a hard limit returning 503.drainAll()completes every subject and is called fromClaimEventsService.onModuleDestroy()to flush in-progress event deliveries before the HTTP server shuts down. Includes inline documentation of backpressure behaviour and max connection guidance.events/events.controller.ts—GET /api/events/claims?claimId=<id>using@Sse. UsesOptionalJwtAuthGuardso authenticated wallets get the standard throttle and anonymous clients get the stricter 5 req/min limit. Setsretry: 5000on every event frame so EventSource clients reconnect within 5 s. Sends 25 s heartbeat comments to survive proxy idle timeouts. No DB transaction is held open during connection lifetime.events/events.module.ts— WiresCacheModule, controller, and providers. ExportsClaimEventsServicefor injection intoIndexerModule.indexer/indexer.service.ts— InjectsClaimEventsServiceoptionally (@Optional()) and callspublish()after each$transactionblock resolves for claim-related topics. The transaction commits first; publish is fire-and-forget (void) so a Redis failure never rolls back a committed indexer write.indexer/indexer.module.ts— AddsEventsModuleto imports to makeClaimEventsServiceavailable.app.module.ts— AddsEventsModuleto root imports.events/__tests__/events.integration.spec.ts— Integration tests covering: registry registration/unregister, broadcast selectivity, connection limit enforcement,drainAll,publishRedis delivery, silent failure on Redis down, message routing, and malformed-message resilience. No real Redis required.Acceptance Criteria
SSE_MAX_CONNECTIONS; 503 returned when limit is exceeded