Skip to content

fix: connect analytics streams, clear rpc timers, and cover notification delivery - #1808

Open
nemeregiftbrown-byte wants to merge 3 commits into
LabsCrypt:mainfrom
nemeregiftbrown-byte:fix/issues-1709-1710-1711
Open

nemeregiftbrown-byte wants to merge 3 commits into
LabsCrypt:mainfrom
nemeregiftbrown-byte:fix/issues-1709-1710-1711

Conversation

@nemeregiftbrown-byte

@nemeregiftbrown-byte nemeregiftbrown-byte commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Overview

This pull request resolves three issues across the frontend analytics explorer, backend RPC connection pool, and backend notification service, and resolves the CI test failures on GitHub Actions:

  • [api] Connect analytics explorer to the actual stream response #1709 — [api] Connect analytics explorer to the actual stream response: Connects the Analytics Explorer to the documented backend stream-list endpoint (/v1/streams) via NEXT_PUBLIC_API_URL by default. Normalizes actual REST stream responses by preferring on-chain streamId over database UUIDs, mapping startTime and endTime to timestamps without zero dates, properly mapping status across active, paused, completed, and cancelled states, and resolving token decimals to the standard 7-decimal scale instead of silently substituting 18 decimals.
  • [fix] Clear RPC timeout timers when calls settle #1710 — [fix] Clear RPC timeout timers when calls settle: Clears allocated timeout handles in finally blocks on settled RPC operations in execute and settled health probes in probeAll. This prevents lingering timers from holding closures in the Node event loop and prevents late AbortSignal abort triggers after an operation has already succeeded or failed early, while preserving timeouts and aborts for genuinely hung requests.
  • [test] Cover notification delivery failures and expired subscriptions #1711 — [test] Cover notification delivery failures and expired subscriptions: Adds comprehensive backend regression test coverage for NotificationService. Exercises failure isolation across WebPush, Telegram, and Discord transports (verifying a rejected channel does not block delivery to other configured channels), verifies deletion of expired endpoints on HTTP 404 and 410, verifies retention of subscriptions on transient errors, and verifies push delivery suppression when VAPID keys are absent.
  • CI Test Suite Resolution: Resolves unhandled rejection in backend/tests/rpc-pool.test.ts during fake timer advancement and eliminates static timestamp expiration in frontend/src/__tests__/stream-analytics.test.tsx by using dynamic current timestamps.

Detailed Changes

