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.

Lebenszyklus eines External Tasks

Worker-Startup und IPC-Kommunikation

Das App SDK startet pro external_task.ts-Datei einen eigenen Node.js-Kindprozess. Die Kommunikation zwischen Hauptprozess (Adapter) und Kindprozess (Worker) laeuft ueber IPC:

IPC-Nachrichten:

ActionRichtungBeschreibung
createAdapter → WorkerInitialer Start: Übergibt Topic, Identity und transpilierten Handler-Code
restartAdapter → WorkerHot-Reload: Stoppt den alten Worker und startet mit neuem Code (gleiche Worker-ID)
updateIdentityAdapter → WorkerAktualisiert den Auth-Token auf dem laufenden Worker

Resilienz

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

Fehlerbehandlung und Restart-Strategie

Worker-Level (Kindprozess)

  • Bei Verbindungsfehlern (ECONNREFUSED, ECONNRESET, ETIMEDOUT, ENOTFOUND, EAI_AGAIN, Socket Hang Up) versucht der Worker bis zu 6 Reconnects mit exponentiellem Backoff (1s → 2s → 4s → 8s → 16s → 30s max).
  • Die Anzahl der Retries ist über die Umgebungsvariable PROCESSCUBE_APP_SDK_ETW_RETRY konfigurierbar.
  • Nach Ausschöpfung der Retries beendet sich der Worker mit Exit Code 3.
  • Bei unbehandelten Exceptions beendet sich der Worker mit Exit Code 4.

Adapter-Level (Hauptprozess)

  • Erkennt der Adapter einen Worker-Exit mit Code 3 oder 4, wird ein Neustart versucht.
  • Maximal 6 Neustarts innerhalb eines 5-Minuten-Fensters sind erlaubt.
  • Die Backoff-Zeiten steigen exponentiell: 1s → 2s → 4s → 8s → 16s → 30s.
  • Wird das Limit erreicht, bleibt der Worker gestoppt — ein manueller Eingriff (z.B. App-Neustart) ist nötig.
  • Nach Ablauf des 5-Minuten-Fensters wird der Zähler zurückgesetzt.

Token-Management

  • Der Token wird bei 85% seiner Lebensdauer automatisch erneuert.
  • Alle aktiven Worker erhalten den neuen Token per IPC-Nachricht.
  • Der initiale Token-Abruf hat 10 Versuche mit exponentiellem Backoff (max. 30s).
  • Der periodische Token-Refresh versucht es unbegrenzt mit Backoff (max. 60s).
  • Ist keine Authority konfiguriert, wird eine Dummy-Identity verwendet (für lokale Entwicklung ohne Auth).

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.