Skip to content

fix: preflight max-age config, durable webhook metrics, degraded boot, ledger cursor CAS (#341-#344) - #437

Merged
ritaifeoluwa merged 1 commit into
SmartDropLabs:mainfrom
Sweet-Kid:fix/issues-341-342-343-344
Sep 26, 2026
Merged

ritaifeoluwa merged 1 commit into
SmartDropLabs:mainfrom
Sweet-Kid:fix/issues-341-342-343-344

Conversation

@Sweet-Kid

Copy link
Copy Markdown
Contributor

What changed

  • ** closes [enhancement] No CORS preflight caching headers #344 — CORS preflight caching:** Access-Control-Max-Age on OPTIONS responses
    is now sourced from CORS_MAX_AGE_SECONDS (default 86400) instead of a hardcoded
    literal, so operators can tune the preflight cache window without a code change.
  • ** closes [bug] webhookDispatcher metrics reset on process restart - no persistence #343 — webhook delivery metrics:** counters moved from process memory to Redis —
    one aggregate hash plus one hash per webhook, written through with HINCRBY on every
    completed delivery (fire-and-forget, never able to fail the delivery). hydrateMetrics()
    reloads them at startup, so success/failure rates survive restarts.
  • ** closes [enhancement] No graceful degradation when Redis is down during startup #342 — startup without Redis:** startServer() now runs degraded when Redis is
    unreachable: one explicit warn, metrics hydration treated as best-effort, then cache
    warm. Neither step can stop the process from listening; both recover once ioredis
    reconnects.
  • ** closes [bug] eventPoller pollOnce uses previousLedger from store but doesn't handle null race #341 — indexer:last_ledger race:** cursor advance is now a compare-and-set Lua
    script (advanceLastLedger) that also refuses to move the cursor backwards. The poller
    saves events first (idempotent), then attempts the CAS; on losing the race it keeps its
    saved batch, warns, and reports { skipped: true, reason: 'concurrent cursor advance' }
    instead of silently rewinding another instance's progress.

Also repaired (broken on main, blocking the fixes above)

  • src/config.js — const config = module.exports; + dangling object properties was a
    syntax error; restructured to const config = module.exports = { … }.
  • /health — duplicate websocket key and undefined wsHealth.
  • priceWebSocket.getHealth() — export lost in a merge, restored.
  • priceOracle.fetchFreshPrice() — wrapperPromise/actualPromise were never declared
    ([bug] priceOracle inFlight map stores promise reference - concurrent callers get same rejection #417), which made single-flight pricing throw and silently failed cache warming.
  • Missing Cache warm complete log asserted by cacheWarm.test.js.
  • Stale test mocks: priceWebSocket, airdropExpiry job health, saveEvents,
    apiKeyRateLimit.tiers, price-refresh scan pattern.

…d boot, ledger cursor CAS

- cors.js/config.js: preflight responses advertise Access-Control-Max-Age
  from CORS_MAX_AGE_SECONDS (default 24h) so the cache window is explicit
  and tunable instead of a magic literal (SmartDropLabs#344)
- webhookDispatcher.js: delivery counters are written through to Redis
  (one aggregate hash plus one hash per webhook) and reloaded once at
  startup via hydrateMetrics(), so success rates survive a restart (SmartDropLabs#343)
- index.js: startServer() runs in degraded mode when Redis is down at
  boot — warn once, hydrate metrics best-effort, then warm the cache —
  rather than letting either step stop the process (SmartDropLabs#342)
- eventStore.js/eventPoller.js: advance indexer:last_ledger through a
  compare-and-set Lua script that also refuses to move the cursor
  backwards; the poller keeps the events it already saved and reports a
  skip when another writer wins the race (SmartDropLabs#341)

Collateral repairs to code that was broken on main and blocked these
fixes: config.js module.exports structure (syntax error), the duplicate
/health websocket key, the priceWebSocket getHealth() export lost in a
merge, and priceOracle's single-flight wrapper promise (SmartDropLabs#417).
@drips-wave

drips-wave Bot commented Sep 26, 2026

Copy link
Copy Markdown

@Sweet-Kid 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

@ritaifeoluwa
ritaifeoluwa merged commit 1f61d87 into SmartDropLabs:main Sep 26, 2026
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