FDN-03: objekt-storage-abstraktion
Ein Driver-Interface, zwei austauschbare Treiber: LocalDriver (Entwicklung, Dateisystem, HMAC-signierte URLs) und S3Driver (Produktion, S3-kompatibel via aws-sdk-go-v2, echte presigned URLs). Pfadschema documents/<id>/ revisions/<id> innerhalb des mandantenspezifischen Buckets. Service verbindet Driver mit Nutzungsmeldung an Core LIC-05 (HTTPUsageReporter, Vertrag von internal/resync.Handler nachgebildet, DMS kann Cores internal/- Pakete als eigenes Modul nicht importieren). Auf 192.168.1.131 verifiziert, S3-Treiber gegen echtes lokal installiertes MinIO (kein Mock): Round-Trip beide Treiber, abgelaufene presigned URL real mit 403 abgewiesen (manuell zusaetzlich zum Unit-Test verifiziert), klare ErrNotFound bei fehlendem Objekt beide Treiber, Nutzungsmeldung mit korrektem Tenant/Metrik/Delta bei Put/Delete. Befund dokumentiert: Cores internal/resync.Handler (Gegenstelle fuer die Nutzungsmeldung) ist noch in keinem cmd/*/main.go verdrahtet (dieselbe Fehlerklasse wie QA-05/AUD-06) - HTTPUsageReporter daher gegen den dokumentierten Vertrag getestet, nicht gegen eine laufende Core-Instanz. Siehe dms/docs/FDN-03-PRUEFPROTOKOLL.md. golangci-lint auf v2.1.6 aktualisiert (v1.63.4 konnte go1.24-Zielstand nicht linten), .golangci.yml auf v2-Konfigurationsformat migriert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
9d4c2bae4a
commit
442bb674e9
@@ -0,0 +1,59 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Service verbindet einen Driver mit der Nutzungsmeldung an Core
|
||||
// (Akzeptanzkriterium 4) — jeder Schreib-/Loeschvorgang ueber Service loest
|
||||
// GENAU EINE Meldung mit der tatsaechlich geschriebenen/geloeschten
|
||||
// Objektgroesse aus. Repository-/Handler-Code (spaetere Kacheln, z.B.
|
||||
// DOC-01) ruft ausschliesslich Service auf, nie einen Driver direkt — das
|
||||
// verhindert einen Schreibpfad, der die Nutzungsmeldung vergisst.
|
||||
type Service struct {
|
||||
driver Driver
|
||||
usage UsageReporter
|
||||
tenantSlug string
|
||||
}
|
||||
|
||||
func NewService(driver Driver, usage UsageReporter, tenantSlug string) *Service {
|
||||
return &Service{driver: driver, usage: usage, tenantSlug: tenantSlug}
|
||||
}
|
||||
|
||||
// Put legt das Objekt ab und meldet die geschriebene Groesse als positives
|
||||
// Delta (Pruefung 4).
|
||||
func (s *Service) Put(ctx context.Context, key string, r io.Reader, size int64, contentType string) (int64, error) {
|
||||
written, err := s.driver.Put(ctx, key, r, size, contentType)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := s.usage.Report(ctx, s.tenantSlug, UsageMetric, written); err != nil {
|
||||
return written, fmt.Errorf("storage: objekt gespeichert, aber nutzungsmeldung fehlgeschlagen: %w", err)
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
|
||||
func (s *Service) Get(ctx context.Context, key string) (io.ReadCloser, error) {
|
||||
return s.driver.Get(ctx, key)
|
||||
}
|
||||
|
||||
// Delete entfernt das Objekt und meldet dessen Groesse als negatives Delta
|
||||
// (Pruefung 4) — dafuer muss der Aufrufer die Groesse kennen (z.B. aus
|
||||
// file_revisions.size_bytes, FDN-02), da Delete selbst die Groesse eines
|
||||
// bereits geloeschten Objekts nicht mehr ermitteln kann.
|
||||
func (s *Service) Delete(ctx context.Context, key string, sizeBytes int64) error {
|
||||
if err := s.driver.Delete(ctx, key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.usage.Report(ctx, s.tenantSlug, UsageMetric, -sizeBytes); err != nil {
|
||||
return fmt.Errorf("storage: objekt geloescht, aber nutzungsmeldung fehlgeschlagen: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) SignedURL(ctx context.Context, key string, ttl time.Duration) (string, error) {
|
||||
return s.driver.SignedURL(ctx, key, ttl)
|
||||
}
|
||||
Reference in New Issue
Block a user