Symptom
Since early July a "Recovered From an Earlier Issue — Electricity Price Data recovered from error (Nordpool Service Call)" banner appears roughly once a day, alongside an HA error card for nordpool.get_prices_for_date returning 500 Server Error. Nothing is actually broken: the optimizer had today's prices cached the whole time and never missed a run.
Root cause
OfficialNordpoolSource.perform_health_check() (core/bess/official_nordpool_source.py:207-220) proves the source is alive with a live nordpool.get_prices_for_date call for today, going straight to self.get_prices_for_date() and bypassing PriceManager's cache.
refresh_health_check runs on CronTrigger(minute="*/5") (backend/app.py:442-447, added in #217) and reaches the price source via health_check.py:372. That is 288 live service calls per day for data that changes once per day.
HealthRecoveryTracker (#239) then fires a banner on every ERROR→OK transition, so a single transient HA 500 — the known-transient failure documented in #583 — produces one error plus one recovery notice.
Proposed fix
Report price health from PriceManager's cache state / last successful fetch instead of forcing a fetch: ERROR only when the last real fetch (the quarterly optimizer run, or the 23:55 next-day prep) actually failed. This removes the 288 redundant calls and the false alarms together.
Alternative considered: require N consecutive failures before flipping to ERROR — keeps the live probe, so it fixes the noise but not the wasted calls.
Symptom
Since early July a "Recovered From an Earlier Issue — Electricity Price Data recovered from error (Nordpool Service Call)" banner appears roughly once a day, alongside an HA error card for
nordpool.get_prices_for_datereturning500 Server Error. Nothing is actually broken: the optimizer had today's prices cached the whole time and never missed a run.Root cause
OfficialNordpoolSource.perform_health_check()(core/bess/official_nordpool_source.py:207-220) proves the source is alive with a livenordpool.get_prices_for_datecall for today, going straight toself.get_prices_for_date()and bypassingPriceManager's cache.refresh_health_checkruns onCronTrigger(minute="*/5")(backend/app.py:442-447, added in #217) and reaches the price source viahealth_check.py:372. That is 288 live service calls per day for data that changes once per day.HealthRecoveryTracker(#239) then fires a banner on every ERROR→OK transition, so a single transient HA 500 — the known-transient failure documented in #583 — produces one error plus one recovery notice.Proposed fix
Report price health from
PriceManager's cache state / last successful fetch instead of forcing a fetch: ERROR only when the last real fetch (the quarterly optimizer run, or the 23:55 next-day prep) actually failed. This removes the 288 redundant calls and the false alarms together.Alternative considered: require N consecutive failures before flipping to ERROR — keeps the live probe, so it fixes the noise but not the wasted calls.