feat(bb-distributed-data): atomic Counter primitive for DSQL#207
Closed
hfurkanbozkurt wants to merge 1 commit into
Closed
feat(bb-distributed-data): atomic Counter primitive for DSQL#207hfurkanbozkurt wants to merge 1 commit into
hfurkanbozkurt wants to merge 1 commit into
Conversation
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
Adds an atomic
Counterprimitive toDistributedDatabase(Aurora DSQL) so applications can get a race-free monotonic sequence number without hand-rolling aSELECT MAX(seq) + 1read-modify-write.The gap this closes
Aurora DSQL has no sequences — the framework's own validation layer rejects
SERIAL/BIGSERIAL/CREATE SEQUENCE. So code that needs a per-entity sequence number is pushed into:Two concurrent same-user writes both read
seq = Nand both insertseq = N+1→ duplicate sequence numbers and unstable ordering. This was surfaced as finding C3-F3 in the PR #194 single-table-bench audit (oidc-dsql-notestask), tagged there as "arguably FRAMEWORK — no atomic sequence/auto-increment helper" and not fixable inside the bench task harness. This PR is that framework fix.What's added
db.counter(name)returns aCounterwith:next(delta = 1)— atomically increment and return the new valuecurrent()— read without incrementing (0 if never seen)reset(value = 0)— set to an explicit valueEach mutation is a single atomic upsert wrapped in OCC retry:
DSQL supports
INSERT ... ON CONFLICT DO UPDATE ... RETURNING, so there is no read-then-write window for a competing writer. It runs insidetransaction({ retryOnConflict: true })so a DSQL OCC conflict on the row retries transparently.The backing store is a framework-managed
_blocks_counterstable:_migrations— no user migration required.provisionAppRolealready grants the app role DML on every admin-owned table!= _migrations, so the app runtime automatically getsSELECT/INSERT/UPDATE/DELETEon it (the app runtime stays DML-only and never issues DDL).DsqlMockEnginecreates the same table inside itswithDdlinit window → identical behavior against PGlite.Tests
11 new tests in
counter.test.ts(real PGlite viaDsqlMockEngine, no mocks/stubs):next()→ 1, 2, 3…; custom + negative deltas;current()/ unseen = 0;reset(); two named counters isolatedsimulateConflict()thennext()still returns the correct value and does not double-count (proves the rolled-back attempt is discarded)Promise.allof 25 concurrentnext()calls → 25 unique values, min 1 / max 25 (proves no duplicate sequence — the exactoidc-dsql-notesrace)DistributedDatabasemock integration: counter table auto-created withoutmigrationsPath; value persists in_blocks_countersFull package suite: 157/157 passing. Build clean (
tsc --build). API report regenerated via api-extractor.Placement rationale (new PR off
main, not bench PR #194)This is a runtime capability gap in deployed Lambda code. A bench/harness helper runs in the test harness, not the deployed app, so it structurally cannot fix a runtime concurrency bug. The PR #194 audit itself separated this: findings #1–#8 (task-test gaps) belong in the bench PR, while C3-F3 was tagged "arguably FRAMEWORK / not tasks-fixable". The fix archetype — "an atomic
increment()/ conditional-update on the data block, or a Counter block" — is exactly a framework primitive. Hence a new branch offmain.Opened as draft.
🤖 Generated with Roko AI Agent