Der Tick
Wie ’tickt’ das Modul
Der Tick ist das Herz des Moduls: einmal pro Minute prüft er alle aktivierten Jobs, entscheidet, was fällig ist, und führt es aus. Weder das webtrees-Core noch das Betriebssystem planen selbst — sie starten nur tick.php
.
flowchart TD
subgraph Triggers["`⏱ Auslöser *(once per minute)*`"]
CRON["`🕑 OS cron / systemd<br/>*every minute*`"]
WATCH["`👁 watch-Daemon<br/>*(in-module)*`"]
end
subgraph Guard["🛡 Guard"]
TP["`📄 cli/tick.php · **cron:tick**<br/>*guard(): 403 over HTTP*`"]
OFF{"`⚠ site offline?<br/>*data/offline.txt*`"}
BOOT["`🚀 boot()<br/>*webtrees + DB*`"]
end
subgraph Selection["🔎 Arbeit auswählen"]
TIME["`📅 time-based jobs<br/>**next_run_at due** *(UTC)*`"]
CE[("`📦 cj_event<br/>*Event-Warteschlange*`")]
DRAIN["`🧮 drain queue<br/>*coalesced · 60 s budget*`"]
end
subgraph Execution["`⚙ Ausführung *(isolated child)*`"]
RUN["`🧪 JobRunner<br/>**proc_open**`"]
LIM["`⏲ timeout 30–3600 s<br/>last **64 KB** · exit code`"]
end
subgraph Storage["💾 Speicherung"]
CJRUN[("`cj_run<br/>*Laufverlauf*`")]
MARK["`🏷 tick.last<br/>*stale > 300 s → tick_stale*`"]
end
CRON --> Guard
WATCH --> Guard
TP --> OFF
OFF -->|"offline"| SKIP["⏭ Tick überspringen"]
OFF -->|"online"| BOOT
BOOT --> TIME
BOOT --> DRAIN
CE --> DRAIN
TIME --> Execution
DRAIN --> Execution
RUN --> LIM
LIM --> CJRUN
BOOT --> MARK
classDef sourceStyle fill:#e3f2fd,stroke:#1565C0,stroke-width:2px
classDef queueStyle fill:#fff3e0,stroke:#E65100,stroke-width:2px
classDef tickStyle fill:#e8f5e9,stroke:#2E7D32,stroke-width:2px
classDef execStyle fill:#fce4ec,stroke:#C2185B,stroke-width:2px
classDef storageStyle fill:#f5f5f5,stroke:#616161,stroke-width:1px
class CRON,WATCH sourceStyle
class OFF,CE queueStyle
class TP,TIME,DRAIN tickStyle
class RUN,LIM execStyle
class CJRUN,MARK,SKIP storageStyle
Was einen Tick startet
Einen Trigger wählen (einmalig):
- OS-Cron —
* * * * *vom webtrees-Root aus (siehe Installation). - systemd-Timer — die generierte Unit von der Modul-Admin-Seite.
- watch-Daemon — der residente Prozess im Modul, der
tick.phpalle 60 s neu startet und FPM-Worker-Recycling überlebt (Installation, die auch das Lifecycle-Diagramm des Daemons trägt).
Alle drei führen denselben Befehl aus: php modules_v4/cronjob/cli/tick.php cron:tick.
Was ein Tick tut
- Guard —
CliBootstrap::guard()antwortet403, falls das Skript jemals über HTTP erreicht wird; danach lädtCliBootstrap::boot()webtrees + die Datenbank. - Offline-Check — wenn
data/offline.txtexistiert, wird der Tick komplett übersprungen, vor jedem Datenbankzugriff — z. B. während eines webtrees-Updates, wenn Schema und Code im Fluss sind. - Arbeit auswählen — zwei Quellen, in einem Durchlauf kombiniert:
- zeitbasierte Jobs, deren
next_run_atverstrichen ist (Cron-Zeitpläne, UTC); die fälligen Trigger werden relativ zum letzten Lauf berechnet (bzw. zur Erzeugung bei nie gelaufenen Jobs). - Event-Jobs — die
cj_event-Warteschlange wird von der ältesten zuerst geleert, gekoppelt auf einen Lauf pro Ereignisnamen, innerhalb eines 60-Sekunden-Budgets. Event-Jobs erhalten den Ereignisnamen und das Payload über die UmgebungsvariablenCRONJOB_EVENT/CRONJOB_EVENT_PAYLOAD. Siehe Event-Pipeline.
- zeitbasierte Jobs, deren
- Jeden Job isoliert ausführen —
JobRunnervalidiert den Befehl (einmodules_v4/<module>/cli/<script>.php-Pfad oder einer der vier erlaubten Core-Befehle; höchstens 10 Argumente) und startet ihn als Kindprozess mit hartem Timeout (30–3600 s). Es werden nur die letzten 64 KB der Ausgabe erfasst; ein Job, der seinen Timeout erreicht, wird beendet (proc_terminate) und als Exit-9gemeldet. - Protokollieren — jeder Lauf wird in
cj_rungeschrieben (Status, Exit-Code, Dauer, der auslösende Trigger, erfasste Ausgabe) — das ist die Ausführungshistorie. Event-gesteuerte Läufe werden zusätzlich übercj_event_runverknüpft. - Marker — der Tick schreibt
data/cronjob/tick.last. Ist dieser Marker älter als 300 s, meldet das Modul sich im Admin-Status alstick_stale.
Manuelle Ausführung
Den Tick kann man auch manuell ausführen — --dry-run, --job=<name>, --strict und --full-output sind auf der Seite CLI-Skripte beschrieben. Achtung: --full-output kann personenbezogene Daten offenlegen — nur verwenden, wenn der Ausgabeort vertrauenswürdig ist.