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.php alle 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

  1. Guard — CliBootstrap::guard() antwortet 403, falls das Skript jemals über HTTP erreicht wird; danach lädt CliBootstrap::boot() webtrees + die Datenbank.
  2. Offline-Check — wenn data/offline.txt existiert, wird der Tick komplett übersprungen, vor jedem Datenbankzugriff — z. B. während eines webtrees-Updates, wenn Schema und Code im Fluss sind.
  3. Arbeit auswählen — zwei Quellen, in einem Durchlauf kombiniert:
    • zeitbasierte Jobs, deren next_run_at verstrichen 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 Umgebungsvariablen CRONJOB_EVENT / CRONJOB_EVENT_PAYLOAD. Siehe Event-Pipeline.
  4. Jeden Job isoliert ausführen — JobRunner validiert den Befehl (ein modules_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 -9 gemeldet.
  5. Protokollieren — jeder Lauf wird in cj_run geschrieben (Status, Exit-Code, Dauer, der auslösende Trigger, erfasste Ausgabe) — das ist die Ausführungshistorie. Event-gesteuerte Läufe werden zusätzlich über cj_event_run verknüpft.
  6. Marker — der Tick schreibt data/cronjob/tick.last. Ist dieser Marker älter als 300 s, meldet das Modul sich im Admin-Status als tick_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.

Zuletzt geändert 08.11.2026: php doc references (f831d42)