timeoutSeconds begrenzt (maximal 900 Sekunden). Alles, was in diesem Zeitfenster nicht abgeschlossen werden kann – ein vollständiger Re-Sync, ein Fan-out pro Datensatz, eine Drittanbieter-API, die dich rate-limitiert – muss in kleinere Läufe aufgeteilt werden.
enqueueJobs macht genau das: Es weist die Twenty-Worker an, eine der Logikfunktionen deiner App später, einmal pro Payload, jeweils in einem eigenen Prozess mit eigenem Timeout-Budget auszuführen. Der Aufrufer kehrt sofort zurück.
Läufe in die Warteschlange stellen
ImportiereenqueueJobs aus twenty-sdk/logic-function, gib den universalIdentifier der auszuführenden Logikfunktion an und übergib zum Einreihen eine Payload pro Lauf.
src/logic-functions/sync-all-contacts.ts
Logic function not found abgelehnt und nichts wird eingereiht. Ein einzelner Aufruf akzeptiert bis zu 200 Payloads.
enqueueJobs kehrt zurück, sobald die Jobs akzeptiert wurden, nicht erst, wenn sie ausgeführt wurden. Sie gibt nicht die Ergebnisse der Ziele zurück — lasse jedes Ziel das, was es erzeugt, in den Key-Value-Speicher oder in einen Workspace-Datensatz schreiben, wenn du es wieder auslesen musst.Der ältere Helper
enqueueJob, der pro Aufruf einen einzelnen Job einreiht, ist veraltet. Verwende stattdessen enqueueJobs mit einer payloads-Liste mit einem Element.Job-Optionen
Optionen gelten für jeden Lauf im Batch.Priorität ist noch nicht konfigurierbar. Eingereihte Jobs laufen immer mit der niedrigsten Priorität, sodass Plattformarbeit niemals hinter Applikationsjobs verzögert wird. Steuerung der Priorität kommt bald.
Wiederholen eines vorübergehenden Fehlers
Twenty wiederholt nicht jede Ausnahme aus dem Anwendungscode. Ein gewöhnlicher ausgelöster Fehler wird als dauerhafter Fehler behandelt. Bei einem vorübergehenden Fehler kann eine eingereihte Logikfunktion durch Auslösen vonRetryableLogicFunctionError bis zu drei Wiederholungen anfordern.
RetryableLogicFunctionError nach Möglichkeit direkt aus. Wenn du sie erweiterst, ersetze ihren name nicht: Twenty erkennt den serialisierten Namen RetryableLogicFunctionError in allen Laufzeitumgebungen.
retryCount ist bei der initialen Ausführung 0 und erhöht sich nur, wenn der Anwendungscode eine Wiederholung anfordert. maxRetries beträgt höchstens 3 und kann geringer sein, wenn der Job in der Warteschlange ein niedrigeres Gesamtlimit für Wiederholungen hat. Plattformfehler erhöhen retryCount nicht, verbrauchen jedoch weiterhin das Gesamtsicherheitsbudget der Warteschlange.
Die Warteschlange verzögert Wiederholungsversuche mit exponentiellem Backoff und Jitter. Die genaue Verzögerung wird absichtlich nicht garantiert, daher sollte der Anwendungscode nicht davon abhängen, dass eine Wiederholung zu einem genauen Zeitpunkt erfolgt. Sobald maxRetries erreicht ist, wird ein weiterer RetryableLogicFunctionError ohne weitere Ausführung als endgültiger Anwendungsfehler erfasst.
Verwendung: eine lange Synchronisation seitenweise verarbeiten
Die klassische Form ist eine Funktion, die sich selbst mit dem nächsten Cursor in die Warteschlange stellt. Jeder Lauf erledigt eine Seite Arbeit deutlich innerhalb seines eigenen Timeouts, und die Kette endet, wenn nichts mehr übrig ist.src/logic-functions/sync-contacts-page.ts
Aufteilung pro Datensatz
Wenn die Arbeit natürlich pro Element anfällt, reihe in einem einzigen Aufruf einen Job pro Element ein und lasse die Worker sie parallel verarbeiten, anstatt inline zu iterieren.Bewährte Vorgehensweisen für langlaufende Arbeit
Zwei Regeln decken fast jeden langen Job ab: rekursiv statt in einer Schleife arbeiten und pro Lauf einen begrenzten Chunk verarbeiten. Ein Lauf, der versucht, alles zu erledigen, ist der Fehlerfall — er erreicht das Timeout, und bei einem Retry startet er den gesamten Vorgang erneut von vorn. Bestimme stattdessen die Größe eines Chunks so, dass er bequem innerhalb vontimeoutSeconds fertig wird, speichere deine Position und reihe den nächsten Lauf ein.
src/logic-functions/enrich-companies-batch.ts
- Lege die Chunk-Größe anhand des langsamsten Elements fest, nicht anhand des Durchschnitts.
CHUNK_SIZE × Worst-Case-Elementzeitmuss mit ausreichendem Puffer intimeoutSecondspassen, sonst geht das Ende eines Chunks verloren, wenn der Lauf abgeschnitten wird. - Mache die Abbruchbedingung explizit. Rekursiere nur, solange ein voller Chunk zurückgekommen ist. Eine Kette, die nur bei „keine Ergebnisse“ anhält, läuft für immer weiter, wenn die Quelle unterwegs einmal eine verkürzte Seite zurückgibt.
- Persistiere den Fortschritt, bevor du den nächsten Lauf einreihst, damit ein fehlgeschlagener Link beim letzten abgeschlossenen Chunk und nicht am Anfang neu startet.
- Halte jeden Chunk idempotent. Die erneute Verarbeitung eines Chunks nach einem Retry darf nicht zu doppelten Schreibvorgängen führen — führe Schlüsselschreibvorgänge auf dem Datensatz oder der externen ID aus, die du verarbeitest.
- Bevorzuge eine verkettete Chunk-Verarbeitung gegenüber einem riesigen Fan-out, wenn die Arbeit auf einen rate-limitierten Drittanbieter trifft: Eine Kette mit
delayMstaktet sich selbst, wohingegen Tausende auf einmal eingereihte Jobs sofort zur Ausführung anstehen.