Skip to content

docs(adr): ADR-174 Amendment 7, the batch admits a bounded list - #2544

Merged
oceanwaves630 merged 1 commit into
mainfrom
docs/adr-174-a7
Sep 10, 2026
Merged

docs(adr): ADR-174 Amendment 7, the batch admits a bounded list#2544
oceanwaves630 merged 1 commit into
mainfrom
docs/adr-174-a7

Conversation

@oceanwaves630

Copy link
Copy Markdown
Collaborator

stream.batch refuses an empty ops list, and says why: an empty list takes the writer for a batch that writes nothing. It does not refuse a large one.

In atomic mode the whole list executes inside one BEGIN IMMEDIATE. Each observation is a paired SELECT id, version, each append member is a prepared note plan plus a ledger INSERT, each write member a prepared plan plus a SELECT version, updated_at. So the statement count inside a single writer hold is whatever the caller sent, and the only ceiling is the daemon's 8 MiB frame — a transport limit, which for a minimal append member admits a member count on the order of a hundred thousand. SQLite admits one writer, so one such call extends every competing writer's wait.

Every comparable admission in the store names its own number: web manifest ingest at 10,000 entities and 50,000 edges, blob GC at 128 rows per unit. This amendment names this verb's.

What it fixes

  • At most 1000 members in ops, at most 100 entries in observed.
  • Over either bound: invalid_input, naming both the cap and the count sent, so a caller learns how far over it is without bisecting.
  • Checked at admission, before any member is parsed into an action, any note plan is prepared, or a writer is requested. A cap enforced after preparation would still bound the hold, but it would pay for the work first, and the refusal exists to avoid paying.
  • The bound is on the list, so it holds in both modes. Per-member mode already runs one member per transaction and is bounded by construction; it is capped anyway so that one input is refused the same way whatever the mode, and a caller moving between modes does not meet a new limit at the boundary. observed requires atomic mode, so its cap has one mode by construction.

This is not the per-namespace or per-stream quota §6 puts out of scope: it is an admission bound on one request's list, and the record size limit is still the note's.

Acceptance is seven arms: at the cap (which keeps the bound from drifting below its stated number), over the cap with the stream head unchanged as the control that the refusal preceded the writer, the observation cap told apart from the member cap, per-member mode refusing the same input the same way, a list of individually-invalid members proving the cap is checked before members are interpreted, help, and two mutations.

Docs only. The implementing change publishes the measured writer hold time at the cap beside the hold at the largest member count the frame admits.

Recorded as unresolved in ADR-091 Amendment 18 (#2445) and filed as #2543.

stream.batch refuses an empty ops list and names the writer it would take
for a batch that writes nothing. It does not refuse a large one, and in
atomic mode the whole list executes inside one BEGIN IMMEDIATE, so the
statement count inside a single writer hold is whatever the caller sent.
The only ceiling today is the 8 MiB frame, a transport limit, which for a
minimal member admits a count on the order of a hundred thousand.

The amendment fixes the numbers: at most 1000 members and at most 100
observations, refused with invalid_input naming both the cap and the count
sent, checked at admission before any member is parsed, any plan prepared
or any writer requested.

The bound is on the list the caller sends, so it holds in both modes.
Per-member mode is already bounded by construction, and is capped anyway so
that one input is refused the same way whatever the mode. This is not the
per-namespace quota section 6 puts out of scope, and the record size limit
is still the note's.

Seven acceptance arms, including the at-the-cap arm that keeps the bound
from drifting below its number, the unchanged stream head as the control
that the refusal preceded the writer, and two mutations.
@oceanwaves630
oceanwaves630 merged commit d1d02f4 into main Sep 10, 2026
28 checks passed
@oceanwaves630
oceanwaves630 deleted the docs/adr-174-a7 branch September 10, 2026 22:36
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.

2 participants