So gehen Sie mit fehlgeschlagenen und doppelten Automatisierungsereignissen um
Gehen Sie davon aus, dass jedes Ereignis fehlschlagen und jedes Ereignis zweimal eintreffen kann. Geben Sie jedem Ereignis eine stabile Identität, damit eine Wiederholung erkannt und ignoriert wird. Wiederholen Sie nur Aktionen, die sich gefahrlos wiederholen lassen, benachrichtigen Sie eine namentlich genannte Person, wenn etwas fehlschlägt, und halten Sie den manuellen Wiederherstellungsschritt in einfachen Worten fest. Testen Sie die Fehlerpfade dann gezielt, statt auf einen echten Fehler zu warten.
Warum Duplikate und Fehler normal sind
Netzwerke brechen ab, Dienste laufen in Zeitüberschreitungen, und Absender wiederholen Anfragen. Eine Anfrage, die gescheitert zu sein scheint, kann tatsächlich funktioniert haben. Wird sie blind wiederholt, entsteht womöglich eine zweite Rechnung, eine zweite Buchung oder eine zweite E-Mail. Dafür vorzusorgen ist Routine und kein Pessimismus.
Geben Sie jedem Ereignis eine stabile Identität
Die Idee hinter einem Idempotenzschlüssel: Der Absender hängt an eine Anfrage einen eindeutigen Schlüssel an, sodass der Empfänger eine Wiederholung erkennen kann. Stripe beschreibt das für seine API: Tritt ein Verbindungsfehler auf, können Sie die Anfrage wiederholen, ohne das Risiko, ein zweites Objekt zu erzeugen oder die Aktualisierung doppelt auszuführen. Stripe speichert Statuscode und Body der ersten Anfrage zu einem Schlüssel und liefert für spätere Anfragen mit diesem Schlüssel dasselbe Ergebnis zurück.
Dasselbe Muster funktioniert auch in Ihren eigenen Automatisierungen. Verwenden Sie eine Kennung, die bereits zum Ereignis gehört, etwa eine Buchungsnummer, als Schlüssel für eine Reservierung. Eine einfache Abfrage mit anschließendem separatem Schreibvorgang reicht allein nicht aus, denn zwei Kopien des Ereignisses können beide nachsehen, beide nichts finden und beide weitermachen. Die nächsten Abschnitte erklären, wie sich diese Lücke schließen lässt und was dennoch nicht abgedeckt ist.
Details, die sich zu übernehmen lohnen
Stripe empfiehlt zufällige Kennungen wie UUIDs der Version 4 und rät davon ab, sensible Daten wie E-Mail-Adressen als Schlüssel zu verwenden. Für API v1 gibt Stripe an, dass Schlüssel nach mindestens 24 Stunden entfernt werden können und dass die Parameter einer wiederholten Anfrage mit dem Original verglichen werden; weichen sie ab, wird ein Fehler zurückgegeben. Für API v1 wird zudem festgehalten, dass alle POST-Anfragen Schlüssel akzeptieren und dass bei GET- und DELETE-Anfragen keine Schlüssel gesendet werden sollten, weil diese per Definition idempotent sind. Außerdem gilt für API v1: Schlägt die Validierung der eingehenden Parameter fehl oder kollidiert die Anfrage mit einer anderen, gleichzeitig laufenden Anfrage, wird kein idempotentes Ergebnis gespeichert, und die Anfrage kann erneut versucht werden. Das sind Besonderheiten von Stripe. Prüfen Sie daher die Dokumentation des Dienstes, den Sie tatsächlich nutzen.
Wenn zwei Kopien im selben Moment eintreffen
Gleichzeitige Duplikate sind der Fall, den eine einfache Prüfung übersieht. Stellen Sie sich vor, zwei Kopien desselben Buchungsereignisses erreichen Ihren Workflow innerhalb einer Sekunde. Jede sucht die Buchungsnummer in einer Liste versendeter Bestätigungen, jede findet sie nicht, und jede versendet eine E-Mail. Wenn Prüfen, Senden und Eintragen drei getrennte Schritte sind, gibt es eine Lücke, in der beide Kopien denselben veralteten Zustand sehen.
Schließen Sie die Lücke, indem Sie das Ereignis beanspruchen, bevor Sie handeln. Machen Sie die Beanspruchung zu einem einzigen Schritt, der nur für eine Kopie gelingen kann, zum Beispiel durch das Einfügen einer Zeile, deren Buchungsnummer eindeutig sein muss, oder durch eine bedingte Aktualisierung, die einen Status nur dann von neu auf in Bearbeitung setzt, wenn er noch neu ist. Die Kopie, die die Beanspruchung gewinnt, macht weiter. Die Kopie, die verliert, hört auf oder wartet und liest das aufgezeichnete Ergebnis. Geben Sie dem Status wenige klare Werte, etwa beansprucht, gesendet, fehlgeschlagen und Ergebnis unbekannt, damit eine Person sehen kann, wo jedes Ereignis steht.
AWS beschreibt dieselbe Idee auf Seiten des Dienstes. Im Artikel der Amazon Builders' Library zu idempotenten APIs müssen das Aufzeichnen des Idempotenz-Tokens und jede für die Anfrage vorgenommene verändernde Operation zusammen die Eigenschaften einer atomaren, konsistenten, isolierten und dauerhaften (ACID) Operation erfüllen, sodass der Dienst nie das Token aufzeichnet, ohne die Ressource zu erstellen, oder die Ressource erstellt, ohne das Token aufzuzeichnen. Das gilt für Änderungen innerhalb der eigenen Transaktion des Dienstes. Es erstreckt sich nicht auf eine E-Mail, die über einen externen Anbieter versendet wird und die keine Datenbanktransaktion rückgängig machen oder bestätigen kann. Behandeln Sie beides als getrennte Probleme.
Wenn der E-Mail-Versand selbst ungewiss ist
Eine atomare Beanspruchung verhindert, dass beide Kopien fortfahren. Sie sagt Ihnen nicht, ob eine E-Mail zugestellt wurde, und sie garantiert allein nicht, dass nie ein Duplikat versendet wird. Angenommen, eine Kopie gewinnt die Beanspruchung, ruft den E-Mail-Dienst auf, und die Verbindung läuft in eine Zeitüberschreitung. Die Nachricht ist möglicherweise rausgegangen, möglicherweise nicht oder steckt in einer Warteschlange. Blindes Wiederholen riskiert eine zweite E-Mail, Nichtstun riskiert gar keine E-Mail. AWS beschreibt dasselbe Dilemma für eine Anfrage ohne Antwort: Der Aufrufer kann nicht erkennen, ob die Arbeit erledigt wurde, und braucht womöglich einen Abgleichsschritt, um es herauszufinden.
Halten Sie daher vor dem Aufruf des E-Mail-Dienstes den Zustand dauerhaft als Versand versucht, Ergebnis unbekannt fest und stellen Sie sicher, dass dieser Eintrag gespeichert ist und einen Absturz übersteht. Ändern Sie ihn erst auf gesendet oder fehlgeschlagen, wenn der Anbieter eine klare Antwort gibt. Stürzt der Prozess ab, nachdem die E-Mail rausgegangen ist, aber bevor sie als gesendet markiert wurde, bleibt das Ereignis sichtbar uneindeutig und kommt in den Abgleich. Es wird niemals automatisch erneut gesendet. Behandeln Sie diesen Zustand als einen, der eine Person braucht, und benennen Sie, wer ihn abgleicht, zum Beispiel die Inhaberin oder der Inhaber oder die Büroleitung. Die Notiz sollte sagen, wo zu prüfen ist, etwa im Ordner „Gesendet“ oder im Zustellprotokoll des E-Mail-Dienstes, und ob die Kundschaft die Bestätigung erhalten hat. Protokolle klären die Frage nicht immer: Ein fehlender Eintrag beweist nicht, dass nichts zugestellt wurde, und macht einen erneuten Versand daher nicht sicher. Lässt sich das Ergebnis durch die Prüfung nicht ermitteln, belassen Sie das Ereignis ungeklärt bei der benannten verantwortlichen Person, statt erneut zu senden. Erst wenn diese das Ergebnis festgestellt hat, markiert sie das Ereignis als gesendet oder sendet einmal erneut und trägt das ein. Wenn Ihr E-Mail-Dienst für Sendungen einen eigenen Schlüssel akzeptiert, nutzen Sie ihn, lesen Sie aber zuerst die Dokumentation, denn Unterstützung und Aufbewahrung unterscheiden sich je nach Dienst.
Wiederholen Sie nur, was sicher ist
Das Einteilen von Aktionen in zwei Gruppen erleichtert Entscheidungen.
- Gefahrlos wiederholbar: Daten lesen, einen Status auf einen festen Wert setzen, denselben Datensatz unter derselben Identität speichern.
- Ohne Schutz unsicher: eine E-Mail senden, eine Karte belasten, einen neuen Datensatz anlegen oder zu einer laufenden Summe addieren.
- Beanspruchen Sie bei unsicheren Aktionen die Identität des Ereignisses in einem Schritt, den nur eine Kopie gewinnen kann, und prüfen Sie vor dem Handeln, ob bereits ein früherer Erfolg vorliegt. Eine Beanspruchung verringert doppelte Versuche, beweist aber nicht, dass eine externe Aktion gelungen ist.
- Legen Sie Wiederholungsversuche in Abständen an und hören Sie nach wenigen auf, damit ein defekter Dienst nicht überlastet wird.
Machen Sie Fehler sichtbar
In n8n können Sie einen Fehler-Workflow festlegen, der läuft, wenn eine Ausführung fehlschlägt, zum Beispiel um eine E-Mail oder eine Slack-Warnung zu senden. Der Fehler-Workflow beginnt mit einem Error-Trigger-Knoten, und ein Fehler-Workflow kann mehrere Workflows bedienen. Mit einem Stop-and-Error-Knoten lässt sich ein Lauf unter selbst gewählten Bedingungen gezielt fehlschlagen. Egal, welches Werkzeug Sie nutzen: Sorgen Sie dafür, dass ein Fehler eine namentlich genannte Person erreicht und nicht ein Protokoll, das niemand liest.
Schreiben Sie den Wiederherstellungsschritt auf
Schreiben Sie für jede Fehlerart einen Satz: Was tut eine Person als Nächstes? Beispiele sind eine Nachricht aus dem Protokoll erneut senden, einen Datensatz von Hand als erledigt markieren oder die Kundschaft kontaktieren. Nennen Sie, wo nachzusehen ist und wer entscheidet. Eine Wiederherstellungsnotiz, die nur im Kopf einer Person existiert, scheitert beim ersten Urlaub.
Ein hypothetisches Beispiel
Stellen Sie sich einen Workflow vor, der eine Bestätigungs-E-Mail sendet, wenn eine Buchung gespeichert wird. Das Buchungssystem ruft den Workflow manchmal zweimal auf, gelegentlich fast gleichzeitig. Der Workflow beansprucht zuerst die Buchungsnummer in einer Bestätigungstabelle, in der jede Nummer eindeutig sein muss. Nur die Kopie, die die Beanspruchung gewinnt, sendet weiter und markiert die Buchung danach als gesendet. Die andere Kopie stoppt. Ist der E-Mail-Dienst ausgefallen und lehnt die Nachricht ab, benachrichtigt der Fehler-Workflow die verantwortliche Person, die einer Notiz folgt, den Versand aus der Liste unbestätigter Buchungen zu wiederholen. Läuft ein Versand ohne klare Antwort in eine Zeitüberschreitung, bleibt die Buchung als Ergebnis unbekannt markiert, und die verantwortliche Person prüft das Zustellprotokoll des E-Mail-Dienstes, bevor sie erneut sendet oder die Buchung als erledigt markiert. Dieses Beispiel ist hypothetisch.