| function marketQuotesKey(marketSymbols) { |
| return `market:quotes:v1:${[...marketSymbols].sort().join(',')}`; |
| } |
|
|
| async function maintainClosedMarketEquityKeys({ |
| marketSymbols, |
| marketSeedTtl, |
| lastEquityQuoteCount = 0, |
| upstashExpire, |
| upstashGet, |
| upstashSet, |
| nowMs = () => Date.now(), |
| metaTtlSeconds = 604800, |
| preserveKeys = [], |
| }) { |
| if (!marketSymbols || typeof marketSymbols[Symbol.iterator] !== 'function') { |
| throw new Error('marketSymbols iterable is required'); |
| } |
| if (typeof upstashExpire !== 'function') throw new Error('upstashExpire dependency is required'); |
| if (typeof upstashGet !== 'function') throw new Error('upstashGet dependency is required'); |
| if (typeof upstashSet !== 'function') throw new Error('upstashSet dependency is required'); |
| if (!preserveKeys || typeof preserveKeys[Symbol.iterator] !== 'function') { |
| throw new Error('preserveKeys iterable is required'); |
| } |
|
|
| const redisKey = marketQuotesKey(marketSymbols); |
| const keys = [...new Set([redisKey, 'market:stocks-bootstrap:v1', ...preserveKeys])]; |
| const results = await Promise.all(keys.map((key) => upstashExpire(key, marketSeedTtl))); |
| if (results.some((ok) => !ok)) return false; |
|
|
| let count = lastEquityQuoteCount; |
| if (!count) { |
| const meta = await upstashGet('seed-meta:market:stocks'); |
| count = (meta && typeof meta.recordCount === 'number') ? meta.recordCount : 0; |
| } |
| if (count > 0) { |
| await upstashSet('seed-meta:market:stocks', { fetchedAt: nowMs(), recordCount: count }, metaTtlSeconds); |
| } |
| return true; |
| } |
|
|
| module.exports = { |
| marketQuotesKey, |
| maintainClosedMarketEquityKeys, |
| }; |
|
|