6.6 KiB
6.6 KiB
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
- src/Framework/Storage/Clients/MinioClient.php
- 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)
- src/Framework/Storage/StorageManager.php
- 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)
- src/Framework/Storage/StorageInitializer.php
- Bucket-API (optional aber DX-freundlich):
- src/Framework/Storage/Bucket.php
- wrappt ObjectStorage für festen Bucket-Namen
- src/Framework/Storage/Bucket.php
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)
- Interface-Änderungen (ObjectStorage)
- FilesystemObjectStorage (inkl. Streaming)
- MinioClient (Basis + Signierung)
- MinioObjectStorage (inkl. Streaming)
- Initializer/DI und Konfig
- Tests (Unit), danach optional Integration
- 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)