diff --git a/src/main.rs b/src/main.rs index a464023..5a9614d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -515,18 +515,33 @@ async fn launch() -> _ { } // Background task: incrementally materialise new 1-hour OHLCV buckets as blocks arrive. - // The full historical backfill above already ran; this task only handles the tail. + // After a version wipe this is also what repopulates history, since the synchronous + // backfill above is skipped in that case. // Only processes buckets older than 3 hours (well beyond BCH reorg depth). { let ohlcv_write = dbpool.cauldron_w.clone(); let ohlcv_read = dbpool.cauldron_r.clone(); let ohlcv_state_bg = ohlcv_state.clone(); + let ohlcv_ibd = ibd_state.clone(); tokio::spawn(async move { // Batch size: 1 day per SQL call to keep each write short. const BATCH_SECS: i64 = 24 * 3600; // Safety margin: only materialise buckets older than this many seconds. const SAFETY_SECS: i64 = 3 * 3600; + // Wait for IBD before materialising anything. + // + // The synchronous backfill above waits too, but it is skipped whenever + // `ohlcv_wiped` is set — which includes every fresh database, since a missing + // version key reads as stale. Without this the task would sweep from the + // first trade all the way to `now - 3h` while indexing is still years behind, + // writing nothing, contending with block writes for the cauldron write lock, + // and advancing `materialized_end` to roughly now against an empty table — at + // which point `candlesticks()` would take the fast path over nothing. + while !ohlcv_ibd.initial_sync_complete.load(Ordering::Relaxed) { + tokio::time::sleep(Duration::from_secs(1)).await; + } + loop { let now = crate::timeutil::time_now(); // Floor to 1-hour boundary, 3 hours ago.