Zum Inhalt springen

Zeitplan-Trigger: Cron mit Zeitzone

Führe einen Workflow nach Cron-Plan in einer IANA-Zeitzone aus. Was an den Umstellungstagen gilt, was nach Ausfällen — und was das Firings-Log erklärt.

Zuletzt aktualisiert:

Wanduhrzeit, wörtlich gemeint

Ein Zeitplan ist ein Cron-Ausdruck plus eine IANA-Zone — Europe/Berlin, nie ein UTC-Offset, denn ein Offset ist das halbe Jahr über falsch. Die Wanduhr-Semantik gilt wörtlich, gerade an den Tagen, die sie auf die Probe stellen. In der Nacht, in der die Uhren zurückgestellt werden, feuert ein täglicher Job einmal, nicht zweimal: Auf einem Portal mit nur einer Sitzung pro Login würde die zweite Anmeldung die erste verdrängen. In der Nacht der Vorstellung feuert ein Job aus der fehlenden Stunde, sobald die Lücke endet — statt gar nicht.

Für Ausfälle gilt dieselbe Disziplin: Egal wie lange die Plattform stand, es gibt genau eine Nachhol-Entscheidung — catchUp überspringt die verpassten Termine oder feuert genau einmal nach. Nie eine Salve von Runs hintereinander.

Einen nächtlichen Trigger anlegen

Voraussetzungen: api-key

BASE="https://browserberg.com"
AUTH="Authorization: Bearer $BROWSERBERG_API_KEY"
JSON="Content-Type: application/json"

WFID=$(curl -s -X POST "$BASE/v1/workflows" -H "$AUTH" -H "$JSON" -d '{
  "title": "Nightly example check",
  "blocks": [ { "blockType": "navigation", "label": "Open_page", "url": "https://example.com" } ]
}' | python3 -c 'import json,sys; print(json.load(sys.stdin)["workflow"]["workflowId"])')

# A schedule is a cron expression plus an IANA zone -- never a UTC offset.
# Wall-clock time is meant literally, including on the DST switch days.
TRIGGER=$(curl -s -X POST "$BASE/v1/workflows/$WFID/triggers" -H "$AUTH" -H "$JSON" -d '{
  "kind": "schedule",
  "name": "Nightly at 02:30 Berlin time",
  "cron": "30 2 * * *",
  "timezone": "Europe/Berlin",
  "catchUp": "run_once",
  "session": { "ttlSeconds": 900 }
}')
echo "$TRIGGER" | python3 -c 'import json,sys; t = json.load(sys.stdin)["trigger"]; print(json.dumps({
  "id": t["id"], "status": t["status"], "nextFireAt": t["nextFireAt"],
  "catchUp": t["catchUp"], "overlap": t["overlap"]}, indent=2))'

TID=$(echo "$TRIGGER" | python3 -c 'import json,sys; print(json.load(sys.stdin)["trigger"]["id"])')
curl -s -X DELETE "$BASE/v1/triggers/$TID" -H "$AUTH" > /dev/null

Zeitplan-Optionen

Das Mindestintervall zwischen zwei Terminen beträgt 5 Minuten.

Name Typ Beschreibung
cron erforderlich string Gewöhnlicher Cron-Ausdruck mit fünf Feldern.
timezone erforderlich string Ein IANA-Zonenname wie Europe/Berlin. Offsets werden abgelehnt.
catchUp skip | run_once skip lässt verpasste Termine aus; run_once holt genau einen nach.
misfireGraceSeconds integer Wie spät ein Termin noch feuern darf und als pünktlich gilt (60 bis 21600). Standard: 300
overlap skip | allow skip verweigert ein neues Feuern, solange der vorige Run läuft; allow startet trotzdem.
session object Die Session für jedes Feuern: poolId, profileId, locale, timezone, ttlSeconds.
version integer Fixiert die auszuführende Workflow-Version; ohne Angabe läuft jeweils die neueste.

Das Firings-Log beantwortet die Morgenfrage

GET /v1/triggers/:id/firings verzeichnet jeden Termin, an dem der Trigger fällig wurde — auch die, an denen nichts lief, mit dem Ausgang started, skipped oder refused und dem Grund. Wenn du morgens fragst, warum letzte Nacht nichts gelaufen ist, ist das Log die Antwort, kein Achselzucken.

Ein gescheiterter Run pausiert keinen Trigger; für Scheitern gibt es Retries und den nächsten Termin. Pausiert wird nur bei einem Fehler, der sich nie von selbst beheben kann — ein gelöschter Workflow, ein widerrufener Zugangsdatensatz.

Ebenfalls lesenswert

  • Webhook-Trigger Auf ein Ereignis feuern statt auf die Uhr
  • Referenz Trigger Alle Trigger-Felder und -Endpunkte
  • Workflows erstellen Was der Trigger eigentlich ausführt