Files
michaelschiemer/src/Framework/Storage/STREAMING_IMPLEMENTATION_PLAN.md

6.6 KiB
Raw Blame History

Streaming-Implementationsliste (Option 2) Storage Modul

Ziel: Dedizierte Streaming-Methoden in der Object Storage API implementieren ohne externe Dependencies. Fokus auf speichereffiziente Downloads/Uploads großer Dateien via Streams (memory-safe).

1) Interface-Erweiterung (ObjectStorage)

  • Ergänze folgende Methoden im ObjectStorage-Interface:
    • get(string $bucket, string $key): string
    • put(string $bucket, string $key, string|mixed $body, array $opts = []): ObjectInfo
    • getToStream(string $bucket, string $key, mixed $destination): int
      • Erwartet eine schreibbare PHP-Stream-Resource als $destination
      • Rückgabewert: Anzahl geschriebener Bytes
    • putFromStream(string $bucket, string $key, mixed $source, array $opts = []): ObjectInfo
      • Erwartet eine lesbare PHP-Stream-Resource als $source
    • openReadStream(string $bucket, string $key)
      • Gibt eine lesbare PHP-Stream-Resource zurück
    • head(string $bucket, string $key): ObjectInfo
    • delete(string $bucket, string $key): void
    • exists(string $bucket, string $key): bool
    • url(string $bucket, string $key): ?string
    • temporaryUrl(string $bucket, string $key, \DateInterval $ttl, array $opts = []): string

Hinweise:

  • Signaturen mit mixed für Stream-Parameter (PHP-Resource), genaue Validierung in den Implementierungen.
  • Bestehende Methoden get/put bleiben kompatibel; Streaming ist ergänzend.

2) Filesystem-Adapter (lokales Backend)

Ziel: ObjectStorage-Implementierung auf Basis des bestehenden Filesystem-Backends.

  • Neue Klasse: src/Framework/Storage/FilesystemObjectStorage.php
  • Verantwortlichkeiten:
    • Pfadaufbau: basePath/bucket/key
    • get/put über Filesystem (kleine Dateien)
    • Streaming:
      • getToStream: Datei lesen und via stream_copy_to_stream in $destination schreiben
      • putFromStream: Stream-Inhalt in Datei schreiben (Chunked Copy)
      • openReadStream: lesbaren Stream auf die Datei öffnen
    • head/exists/delete/url/temporaryUrl:
      • head: Dateigröße, mtime, mimetype (falls verfügbar)
      • url: für lokales Storage in der Regel null (oder optionaler lokaler URL-Generator)
      • temporaryUrl: nicht unterstützt -> Exception oder leer lassen mit Doku
  • Fehlerbehandlung:
    • File not found, Permission, Read/Write-Errors sauber abbilden
  • Performance:
    • Buffersize bei stream_copy_to_stream kontrollierbar machen (Optionen)

3) MinIO-Backend (ohne Dependencies)

Ziel: S3-kompatibler MinIO-Client mittels nativer PHP-Funktionen (HTTP-Streams und AWS SigV4) + ObjectStorage-Adapter.

  • Dateien:
    • src/Framework/Storage/Clients/MinioClient.php
      • Funktionen: putObject, getObject, headObject, deleteObject, createPresignedUrl
      • Streaming-Funktionen:
        • getObjectToStream($bucket, $key, $destination): int
        • putObjectFromStream($bucket, $key, $source, array $opts = []): array
        • openStream($bucket, $key) -> resource
      • Interne Helfer:
        • AWS SigV4 Signierung (kanonische Anfrage, Header, Query, Hashes)
        • Response-Parsing (Headers, Status, Fehler-XML)
        • Chunked Transfer wenn keine Content-Length verfügbar
    • src/Framework/Storage/MinioObjectStorage.php
      • Implementiert ObjectStorage
      • get/put: kleinere Dateien
      • getToStream/putFromStream/openReadStream: nutzen die Streaming-APIs des MinioClient
      • head/delete/exists/url/temporaryUrl:
        • temporaryUrl via createPresignedUrl
  • Sicherheit:
    • TTL-Limits für temporaryUrl (z. B. max 24h)
    • Path-Style vs. Virtual Host Style konfigurierbar
    • Keine externen Pakete

4) Manager/Factory/DI

  • Option A: StorageManager für ObjectStorage-Driver (local/minio)
    • src/Framework/Storage/StorageManager.php
      • driver(string $name): ObjectStorage
      • bucket(string $name): Bucket (Convenience)
  • Option B (einfach): Container-Bindings direkt
    • Default ObjectStorage anhand ENV
  • Initializer:
    • src/Framework/Storage/StorageInitializer.php
      • Konfig aus ENV (DEFAULT_DRIVER, MINIO_ENDPOINT, KEYS, LOCAL_ROOT, PATH_STYLE etc.)
      • Registriere:
        • FilesystemObjectStorage (als "local")
        • MinioClient + MinioObjectStorage (als "minio")
        • ObjectStorage (Default: ENV)
  • Bucket-API (optional aber DX-freundlich):
    • src/Framework/Storage/Bucket.php
      • wrappt ObjectStorage für festen Bucket-Namen

5) Konfiguration

  • ENV Variablen vorschlagen (Beispiele):
    • STORAGE_DRIVER=local|minio
    • STORAGE_LOCAL_ROOT=/var/www/html/storage/objects
    • MINIO_ENDPOINT=http://minio:9000
    • MINIO_ACCESS_KEY=...
    • MINIO_SECRET_KEY=...
    • MINIO_REGION=us-east-1
    • MINIO_USE_PATH_STYLE=true
  • StorageConfig Klasse (optional) für strukturierte Konfig-Verwaltung

6) Tests (kritisch, da streaming-sensitiv)

  • Unit-Tests FilesystemObjectStorage:
    • put/get mit Strings
    • putFromStream/getToStream mit temp Streams (php://temp)
    • openReadStream und sequentielles Lesen
    • head/exists/delete
  • Unit-Tests MinioClient (Signierung) isoliert:
    • Signatur-Konsistenz (Golden Master)
    • Parsing von Fehlern/Headers
  • Integration-Tests (optional, per docker-compose mit MinIO):
    • Upload/Download großer Dateien (z. B. >100MB) per Streams
    • temporaryUrl Zugriff (GET) mit TTL
  • Edge Cases:
    • fehlende Read-/Write-Berechtigungen (Filesystem)
    • Netzwerkfehler (MinIO)
    • Nicht existierende Objekte
    • Streams ohne bekannte Länge (Chunked Transfer)

7) Fehler- und Ausnahmebehandlung

  • Konsistente Exceptions im Storage-Namespace (z. B. StorageException)
  • Filesystem-spezifische Fehler sauber mappen
  • Aussagekräftige Meldungen (inkl. Pfad/Bucket/Key)

8) Performance/Robustheit

  • Stream-Buffer konfigurierbar (z. B. 8192 Bytes Default)
  • Keine vollständigen Dateiladungen in Memory bei Streams
  • Zeitouts/Retry-Strategie (MinIO) minimal vorsehen (optional)
  • Sauberes Schließen aller Streams (try/finally)

9) Sicherheit

  • Path-Sanitizing im Filesystem-Adapter (keine Directory-Traversal)
  • Eindeutige Handhabung von public URL vs. presigned URL
  • Limitierung der Presign-Dauer und Validierung von Eingaben

10) Dokumentation

  • README/HowTo:
    • Beispiel für lokale und MinIO-Nutzung
    • Beispiele für Streaming (Upload/Download)
    • Hinweise zu großen Dateien, Memory-Effizienz
  • PHPDoc ausführlich an allen Public-APIs

11) Milestones (Reihenfolge)

  1. Interface-Änderungen (ObjectStorage)
  2. FilesystemObjectStorage (inkl. Streaming)
  3. MinioClient (Basis + Signierung)
  4. MinioObjectStorage (inkl. Streaming)
  5. Initializer/DI und Konfig
  6. Tests (Unit), danach optional Integration
  7. Doku + Beispiele

12) Definition of Done

  • Alle neuen Methoden implementiert und getestet
  • Große Dateien via Streams funktionieren, ohne OOM
  • Kein externer Dependency-Einsatz
  • Doku und Beispiele vorhanden
  • CI-Tests grün (Unit; Integration optional)