Zum Inhalt springen
use-cases / cleanup-jobs-self-retire / hero
CRON · FILES · SELBST-PENSIONIEREND

Cleanup-Jobs, die ihren eigenen Ruhestand planen

Provisioniere am Tag, an dem das Cleanup beginnt, einen Managed-Cron-Eintrag. Setze expires_at ein paar Tage hinter den letzten erwarteten Lauf. Das Skript schneidet sich nächtlich durch die Arbeit und schickt sich dann selbst per DELETE weg, wenn nichts mehr übrig ist. Keine Kalendererinnerung, keine Zombie-Crontab, kein jährliches Aufräum-die-Aufräumer-Review.

Cron-Docs
cleanup-stale-uploads.sh
# tail of cleanup-stale-uploads.sh
removed=$(find /uploads -mtime +90 -delete -print | wc -l)
echo "$removed files removed"

# self-aware tail: nothing left → retire
if [ -z "$(ls /uploads)" ]; then
  curl -fsS -X DELETE \
    "$CRON_URL/entries/$ENTRY_ID"
fi

Der selbstbewusste Schwanz. Der Cron-Eintrag ist die letzte Zeile seines eigenen Skripts.

use-cases / cleanup-jobs-self-retire / lifecycle

Ein Cleanup mit endlicher Lebensdauer, by construction

Drei diskrete Phasen. Jeder Übergang ist mechanisch, keiner verlangt, dass ein Mensch sich erinnert. Der Eintrag weiß, wann seine Arbeit getan ist und wann sein Kalenderslot vorbei ist.

LIFECYCLE · SCHEDULE → SLICE → SELF-DELETEEIN EINTRAG, EIN ENDLICHES LEBEN
1 · SCHEDULE

POST einen Eintrag am Tag, an dem das Cleanup startet

Schedule @daily, command zeigt auf ein Slicer-Skript, expires_at ist knapp hinter den letzten erwarteten Lauf gesetzt. Die Deadline steht im Eintrag — nicht in einem Notion-Doc, nicht in einem Slack-Thread.

2 · SLICE

Das Skript trägt nächtlich sanft ab

Jeder Lauf löscht eine Scheibe veralteter Daten, damit die Datenbank nicht überfahren wird. Tag 1 räumt vielleicht 247 Dateien weg; Tag 6 nur noch 1. Das Tempo ist begrenzt durch das, was tatsächlich übrig ist.

3 · SELF-DELETE

Wenn die Arbeit getan ist, geht der Eintrag in Rente

Der letzte Block des Skripts prüft, ob das Ziel leer ist. Wenn ja, feuert er DELETE /entries/[self]. Falls das irgendwie nicht klappt, feuert expires_at ein paar Tage später das Sicherheitsnetz.

Zwei unabhängige Trigger — die eigene Prüfung des Skripts und das expires_at der API — laufen auf dasselbe Ergebnis hinaus: eine Crontab-Zeile, die ihren Zweck nicht überlebt.

use-cases / cleanup-jobs-self-retire / mechanism

Zwei HTTP-Calls, ein endliches Cleanup

Hoody Cron ist ein JSON-CRUD-Wrapper um die System-Crontab. POST erstellt den Eintrag; DELETE entfernt ihn; expires_at ist das Sicherheitsnetz. Das Skript, das nächtlich läuft, ist dasjenige, das weiß, wann es fertig ist — also ist es dasjenige, das DELETE aufruft.

create-entry.sh
TAG 0 · POST
# day 0 — provision the cleanup
curl -X POST \
  https://cron.containers.hoody.com/users/me/entries \
  -H "Content-Type: application/json" \
  -d '["schedule":"@daily","command":"/srv/jobs/cleanup-stale-uploads.sh","expires_at":"2026-05-05T00:00:00Z"]'

# response
HTTP/1.1 201 Created
{ "id":"f3a1", "expires_at":"2026-05-05T00:00:00Z", "enabled":true }
cleanup-stale-uploads.sh
TAG 7 · DELETE
# inside the cron command itself
if [ -z "$(ls /uploads)" ]; then
  curl -X DELETE \
    "$CRON_URL/entries/$ENTRY_ID"
fi

# response
HTTP/1.1 204 No Content
# entry f3a1 was here. f3a1 deleted itself.

$ENTRY_ID ist die UUID, die der POST zurückgibt — das Skript kann sie aus einer Datei lesen, die die Command-Line des Eintrags übergeben hat, oder zur Laufzeit aus $HOODY_ENTRY_ID. So oder so: Der Cron-Eintrag löscht den Cron-Eintrag.

use-cases / cleanup-jobs-self-retire / powers

Was das selbst-pensionierende Cleanup freischaltet

