fix(fiat-rates): if historical rate missing for given date, return -1#1545
fix(fiat-rates): if historical rate missing for given date, return -1#1545cranycrane wants to merge 4 commits into
Conversation
|
this would possible break some suite code. It needs to be fixed there first. |
Partial-day fiat-rate holes (write-side detection/repair) — context for this PRSurfaced during the review of #1560. We will not fix this in #1560; filing it here because this PR (return The problemThe fiat-rate store keeps one record per day holding both base
Relationship to the #1560 changes#1560 reworked fiat-rate fetching. Two of its changes bear directly on this:
Proposed solution (two complementary halves)A. Read-side — this PR. Return the B. Write-side — detect + repair (separate follow-up, not in #1560).
Suggested sequencing
cc: tracked out of the #1560 review. |
…void losing token series ReconcileHistoricalRates accumulates every series (base coin x each vsCurrency, then every token) into one shared per-day record, so a day record is only as complete as it will ever be once all targets have run. The previous code persisted the partial map on any early exit (shutdown/budget abort, Cloudflare ban, or DB fill error). After a base-phase or mid-token-phase abort that left a day with base rates but no token rates; because stage-1 detection is whole-day key-only, the day was then seen as "present" and never reconciled again -- silently dropping its token series for good. Make persistence all-or-nothing: write only after a clean, complete pass; on any early exit discard the partial map and report 0 filled, so the next startup re-reconciles the whole gap. Move the fetched-units/tokens metrics to the clean-completion path so discarded fetches are not counted, and generalize observeFetchedToken to take a count. Tradeoff: an aborted run no longer resumes from partial progress and refetches the gap next startup (a future per-day completion checkpoint can restore that). An isolated per-series failure on an otherwise-clean run still persists a partial-day hole -- tracked separately (see #1545). Tests: TokenPhaseAbortDiscardsBaseOnly (verified to fail on the old persist-on-abort behavior) and NoTokensPersistsBaseOnly (clean base-only pass still persists). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…void losing token series ReconcileHistoricalRates accumulates every series (base coin x each vsCurrency, then every token) into one shared per-day record, so a day record is only as complete as it will ever be once all targets have run. The previous code persisted the partial map on any early exit (shutdown/budget abort, Cloudflare ban, or DB fill error). After a base-phase or mid-token-phase abort that left a day with base rates but no token rates; because stage-1 detection is whole-day key-only, the day was then seen as "present" and never reconciled again -- silently dropping its token series for good. Make persistence all-or-nothing: write only after a clean, complete pass; on any early exit discard the partial map and report 0 filled, so the next startup re-reconciles the whole gap. Move the fetched-units/tokens metrics to the clean-completion path so discarded fetches are not counted, and generalize observeFetchedToken to take a count. Tradeoff: an aborted run no longer resumes from partial progress and refetches the gap next startup (a future per-day completion checkpoint can restore that). An isolated per-series failure on an otherwise-clean run still persists a partial-day hole -- tracked separately (see #1545). Tests: TokenPhaseAbortDiscardsBaseOnly (verified to fail on the old persist-on-abort behavior) and NoTokensPersistsBaseOnly (clean base-only pass still persists). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
b7a48bf to
846bde6
Compare
Return -1 for missing historical fiat rates on a given day
Closes #1543
What & why
For a historical timestamp,
GetTickersForTimestampspreviously scanned forward across daysfor the closest available daily ticker and, if none was found, fell back to the current
ticker. This silently returned a rate from a different day (at worst, today's price) for dates
we have no data for - misleading for old/sparse history.
Now a historical lookup serves only the ticker stored for the resolved UTC day. If no rate
is stored for that day, the rate is left unset and the API returns
-1. Timestamps newerthan the stored history continue to return the current ticker.
Behavior change
-1-1previously meant only "invalid/unavailable currency"; it now also means "no stored ratefor that day". Affects
/api/v2/tickers,/api/v2/multi-tickers, andbalancehistoryfiatrates.
Changes
fiat/fiat_rates.go- drop the forward/closest fallback in the daily branch; serve only therate resolved for the same UTC day.
common/metrics.go,configs/metrics.yaml- add Prometheus counterblockbook_fiat_rates_missing_day_lookupsto track days resolved to an unavailable rate.openapi.yaml- document the new resolution semantics and-1meaning.fiat/fiat_rates_test.go- coverage for the missing-day →-1path and the metric.Client impact
Clients must treat
-1as "rate unavailable" (not a real price).