fix(hotblocks): keep ingesting when a block time is unrepresentable#100
Merged
Conversation
The datetime conversion in `flush` feeds nothing but a `debug!` field, yet its `?` killed the batch and wedged the dataset on a 60 s retry loop forever — at info level, over a line that is never emitted. `time` is informational (DEF-4, CN-8), so the conversion is best-effort now and the raw millis are logged beside it. The seconds→millis conversions saturate so an absurd source value neither panics in debug nor wraps into a plausible date. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mo4islona
force-pushed
the
fix/hotblocks-block-time-range
branch
from
July 20, 2026 10:39
7fd177c to
89069a7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A block time outside the datetime-conversion range killed the ingest flush and left the
dataset re-requesting the same block every
P-EPOCH-RETRYforever. The conversion feedsnothing but a
debug!field, so this was a log line taking the dataset down with it — andat
infolevel, over a line that is never emitted: the field is evaluated lazily, thefallible conversion above it was not.
timeis informational — DEF-4 says so and CN-8 forbids correctness depending on it. Sothe conversion is best-effort now. What is stored is unchanged and always was the raw
Option<i64>; only the human-readable rendering could ever fail, and it degrades toNonewith
last_block_time_mscarrying the number, so an absurd value is still diagnosable fromthe log.
Saturating conversion
self.header.timestamp * 1000on the evm and solana paths is an uncheckedi64multiply.With no
[profile]overrides in the workspace root, dev builds runoverflow-checks = trueand it panics; release wraps, and a sliver of overflowing inputs wrap back onto a
plausible-looking date. Saturating keeps an absurd input absurd. Bitcoin's
timestamp: u32cannot overflow and is untouched.
GAP-26
Closed. The register's expected behavior — "the dataset must ingest it and keep serving" —
is now what happens, so the row leaves the open register for §6.1, the way GAP-11/19/32/38
did. No regression test was written; the §6.1 entry says so and names the CT-9 scenario
(last block at
time = i64::MAX).Testing
cargo clippyandcargo +nightly fmt --checkclean, with no new warnings on the changedfiles. No test added — the regression test is registered against CT-9 rather than written
here. Thirty days of logs across the hotblocks-db containers carry zero occurrences of the
rejection this removes, so the path is reachable by construction rather than observed.
🤖 Generated with Claude Code