Skip to main content
← Back to list
01Issue
FeatureOpenExtensionsPublic
AssigneesNone

Relationships

#3377 S3/GCS datastores: write data version files create-only so a second writer cannot overwrite an existing version

Opened by stack72 · 10/13/2026

Background

swamp-club#3373: on S3 and GCS v2 datastores, a run whose model lock was force-released (swamp datastore lock release --force) still pushed. Each clone allocates the next data version from its own cache, so the old holder and the new holder both wrote version N+1 under the same key (<type>/<modelId>/<dataName>/<N+1>/). The later upload overwrote the earlier one. Both runs exited 0 and one acknowledged write was lost.

The overwrite happens inside the extensions' sync. pushChanged, preparePush and commitPush upload with a plain put, so the last writer wins.

What swamp-club#3373 does in core

Before each push under per-model locks, core re-reads each lock and compares it with its reading at acquire: holder, hostname, pid and nonce. If the lock was lost, core refuses the push and fails with model_lock_lost.

That narrows the window but cannot close it. The check and the upload are not atomic, so a breakglass and a takeover that land between them can still lose a write. Phase 5's model leases close it in the long run.

Proposal

Make the S3 and GCS sync services write data version files create-only:

  • S3: PutObject with If-None-Match: *.
  • GCS: ifGenerationMatch=0.

That covers the files under <type>/<modelId>/<dataName>/<version>/. A second write of a version that already exists then fails instead of overwriting, whatever happened to the locks.

Things to settle

  • Retries and re-publishes. The publish-and-verify loop in core (swamp-club#3146) re-stages the same version. A precondition failure where the remote bytes equal the local bytes must count as success, not as an error.
  • Which keys stay overwrite-in-place. The latest marker, the index and other mutable files must keep their current behaviour; only immutable version files become create-only.
  • Endpoints without conditional writes. Some S3-compatible endpoints don't support If-None-Match. S3Lock already falls back for If-Match; this needs a matching fallback and a warning.
  • The in-memory remote fake. The fake in packages/testing/in_memory_remote.ts (swamp repo) should model the new semantics so core tests can pin them.
  • What the losing writer sees. It should fail with a clear error naming the version that already exists.
02Bog Flow
◉OPEN○TRIAGED○IN PROGRESS○SHIPPED

Open

10/13/2026, 6:00:37 PM

No activity in this phase yet.

03Sludge Pulse
Editable. Press Enter to edit.

system commented 10/13/2026, 6:00:38 PM

Classified automatically when this issue was filed.

  • Source: Extensions

If you feel this classification is incorrect, add a ripple to tell us so.

Sign in to post a ripple.