diff --git a/crates/superbank/README.md b/crates/superbank/README.md index eef13f9..2389877 100644 --- a/crates/superbank/README.md +++ b/crates/superbank/README.md @@ -227,7 +227,9 @@ cargo run -p superbank -- --config path/to/superbank.yaml - `dragonsmouth-from-slot: 0` attempts slot 0; if unavailable, superbank parses the gRPC error to find the earliest available slot. - `dragonsmouth-from-slot: "*"` uses the highest slot in `blocks_metadata` before subscribing; if - rejected, superbank falls back to the gRPC-reported available slot. + rejected, superbank falls back to the gRPC-reported available slot. If `blocks_metadata` has no + rows yet (fresh deployment), superbank skips straight to that same gRPC-reported available slot + instead of erroring. - For seeded live-tail gRPC deployments, prefer `dragonsmouth-from-slot: "*"` so process restarts resume from the latest durable ClickHouse slot instead of replaying from the earliest available upstream slot. diff --git a/crates/superbank/src/ingest/grpc.rs b/crates/superbank/src/ingest/grpc.rs index 33d455f..fd53498 100644 --- a/crates/superbank/src/ingest/grpc.rs +++ b/crates/superbank/src/ingest/grpc.rs @@ -483,20 +483,24 @@ async fn resolve_initial_from_slot( ) -> Result<(Option, Option)> { match args.dragonsmouth_from_slot { Some(FromSlotSpec::LatestDb) => { - let latest = fetch_latest_slot_from_blocks(clickhouse, &args.blocks_table) - .await? - .ok_or_else(|| { - anyhow!( - "dragonsmouth-from-slot '*' requires at least one row in {}", + match fetch_latest_slot_from_blocks(clickhouse, &args.blocks_table).await? { + Some(latest) => { + info!( + slot = latest, + table = %args.blocks_table, + "resolved dragonsmouth-from-slot='*' to latest slot in blocks_metadata" + ); + Ok((Some(latest), Some(FromSlotMode::LatestDb))) + } + None => { + info!( + table = %args.blocks_table, + "dragonsmouth-from-slot='*' found no rows in {}; falling back to gRPC-reported available slot", args.blocks_table - ) - })?; - info!( - slot = latest, - table = %args.blocks_table, - "resolved dragonsmouth-from-slot='*' to latest slot in blocks_metadata" - ); - Ok((Some(latest), Some(FromSlotMode::LatestDb))) + ); + Ok((None, Some(FromSlotMode::LatestDb))) + } + } } Some(FromSlotSpec::Slot(0)) => Ok((Some(0), Some(FromSlotMode::Zero))), Some(FromSlotSpec::Slot(slot)) => Ok((Some(slot), Some(FromSlotMode::Strict))),