feat(archive): BAK-05 Reconciliation Storage vs. DB
Deterministischer Abgleich zwischen DMS file_revisions und Objekt-Storage-Verzeichnis, existenz-only (keine Inhaltspruefung, saubere Abgrenzung zu BAK-08). Report sortiert nach storage_key fuer stabile Weiterverarbeitung durch BAK-08. Systemd-Timer taeglich, real auf 192.168.1.131 verdrahtet und ausgeloest.
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# BAK-05 – Prüfprotokoll: Reconciliation / Konsistenzprüfung Storage vs. DB
|
||||
|
||||
Voraussetzung BAK-01, BAK-02 (Welle 1) – erledigt, siehe eigene Protokolle.
|
||||
|
||||
## Grundsatzentscheidung: reine Funktion + zwei Quell-Adapter
|
||||
|
||||
`internal/reconcile.Reconcile` ist eine reine Funktion ohne DB-/Storage-
|
||||
Zugriff (leicht ohne echte Infrastruktur testbar), die Ein- und
|
||||
Auslesen echter Systeme ist strikt in `sources.go` getrennt
|
||||
(`ListDBStorageKeys` gegen echtes Postgres, `ListStorageObjects` gegen
|
||||
echtes Dateisystem). Beide Seiten liefern nur SCHLÜSSEL – niemals Inhalt
|
||||
– dadurch bleibt BAK-05 sauber getrennt von BAK-08 (Inhalts-/Prüfsummen-
|
||||
verifikation, eigene Fehlerklasse, eigenes Ticket).
|
||||
|
||||
Report-Format bewusst deterministisch: beide Ergebnislisten
|
||||
(`missing_in_storage`, `orphaned_in_storage`) nach `storage_key`
|
||||
aufsteigend sortiert, damit BAK-08 später dieselbe Objektliste als
|
||||
stabile Stichprobenquelle weiterverarbeiten kann, ohne selbst neu zu
|
||||
sortieren/filtern (Nutzervorgabe).
|
||||
|
||||
Meldeweg über OPS-05 (wie später BAK-08) wurde als offene Design-Frage
|
||||
aufgeworfen, aber nicht zur Vorbedingung gemacht – hier bewusst noch
|
||||
nicht umgesetzt (kein OPS-05-Abhängigkeitseintrag im Board für BAK-05);
|
||||
Report wird aktuell nur als JSON auf stdout ausgegeben und per
|
||||
Exit-Code (1 bei Abweichungen) für systemd/Monitoring sichtbar gemacht.
|
||||
Anbindung an OPS-05 kann bei Bedarf nachgezogen werden, ohne
|
||||
`Reconcile` selbst zu ändern.
|
||||
|
||||
## Umsetzung
|
||||
|
||||
- `internal/reconcile.Reconcile(dbEntries, storageKeys) Report` – reine
|
||||
Vergleichsfunktion, liefert `MissingInStorage`/`OrphanedInStorage`,
|
||||
`Report.IsClean()` als eindeutiges Sauber-Merkmal.
|
||||
- `internal/reconcile.ListDBStorageKeys` – liest `file_revisions`
|
||||
(DMS FDN-02) per direktem SQL aus derselben physischen Tenant-DB
|
||||
(Modell C, Core TEN-01) – kein Import von DMS-Go-Paketen möglich
|
||||
(eigenes Go-Modul), daher reiner SQL-Zugriff gegen das dokumentierte
|
||||
Schema.
|
||||
- `internal/reconcile.ListStorageObjects` – durchläuft den lokalen
|
||||
FDN-03-`LocalDriver`-Basisordner (`filepath.WalkDir`), liefert `nil,
|
||||
nil` bei fehlendem Verzeichnis statt Fehler (noch keine Objekte ist
|
||||
kein Fehlerzustand).
|
||||
- `cmd/reconcile-cli` – liest `NEXARCH_RECONCILE_TENANT_DSN` und
|
||||
`NEXARCH_RECONCILE_STORAGE_DIR`, gibt Report als JSON auf stdout aus,
|
||||
Exit-Code 1 bei Abweichungen.
|
||||
|
||||
## Prüfungen
|
||||
|
||||
| # | Prüfung | Ergebnis |
|
||||
|---|---|---|
|
||||
| 1 | Datenbankeintrag ohne Storage-Objekt wird erkannt | **bestanden** — `TestReconcile_DetectsMissingInStorage` |
|
||||
| 2 | Storage-Objekt ohne Datenbankeintrag wird erkannt | **bestanden** — `TestReconcile_DetectsOrphanedInStorage` |
|
||||
| 3 | Lauf ohne Abweichungen liefert leeren, eindeutig sauberen Bericht | **bestanden** — `TestReconcile_CleanRunProducesEmptyReport` (zusätzlich `IsClean()`-Konsistenzprüfung) |
|
||||
|
||||
Zusätzlich (Nutzervorgaben, nicht explizit im Ticket als Pflichtprüfung
|
||||
benannt, aber zentral für die Abgrenzung/Weiterverwendbarkeit):
|
||||
|
||||
- `TestReconcile_ExistingButCorruptedObjectProducesNoFinding` – Nachweis,
|
||||
dass Reconcile AUSSCHLIESSLICH Existenz prüft, niemals Inhalt (Trennung
|
||||
von BAK-08).
|
||||
- `TestReconcile_DeterministicOrdering` – zwei Läufe mit identischer
|
||||
Eingabe liefern identische Reihenfolge, aufsteigend nach `storage_key`.
|
||||
- `TestListDBStorageKeys_ReadsRealFileRevisions` – liest echt gegen die
|
||||
gemeinsame Tenant-Testdatenbank `dms_tenant_test` (reales DMS-FDN-02-
|
||||
Schema, kein Mock).
|
||||
- `TestListStorageObjects_WalksRealDirectory` /
|
||||
`_MissingDirectoryReturnsEmpty` – echtes Dateisystem, kein Mock.
|
||||
|
||||
## Echte Verdrahtung auf 192.168.1.131
|
||||
|
||||
- `reconcile-cli` gebaut nach `/opt/nexarch-archive/bin/`
|
||||
- `/etc/nexarch/archive-reconcile.env` (0600): `NEXARCH_RECONCILE_TENANT_DSN`
|
||||
zeigt auf die gemeinsame Tenant-Testdatenbank `dms_tenant_test`
|
||||
(DMS selbst läuft auf 192.168.1.131 noch nicht als eigener systemd-
|
||||
Dienst mit persistenter Konfiguration – dies ist die real verfügbare
|
||||
Tenant-DB mit echtem FDN-02-Schema, dokumentierter bekannter Stand,
|
||||
kein stiller Mock); `NEXARCH_RECONCILE_STORAGE_DIR` zeigt auf
|
||||
`/var/nexarch-archiv/dms-objects` (persistentes ZFS-Dataset, NICHT
|
||||
`/var/nexarch-test/`).
|
||||
- Timer `nexarch-archive-reconcile.timer` installiert und aktiviert
|
||||
(täglich 05:00 UTC), `systemctl list-timers` bestätigt scharf.
|
||||
- `systemctl start nexarch-archive-reconcile.service` real ausgelöst:
|
||||
`status=0/SUCCESS`, Journal zeigt echten JSON-Report
|
||||
(`missing_in_storage: null, orphaned_in_storage: null` – Tenant-DB
|
||||
aktuell leer, daher sauberer Bericht, keine synthetische Ausgabe).
|
||||
|
||||
## Build/Test-Ergebnis (192.168.1.131, `make check`)
|
||||
|
||||
```
|
||||
go build ./... -> clean
|
||||
go vet ./... -> clean
|
||||
golangci-lint run ./... -> 0 issues
|
||||
go test ./... -p 1 -count=1 -> 3/3 Pakete mit Tests ok (internal/backup, internal/objectbackup, internal/reconcile), 0 Fehlschläge
|
||||
```
|
||||
|
||||
`internal/reconcile`-Tests separat mit gesetzter `TEST_TENANT_DSN` gegen
|
||||
`dms_tenant_test` verifiziert: 8/8 Tests bestanden (5 reine
|
||||
`Reconcile`-Tests + 3 `sources.go`-Integrationstests).
|
||||
|
||||
## Gesamtergebnis
|
||||
|
||||
**Bestanden.** Alle drei Akzeptanzkriterien und alle Pflicht- sowie
|
||||
Nutzervorgaben-Prüfungen real erfüllt (echte Postgres-Instanz, echtes
|
||||
Dateisystem, echter systemd-Lauf). Zwei Testfehler während der
|
||||
Entwicklung (Schema-Abweichung `revision_number` NOT NULL in der realen
|
||||
`dms_tenant_test`-Tabelle; inkonsistente Fixture-Daten in
|
||||
`TestReconcile_DeterministicOrdering`) gefunden und korrigiert – beide
|
||||
waren Testautorenfehler, keine Fehler in `Reconcile` selbst.
|
||||
Reference in New Issue
Block a user