You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Dapper and MongoDB IKeyValueStore: atomic TryDeleteAsync overrides for legacy-pause adoption (elsa-core#8529) #260
3.9 blocker. This is required to close elsa-core#8529 for the Dapper and MongoDB providers. Approved by Crew Lead as option A.
Problem
elsa-core #8538 (main) and #8539 (release/3.9.0) add IKeyValueStore.TryDeleteAsync as a default interface method. The default implementation finds the row and then deletes it, so it is not atomic. When two nodes adopt the same legacy pause (the legacy key elsa.quiescence.pause.{shell} moving to the host-wide key in QuiescenceSignal.SweepAndAdoptLegacyPauseAsync), both nodes can find the row, both can delete it, and both get true. Both then save the host key, so a pause that an operator cleared in between can be resurrected (#8529).
The EF Core and in-memory stores override the method atomically. The Dapper and MongoDB key-value stores fall back to the default, which leaves the blocker open for those providers.
Scope
Bump ElsaVersion to a core preview that contains the method (post-#8529). This bump is needed for the ext 3.9 rebuild anyway.
DapperKeyValueStore: override with a single tenant-filtered DELETE and return whether it affected any rows: TryDeleteAsync => (await store.DeleteAsync(q => q.Is(nameof(KeyValuePairRecord.Id), key), ct)) > 0
MongoDBKeyValueStore: override with DeleteOneAsync(store.ApplyTenantScope(Builders<SerializedKeyValuePair>.Filter.Eq(x => x.Key, key))) and return DeletedCount > 0.
Do not use MongoDbStore.DeleteWhereAsync. It finds the rows, then runs DeleteMany, and returns the number it found rather than DeletedCount, so it isn't atomic.
Tests: a two-node test where only one TryDeleteAsync returns true for the same key, for Dapper (SQLite) and for Mongo (Testcontainers).
Starting: atomic TryDeleteAsync overrides for Dapper (DELETE row count > 0) and Mongo (DeleteOneAsync(ApplyTenantScope(...)).DeletedCount > 0) with two-node tests, pinned to core 3.9.0-preview.5726 (includes elsa-core#8539). Lands on the 3.9 train PR #266 (with #263/#264), ported to main via #267.
Delivered via #266 (release/3.9.0, squash aa646675, pinned to core 3.9.0-preview.5726, which includes elsa-core#8539) and #267 (main, merge dc30ffbc). Dapper and MongoDB TryDeleteAsync are now atomic: Dapper checks the deleted row count, and MongoDB uses DeleteOne with the tenant scope. Legacy rows with a NULL TenantId are matched for the default tenant. On main, the fix takes effect once the core pin moves to a 3.10 preview at or after c1c935ce.
Activity
sfmskywalker commentedon Sep 28, 2026
Starting: atomic
TryDeleteAsyncoverrides for Dapper (DELETE row count > 0) and Mongo (DeleteOneAsync(ApplyTenantScope(...)).DeletedCount > 0) with two-node tests, pinned to core 3.9.0-preview.5726 (includes elsa-core#8539). Lands on the 3.9 train PR #266 (with #263/#264), ported tomainvia #267.fix(persistence): atomic TryDeleteAsync on Dapper and Mongo (#260)
fix(persistence): atomic TryDeleteAsync on Dapper and Mongo (#260)
ci: retrigger pr workflow for #260
ci: retrigger pr workflow for #260
fix(persistence): atomic TryDeleteAsync on Dapper and Mongo (#260)
ci: retrigger pr workflow for #260
fix(persistence): atomic TryDeleteAsync on Dapper and Mongo (#260)
ci: retrigger pr workflow for #260
fix(persistence): KeyValues, SerializedOptions, and atomic TryDeleteA…
sfmskywalker commentedon Oct 2, 2026
Delivered via #266 (release/3.9.0, squash
aa646675, pinned to core 3.9.0-preview.5726, which includes elsa-core#8539) and #267 (main, mergedc30ffbc). Dapper and MongoDB TryDeleteAsync are now atomic: Dapper checks the deleted row count, and MongoDB uses DeleteOne with the tenant scope. Legacy rows with a NULL TenantId are matched for the default tenant. On main, the fix takes effect once the core pin moves to a 3.10 preview at or after c1c935ce.