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

@@ -11,12 +11,19 @@ public sealed class InMemoryWorkflowClient : IWorkflowClient
public const string StartedProcessInstanceId = "proc-acc-1";
public RegistrationId? StartedFor { get; private set; }
public string? WithdrawnProcessInstanceId { get; private set; }
public Task<string> StartRegistrationProcessAsync(RegistrationId registrationId, CancellationToken ct = default)
{
StartedFor = registrationId;
return Task.FromResult(StartedProcessInstanceId);
}
public Task WithdrawProcessAsync(string processInstanceId, CancellationToken ct = default)
{
WithdrawnProcessInstanceId = processInstanceId;
return Task.CompletedTask;
}
}
/// <summary>An in-memory ACL stand-in: records the bsn it opened a zaak for and returns a fixed URL,
@@ -50,10 +57,8 @@ public sealed class InMemoryUserTaskClient : IUserTaskClient
private readonly List<BeoordelingTask> _open = [];
public (string TaskId, BeoordelingsBesluit Besluit)? Completed { get; private set; }
public string? WithdrawnExecutionId { get; private set; }
public void Open(RegistrationId registrationId) =>
_open.Add(new BeoordelingTask($"task-{registrationId}", $"exec-{registrationId}", registrationId));
public void Open(RegistrationId registrationId) => _open.Add(new BeoordelingTask($"task-{registrationId}", registrationId));
public Task<IReadOnlyList<BeoordelingTask>> GetOpenBeoordelingenAsync(CancellationToken ct = default)
=> Task.FromResult<IReadOnlyList<BeoordelingTask>>(_open);
@@ -66,13 +71,6 @@ public sealed class InMemoryUserTaskClient : IUserTaskClient
_open.RemoveAll(t => t.TaskId == taskId);
return Task.CompletedTask;
}
public Task WithdrawBeoordelingAsync(string executionId, CancellationToken ct = default)
{
WithdrawnExecutionId = executionId;
_open.RemoveAll(t => t.ExecutionId == executionId);
return Task.CompletedTask;
}
}
/// <summary>An in-memory registration store for the domain acceptance scenario.</summary>