Skip to Content
DocsClientsDotnetFlowNode Instances

FlowNode Instances

Der FlowNodeInstancesClient ermöglicht das Abfragen der Ausführungshistorie von BPMN-FlowNodes innerhalb einer Prozess-Instanz.

Was sind FlowNode Instances?

FlowNode Instances repräsentieren die Ausführung einzelner BPMN-Elemente (Tasks, Gateways, Events) in einem Prozess. Sie ermöglichen detaillierte Einblicke in den Prozessverlauf.

Client erstellen

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

QueryAsync()

Fragt FlowNode Instances mit Filtern ab:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateFlowNodeInstancesClient(engineAddress); var processInstanceId = "abc-123-def-456"; // Alle FlowNode Instances einer Prozess-Instanz abrufen var flowNodes = await client.QueryAsync(query => { query.FilterByProcessInstanceId(processInstanceId); }); Console.WriteLine($"Ausgeführte FlowNodes: {flowNodes.Count}"); foreach (var flowNode in flowNodes) { Console.WriteLine($" {flowNode.FlowNodeId}: {flowNode.State}"); Console.WriteLine($" Type: {flowNode.FlowNodeType}"); Console.WriteLine($" Started: {flowNode.CreatedAt:HH:mm:ss}"); if (flowNode.FinishedAt.HasValue) { var duration = flowNode.FinishedAt.Value - flowNode.CreatedAt; Console.WriteLine($" Duration: {duration.TotalSeconds:F2}s"); } }

Filter-Optionen

Nach ProcessInstanceId

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateFlowNodeInstancesClient(engineAddress); var flowNodes = await client.QueryAsync(query => { query.FilterByProcessInstanceId("abc-123"); }); Console.WriteLine($"FlowNodes in Prozess: {flowNodes.Count}");

Nach FlowNodeId

Alle Ausführungen eines bestimmten FlowNodes:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateFlowNodeInstancesClient(engineAddress); // Alle Ausführungen der "CheckInventory" Task var flowNodes = await client.QueryAsync(query => { query.FilterByFlowNodeId("Task_CheckInventory"); }); Console.WriteLine($"'CheckInventory' wurde {flowNodes.Count} mal ausgeführt"); // Durchschnittliche Ausführungszeit var completedNodes = flowNodes.Where(fn => fn.FinishedAt.HasValue); if (completedNodes.Any()) { var avgDuration = completedNodes .Average(fn => (fn.FinishedAt!.Value - fn.CreatedAt).TotalSeconds); Console.WriteLine($"Durchschnittliche Dauer: {avgDuration:F2}s"); }

Nach State

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateFlowNodeInstancesClient(engineAddress); var processInstanceId = "abc-123"; // Nur laufende FlowNodes var runningNodes = await client.QueryAsync(query => { query.FilterByProcessInstanceId(processInstanceId); query.FilterByState(FlowNodeState.Running); }); Console.WriteLine($"Aktuell laufende FlowNodes: {runningNodes.Count}");

FlowNodeInstance Properties

PropertyTypBeschreibung
IdstringEindeutige ID der FlowNode Instance
FlowNodeIdstringID des FlowNode aus dem BPMN
FlowNodeTypeFlowNodeTypeArt des FlowNode (Task, Gateway, etc.)
StateFlowNodeStateAktueller Status
ProcessInstanceIdstringZugehörige Prozess-Instanz
CreatedAtDateTimeStartzeitpunkt
FinishedAtDateTime?Endzeitpunkt (falls beendet)
TokensDictionary<TokenType, Token>Ein/Ausgabe-Tokens

FlowNodeType Enum

TypeBeschreibung
StartEventStart-Event
EndEventEnd-Event
IntermediateCatchEventIntermediate Catch Event
IntermediateThrowEventIntermediate Throw Event
TaskStandard-Task
ServiceTaskService-Task
UserTaskUser-Task
ManualTaskManual-Task
ScriptTaskScript-Task
CallActivityCall-Activity
SubProcessSubProcess
ExclusiveGatewayExclusive Gateway (XOR)
ParallelGatewayParallel Gateway (AND)
InclusiveGatewayInclusive Gateway (OR)
EventBasedGatewayEvent-Based Gateway

FlowNodeState Enum

StateBeschreibung
RunningFlowNode wird ausgeführt
SuspendedFlowNode wartet (z.B. User Task)
FinishedFlowNode erfolgreich beendet
ErrorFlowNode mit Fehler beendet
TerminatedFlowNode wurde abgebrochen

Prozess-Pfad nachvollziehen

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateFlowNodeInstancesClient(engineAddress); var processInstanceId = "abc-123"; // FlowNodes chronologisch sortiert abrufen var flowNodes = await client.QueryAsync(query => { query.FilterByProcessInstanceId(processInstanceId); }); var orderedFlowNodes = flowNodes .OrderBy(fn => fn.CreatedAt) .ToList(); Console.WriteLine("Prozess-Pfad:"); foreach (var flowNode in orderedFlowNodes) { var status = flowNode.State == FlowNodeState.Finished ? "✓" : "⟳"; var duration = flowNode.FinishedAt.HasValue ? $"({(flowNode.FinishedAt.Value - flowNode.CreatedAt).TotalSeconds:F1}s)" : "(läuft)"; Console.WriteLine($"{status} {flowNode.FlowNodeId} {duration}"); }

