Live market prices: 60s fast-refresh loop between sweeps#3
Open
devin-ai-integration[bot] wants to merge 4 commits intodevin/1775767691-phase2a-data-sourcesfrom
Open
Conversation
- Add dedicated market data loop (every 60s) independent of 15-min full sweep - Switch YFinance from daily (5d/1d) to intraday (1d/5m) candles for sparklines - Add collectQuick() lightweight fetch (price-only, no history) for fast loop - Add market_update SSE event type for efficient client-side patching - Dashboard handles market_update by re-rendering topbar + right panel only - New MARKET_REFRESH_SECONDS env var (default 60) for configurable refresh rate - Health endpoint now reports marketRefreshSeconds Co-Authored-By: Jake Cosme <jake@cognition.ai>
Author
Original prompt from Jake
|
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…tial failure - Revert fetchQuote back to range=5d&interval=1d so prevClose fallback (closes[closes.length - 2]) correctly returns previous trading day's close - Add mergeCategory() in runMarketRefresh to preserve previously-good symbols when individual quick fetches fail, instead of dropping them from the dashboard Co-Authored-By: Jake Cosme <jake@cognition.ai>
renderLower() is where D.markets is actually read and rendered (VIX, indexes, crypto, rates). renderRight() doesn't reference D.markets. Co-Authored-By: Jake Cosme <jake@cognition.ai>
…ation Co-Authored-By: Jake Cosme <jake@cognition.ai>
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.
Summary
Adds a dedicated 60-second market data refresh loop that runs independently of the 15-minute full sweep cycle, so market prices update continuously between sweeps.
Problem: BTC, ETH, and all other market prices only updated every 15 minutes (when the full 32-source sweep ran). Between sweeps, prices appeared stale on the dashboard.
Fix: Two-tier refresh architecture:
currentData.marketsin-place and pushes amarket_updateSSE eventWhy
Users reported BTC/ETH prices looked stale. Investigation confirmed prices only updated on the 15-minute sweep cycle. There was no caching bug — the architecture just didn't have a fast path for market data.
Scope
Changes
apis/sources/yfinance.mjscollectQuick()+fetchQuoteQuick()for lightweight price-only fetch (6s timeout, no history,range=1d&interval=1d). ExistingfetchQuoteunchanged (range=5d&interval=1d).server.mjsrunMarketRefresh()on a 60ssetInterval. Skips when sweep is in progress. UsesmergeCategory()to patch prices intocurrentData.marketswhile preserving symbols that failed the quick fetch. Broadcastsmarket_updateSSE.dashboard/public/jarvis.htmlmarket_update: patchesD.markets, callsrenderLower()(where market panels live) +renderTopbar(). No fullreinit()..env.exampleMARKET_REFRESH_SECONDS=60config var.Validation
[Crucix] Market ticker refresh: every 60sin logs/api/healthreturns"marketRefreshSeconds": 60Config and Docs
.env.exampleupdated — newMARKET_REFRESH_SECONDSvariableREADME.mdnot updated (consider adding a note about the two-tier refresh)Updates Since Initial Review
Addressed three Devin Review findings:
fetchQuoteinterval change — Initially changedfetchQuotefrom5d/1dto1d/5m, but this broke theprevClosefallback (closes[closes.length - 2]would return a 5-min candle instead of previous day's close). Reverted to5d/1d; the fast loop uses its ownfetchQuoteQuickwith1d/1dwhich only readsmetafields.mergeCategory()for partial-failure resilience — Previously, if a single symbol failed the quick fetch, it was dropped fromcurrentData.marketsentirely. Now, previously-good data for failed symbols is preserved until the next successful fetch or full sweep.market_updateSSE render target — The handler originally calledrenderRight(), butD.marketsis only read insiderenderLower()(line 1572). Updated to callrenderLower()so updated prices are actually rendered on screen.Human Review Checklist
fetchQuoteQuickreturnsnullon failure (graceful degradation viamergeCategory), but verify this rate is sustainable in practice.fetchQuoteQuickhas a barecatch { return null; }with no logging. Consider whether a debug-level log would help troubleshooting.mergeCategorycorrectness: Verify the merge logic correctly handles edge cases — e.g., whenprevItemshas symbols not innewItems, they should be appended (stale but visible is better than missing).renderLower()fix was identified via code review. End-to-end browser testing to confirm prices visually update every 60s is recommended.Checklist
Link to Devin session: https://app.devin.ai/sessions/a046d43371284e3f8175cb76185f3ced
Requested by: @jakexcosme