Files
worldmonitor/scripts
Elie Habib e6bae4d7a8 feat(seeds): shared FX rate cache + BigMac WoW data quality guards (#2003)
* feat(seeds): shared FX rate cache + BigMac WoW guards

- Extract SHARED_FX_FALLBACKS to _seed-utils.mjs as single source of truth,
  eliminating duplicated FX fallback tables across seed-bigmac, seed-grocery-basket,
  and seed-fx-rates
- Add getSharedFxRates() / fetchYahooFxRates() to _seed-utils.mjs so all seeds
  share one Redis-cached rate set (shared:fx-rates:v1, 4h TTL) instead of each
  making ~46 independent Yahoo Finance calls per run
- Add seed-fx-rates.mjs: dedicated daily Railway cron that pre-warms the shared
  FX cache, saving ~90 Yahoo calls per weekly bigmac+grocery-basket cycle
- Add WoW minimum-age guard (6 days): prevents week-on-week display when previous
  snapshot is less than 6 days old (fixes -98.5% France WoW on first seed run)
- Add per-country WoW anomaly filter (+-20%): nulls suspicious entries and logs
  admin alert with country name and delta for Railway log monitoring
- Fix global WoW anomaly check to use unfiltered raw average so it can actually
  exceed +-20% (filtered average was mathematically bounded and never triggered)
- Add USD price sanity range guard ($1.50-$12.00): drops prices from bad scrapes
  before they reach Redis (would have caught the $470 France value)
- Move WOW_ANOMALY_THRESHOLD, MIN_WOW_AGE_MS, USD_MIN, USD_MAX to module scope

* fix(seed-fx): address PR review — TTL mismatch and partial write-back risk

- Extend shared:fx-rates:v1 TTL from 4h to 25h so cache stays warm
  between daily cron runs (with 1h drift buffer)
- Make getSharedFxRates() read-only: remove write-back on partial cache
  hit and on cache miss; only seed-fx-rates.mjs owns writes to this key,
  preventing a subset consumer from silently overwriting a fuller cache
2026-03-21 18:41:04 +04:00
..