Frontend Analytics Stream Normalization (#1709)

  • Default Endpoint Resolution: Updated useStreams to default endpoint to getDefaultStreamsEndpoint(), which resolves against getApiBaseUrl() (respecting NEXT_PUBLIC_API_URL or falling back to http://localhost:3001/v1/streams). This replaces the hardcoded frontend origin /api/streams route where no rewrite or handler existed.
  • On-chain Stream ID: normalizeStream now prioritizes record.streamId / record.stream_id over the database UUID record.id, ensuring UI table rows and filters display the user-facing Soroban on-chain stream IDs.
  • Timestamps: REST startTime and endTime are correctly mapped to startTimestamp and endTimestamp. When createdAt is omitted, it derives safely from startTimestamp instead of generating current timestamps or zero dates.
  • Status Flag Derivation: Maps backend boolean flags (isActive, isPaused, and events) into active, paused, completed, and cancelled (when CANCELLED event is present), while continuing to support explicit status strings.
  • Token Decimals & Amounts: Token metadata resolves addresses against TOKEN_ADDRESSES (USDC, XLM, EURC) and defaults to 7 decimals (the Stellar standard scale) rather than silently substituting 18 decimals when decimals are omitted. remainingBalance is derived from depositedAmount - withdrawnAmount when not explicitly present in the REST payload.
  • Accounting & Metrics Fallback Alignment: Updated export-accounting.ts and stream-metrics.ts fallback decimals from 18 to getDefaultTokenDecimals(symbol) (7 decimals).
  • Test Coverage: Added comprehensive unit and integration tests covering normalization of REST backend payloads, endpoint generation, and full mounting of AnalyticsPage against representative active, paused, cancelled, and completed records.

Backend RPC Pool Timeout Cleanup (#1710)

  • Execute Timeout Cleanup: Stored timeoutHandle from setTimeout and wrapped operation execution in try ... finally to ensure clearTimeout(timeoutHandle) is invoked upon settlement (success or early failure).
  • Late Abort Prevention: Verified that settled operations clear their timers so that controller.abort() is never invoked after success, avoiding false abort signals.
  • Probe All Cleanup: Stored and cleared probe timeout handles in finally for all endpoints in probeAll.
  • Preserved Timeout Behavior: Genuinely hung operations still trigger timeout rejection after timeoutMs, fire the AbortSignal, and proceed with endpoint failover.
  • Test Coverage: Added unit test suite backend/tests/rpc-pool.test.ts utilizing Vitest fake timers (vi.useFakeTimers) to verify timer cleanup, absence of late aborts, early failure failover, genuine timeout aborts, and health probe timeout cleanup.

Backend Notification Service Delivery & Expired Subscription Tests (#1711)

  • Transport Mocking & Failure Isolation: Mocked webpush, Telegram fetch, and Discord fetch transports. Verified that a rejected push notification does not prevent Telegram or Discord deliveries, a rejected Telegram call does not prevent push or Discord deliveries, and a rejected Discord call does not prevent push or Telegram deliveries.
  • Expired Subscription Deletion: Verified that HTTP 404 (Not Found) and HTTP 410 (Gone) from the push service trigger deletion of the expired endpoint via prisma.pushSubscription.deleteMany({ where: { endpoint } }).
  • Transient Failure Retention: Verified that HTTP 500, 503, and network errors retain the push subscription in the database.
  • VAPID Configuration Handling: Verified that missing VAPID_PUBLIC_KEY or VAPID_PRIVATE_KEY prevents push delivery attempts while permitting Telegram and Discord channels.
  • Helper Method Tests: Added unit tests for subscribeWebPush, unsubscribeWebPush, generateLinkCode, linkTelegram, and setDiscordWebhook.

CI Bugfixes & Stability

  • RPC Pool Fake-Timer Unhandled Rejection: In backend/tests/rpc-pool.test.ts, when testing rejects with timeout when all endpoints genuinely hang, vi.advanceTimersByTimeAsync(2000) was triggered before attaching the rejection assertion on the returned promise. Node.js emitted an unhandled promise rejection error caught by Vitest. Fixed by attaching the expectation assertion const assertion = expect(resultPromise).rejects.toThrow(...) before advancing fake timers, then awaiting the assertion.
  • Analytics KPI Active Positions Timestamp Drift: In frontend/src/__tests__/stream-analytics.test.tsx, mock stream fixtures used a fixed January 2025 date for NOW_SECONDS. When AnalyticsPage rendered in 2026, Date.now() determined the streams had expired in the past (secondsRemaining === 0), yielding 0 active positions instead of 1. Updated the fixture to compute nowSeconds = Math.floor(Date.now() / 1000) dynamically.

Verification

  • Frontend CI verification:
    • npm run lint --workspace=frontend: passed (0 errors, 17 warnings).
    • npm test --workspace=frontend: 78 test files passed (728 total tests passed, including stream-analytics.test.tsx).
    • npm run build --workspace=frontend: Next.js Turbopack build succeeded with static page generation.
    • bash frontend/scripts/check-bundle-size.sh: passed (568,989 bytes within 614,400 byte budget).
  • Backend CI verification:
    • npm run build --workspace=backend: tsc compilation succeeded with exit code 0.
    • npm run codegen:openapi & npm run codegen:api-types: OpenAPI spec and TypeScript client drift check passed with clean diff.
    • npx vitest run tests/rpc-pool.test.ts: all 8 tests passed with 0 unhandled rejections.
    • npx vitest run tests/notification.service.test.ts: all 17 tests passed.

Issue Links

Closes #1709
Closes #1710
Closes #1711

…ion delivery (LabsCrypt#1709, LabsCrypt#1710, LabsCrypt#1711)

- LabsCrypt#1709: Connect analytics explorer to documented backend stream endpoint.
  Update useStreams to query the configured backend API URL and documented
  stream-list endpoint (/v1/streams) by default. Normalize actual REST
  streamId instead of database UUID, map startTime and endTime without zero
  dates, derive status across active/paused/completed/cancelled states, and
  resolve token metadata with standard 7 decimals instead of silently
  defaulting to 18. Add unit and integration tests mounting AnalyticsPage
  against representative backend responses.
- LabsCrypt#1710: Clear RPC timeout timers on settled operations and probes.
  Store timeout handles in execute and probeAll and clear them in finally
  blocks upon settlement or early failure, preventing lingering timers
  and late AbortSignal triggers on already completed operations while
  preserving timeouts for hung requests. Add fake-timer unit tests.
- LabsCrypt#1711: Cover notification delivery failures and expired subscriptions.
  Add backend test suite for NotificationService verifying failure
  isolation across WebPush, Telegram, and Discord transports, removal
  of expired endpoints on HTTP 404/410, retention on transient failures,
  and suppression of push delivery when VAPID is unconfigured.

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

1 participant