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
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 5000–10000 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:
| Ereignis | Aktion |
|---|---|
| Datei hinzugefügt | Neuer Worker wird gestartet |
| Datei geändert | Worker wird mit neuem Code neu gestartet (Worker-ID bleibt erhalten) |
| Datei gelöscht | Worker 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:
| Dateipfad | Topic |
|---|---|
app/(workers)/send_email/external_task.ts | send_email |
app/(email)/filter/external_task.ts | filter |
app/(group1)/(group2)/task/external_task.ts | task |
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: /dashboardTranspilation
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/apiwird nicht gebündelt
Das bedeutet: TypeScript, moderne ES-Syntax und Imports von npm-Paketen funktionieren direkt, ohne zusätzliche Build-Konfiguration.