Skip to Content
Client LibrariesDotnetExternal TasksExternal Tasks

External Tasks

External Tasks sind der primäre Mechanismus, um externe Geschäftslogik an BPMN-Prozesse in der ProcessCube® Engine anzubinden. Ein External Task repräsentiert eine Aufgabe im Prozess, die von einem externen Worker abgearbeitet wird.

Architektur

Konzepte

Fetch-and-Lock-Muster

Der Worker pollt die Engine per Long Polling: Er sendet eine Anfrage an /fetch_and_lock, die von der Engine gehalten wird, bis entweder Tasks verfügbar sind oder der Timeout (Standard: 60 Sekunden) erreicht ist. Dadurch wird ein quasi-echtzeitnahes Verhalten ohne hohe Last auf der Engine erreicht.

Beim Fetch werden die Tasks sofort für den Worker gesperrt (Standard: 30 Sekunden). Nur der Worker mit der passenden WorkerId kann den Task abschließen oder den Lock verlängern.

Kapazitätssteuerung

Der Worker holt nur so viele Tasks, wie er gleichzeitig verarbeiten kann:

MaxTasksToFetch = MaxParallelWorkerCount - AktuelleTasksInBearbeitung

Wenn alle Slots belegt sind, pausiert der Fetch-Zyklus, bis Kapazität frei wird.

Lock-Management

Der LockScheduler läuft als Hintergrund-Task und überwacht alle aktiven Locks:

  1. Prüft jede Sekunde, ob ein Lock in weniger als 5 Sekunden abläuft
  2. Verlängert den Lock rechtzeitig per PUT /extend_lock
  3. Falls ein Lock bereits abgelaufen ist, wird der Task abgebrochen
  4. Handler-Ausführung und Lock-Erneuerung laufen als Race (Task.WhenAny) — wer zuerst fertig ist, bestimmt das Ergebnis

Exponential Backoff

Bei Fetch-Fehlern (z.B. Engine nicht erreichbar) greift ein exponentieller Backoff:

Wartezeit = 2^Fehleranzahl + Zufallsoffset (30-300ms)

Die Sequenz ist: 2s → 4s → 8s → 16s → 30s (Maximum, konfigurierbar). Bei erfolgreichem Fetch wird der Zähler zurückgesetzt.

ExternalTask-Datenmodell

public class ExternalTask { public string Id { get; set; } // Eindeutige Task-ID public string WorkerId { get; set; } // ID des zugewiesenen Workers public string Topic { get; set; } // Topic-Name (z.B. "BestellungVerarbeiten") public string FlowNodeInstanceId { get; set; } // Zugehöriger Flow-Node public string CorrelationId { get; set; } // Korrelations-ID der Prozessinstanz public string ProcessModelId { get; set; } // Prozessmodell-ID public string ProcessInstanceId { get; set; } // Prozessinstanz-ID public IIdentityReference Identity { get; set; } // Identität des Prozessstarters public IPayloadAccessor Payload { get; set; } // Typisierter Zugriff auf den Payload public DateTime? LockExpirationTime { get; set; }// Ablaufzeit des Locks public DateTime CreatedAt { get; set; } // Erstellungszeitpunkt }

Handler-Aufrufstrategien

StrategieVerwendung
UseHandlerMethod (async)Einfache Fälle, Logik direkt als Lambda
UseHandlerMethod (sync)Synchrone Verarbeitung ohne async/await
UseHandlerFactoryNeue Handler-Instanz pro Task via Factory
UseHandlerActivatorEigener Aktivierungsmechanismus (z.B. Custom DI)
DI-basiert (Hosting)Automatisch über [ExternalTaskHandler] + DI-Container

Weiterführende Seiten