Skip to Content
AppSDKExternal TasksErweiterte Konzepte

Erweiterte Konzepte

Dieses Kapitel behandelt fortgeschrittene Features des External-Task-Systems im App-SDK.

AbortSignal

Der dritte Parameter der Handler-Funktion ist ein AbortSignal. Dieses Signal wird ausgelöst, wenn ein Boundary Event den External Service Task im Prozess abbricht — beispielsweise ein Timer-Boundary-Event oder ein Signal-Boundary-Event.

Grundlegendes Beispiel

app/long_task/external_task.ts
export const config = { lockDuration: 5000, }; export default async function longTask( payload: any, _task: any, signal: AbortSignal ) { signal.addEventListener('abort', () => { console.log('Task abgebrochen — Aufräumarbeiten durchführen'); }, { once: true }); await langwierigeOperation(signal); if (signal.aborted) return; return { result: 'fertig' }; }

Delay mit AbortSignal

Ein häufiges Muster: eine Wartezeit, die bei Abbruch sofort beendet wird.

function delay(ms: number, signal?: AbortSignal) { return new Promise<void>((resolve, reject) => { if (signal?.aborted) { reject(new Error('Aborted')); return; } const timer = setTimeout(resolve, ms); signal?.addEventListener('abort', () => { clearTimeout(timer); reject(new Error('Aborted')); }, { once: true }); }); }

Zusammenhang mit lockDuration

Die lockDuration bestimmt, wie schnell ein Abbruch erkannt wird:

  • Die Engine prüft bei jeder Lock-Verlängerung, ob der Task noch aktiv ist
  • Eine niedrige lockDuration (z.B. 5000) ermöglicht schnelle Abbrüche
  • Eine hohe lockDuration (z.B. 300000) verzögert die Erkennung

Für Tasks mit Boundary Events empfiehlt sich eine lockDuration von 500010000 ms.

Resilienz

Das App-SDK bietet mehrere Mechanismen, um External Task Worker zuverlässig zu betreiben.

Automatischer Neustart

Wenn ein Worker-Prozess mit einem Fehler-Exit-Code beendet wird (Code 3: Worker-Fehler, Code 4: Uncaught Exception), wird er automatisch neu gestartet:

  • Exponential Backoff: Die Wartezeit verdoppelt sich mit jedem Versuch (1s → 2s → 4s → 8s → 16s → 30s)
  • Maximale Wartezeit: 30 Sekunden
  • Maximale Versuche: 6 Versuche innerhalb von 5 Minuten
  • Reset: Nach 5 Minuten ohne Fehler wird der Zähler zurückgesetzt

Verbindungsfehler

Bei Verbindungsfehlern zur Engine (ECONNREFUSED, ECONNRESET, ETIMEDOUT) startet der Worker-Prozess intern einen eigenen Reconnect-Zyklus:

  • Bis zu 6 Versuche (konfigurierbar über PROCESSCUBE_APP_SDK_ETW_RETRY)
  • Exponential Backoff bis maximal 30 Sekunden
  • Kein Prozess-Neustart nötig — der Worker versucht sich selbst zu reconnecten

Token-Refresh

Bei aktiver Authority-Integration wird das Access-Token automatisch vor Ablauf erneuert:

  • Refresh erfolgt bei 85% der Token-Laufzeit
  • Bei Fehlern: bis zu 10 Versuche mit Exponential Backoff (max. 60s)
  • Aktualisierte Tokens werden an alle laufenden Worker-Prozesse verteilt

Hot Reload

Das App-SDK überwacht das App-Verzeichnis mit Chokidar . Änderungen an external_task.ts-Dateien werden automatisch erkannt:

EreignisAktion
Datei hinzugefügtNeuer Worker wird gestartet
Datei geändertWorker wird mit neuem Code neu gestartet (Worker-ID bleibt erhalten)
Datei gelöschtWorker wird gestoppt

Beim Neustart durch Code-Änderungen bleibt die Worker-ID erhalten. Laufende Tasks werden sauber beendet, bevor der neue Code aktiviert wird.

Route Groups

Next.js Route Groups  (Verzeichnisse in runden Klammern) werden aus dem Topic entfernt:

DateipfadTopic
app/(workers)/send_email/external_task.tssend_email
app/(email)/filter/external_task.tsfilter
app/(group1)/(group2)/task/external_task.tstask

So können External Tasks organisiert werden, ohne das Topic zu beeinflussen:

app/ ├── (email-workers)/ │ ├── filter_email/ │ │ └── external_task.ts → Topic: filter_email │ ├── forward_email/ │ │ └── external_task.ts → Topic: forward_email │ └── delete_email/ │ └── external_task.ts → Topic: delete_email ├── (order-workers)/ │ └── process_order/ │ └── external_task.ts → Topic: process_order └── dashboard/ └── page.tsx → Route: /dashboard

Transpilation

External Task Dateien werden automatisch mit esbuild  transpiliert, bevor sie als Worker-Prozess gestartet werden:

  • Plattform: Node.js
  • Target: node18
  • Format: CommonJS
  • Bundling: Aktiviert (Dependencies werden eingebunden)
  • Externe Pakete: @opentelemetry/api wird nicht gebündelt

Das bedeutet: TypeScript, moderne ES-Syntax und Imports von npm-Paketen funktionieren direkt, ohne zusätzliche Build-Konfiguration.