Summary
Ensures context flows correctly down through nested execution boundaries and back up via explicit return-path tracking. Introduces CompletionTracker — a unified service that eliminates duplicate fan-in logic across SubCase, MultiInstance WorkItem, Plan step, and FlowWorker step completion.
Consolidation — CompletionTracker
Every spawning completion currently reimplements the same logic: find the spawn record by child ID, check whether the group policy is satisfied, route output to the returnTo target. CompletionTracker unifies this:
interface CompletionTracker {
// Called at spawn time by every spawning operation
SpawnHandle track(UUID parentLedgerEntryId,
List<UUID> childIds,
CompletionPolicy policy,
Object returnTo);
// Called at every completion event
Optional<GroupResult> recordCompletion(UUID childId, Map<String, Object> output);
// Returns non-empty when policy satisfied — caller routes GroupResult.output to returnTo
}
enum CompletionPolicy { ALL, M_OF_N, FIRST, ANY }
SubCaseCompletionListener, MultiInstanceCoordinator (quarkus-work), PlanStepHandler, and WorkflowStepCompletion all register with CompletionTracker at spawn time. At completion they call recordCompletion(). The tracker fires when the policy is satisfied.
This also eliminates the EventLog scan at completion time — the tracker holds returnTo directly, so completion listeners no longer need to query EventLog to find the parent. The findByWorkerAndType workaround (#195 fix) is structurally superseded.
Return-path tracking
SpawnHandle returned by track() carries: spawnId, returnTo, policy, groupSize
- Completion routes to the enclosing context (WorkflowContext if inside FlowWorker), not root CaseContext
returnTo is recorded at spawn time; never inferred at completion time
Context stack
- Runtime tracking of active context frames per case execution
- Each
ContextBridge.initialise() pushes a frame; complete() pops it
- Stack is used by CompletionTracker to resolve
returnTo references at completion
Write-through (optional per bridge)
ContextBridge.onWrite() — called when a key is written to the bridged context
- Bridges opt in to immediate EventLog entries for significant intermediate state
- Default: no write-through (current behaviour)
quarkus-work multi-instance
Part of
#201
Summary
Ensures context flows correctly down through nested execution boundaries and back up via explicit return-path tracking. Introduces
CompletionTracker— a unified service that eliminates duplicate fan-in logic across SubCase, MultiInstance WorkItem, Plan step, and FlowWorker step completion.Consolidation — CompletionTracker
Every spawning completion currently reimplements the same logic: find the spawn record by child ID, check whether the group policy is satisfied, route output to the returnTo target.
CompletionTrackerunifies this:SubCaseCompletionListener,MultiInstanceCoordinator(quarkus-work),PlanStepHandler, andWorkflowStepCompletionall register withCompletionTrackerat spawn time. At completion they callrecordCompletion(). The tracker fires when the policy is satisfied.This also eliminates the EventLog scan at completion time — the tracker holds
returnTodirectly, so completion listeners no longer need to query EventLog to find the parent. ThefindByWorkerAndTypeworkaround (#195 fix) is structurally superseded.Return-path tracking
SpawnHandlereturned bytrack()carries:spawnId,returnTo,policy,groupSizereturnTois recorded at spawn time; never inferred at completion timeContext stack
ContextBridge.initialise()pushes a frame;complete()pops itreturnToreferences at completionWrite-through (optional per bridge)
ContextBridge.onWrite()— called when a key is written to the bridged contextquarkus-work multi-instance
MultiInstanceCoordinatorregisters each child WorkItem viaCompletionTracker.track(policy=M_OF_N)Part of
#201