Store: declared non-overlapping intervals and retry-safe host transactions (#902) - #925
Merged
Merged
Conversation
…ransactions (#902) - intervals: {start, end, within?, scope?, when?} on a collection refuses any create, PUT, PATCH or transition whose half-open [start, end) overlaps another constrained record's in its scope with 409 interval_conflict, inside the write transaction, through a partial expression index (one descending index step; 2.4 us median at 10k records vs 3.2 ms without the index). error.conflict.id only for a record the caller may read, so another owner's booking blocks without being named. Bounds are numbers or UTC (Z) date-times with at most millisecond precision. Activation refuses stored overlaps and drops stale interval indexes; reassign and ownerless-assign refuse moves that would overlap under scope: owner. - StoreExports.transaction(work, {idempotencyKey, fingerprint}) keeps hashed key/fingerprint and the JSON result (<= 16 KiB) in the same transaction and replays it without running work; different fingerprint is 422 idempotency_key_reused. Schema version 4 adds store_transaction_results. - bench:store --intervals, OpenAPI 409/conflict, STORE.md, README, llms, CHANGELOG; STORE.md "What is not covered" points at #902 for items 2, 4-6. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jimhoyd
enabled auto-merge (squash)
September 29, 2026 15:46
This was referenced Sep 29, 2026
Closed
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.
Implements #902 items 1 and 3. Items 2, 4, 5 and 6 stay on #902; STORE.md's "What is not covered" points there.
Item 1:
collections.<c>.intervals: {start, end, within?, scope?, when?}withinvalues, may overlap as half-open[start, end). Intervals that only touch are allowed.409 interval_conflictand writes nothing: no record, no retry claim, no audit event.when: an equality filter such as{status: booked}, so cancelling frees a slot. Reopening into a taken slot is refused.scope:collection(the default) blocks across owners;ownerconstrains each owner's records alone.conflict.idappears only when the caller may read the conflicting record. Another owner's booking blocks the slot and nothing about it is returned.start,endandwithinproperties must be required and not increments.date-timein UTC…Z(offsets are refused).reassignandownerless-assignrefuse moves that would overlap underscope: owner.Item 3:
StoreExports.transaction(work, {idempotencyKey, fingerprint?})store_transaction_results, which stores the key and fingerprint as SHA-256 only.work.422 idempotency_key_reused.Measurements (
npm run bench:store -- --intervals, M4 Pro, Node 26.10, SQLite 3.53.4)Evidence
intervals.test.ts(13 tests) covers:scope: owner;reassignrefusal, and rollback on an injected failure;transaction-retries.test.ts(5 tests) covers replay, a mismatched fingerprint, nothing kept on failure, restart, hashing, eviction and races.npm run verifyandnpm run test:packagepass, based on main after Store collections name project schemas; defaults and readOnlyProperties on the collection (#908) #924.Limits
🤖 Generated with Claude Code