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
- Prozess starten - Prozesse initiieren
- Prozess-Instanzen abfragen - Signal-Empfänger finden
- Prozess-Verwaltung - Zurück zur Übersicht