Skip to content

[Task] Preserve atomic BPMN edits in Dapper workflow definitions #8293

Description

@sfmskywalker

Program: #8194
Parent: #8286
Related: #8287

Deliverable

Implement atomic latest-definition compare-and-swap in the Dapper persistence provider so BPMN document PUT uses the same concurrency contract as the in-memory and EF Core stores.

Acceptance

  • Evaluate the supplied match predicate against the latest row selected within the same tenant scope used for the write, and build the new definition from that loaded snapshot.
  • For same-ID updates, use a provider-neutral conditional write token or complete persisted-snapshot predicate that detects metadata-only concurrent changes without relying on collation-sensitive payload equality.
  • For a published-to-draft update, atomically conditionally unmark the prior latest row and insert the draft in one transaction; a lost race returns Conflict and leaves no partial state or unique-key exception.
  • Honor filter.TenantAgnostic when selecting the row while preserving that row tenant ID on mutation; do not replace an explicit tenant with ambient tenant state. Keep the tenant write predicate scoped to the selected row.
  • Ensure a CAS token changes for every supported writer. An application-managed token is insufficient while old-version writers can update rows without rotating it; use a provider-level guard or block mixed-version writers before activating CAS, and document that compatibility gate.
  • Add deterministic winner/loser, stale-metadata, not-found, and tenant-scope tests on SQLite. Add SQL Server/PostgreSQL coverage where the existing integration lanes permit it, and report any unavailable service lane explicitly.
  • Keep migrations compatible with existing rows and avoid changing package publication configuration.

Scope boundary

This task implements and verifies the Dapper provider path only. It does not claim MongoDB or every distributed persistence provider is concurrency-safe, and it does not publish packages.

Activity

  1. added
    elsa 3This issue is specific to Elsa 3
    enhancementNew feature or request
    prio highIs on the roadmap for the near-future
    on Sep 23, 2026
  2. sfmskywalker commented on Sep 23, 2026

    @sfmskywalker
    MemberAuthor

    The isolated Dapper implementation now uses one SERIALIZABLE read/predicate/write transaction, preserving existing SaveAsync writer participation without a new CAS stamp. Nine conformance scenarios pass independently on SQLite, PostgreSQL 17 and SQL Server 2022: current metadata, failed predicate, missing row, atomic draft creation, rollback, competing legacy writer, two-worker contention and tenant preservation/rejection. SQL Server with an artificially short one-second command timeout correctly propagated timeout rather than misreporting it as a conflict; its normal 15-second bound allowed deadlock detection and the suite passed. PostgreSQL proof exposed and fixed existing primary-key omission in Upsert and integer-vs-Boolean version predicates. Final patch/guard tests and review are in progress; no source import or package publication is claimed.

  3. sfmskywalker commented on Sep 23, 2026

    @sfmskywalker
    MemberAuthor

    Preparation PR: #8297 . Final suite totals are 28/28 SQLite (including existing query/bookmark tests), 15/15 PostgreSQL and 15/15 SQL Server. A clean patch replay matched the reviewed source byte-for-byte and passed 28 SQLite tests. Exact pins, hashes, database images, limits and reproduction instructions are in the PR. This task stays open until incorporation and validation in the actual consolidated source.

  4. sfmskywalker commented on Sep 23, 2026

    @sfmskywalker
    MemberAuthor

    Preparation PR #8297 merged as 9fee71f after all exact-head checks, Greptile5/5 and resolved review threads. Final recorded tests:29/29 SQLite (also clean patch replay),16/16 PostgreSQL,16/16 SQL Server; all declared net8/net9/net10 targets build. This is the reviewed patch artifact, not actual imported source; #8293 stays open until consolidated integration and final-layout validation. The merge subject suppresses automatic publishing; no package feed publication was authorized.

  5. added a commit that references this issue on Sep 27, 2026
  6. sfmskywalker commented on Sep 27, 2026

    @sfmskywalker
    MemberAuthor

    #8506 merged into draft import #8409 as ce1111e4421b0e2af9852d55d9e2ebde937fcab5 (merge commit). It passed exact-head checks, including mapped-source-artifact-proof and import-rehearsal-tests, and all review threads were resolved (Greptile 4/5, one non-blocking P2).

    Why it was needed: the Dapper TryUpdateLatestAsync that had reached the import (from Extensions #216) was unreviewed and diverged from the reviewed #8297 patch:

    • no transaction, and tenant scope ignored;
    • whole stale rows written back;
    • missing the PostgreSQL primary-key and Boolean-filter fixes.

    The reviewed tests fail against it: 4 on SQLite, all 17 on PostgreSQL.

    What changed: the imported code now matches the reviewed patch. One deliberate difference: a superseded version returns Conflict, matching the other stores.

    Tests:

    • SQLite 35/35 on net10 and net9.
    • PostgreSQL 17.11 and SQL Server 2022 CU27: 17/17 each, over five runs.
    • Net8 is build-only; a test dependency doesn't support it.

    Receipts: the new sixth receipt (source-tip-refresh-2026-09-27-r6.json) pins the change. r1 and r5 defer to it only for the two superseded paths.

    Follow-up: running the PostgreSQL and SQL Server tests in CI is tracked separately.

    This issue stays open until the history-preserving import reaches main. No package publication occurred.

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

    elsa 3This issue is specific to Elsa 3enhancementNew feature or requestprio highIs on the roadmap for the near-futuretriaged

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions