un

guest
1 / ?
back to lessons

Form 1: Zustands-Reparatur. Form 2: Verschwenderischer Bericht.

Ein gemessenes Herz schlägt nach dem Uhrwerk. Nicht nach Bedarf. Nicht nach Veränderung. Nach einem Timer.

Zwei Formen, eine Wurzel: eine geplante Aufgabe, die richtiges Design ersetzt.

Form 1: Zustands-Reparatur

Eine Zustandsübergang misslingt, atomar vollständig werden zu können. Statt den Übergang zu beheben, läuft eine Hintergrundaufgabe nach einer Verzögerung ab und vereinigt. Benutzer sehen kaputtes Zustand während des Vereinigungsfensters.

GitHub-Beispiel (2026-04-08): Ein Pull-Antrag wurde in das upstream-Repository privatisiert. GitHub versuchte einen Zustandsübergang: Schließen Sie den PR, aktualisieren Sie den Branch-Status, löschen Sie den Merge-Status. Der Übergang schaffte es nicht, atomar vollständig zu sein. Der PR-Status zeigte 'branch-forced-closed' und 'Merge status cannot be loaded' gleichzeitig. Eine Sidekiq-Hintergrundaufgabe lief später Minuten und beendete die Vereinigung. Beobachter sahen kaputtes Zustand für die Dauer des Fensters.

Das gemessene Herz: Die Sidekiq-Aufgabe lief nach dem Timer. Sie lief nicht, weil GitHub kaputtes Zustand erkannte; sie lief, weil der Timer abging. Ein Benutzer, der den PR in Echtzeit beobachtete, sah einen PR, der sich selbst widersprach, bis die nächste Ausführung der Aufgabe erfolgte.

Form 2: Verschwenderischer Bericht

Ein Bericht oder eine Aggregation berechnet von vorne auf einem festen Intervall neu. Keine Cache-Überprüfung. Kein Idempotenzschutz. Kein inkrementelles Update. Jede Ausführung: eine vollständige Durchsuchung.

Beispiele: eine Nachtarbeit, die jede Benutzerkäufe insgesamt neu berechnet, indem sie alle Bestellungen von Anfang an durchsucht. Eine tägliche Analysearbeit, die eine Dashboard-Regeneration aus Rohereignisprotokollen durchführt. Eine wöchentliche Zusammenfassungs-E-Mail, die jede Zeile in der Aktivitäts-Tabelle abfragt.

Jede läuft, obwohl sich die Daten seit der letzten Ausführung geändert haben. Jede scannt die gesamte Geschichte, obwohl nur die letzten 24 Stunden neue Daten enthalten. Jede ersetzt geplante Wiederholung durch inkrementelles Design.

Die gemeinsame Wurzel

Ein gemessenes Herz kann nicht über seinen eigenen Zustand die Wahrheit sagen. Es weiß nur vom Uhrwerk. Form 1: Die Zustands-Reparaturaufgabe läuft um T+5 Minuten, unabhängig davon, ob der Zustand um T+0 kaputt ist. Form 2: Die Berichtsaufgabe läuft um 2 Uhr früh, unabhängig davon, ob sich seit gestern irgendeine Daten geändert haben.

Das Uhrwerk trägt keine Informationen darüber, was getan werden muss. Ein Ereignis trägt diese Informationen: 'Eine Zustandsübergang ist gerade gescheitert', 'Neue Bestellungen sind gerade eingetroffen'. Ein gemessenes Herz wirft diese Informationen weg und ersetzt sie durch einen Zeitplan.

Kapitalentzug

Ein gemessenes Herz zieht lebendes Kapital: Ingenieure im Einsatz für defekte-Zustand-Incidenten. Lässt den sozialen Vertrauen ein: Benutzer sehen inkonsistente Daten und melden Fehler, die sich selbst beheben. Verstärkt andere MOADs: Eine Zustands-Reparatur-Arbeit, die alle Aufzeichnungen scannt, um defekten Zustand zu finden, enthält oft MOAD-0001 (O(N²)-Scan). Eine Berichterstellungsaufgabe, die Kaltrechnungen neu berechnet, kann MOAD-0005 (Cache-Stampede) auslösen. MOAD-0009 verbindet andere Fehler.

Der geteilte Wurzel

Form 1 & Form 2 erscheinen unterschiedlich auf der Oberfläche: Eine repariert den Zustand, die andere berechnet Daten neu. Die Ursachenwurzel verbindet sie.

Form 1 und Form 2 teilen sich eine Ursachenwurzel. Beschreiben Sie sie in einer Satz. Geben Sie dann ein Beispiel für jede Form aus Software, die Sie verwendet haben.

Feuer bei Änderung, nicht bei Uhr

Ereignisgetriebene Konzepte entfachen, wenn etwas geändert hat. Der Zustandswechsel ist das Ereignis. Das Ereignis ist der Auslöser.

Form 1: Der atomare Übergang ersetzt den Reparaturjob.

Wenn ein Zustandsübergang den Systemzustand in einem defekten Zwischenzustand lassen kann, befindet sich der Fehler im Übergang und nicht in seiner Abwesenheit eines Reparaturjobs. Beheben Sie den Übergang, um vollständig atomar (oder transaktional) zu sein. Wenn der Übergang vollständig atomar ist, existiert defekter Zustand nie. Der Reparaturjob hat nichts zu reparieren.

# Fehlertyp: nicht-atomarer Übergang lässt defekten Zustand zurück
def close_pr_on_repo_private(pr_id):
    pr = PR.get(pr_id)
    pr.status = 'branch-forced-closed'   # Schritt 1: partieller Zustand
    pr.save()                             # sichtbar für Benutzer NUN
    # ... möglicherweise fehlgeschlagene Schritte ...
    pr.merge_status = 'not_applicable'
    pr.save()                             # Schritt 2: jetzt konsistent
    # Sidekiq-Job stellt im Falle eines Schritt-2-Fehlers die Vereinbarung her
# KORREKTUR: atomarer Übergang; kein intermediäres Zustand sichtbar
def close_pr_on_repo_private(pr_id):
    with db.transaction():
        pr = PR.get(pr_id)
        pr.status = 'branch-forced-closed'
        pr.merge_status = 'not_applicable'
        pr.save()   # beide Felder werden atomar geschrieben; nie halb geschrieben

Form 2: Die inkrementelle Aktualisierung ersetzt die vollständige Neuberechnung.

Ein Bericht, der von vorne losrechnet, wird ausgelöst, weil alte Daten + neue Daten = neue Ergebnisse. Aber die alten Ergebnisse + Deltas = das gleiche neue Ergebnis, berechnet inkrementell. Der Ereignis: neue Daten sind eingegangen. Der Auslöser: Aktualisieren des Aggregats nur für die neuen Daten.

# FEHLER: vollständige Neuberechnung nach Zeitplan
def nightly_totals_job():
    for user in all_users():
        total = sum(o.amount for o in user.orders)  # Durchsuchen aller Zeit
        user.total_purchases = total
        user.save()

# KORREKTUR: ereignsgetriebene inkrementelle Aktualisierung
def on_order_placed(order):
    order.user.total_purchases += order.amount   # nur Delta
    order.user.save()

Die inkrementelle Aktualisierung wird nicht um 2 Uhr früh ausgelöst, sondern wenn eine Bestellung eingegangen ist. Sie aktualisiert nur den betroffenen Benutzer. Sie liest nur die neue Bestellung und nicht alle Bestellungen von alters her. Die Nachtjob verschwindet.

Warum Form 1 einen gebrochenen Übergang zeigt

Ein Form-1-Metered-Heart zeigt an, dass ein Zustandsübergang unvollständig blieb. Die Reparatur-Job existiert, weil ein Ingenieur einen gebrochenen Zustand bemerkt hat und anstelle des Zustandsübergangs eine Wiederherstellungsmechanismus hinzugefügt hat. Der Reparatur-Job: ein Patch über eine gebrochene architektonische Entscheidung.

MOAD-0009 als Verstärker

MOAD-0009 verstärkt andere MOADs. Ein Zustands-Reparatur-Job, der alle Datensätze durchsucht, um gebrochenen Zustand zu finden: MOAD-0001 (O(N) oder O(N²) Scan pro Jobausführung). Eine Berichterstellung, die alles kalt neu berechnet: MOAD-0005 (Cache-Stampede, wenn die Jobausführung losgeht und eine warme Quelle trifft). MOAD-0009 schädigt nicht nur selbst; sie liefert andere MOADs termingerecht.

Diagnose & Umgestaltung

Eine Mannschaft führt eine tägliche cron-Job-Ausführung um 2 Uhr morgens durch. Das Job scannet alle Bestellungen für alle Benutzer und berechnet jeden Benutzers Gesamtkaufbetrag von vorne. Das Job dauert 4 Stunden. Bis 6 Uhr morgens zeigt das Dashboard frische Gesamtbeträge. Zwischen 2 Uhr morgens und 6 Uhr morgens zeigt das Dashboard die Gesamtbeträge von gestern.

Welche Form von MOAD-0009 ist dies? Welches Ereignis sollte stattdessen die Neuberechnung auslösen? Welches Zwischenspeicherschema ermöglicht die inkrementelle Aktualisierung?