Skip to content

feat(trade): shared market data subscriptions, bounded cache, and typed order events (OB-111, OB-109, OB-110, OB-112) - #799

Merged
IbrahimIjai merged 2 commits into
SO4-Markets:mainfrom
Prudentdev-xyz:feat/ob-market-data-subscription-cache-events
Sep 26, 2026
Merged

IbrahimIjai merged 2 commits into
SO4-Markets:mainfrom
Prudentdev-xyz:feat/ob-market-data-subscription-cache-events

Conversation

@Prudentdev-xyz

Copy link
Copy Markdown
Contributor

Summary

Closes #766
Closes #764
Closes #765
Closes #767

Comprehensive implementation addressing real-time market data subscriptions, query cache retention bounds, cache correctness regression testing, and typed contract order-event processing across 4 interconnected issues:


OB-111: Manage one shared market-data subscription per active source (#766)

  • Centralized Stream Manager: Implemented marketSubscriptionManager to manage a single shared connection per active symbol with subscriber reference counting.
  • Deduplicated Connections & Timers: useOrderBook, useRecentTrades, and useLiveBar share the same underlying connection. Mounting/unmounting panels (e.g. toggling tabs in OrderBookPanel) does not multiply WebSocket connections or timers.
  • Explicit Polling Fallback: When streaming is unavailable or fails, gracefully falls back to a single bounded REST polling policy (2000 ms) explicitly labeled with status "polling" in DepthLadder and RecentTradesTape.
  • Clean Context Teardown: Switching markets decrements and unsubscribes from the old market context immediately.

OB-109: Bound cache retention and server-state duplication (#764)

  • Cache Policies by Data Class: Defined distinct staleTime and gcTime limits in cache-policy.ts (MARKET_DATA: 30s/5m, REALTIME_TAPE: 2s/1m, ACCOUNT_FINANCIAL: 5s/2m, HISTORY: 30s/3m).
  • Bounded Inactive Cache: Added boundQueryCache to QueryProvider, ensuring inactive queries across extended sessions with repeated market/account switches are pruned and capped (max 50 inactive queries).
  • No Stale Local Mirror: Live financial state (positions, balances, orders) is never persisted authoritatively in localStorage.
  • Freshness-Checked & Versioned Persistence: Scoped and versioned wallet-store; added pendingTransactionTimestamp with a 15-minute max age check to ensure pending execution state is not blindly hydrated as truth.
  • Long-Session Scenario Documentation: Authored specification in cache-retention-long-session.md.

OB-110: Add cache correctness and request-deduplication regression coverage (#765)

  • Observable Behavior Coverage: Added cache-correctness.test.tsx testing combined cache policies via network/data behavior rather than isolated spy checks.
  • Request Deduplication: Verified that concurrent consumers subscribing to identical query keys execute only a single fetch request.
  • Scope Isolation: Verified that switching accounts and markets isolates cache entries without data bleed.
  • Mutation-Driven Refresh: Confirmed transaction invalidations propagate reactive data updates without manual page reload.
  • Failure Cases: Verified out-of-order response rejection and unrelated-market isolation.

OB-112: Replace loose order-event polling with typed cursor processing (#767)

  • Typed Event Adapter: Replaced raw string-matching and JSON parsing in useOrderEventPolling.ts with typed event querying via queryContractEvents.
  • Decoded Identity & Event Matching: Implemented order-event-decoder.ts to decode contract topics and payloads, matching account addresses strictly.
  • Multi-Page Burst Processing: Traverses all pages during event bursts (up to 10 pages per poll) so no events are skipped.
  • Safe Cursor Advancement & Persistence: Scoped cursor persistence per account (so4:order-events:cursor:${account}); advances cursor only after successful page processing.
  • Targeted Refresh Matrix: Mapped OrderExecuted to positions/orders/balances/market stats, OrderCancelled and OrderCreated to orders/balances, and OrderUpdated to orders.
  • Comprehensive Unit Tests: Added useOrderEventPolling.test.ts covering bursts, restart recovery, deduplication, malformed events, and failure handling.

Changes

Modified Files

  • apps/web/src/app/providers/QueryProvider.tsx
  • apps/web/src/features/trade/hooks/useOrderBook.ts
  • apps/web/src/features/trade/hooks/useRecentTrades.ts
  • apps/web/src/features/trade/hooks/useLiveBar.ts
  • apps/web/src/features/trade/hooks/useOrderEventPolling.ts
  • apps/web/src/features/trade/components/orderbook/DepthLadder.tsx
  • apps/web/src/features/trade/components/orderbook/RecentTradesTape.tsx
  • apps/web/src/features/wallet/store/wallet-store.ts

New Files

  • apps/web/src/features/trade/lib/market-data-stream.ts
  • apps/web/src/features/trade/lib/market-data-stream.test.ts
  • apps/web/src/features/trade/lib/cache-policy.ts
  • apps/web/src/features/trade/lib/cache-correctness.test.tsx
  • apps/web/src/features/trade/lib/cache-retention-long-session.md
  • apps/web/src/features/trade/lib/order-event-decoder.ts
  • apps/web/src/features/trade/hooks/useOrderEventPolling.test.ts
  • .changelog/unreleased/766-shared-market-data-cache-order-events.md

…ed order events (OB-111, OB-109, OB-110, OB-112)

- Manage one shared market-data subscription per active source with consumer reference-counting and bounded polling fallback (OB-111)
- Bound inactive cache retention and server-state duplication across long sessions (OB-109)
- Add cache correctness, scope isolation, and request-deduplication regression coverage (OB-110)
- Replace loose order-event polling with typed event decoding, multi-page burst pagination, and cursor persistence (OB-112)
@vercel

vercel Bot commented Sep 24, 2026

Copy link
Copy Markdown

@Prudentdev-xyz is attempting to deploy a commit to the Ijai's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Sep 24, 2026

Copy link
Copy Markdown

@Prudentdev-xyz 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

@IbrahimIjai
IbrahimIjai merged commit 62f5cfc into SO4-Markets:main Sep 26, 2026
1 of 4 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

2 participants