Skip to content

Uuid: make v7 monotonic within a millisecond (de-flake the transcript ordering) - #130

Merged
WebTigers merged 1 commit into
mainfrom
fix/uuid-v7-monotonic
Aug 17, 2026
Merged

Uuid: make v7 monotonic within a millisecond (de-flake the transcript ordering)#130
WebTigers merged 1 commit into
mainfrom
fix/uuid-v7-monotonic

Conversation

@WebTigers

Copy link
Copy Markdown
Owner

Root cause

The flaky AgentServiceTest::history_returns_a_transcript_... (expected 'user', got 'assistant') isn't a test bug — it's the UUID generator. Tiger_Uuid::v7() filled the sub-millisecond bits with pure randomness and explicitly punted on a counter ("isn't worth the complexity here"). So two messages appended in the same millisecond got IDs with random tails, and the transcript's created_at DESC, message_id DESC sort had a non-deterministic tiebreak → the two rows re-ordered ~1/20 runs. It recurred across #68 / #125 / #129.

Fix (at the root, benefits every v7-keyed table)

RFC 9562 §6.2 "monotonic random" (method 2): rand_a becomes a 12-bit monotonic counter that increments for each same-ms mint (seeded randomly per ms so it doesn't leak a mint count; rolls into the next ms if 4096 are exhausted). rand_b stays fully random → uniqueness + index locality unchanged, still a valid v7, timeOf() still works. ORDER BY id is now a stable insertion order for same-process appends — exactly the transcript case (a conversation's turns are appended in one request).

No change to the model or the test's intent — the ordering ambiguity simply no longer exists.

Verification

  • The previously ~1/20-flaky transcript test: 40/40 passes.
  • UuidTest now asserts strict full-string monotonicity over 5000 tight-loop mints (forces same-ms collisions) — the regression guard, replacing the old "full-string order NOT guaranteed within a ms" assertion.
  • Full unit (821) + integration (1094) green; v7 unique over 20k draws; version/variant valid.

🤖 Generated with Claude Code

…ake class)

Tiger_Uuid::v7() filled the sub-ms bits with pure randomness, so two IDs minted
in the same millisecond had no deterministic order. Any v7-keyed append log that
sorts by id (or falls back to id as a created_at tiebreak) could therefore
re-order two rows written in the same tick — the AgentServiceTest transcript
flake (expected 'user', got 'assistant'), which has recurred across #68/#125/#129.

Fix at the root (RFC 9562 §6.2 "monotonic random", method 2): rand_a becomes a
12-bit counter that increments for each same-ms mint (seeded randomly per ms so it
doesn't leak a mint count; rolls into the next ms if it exhausts 4096). rand_b stays
fully random, so uniqueness and index locality are unchanged, and the ID is still a
valid v7 whose embedded timestamp timeOf() reads. `ORDER BY id` is now a stable
insertion order for same-process appends — the case that matters (a conversation's
turns are appended within one request).

- UuidTest: assert STRICT full-string monotonicity over 5000 tight-loop mints
  (forces same-ms collisions) — the direct regression guard, replacing the old
  "full-string order NOT guaranteed within a ms" assertion.
- Verified: the previously ~1/20-flaky transcript test now passes 40/40; full unit
  (821) + integration (1094) green; v7 still unique over 20k and version/variant-valid.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@WebTigers
WebTigers merged commit 65cae48 into main Aug 17, 2026
13 checks passed
@WebTigers
WebTigers deleted the fix/uuid-v7-monotonic branch August 17, 2026 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant