feat: add bounded prediction cache (max 100 entries, FIFO eviction)

- Before inserting into predictionCacheRef, check if size >= 100
- If so, evict oldest entry via cache.keys().next().value (FIFO)
- Applied at both cache write sites (lines ~549 and ~671 in page.tsx)
- Marks task 8.5 as done in tasks.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marko Djordjevic 2026-02-18 15:22:38 +01:00
parent acf31d3edf
commit 8395f23744
2 changed files with 12 additions and 4 deletions

View file

@ -74,7 +74,7 @@
- [x] 8.2 `[sonnet]` Use `chart.applyOptions()` for theme changes instead of re-creating chart (`src/components/CandleChart.tsx:333`)
- [x] 8.3 `[sonnet]` Remove `fitContent()` from reconciliation effect, only call on initial load (`src/components/SpanAnnotationManager.tsx:160`)
- [x] 8.4 `[opus]` Implement incremental primitive updates in SpanAnnotationManager: update only selection state on selection change, full reconciliation only on annotation list changes (`src/components/SpanAnnotationManager.tsx:104-161`)
- [ ] 8.5 `[sonnet]` Add bounded prediction cache (max 100 entries, FIFO eviction) to `predictionCacheRef` (`src/app/page.tsx:195-199`)
- [x] 8.5 `[sonnet]` Add bounded prediction cache (max 100 entries, FIFO eviction) to `predictionCacheRef` (`src/app/page.tsx:195-199`)
- [ ] 8.6 `[sonnet]` Fix hardcoded 1-minute candle interval: detect interval from data, use for span iteration (`src/components/CandleChart.tsx:452`)
- [ ] 8.7 `[haiku]` Extract magic numbers (8px, 60s, colors) to named constants in `CandleChart.tsx`
- [ ] 8.8 `[haiku]` Move `new Set<string>()` default prop to module-level constant in `CandleChart.tsx:125`

View file

@ -544,9 +544,13 @@ export default function Home() {
const data = await response.json();
// Cache the results
// Cache the results (bounded: max 100 entries, FIFO eviction)
if (cacheKey) {
predictionCacheRef.current.set(cacheKey, {
const cache = predictionCacheRef.current;
if (cache.size >= 100) {
cache.delete(cache.keys().next().value);
}
cache.set(cacheKey, {
spans: data.spans,
predictions: data.predictions,
modelVersion: data.model_info.model_version,
@ -668,7 +672,11 @@ export default function Home() {
const cacheKey = generateCacheKey(activeChartId, data.model_info.model_version);
if (cacheKey) {
predictionCacheRef.current.set(cacheKey, {
const cache = predictionCacheRef.current;
if (cache.size >= 100) {
cache.delete(cache.keys().next().value);
}
cache.set(cacheKey, {
spans: data.spans,
predictions: data.predictions,
modelVersion: data.model_info.model_version,