Wir hatten gestern beim Hub KI über Vibe Coding gesprochen. Ich hatte erzählt, dass ich von Claude (GPT, bzw. Agent - heißt bei Claude Chat & Cowork) Programmiervorgaben schreiben lasse. Diese Programmiervorgaben setzt dann Claude code um.
Da ich es gestern nicht live herzeigen konnte (VPN und 4future Seminar vertragen sich nicht gut) - hier ein Beispiel einer Programmieranweisung:
aufgabe-sweeper-takt.md — Seat-Provisionierung im Fünf-Minuten-Takt statt einmal täglich
Live gefunden 2026-09-02 beim Aufbau der Demofirma Digiwork.
Befund
Der Sweeper hängt vollständig an einem Hook:
add_hook('DailyCronJob', 1, function ($vars) { ... ispcfg3_sweeper_run(); });
DailyCronJobfeuert einmal am Tag. Eine Seat-Zuweisung, die ein OrgAdmin im
Portal vornimmt, bleibt deshalb bis zum nächsten Tageslauf aufpending— die
Person sieht in ihrem Profil vier Dienste mit „wird eingerichtet", und es
passiert stundenlang nichts.Das Portal verspricht etwas anderes.
Org\UserControllermeldet nach der
Zuweisung: „Die Einrichtung läuft (bis zu 5 Minuten)." Diese Zusage war noch
nie gedeckt.Der WHMCS-System-Cron läuft bereits alle fünf Minuten:
/etc/crontab: */5 * * * * www-data /usr/bin/php8.3 -q /var/www/_secure/whmcs4fd/crons/cron.php
AfterCronJobfeuert damit alle fĂĽnf Minuten. Der kurze Takt ist also
vorhanden, er wird nur nicht genutzt. Kein Eingriff am Systemcron nötig.Nicht: den ganzen Sweeper häufiger laufen lassen
Ein Sweeper-Lauf macht sehr viel mehr als Seats — Let’s-Encrypt-Bestellungen,
DMARC-Weiterleitungen, Web-Quota-PrĂĽfungen, Waisen-Abgleich,
WordPress-Umstellungen, Addon-Abgleich und den vollen Kontingent-Abgleich ĂĽber
alle WHMCS-Kunden. Das ist auf einen Lauf pro Tag ausgelegt; im Code steht
ISPCFG_SWEEPER_SSL_BUDGET_PER_RUN = 25mit dem Kommentar „bewusst weit unter
dem Limit". Bei 288 Läufen am Tag ist dieses Budget bedeutungslos und die
Let’s-Encrypt-Ratenbegrenzung ein realistisches Ziel.Teil 1 — Zweiter Hook, nur für die wartenden Pfade
Neuer
add_hook('AfterCronJob', ...), der ausschlieĂźlich die drei Funktionen
aufruft, auf die ein Mensch wartet:
ispcfg3_sweeper_reconcile_seat_provisioning()ispcfg3_sweeper_reconcile_seat_revocations()ispcfg3_sweeper_reconcile_mailbox_unlocks()
ispcfg3_sweeper_run()bleibt unverändert amDailyCronJobund ruft dieselben
drei Funktionen weiterhin mit auf — sie sind idempotent, ein zusätzlicher
Durchlauf im Tageslauf schadet nicht und dient als Netz, falls der kurze Takt
ausfällt.Der neue Hook braucht denselben
require_once- undISPCFG_SWEEPER_DRY_RUN-
Vorspann wie der bestehende (siehe dortigen Kommentar: der Guard gehört hinter
dasrequire_once, nicht als top-leveldefine()).Teil 2 — Sperre gegen überlappende Läufe
Bei fünf Minuten Takt können sich zwei Läufe überholen, wenn einer hängt. Die
drei Pfade legen Mailboxen in ISPConfig an und setzen FreeIPA-Gruppen — zweimal
parallel ist nicht harmlos.Lock-Datei mit
flock(nicht blockierend): läuft bereits einer, still
zurückkehren, ohne Logzeile. Zusätzlich eine Altersgrenze, damit ein
abgestürzter Lauf die Sperre nicht dauerhaft hält.Teil 3 — Nicht ins Log spammen
Der bestehende Lauf beginnt mit
ISPConfigLogger::info('Sweeper', 'Start', ...).
288 solcher Zeilen pro Tag machen das Log unbrauchbar, in dem man sonst genau
die Seat-Meldungen sucht.Der kurze Lauf loggt deshalb nur, wenn es etwas zu tun gab: keine offenen
Zuweisungen, keine Widerrufe, keine Entsperrungen → keine Zeile. Die
bestehenden Meldungen im Erfolgs- und Fehlerfall („Seat provisioniert",
„Seat-Provisionierung übersprungen - …") bleiben unverändert.Auch die Zusammenfassungsmail (
ispcfg3_sweeper_send_summary()) bleibt dem
Tageslauf vorbehalten.Teil 4 — Verhältnis zu DRY_RUN klären
ISPCFG_SWEEPER_DRY_RUNgatet heute den Addon-Abgleich, DMARC und SSL, aber
nicht den Seat-Pfad. PrĂĽfen, ob das Absicht ist, und die Entscheidung im neuen
Hook kommentieren — sonst provisioniert eine Umgebung, die sich für einen
Trockenlauf hält, munter Mailboxen.Teil 5 — Bekannte Grenze benennen
Der Kontingent-Abgleich (
ispcfg3_sweeper_reconcile_seat_contingent()) bleibt
bewusst im Tageslauf: er geht alle WHMCS-Kunden durch. Folge — eine frisch
gekaufte Lizenz ist im Portal erst am nächsten Tag als Kontingent sichtbar,
und bis dahin lässt sie sich nicht zuweisen.Für den Kaufweg ist das die eigentlich störende Wartezeit, und sie bleibt nach
dieser Aufgabe bestehen. Als bekannte Grenze im Code kommentieren, nicht
stillschweigend lassen; die Lösung wäre ein gezielter Abgleich für einen
Kunden direkt nach der Bestellung, und das ist eine eigene Aufgabe.Akzeptanzkriterien
- Eine Seat-Zuweisung im Portal ist spätestens fünf Minuten später
provisioniert; die Dienste in der Personen-Detailansicht stehen auf
eingerichtet.- Der Tageslauf verhält sich unverändert — SSL-Budget, DMARC, Quota, Addons,
Kontingent-Abgleich und Zusammenfassungsmail wie bisher.- Zwei gleichzeitige Läufe des kurzen Hooks sind ausgeschlossen.
- Ein Lauf ohne offene Arbeit hinterlässt keine Logzeile.
- Die Portal-Meldung „bis zu 5 Minuten" stimmt danach.
Regeln fĂĽr die Umsetzung
- Branch statt
main, kleiner Diff, deutsche Kommentare mit Begründung.- Kein Eingriff am Systemcron — der Fünf-Minuten-Takt ist bereits da.
- Testen: WHMCS hat kein Testsystem. Nach dem Deploy eine Zuweisung im Portal
vornehmen und die Uhr laufen lassen; das Modul-Log zeigt, ob der kurze Hook
gefeuert hat.