Skip to Content
DocsClientsDotnetSignals & Events

Signals & Events

Der EventClient ermöglicht das Auslösen von BPMN Signals und Messages, um Prozesse zu starten oder fortzusetzen.

Client erstellen

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateEventClient(engineAddress);

Signals

TriggerSignalAsync()

Löst ein Signal aus, das von allen wartenden Prozessen empfangen wird:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateEventClient(engineAddress); // Signal ohne Payload await client.TriggerSignalAsync("OrderReceived"); Console.WriteLine("Signal 'OrderReceived' gesendet");

Signal mit Payload

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateEventClient(engineAddress); // Signal mit Payload var payload = new OrderSignalPayload( OrderId: "ORD-12345", Priority: "High" ); await client.TriggerSignalAsync( signalName: "OrderReceived", payload: payload ); Console.WriteLine($"Signal mit Order-ID {payload.OrderId} gesendet"); internal sealed record OrderSignalPayload(string OrderId, string Priority);

Signals sind Broadcast-Events. Alle Prozesse, die auf dieses Signal warten, werden benachrichtigt.

Messages

TriggerMessageAsync()

Löst eine Message aus, die an eine spezifische Prozess-Instanz gerichtet ist:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateEventClient(engineAddress); var correlationId = "ORDER-2025-001"; // Message mit Correlation-ID var payload = new PaymentConfirmationPayload( PaymentId: "PAY-789", Amount: 1500.00m, Status: "Confirmed" ); await client.TriggerMessageAsync( messageName: "PaymentConfirmed", correlationId: correlationId, payload: payload ); Console.WriteLine($"Message an Correlation '{correlationId}' gesendet"); internal sealed record PaymentConfirmationPayload( string PaymentId, decimal Amount, string Status );

Messages benötigen eine Correlation-ID, um die richtige Prozess-Instanz zu finden.

Signal Start Event

Prozess mit Signal Start Event starten:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var eventClient = ClientFactory.CreateEventClient(engineAddress); var instanceClient = ClientFactory.CreateProcessInstancesClient(engineAddress); // Signal senden var payload = new DataReadyPayload( DataSource: "ImportJob", RecordCount: 1000 ); await eventClient.TriggerSignalAsync("DataReady", payload); Console.WriteLine("Signal gesendet"); // Warten... await Task.Delay(2000); // Prüfen ob Prozess gestartet wurde var instances = await instanceClient.QueryAsync(query => { query.FilterByProcessModelId("DataProcessingFlow"); query.FilterByState(ProcessState.Running); }); Console.WriteLine($"Gestartete Prozesse: {instances.Count}"); internal sealed record DataReadyPayload(string DataSource, int RecordCount);

Intermediate Catch Event

Signal an wartenden Prozess senden:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var definitionsClient = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var eventClient = ClientFactory.CreateEventClient(engineAddress); // 1. Prozess starten (der auf Signal wartet) var response = await definitionsClient.StartProcessInstanceAsync( processModelId: "ApprovalProcess", startEventId: "StartEvent_1", initialToken: new { requestId = "REQ-456" } ); Console.WriteLine($"Prozess gestartet: {response.ProcessInstanceId}"); // 2. Warten bis Prozess auf Signal wartet await Task.Delay(3000); // 3. Signal senden um Prozess fortzusetzen var approvalPayload = new ApprovalSignalPayload( Decision: "Approved", ApprovedBy: "manager@company.com" ); await eventClient.TriggerSignalAsync("ApprovalDecision", approvalPayload); Console.WriteLine("Approval-Signal gesendet"); internal sealed record ApprovalSignalPayload(string Decision, string ApprovedBy);

Message Intermediate Catch Event

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var definitionsClient = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var eventClient = ClientFactory.CreateEventClient(engineAddress); // Correlation-ID festlegen var correlationId = $"ORDER-{Guid.NewGuid()}"; // 1. Prozess mit Correlation-ID starten var response = await definitionsClient.StartProcessInstanceAsync( processModelId: "OrderFulfillment", startEventId: "StartEvent_1", initialToken: new { orderId = "ORD-789" }, correlationId: correlationId ); Console.WriteLine($"Prozess gestartet mit Correlation: {correlationId}"); // 2. Warten bis Prozess auf Message wartet await Task.Delay(3000); // 3. Message an spezifische Prozess-Instanz senden var shippingPayload = new ShippingUpdatePayload( TrackingNumber: "TRACK-123456", Carrier: "DHL", EstimatedDelivery: DateTime.Now.AddDays(3) ); await eventClient.TriggerMessageAsync( messageName: "ShippingUpdate", correlationId: correlationId, payload: shippingPayload ); Console.WriteLine("Shipping-Message gesendet"); internal sealed record ShippingUpdatePayload( string TrackingNumber, string Carrier, DateTime EstimatedDelivery );

Mit Authentifizierung

using ProcessCube.Engine; using ProcessCube.Engine.Client.Identity; var identityProvider = new ClientCredentialsIdentityProvider( authorityAddress: "http://localhost:11235", clientId: "event-service", clientSecret: "secret-key", scope: "engine_write" ); var identity = await identityProvider.GetIdentityAsync(); var client = ClientFactory.CreateEventClient( engineAddress: "http://localhost:8000", identity: identity ); await client.TriggerSignalAsync("DataReady"); Console.WriteLine("Authenticated signal sent");

Event-Handler Pattern

public class ProcessEventService { private readonly IEventClient _eventClient; private readonly IProcessInstancesClient _instanceClient; public ProcessEventService( IEventClient eventClient, IProcessInstancesClient instanceClient) { _eventClient = eventClient; _instanceClient = instanceClient; } public async Task HandleOrderReceivedAsync(OrderReceivedEvent orderEvent) { // Signal senden var payload = new OrderSignalPayload( orderEvent.OrderId, orderEvent.CustomerName, orderEvent.TotalAmount ); await _eventClient.TriggerSignalAsync("OrderReceived", payload); // Warten auf Prozess-Start await Task.Delay(1000); // Prozess suchen var instances = await _instanceClient.QueryAsync(query => { query.FilterByCorrelationId(orderEvent.OrderId); }); if (instances.Any()) { Console.WriteLine($"Order-Prozess gestartet für {orderEvent.OrderId}"); } } } public record OrderReceivedEvent( string OrderId, string CustomerName, decimal TotalAmount ); internal sealed record OrderSignalPayload( string OrderId, string CustomerName, decimal TotalAmount );

Fehlerbehandlung

using ProcessCube.Engine; using ProcessCube.Engine.Client.Exceptions; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateEventClient(engineAddress); try { await client.TriggerSignalAsync("DataReady", new { status = "ready" }); Console.WriteLine("Signal erfolgreich gesendet"); } catch (EngineClientException ex) when (ex.StatusCode == 404) { Console.WriteLine("Signal-Definition nicht gefunden"); } catch (EngineClientException ex) when (ex.StatusCode == 401) { Console.WriteLine("Nicht authentifiziert"); } catch (HttpRequestException ex) { Console.WriteLine($"Verbindungsfehler: {ex.Message}"); }

Best Practice: Verwenden Sie Signals für Broadcast-Benachrichtigungen und Messages für gezielte Kommunikation mit spezifischen Prozess-Instanzen.

Nächste Schritte