fix(genesis-writer): keep sub-second precision on every emitted timestamp - #534
Merged
Conversation
rickyrombo
force-pushed
the
mjp-release-date-nano
branch
from
August 20, 2026 04:20
6169a16 to
965c5e2
Compare
time.RFC3339 has no fractional-second component, so every release_date carrying microseconds was rounded down to the whole second on the way out. A full-snapshot replay compared against its source showed 26,129 current tracks affected, e.g. 2026-02-02T15:53:12.050585Z emitted as 2026-02-02T15:53:12Z. The indexer already accepts RFC3339Nano, and a value with no fractional part formats identically under both layouts, so rows without microseconds are unchanged. This is a different failure from the one #519 fixed. That emitted Postgres text format, which no accepted layout matched, so the indexer fell back to block time. This parses cleanly and quietly rounds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tamp
time.RFC3339 has no fractional-second component, so every timestamp the
writer emitted was rounded down to the whole second. Verified against a
full-snapshot replay:
track_downloads 78,032 of 78,032 source rows carry sub-second
created_at; the migrated table has zero
subscriptions 1,022,554 playlist_tracks 1,014,903
saves 380,604 reposts 361,803
follows 104,614 comments 7,530
tracks.release_date 26,129
created_at is not cosmetic here: the indexer replays each migrated row as
of its created_at (migrationBlockTime), and parity keys track_downloads on
it -- which is why every sampled row of that table reported as missing
rather than mismatched.
Safe for every reader. parseMigrationTimestamp tries RFC3339Nano before
RFC3339, and Go's parser accepts a fractional second against a layout that
lacks one, so event_create.go's stricter RFC3339 parse still succeeds. A
value with no fractional part formats identically under both layouts, so
rows without microseconds are untouched.
The UTC guard now matches both layouts, so reintroducing the truncating
form still trips its .UTC() half.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rickyrombo
force-pushed
the
mjp-release-date-nano
branch
from
August 20, 2026 05:17
965c5e2 to
2f9a131
Compare
Merged
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.
time.RFC3339has no fractional-second component, so every timestamp the writer emits was rounded down to the whole second. Measured against a full-snapshot replay compared to its source:subscriptionsplaylist_trackssavesrepostsfollowstrack_downloadscommentstracks.release_dateWhy created_at isn't cosmetic
The indexer replays each migrated row as of its created_at (
migrationBlockTime), so the timestamp drives replay semantics, not just display. Parity also keystrack_downloadsoncreated_at— which is why every sampled row of that table reported as missing rather than mismatched. The row counts match exactly (78,032 both sides); only the key failed to join.Safety
parseMigrationTimestamptriesRFC3339NanobeforeRFC3339event_create.go's strictertime.Parse(time.RFC3339, …)still succeedsNote on the guard
TestAllEmittedTimestampsAreUTCscans for formatting sites and fails if it finds none — it caught this rename immediately. Its pattern now matches both layouts, so reintroducing the truncating form still trips the.UTC()half.This is a different failure from the one #519 fixed. That emitted Postgres text format, which matched no accepted layout, so the indexer fell back to block time. This parses cleanly and quietly rounds.
🤖 Generated with Claude Code