You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(fiat-rates): discard partial reconcile results on early exit to avoid 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>
glog.Warningf("FiatRates reconcile stage 2: aborted (%v), persisted %d point(s) (%d token series), %d fetch failures, %d series unprocessed; remaining gap will be reconciled on next startup", abortErr, filled, repairedTokens, failed, remaining)
1309
-
returnfilled, nil
1324
+
glog.Warningf("FiatRates reconcile stage 2: aborted (%v) after %d/%d series, %d fetch failures; discarding partial results, gap will be reconciled on next startup", abortErr, abortAt, len(targets), failed)
1325
+
return0, nil
1310
1326
}
1311
-
glog.Infof("FiatRates reconcile stage 2: filled %d point(s) across %d series (%d token series), %d fetch failures", filled, len(targets), repairedTokens, failed)
1312
1327
ifbanErr!=nil {
1313
-
returnfilled, banErr
1328
+
glog.Warningf("FiatRates reconcile stage 2: Cloudflare ban after %d/%d series, %d fetch failures; discarding partial results, gap will be reconciled on next startup", abortAt, len(targets), failed)
1329
+
return0, banErr
1314
1330
}
1331
+
1332
+
// Clean, complete pass: persist, then record what was actually fetched and persisted.
0 commit comments