Es ist nicht das Löschen, was zählt. Es ist, dass sich in drei Monaten niemand mehr erinnern muss, dass das überhaupt existiert.

DRUCKLOSES TEMPO

Scheibe für Scheibe, nicht alles auf einmal

@daily läuft alle 24 Stunden. Das Skript löscht eine Scheibe veralteter Daten — ein paar tausend Dateien, ein paar tausend Zeilen — und beendet sich. Die Datenbank bleibt ruhig; die Last-Kurve sieht aus, als wäre nichts passiert.

KEINE ZOMBIE-CRONTAB

Die Zeile überlebt den Engineer nicht

expires_at steht als JSON im Eintrag. Wenn es feuert, wird die Zeile aus der System-Crontab entfernt. Drei Engineers später blättert niemand mehr durch 200 Zeilen und fragt sich, was cleanup-stale-uploads-v3 wohl noch tut.

ZWEI TRIGGER, EIN ERGEBNIS

Selbst-DELETE plus expires_at-Sicherheitsnetz

Das Skript schickt sich selbst per DELETE weg in der Nacht, in der die Arbeit getan ist. Falls ein Bug diesen Pfad überspringt, pensioniert expires_at den Eintrag ein paar Tage später. Zwei unabhängige Mechanismen; einer von beiden wird feuern.

use-cases / cleanup-jobs-self-retire / capacity

Wie das skaliert

Jeder Managed Entry ist eine JSON-Zeile, die die API in die System-Crontab injiziert. Die Skalierung ist begrenzt durch das, was Cron selbst aufnehmen kann, nicht durch Hoody.

  1. RUN-TAKT1 / Tag

    @daily ist der kanonische Cleanup-Rhythmus. Wenn du häufiger durchgehen willst, kannst du 5-Feld-Ausdrücke bis runter auf * * * * * verwenden — Minuten-Auflösung.

  2. EINTRAGS-LEBENSDAUERexpires_at

    Ein ISO-8601-Timestamp am Eintrag. Wenn er abläuft, entfernt die API die Zeile beim nächsten Sweep. Das Cleanup verweilt nie über seine eigene Deadline hinaus.

  3. TEARDOWN HTTPDELETE · 204

    DELETE /users/[user]/entries/[id] aus dem laufenden Befehl heraus funktioniert, weil der Cron-Daemon seine eigene Crontab nicht sperrt — die API zieht die Änderung beim Sweep sicher rein.

Standard-5-Feld-Cron-Ausdrücke plus Macros (@hourly, @daily, @weekly, @monthly, @yearly). Pro-User-Isolation; jeder System-User bekommt seine eigene Crontab. Die Cron-Seite des Hoody Kits dokumentiert sowohl Managed Entries als auch rohen Crontab-Zugriff, falls du die ältere Form brauchst.

use-cases / cleanup-jobs-self-retire / punchline

Das Cleanup läuft nächtlich, bis das, was aufgeräumt wird, weg ist.

VORHER · KALENDERERINNERUNGEN, ZOMBIE-CRON-ZEILENNACHHER · EIN CRON-EINTRAG, DER WEISS, WANN ER FERTIG IST
VORHER// TODO: delete this when /uploads is empty (2026?)Ein Kommentar, den dein zukünftiges Ich einmal liest und danach nie wieder.
JETZTDELETE /entries/$ENTRY_ID · expires_at: 2026-05-05Ein Teardown, der aus dem Skript feuert, und eine Deadline, die in den Eintrag selbst eincodiert ist.
Cron-API-Referenz
use-cases / cleanup-jobs-self-retire / replaces

Was das ersetzt

Überall dort, wo ein Cleanup-Task von selbst verschwinden soll — das sind die Muster, die es ersetzt:

  • Zombie-Cleanup-Cron-JobsZeilen aus 2022, die niemand zu löschen wagt
  • // TODO: delete this when X is emptyEin Kommentar, der zur Dauereinrichtung wurde
  • Manuelle Hausmeister-SkripteEine Teamkollegin lässt sie quartalsweise laufen, wenn dran gedacht wird
  • Kubernetes CronJobs, die sich nie selbst löschenttlSecondsAfterFinished am Pod, nicht am Schedule
  • Selbstgebaute, selbstbewusste Lifecycle-ManagerEin Eigenbau-Service, der deine anderen Services beobachtet
  • Terraform-verwaltete Lifecycle-PoliciesPlan, apply, sechs Monate später immer noch im tfstate
use-cases / cleanup-jobs-self-retire / cta

Provisioniere das Cleanup. Setz sein Renten-Datum. Geh weg.

Cron-Docs lesen
use-cases / cleanup-jobs-self-retire / related

Lies die anderen