Die zeitliche Reihenfolge der FlowNode Instances zeigt den tatsächlichen Ausführungspfad durch das BPMN-Diagramm.

Token-Daten auslesen

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateFlowNodeInstancesClient(engineAddress); var processInstanceId = "abc-123"; var flowNodes = await client.QueryAsync(query => { query.FilterByProcessInstanceId(processInstanceId); query.FilterByFlowNodeId("Task_ProcessOrder"); }); var flowNode = flowNodes.FirstOrDefault(); if (flowNode != null && flowNode.Tokens.ContainsKey(TokenType.OnEnter)) { var onEnterToken = flowNode.Tokens[TokenType.OnEnter]; // Token-Payload deserialisieren var payload = onEnterToken.GetPayload<OrderData>(); Console.WriteLine($"Order-ID: {payload.OrderId}"); Console.WriteLine($"Amount: {payload.Amount}"); } internal sealed record OrderData(string OrderId, decimal Amount);

Performance-Analyse

using ProcessCube.Engine; public class ProcessPerformanceAnalyzer { private readonly IFlowNodeInstancesClient _client; public ProcessPerformanceAnalyzer(IFlowNodeInstancesClient client) { _client = client; } public async Task<PerformanceReport> AnalyzeProcessAsync(string processInstanceId) { var flowNodes = await _client.QueryAsync(query => { query.FilterByProcessInstanceId(processInstanceId); }); var report = new PerformanceReport { ProcessInstanceId = processInstanceId, TotalFlowNodes = flowNodes.Count }; // Prozess-Start und -Ende var startNode = flowNodes .Where(fn => fn.FlowNodeType == FlowNodeType.StartEvent) .OrderBy(fn => fn.CreatedAt) .FirstOrDefault(); var endNode = flowNodes .Where(fn => fn.FlowNodeType == FlowNodeType.EndEvent && fn.FinishedAt.HasValue) .OrderByDescending(fn => fn.FinishedAt) .FirstOrDefault(); if (startNode != null && endNode != null && endNode.FinishedAt.HasValue) { report.TotalDuration = endNode.FinishedAt.Value - startNode.CreatedAt; } // Längste Task finden var completedTasks = flowNodes .Where(fn => fn.FlowNodeType == FlowNodeType.Task || fn.FlowNodeType == FlowNodeType.ServiceTask || fn.FlowNodeType == FlowNodeType.UserTask) .Where(fn => fn.FinishedAt.HasValue) .Select(fn => new { fn.FlowNodeId, Duration = fn.FinishedAt!.Value - fn.CreatedAt }) .OrderByDescending(t => t.Duration) .ToList(); if (completedTasks.Any()) { var longestTask = completedTasks.First(); report.LongestTaskId = longestTask.FlowNodeId; report.LongestTaskDuration = longestTask.Duration; } return report; } } public class PerformanceReport { public string ProcessInstanceId { get; set; } public int TotalFlowNodes { get; set; } public TimeSpan TotalDuration { get; set; } public string? LongestTaskId { get; set; } public TimeSpan LongestTaskDuration { get; set; } }

Mit Authentifizierung

using ProcessCube.Engine; using ProcessCube.Engine.Client.Identity; var identityProvider = new ClientCredentialsIdentityProvider( authorityAddress: "http://localhost:11235", clientId: "monitoring-service", clientSecret: "secret-key", scope: "engine_read" ); var identity = await identityProvider.GetIdentityAsync(); var client = ClientFactory.CreateFlowNodeInstancesClient( engineAddress: "http://localhost:8000", identity: identity ); var flowNodes = await client.QueryAsync(query => { query.FilterByProcessInstanceId("abc-123"); }); Console.WriteLine($"FlowNodes: {flowNodes.Count}");

Fehlerbehandlung

using ProcessCube.Engine; using ProcessCube.Engine.Client.Exceptions; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateFlowNodeInstancesClient(engineAddress); try { var flowNodes = await client.QueryAsync(query => { query.FilterByProcessInstanceId("abc-123"); }); Console.WriteLine($"Gefunden: {flowNodes.Count} FlowNodes"); } catch (EngineClientException ex) when (ex.StatusCode == 404) { Console.WriteLine("Prozess-Instanz nicht gefunden"); } catch (EngineClientException ex) when (ex.StatusCode == 401) { Console.WriteLine("Nicht authentifiziert"); } catch (HttpRequestException ex) { Console.WriteLine($"Verbindungsfehler: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Fehler: {ex.Message}"); }

Verwendungszweck: FlowNode Instances eignen sich hervorragend für Prozess-Monitoring, Performance-Analyse und Debugging von Prozessausführungen.

Nächste Schritte