Skip to content

fix(s3): re-land the same-id concurrency guard + raw coalescing dropped from #1411 - #1433

Open
angela-helios wants to merge 2 commits into
mainfrom
fix/945-reland-s3-ingest-guard-and-raw
Open

angela-helios wants to merge 2 commits into
mainfrom
fix/945-reland-s3-ingest-guard-and-raw

Conversation

@angela-helios

Copy link
Copy Markdown
Contributor

Why

#1411 was merged at its first commit (553030d8b, bare bounded concurrency) before its follow-up commits landed on the branch, so two changes that were part of that work never reached main:

  1. fix(s3): keep same-id entries in a batch serial — a correctness fix. Without it, the concurrent ingest path races two entries in one batch that target the same resource id: their conditional writes interleave to a non-deterministic result, where the serial loop resolves them last-write-wins in file order. main currently has the concurrent path without this guard. The guard falls a batch with any id collision back to serial; distinct-id batches (the common case) still parallelize.
  2. perf(s3): coalesce the raw NDJSON archive to one object per batch — 7→6 PUTs/resource. The raw archive has zero production readers, so it's written once per batch (persist_raw_batch, keyed by first line, file_url-discriminated per bulk-submit: multi-file manifests collide in bulk_entry_results — the PK has no file discriminator, so every file after the first fails at its first line #457) instead of per entry.

Both were validated on MinIO by the #945/#1429 measurement (correctness: 0 errors / 0 lease-lost, rollback OK, same-id → last write wins over 5 rounds; perf: raw coalescing +14–15% A/B, objects/resource 7.0→6.01) — see #1429 — but that measurement ran against the full branch head (1434c83e1), which is not what merged.

What

Cherry-picks of 61665ea60 and 1434c83e1 onto current main (they were built on 553030d8b, which is in main, so they apply cleanly). No new work.

Test

s3::tests bulk-submit suite green (27): same-id batch stays serial (second write wins), 20-entry concurrent batch stays ordered and fully written, raw archive is one object per batch, #457 two-file discrimination on the batch key. fmt + clippy clean under the CI allow-flags.

…ess)

The concurrent ingest path races two entries that target the same
resource id: their conditional writes interleave to a non-deterministic
final state, where the serial loop resolves them last-write-wins in file
order. A batch with any id collision therefore falls back to the serial
path; a bulk file usually carries distinct resources, so the common case
still parallelizes. Entries with no client id are server-assigned a unique
one and never collide.

Test: two entries for the same id, second content wins. Flagged by the
#945 perf measurement (5.7x at N=16, latency-bound, 7 PUTs/entry).
The per-entry raw-line PUT was one of the 7 PUTs/resource the #1429
measurement found the ingest is bound by, and the raw archive has zero
production readers — it is a write-only auditable copy of the input. Write
it once per batch instead: persist_raw_batch archives the whole chunk's
NDJSON in a single object, keyed by the batch's first line number
(submit_raw_batch_key) so successive chunks of one file never collide, and
still discriminated by file_url like the receipts (#457). Written upfront,
before any entry processing, so a failure aborts before anything is stored.

Drops the raw PUT from 1/entry to 1/batch — 7->6 PUTs per resource, and one
of the follow-ups the #1429 phase breakdown pointed at (raw + change +
receipt are the coalescible three; change and receipt have readers and come
next). Tests: one raw object per batch holding every line, and the #457
two-file archive discrimination updated to the batch key.
@codecov

codecov Bot commented Sep 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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