fix(domain): correlate withdrawal by process instance to the subscribed execution (refs #12)
All checks were successful
CI / lint (pull_request) Successful in 1m15s
CI / build (pull_request) Successful in 1m1s
CI / unit (pull_request) Successful in 1m20s
CI / frontend (pull_request) Successful in 2m50s
CI / mutation (pull_request) Successful in 5m22s
CI / verify-stack (pull_request) Successful in 7m18s

verify-stack surfaced a Flowable 500: delivering messageEventReceived to the Beoordelen task's

execution is wrong — a message boundary event's subscription lives on its own execution. Correlate

instead by the registration's process instance id (recorded at submit): query the execution

subscribed to RegistratieIngetrokken and deliver the message there. Withdrawal moves from

IUserTaskClient to IWorkflowClient.WithdrawProcessAsync; the handler no longer needs a task lookup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-16 12:13:47 +02:00
parent 66af21853f
commit ddfdedc302
10 changed files with 144 additions and 97 deletions

View File

@@ -15,6 +15,14 @@ public interface IWorkflowClient
/// aggregate. Returns the process instance id.
/// </summary>
Task<string> StartRegistrationProcessAsync(RegistrationId registrationId, CancellationToken ct = default);
/// <summary>
/// Cancel a running <c>registratie</c> process on withdrawal (S-11): correlate the
/// <c>RegistratieIngetrokken</c> message to the instance, tripping the interrupting message event
/// that ends it (ADR-0014). Best-effort — if the instance is not waiting on that message (already
/// ended, or not yet parked) it is a no-op; the aggregate is INGETROKKEN regardless.
/// </summary>
Task WithdrawProcessAsync(string processInstanceId, CancellationToken ct = default);
}
/// <summary>
@@ -54,18 +62,11 @@ public interface IUserTaskClient
/// <summary>Complete a beoordeling task, carrying the decision into the process as the
/// <c>besluit</c> variable so the workflow can continue on the chosen branch.</summary>
Task CompleteBeoordelingAsync(string taskId, BeoordelingsBesluit besluit, CancellationToken ct = default);
/// <summary>Deliver the withdrawal message to a <c>Beoordelen</c> task's execution, tripping the
/// process's interrupting message boundary event so the registratie process cancels (S-11,
/// ADR-0014). The registration itself is already INGETROKKEN in the domain; this ends its
/// workflow so the case leaves the werkbak.</summary>
Task WithdrawBeoordelingAsync(string executionId, CancellationToken ct = default);
}
/// <summary>A <c>Beoordelen</c> user task in the werkbak: the Flowable task id (needed to claim and
/// complete it), the execution it runs in (needed to deliver the withdrawal message to its boundary
/// event), and the registration it carries as a process variable.</summary>
public sealed record BeoordelingTask(string TaskId, string ExecutionId, RegistrationId RegistrationId);
/// complete it) and the registration it carries as a process variable.</summary>
public sealed record BeoordelingTask(string TaskId, RegistrationId RegistrationId);
/// <summary>
/// Persistence port for the <see cref="Registration"/> aggregate. In-memory for the minimal slice