Skip to content

surface updateIf / deleteIf (version-fenced CAS) — needs a wasm release carrying stitch-rs#47 #57

Closed

Description

@fabracht

Request

stitch-rs PR #47 ("add update_if and delete_if compare-and-set", merged f25ae800 to main on 2026-10-17, closing stitch-rs#26) adds client-driven version-fenced writes and exposes them on the wasm surface as updateIf / deleteIf, with a stale-version failure surfaced to JS as err.kind = "preconditionFailed" (a new terminal error, distinct from the retryable conflict).

Please cut a stitch-wasm release carrying f25ae800, then a wrapper release that raises the stitch-wasm floor to it and surfaces updateIf / deleteIf (plus the err.kind = "preconditionFailed" mapping) through the TS API.

Why

This is the one primitive gating an atomic stale-hold reclaim downstream. Without a client CAS, reclaiming a departed holder's row is a non-atomic delete(stale) → create(new) (ticket-live holds.ts acquireHold), which races — another client can claim the key between the two ops. A single fenced deleteIf / updateIf collapses it into one atomic op and closes the gap.

Current state (verified 2026-10-21)

  • PR Bump @vue/server-renderer and vue in /examples/vue #47 merged after the stitch-rs v0.5.1 tag (2026-10-17 16:07) and sits in CHANGELOG [Unreleased] — so it's in main but not in any published release.
  • Installed @laboverwire/stitch@0.6.2 → @laboverwire/stitch-wasm@0.5.1: update_if / delete_if / updateIf / deleteIf / preconditionFailed are all absent (grepped the published package).

Notes

  • Upstream calls it remote-first / online-only (sent to the broker first, never queued, applied locally only on success) — the wrapper surface should preserve that contract, not optimistic-queue it.
  • Built on mqdb-core 0.7.12's _expected_version CAS (412 → PreconditionFailed); confirm the adapter binding matches the new wasm exports.

Activity

  1. fabracht commented on Oct 22, 2026

    @fabracht
    ContributorAuthor

    The engine half of this shipped, but the wrapper surface this issue asks for did not — so this should stay open.

    Engine (done): @laboverwire/stitch-wasm@0.6.0 is published and its tarball contains updateIf / deleteIf / preconditionFailed. ✅

    Wrapper (still needed): @laboverwire/stitch@0.6.4 raised the stitch-wasm floor to ^0.6.0 but does not expose the CAS methods. Its Store interface (dist/types.d.ts) has only create / update / delete — no updateIf / deleteIf / rowVersion, and no typed err.kind. The 0.6.4 CHANGELOG says so directly:

    "two new compare-and-set methods (updateIf, deleteIf) the wrapper does not expose"

    Since the wrapper's compiled JS never forwards to the engine methods, there's no typed (or even cast) path to store.deleteIf(...) through @laboverwire/stitch.

    The remaining ask: a wrapper release that adds to the Store interface:

    • updateIf / deleteIf forwarding to the engine, preserving the engine's remote-first / online-only contract (sent to the broker first, never optimistic-queued, applied locally only on success)
    • rowVersion(record) to read _version for the fence
    • the terminal precondition failure mapped to a typed err.kind === 'preconditionFailed', distinct from the retryable conflict

    Downstream use: ticket-live's stale-hold reclaim (holds.ts acquireHold) is a non-atomic delete(stale) → create(new) today; a single fenced deleteIf / updateIf collapses it into one atomic op and closes the reclaim race.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions