Commit Graph
2 Commits
Author SHA1 Message Date
sysopsandClaude Sonnet 5 b6184b67aa LIC-05: speicherverbrauch-metrik-je-tenant
internal/usage/storage.go: ReportStorageWrite/ReportStorageDelete sind
duenne Spezialisierungen von LIC-03s bereits atomarem Store.Increment auf
die feste Metrik "storage_bytes" — Loeschung nutzt einfach ein negatives
Delta desselben UPSERT-Mechanismus, kein zweiter Zaehl-Codepfad. Damit
uebernehmen Akzeptanzkriterium 2 (atomar, race-frei) und die zugehoerigen
LIC-03-Garantien direkt, ohne Duplikat.

CurrentStorageUsage ist ein einfaches Store.Get auf dieselbe Metrik —
LIC-03 kann denselben Wert ueber Store.Get(tenant, StorageBytesMetric)
abfragen (Akzeptanzkriterium 3, per Test TestCurrentStorageUsage_MatchesGenericStoreGet
belegt: kein zweiter, abweichender Zaehlmechanismus).

Die Objekt-Storage-Treiber der Module (DMS FDN-03, Mail ARC-01), die diese
Funktionen bei jedem Schreib-/Loeschvorgang aufrufen wuerden, existieren als
Code noch nicht (nur geplant in dms-kanban/mail-kanban) — diese Kachel
implementiert nur die Core-seitige Zaehl-Schnittstelle, analog zum
AUD-05/RetentionRegistrar-Muster.

Pruefungen (ausgefuehrt auf root@192.168.1.131, go build/vet/test PASS):
1. Paralleler Schreib-Test (viele gleichzeitige Uploads) ergibt korrekten
   Endstand ohne verlorene Updates —
   TestReportStorageWrite_ConcurrentUploadsSumCorrectly: 10 parallele
   Schreibvorgaenge unterschiedlicher Groesse, Endstand exakt gleich der in
   Go unabhaengig berechneten Summe. PASS.
2. Loeschvorgang dekrementiert korrekt — TestReportStorageDelete_Decrements. PASS.
3. Abfrage liefert konsistenten Wert mit unabhaengiger Kontrollzaehlung —
   TestCurrentStorageUsage_MatchesIndependentTally (gemischte Schreib-/
   Loeschfolge, in Go parallel mitgezaehlt) und
   TestCurrentStorageUsage_MatchesGenericStoreGet. PASS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 21:13:26 +02:00
sysopsandClaude Sonnet 5 d447869246 LIC-03: nutzungszaehler-quotas
internal/usage: Store.Increment aktualisiert Zaehlerstaende ueber ein
einziges atomares SQL-UPSERT (value = value + delta) statt Read-Modify-Write
in Go — haelt Zaehlerstaende bei parallelen Schreibzugriffen konsistent
(Akzeptanzkriterium 1), ganz ohne Anwendungs-Lock. Quotas sind Konfiguration
(usage_quotas-Tabelle je Tenant+Metrik), kein Hardcode.

Check/Enforce leiten aus Zaehlerstand + Quota eine definierte Reaktion ab
(StatusOK/Warning bei 80%/Exceeded, Akzeptanzkriterium 2) — Enforce ruft eine
uebergebene Reaction-Funktion auf, wenn der Status nicht OK ist; die
konkrete Sperr-/Benachrichtigungslogik bleibt beim Aufrufer (z.B. TEN-02 vor
Benutzeranlage), Enforce garantiert nur zuverlaessiges Ausloesen. Fehlende
Quota-Konfiguration bedeutet unbegrenzt (StatusOK), kein Fehler.

RunPeriodicAggregation ist das Aggregations-Grundgerüst (Akzeptanzkriterium 1:
"periodisch aggregiert") — dieselbe In-Prozess-Worker-Goroutine-Konvention
wie internal/tenant.Lifecycle.RunSweeper. Die konkrete Aggregationsquelle
(Zeilen zaehlen in Modul-Tabellen) haengt vom jeweiligen Modul ab und ist
nicht Teil dieser Kachel.

Pruefungen (ausgefuehrt auf root@192.168.1.131, go build/vet/test PASS):
1. Quota-Ueberschreitung automatisiert erkannt, definierte Reaktion
   ausgeloest — TestEnforce_TriggersReactionOnExceeded: Reaction-Callback
   wird mit StatusExceeded aufgerufen. PASS.
2. Aggregationsjob liefert bei parallelen Schreibzugriffen konsistente
   Zaehlerstaende — TestIncrement_ConsistentUnderConcurrentWrites: 50
   nebenlaeufige Increments, Endstand exakt 50 (kein Lost Update). PASS.
3. Zaehlerstand eines Tenants beeinflusst nicht den eines anderen —
   TestIncrement_IsolatedBetweenTenants. PASS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 21:10:11 +02:00