feat(bpmn): adopt Bpmn.* 0.2.0, and start shipping the two BPMN modules (#7970)
Bpmn.Interchange, Bpmn.Model and Bpmn.Semantics move from 0.1.1-preview.19 to 0.2.0. The three changes below are one unit: the bump is what makes the other two true. Retire the private feed. All three packages are on nuget.org at 0.2.0 -- including Bpmn.Semantics, which had no stable release under 0.1.x. The bpmn-feedz source and its Bpmn.* packageSourceMapping entry both go, which removes a setup step for every consumer. This is not merely cleanup: the feedz feed does not carry 0.2.0 stable, so with the mapping left in place the bump would not restore at all. Restore now resolves Bpmn.* from nuget.org via the existing `*` mapping. Lift IsPackable=false. The comment on the flag named its own removal condition -- the Bpmn.* packages reaching nuget.org -- and that condition is now met, so Elsa.Bpmn and Elsa.Bpmn.Interchange begin shipping. Both pack with every dependency publicly restorable, and both emit a package manifest carrying runtimeKinds ["elsa.server"], so neither is silently excluded from the catalog. They were the last two IsPackable=false projects under src/. Flip the compensation pin to the fixed behaviour. 0.2.0 contains the fix for valence-works/bpmn#13 (filed from here as #7959), so CompensationRunCancelledMidReplay went red on the bump exactly as it was built to. Upstream took the wide fix: every token a cancelled transaction abandons now gets a real teardown. The head handler still starts twice -- that is the release being real -- but the first run is now torn down, so the scope is left holding one live record for the slot instead of two. The applier is deliberately unpatched; the assertions moved to describe the fix, not to accommodate it. Note on persisted state: 0.2.0 freezes the payload format at 1.0.0 and state persisted by 0.1.x no longer deserializes. Elsa persists the library's BpmnExecutionState into workflow state, so an in-flight BPMN instance does not survive this bump. Neither module has ever been published, so no released consumer can be holding such state -- which is why this is the moment to take the break. BpmnRuntimeCapabilitiesTests stays green: 0.2.0 defines no capability flag Elsa does not already declare. The new cancel-end-event requirement is SubtreeCancellation, which BpmnRuntimeCapabilities.Declared already carries. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1b38c3511d
commit
b24beadca9
|
|
@ -98,9 +98,9 @@
|
|||
<PackageVersion Include="Azure.ResourceManager.ServiceBus" Version="1.1.0"/>
|
||||
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8"/>
|
||||
<PackageVersion Include="Bogus" Version="35.6.5"/>
|
||||
<PackageVersion Include="Bpmn.Interchange" Version="0.1.1-preview.19"/>
|
||||
<PackageVersion Include="Bpmn.Model" Version="0.1.1-preview.19"/>
|
||||
<PackageVersion Include="Bpmn.Semantics" Version="0.1.1-preview.19"/>
|
||||
<PackageVersion Include="Bpmn.Interchange" Version="0.2.0"/>
|
||||
<PackageVersion Include="Bpmn.Model" Version="0.2.0"/>
|
||||
<PackageVersion Include="Bpmn.Semantics" Version="0.2.0"/>
|
||||
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" PrivateAssets="All"/>
|
||||
<PackageVersion Include="ConsoleLogStreaming.Contracts" Version="1.1.0"/>
|
||||
<PackageVersion Include="ConsoleLogStreaming.Core" Version="1.1.0"/>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<add key="NuGet official package source" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="cshells-feedz" value="https://f.feedz.io/sfmskywalker/cshells/nuget/index.json" />
|
||||
<add key="elsa-preview-feedz" value="https://f.feedz.io/elsa-workflows/elsa-3/nuget/index.json" />
|
||||
<add key="bpmn-feedz" value="https://f.feedz.io/valence-works/bpmn/nuget/index.json" />
|
||||
<add key="valence-loom-feedz" value="https://f.feedz.io/valence-works/loom/nuget/index.json" />
|
||||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
|
|
@ -23,9 +22,6 @@
|
|||
<package pattern="Elsa.Platform.PackageManifest.Generator" />
|
||||
<package pattern="Elsa.Platform.PackageManifest" />
|
||||
</packageSource>
|
||||
<packageSource key="bpmn-feedz">
|
||||
<package pattern="Bpmn.*" />
|
||||
</packageSource>
|
||||
<packageSource key="valence-loom-feedz">
|
||||
<package pattern="Loom" />
|
||||
<package pattern="Loom.*" />
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
Provides BPMN XML interchange support by wiring the Bpmn.Interchange library into Elsa.
|
||||
</Description>
|
||||
<PackageTags>elsa extension module bpmn interchange</PackageTags>
|
||||
<!-- Not packable until the Bpmn.* packages are published to nuget.org; they currently live only on the valence-works/bpmn feedz feed, so a published Elsa.Bpmn.Interchange would fail to restore for consumers. -->
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
Provides BPMN execution support by wiring the Bpmn.Model and Bpmn.Semantics libraries into Elsa.
|
||||
</Description>
|
||||
<PackageTags>elsa extension module bpmn</PackageTags>
|
||||
<!-- Not packable until the Bpmn.* packages are published to nuget.org; they currently live only on the valence-works/bpmn feedz feed, so a published Elsa.Bpmn would fail to restore for consumers. -->
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -88,23 +88,34 @@ public class BpmnCompensationTests(ITestOutputHelper testOutputHelper)
|
|||
// Act: the other branch cancels the transaction, which stops the replay's coordinating token.
|
||||
await _host.FinishWorkAsync("fraudCheck");
|
||||
|
||||
// Assert: the released entries are registered again, so the cancellation's own replay claims them -- the head
|
||||
// handler starting a second time is both the first half of the release being real *and* the symptom of
|
||||
// valence-works/bpmn#13: BpmnInterpreter.CancelTransaction drops the live work it is abandoning without ever
|
||||
// producing a PendingTeardown/CancelWorkSubtree command for it, so the host's original ledger record and
|
||||
// bookmark for the releaseSeat slot survive untouched alongside the replay's freshly started one. The scope
|
||||
// now holds two live records for the same (BindingRef, IterationId) slot -- pinned below so this fails the
|
||||
// moment the library fix lands, at which point both counts become 1. Filed from here as #7959, closed as
|
||||
// routed upstream; the applier is deliberately unpatched so this stays visible rather than worked around.
|
||||
// Assert: the released entries are registered again, so the cancellation's own replay claims them, and the head
|
||||
// handler starts a second time -- the first half of the release being real.
|
||||
//
|
||||
// The flip may not be mechanical. Upstream is choosing between tearing down only the compensation handler it
|
||||
// re-starts and tearing down every abandoned token; the second also cancels transaction branches still in
|
||||
// flight, which can move other scenarios in this suite. Check which shipped when the Bpmn.Semantics pin moves.
|
||||
// The second start is a *replacement*, not a duplicate, and that is what valence-works/bpmn#13 fixed in
|
||||
// Bpmn.Semantics 0.2.0. CancelTransaction used to abandon the live work it was superseding without issuing a
|
||||
// CancelWorkSubtree for it, so the host's original ledger record and bookmark for the releaseSeat slot
|
||||
// survived alongside the replay's freshly started one -- two live records for one (BindingRef, IterationId)
|
||||
// slot, which BpmnHostSnapshot documents as a host obligation never to allow, and which the interpreter's own
|
||||
// BuildLiveWorkHandles then collapses last-wins. Upstream took the wide fix: every token a cancelled
|
||||
// transaction abandons now gets a real teardown, not just the compensation handler being re-started.
|
||||
//
|
||||
// So all three of these are the fix, and each fails differently if it regresses: the handler runs twice
|
||||
// (release), the first run is torn down (teardown), and the slot is left holding exactly one record
|
||||
// (the invariant).
|
||||
Assert.Equal(2, _host.Log.Occurrences("executed:releaseSeat"));
|
||||
Assert.Contains("cancelled:releaseSeat", _host.Log.Entries);
|
||||
|
||||
var releaseSeatBindingRef = BpmnTestProcesses.BindingRef("releaseSeat");
|
||||
var releaseSeatLiveRecords = _host.LiveWorkOf("sub").Count(record => record.BindingRef == releaseSeatBindingRef);
|
||||
Assert.Equal(2, releaseSeatLiveRecords);
|
||||
Assert.Equal(1, releaseSeatLiveRecords);
|
||||
|
||||
// And the invariant holds at the moment that matters, not just once the dust settles. 0.2.0 states the
|
||||
// at-most-one-live-unit-per-slot rule as holding after a command batch is applied in full and in order,
|
||||
// because an interrupting path may emit the replacement StartWork ahead of the CancelWorkSubtree it
|
||||
// supersedes. This snapshot is taken inside the replacement's own execution -- overwritten on each start, so
|
||||
// it is the second one -- and a host that applied the batch out of order, or keyed its ledger by slot rather
|
||||
// than by handle, would be holding two records here even though the count above settles at one.
|
||||
Assert.Equal([releaseSeatBindingRef], _host.Log.Snapshot("liveWork@releaseSeat"));
|
||||
|
||||
// And the entry that was claimed but never ran is reached once that head handler finishes: the other half.
|
||||
var result = await _host.FinishWorkAsync("releaseSeat");
|
||||
|
|
|
|||
Loading…
Reference in a new issue