3 KiB
3 KiB
Object Storage
This document explains how object storage works today, and how to control it across environments.
TL;DR
- The app has one storage interface (
StorageClient) and two implementations:MinioClientfor local/dev (S3-compatible MinIO)BunnyClientfor deployed environments (Bunny Storage + Bunny CDN)
- Provider selection is controlled by
STORAGE_PROVIDER:local-> MinIObunny-> Bunny
- The client is initialised once at API startup and stored as a process-level singleton.
Runtime Lifecycle
- API startup runs
init_storage()fromapp.outbound.storage_factory. init_storage()reads config fromapp.config.settings.- It creates either
MinioClientorBunnyClient. - The client instance is set via
_set_storage_client(...). - App code calls
get_storage_client()anywhere it needs object URLs or file operations.
If storage is used before startup initialisation, get_storage_client() raises an assertion error.
Interface Contract
StorageClient currently exposes:
upload(path, data) -> boolget_url(path) -> strget_public_url(path) -> strdelete(path) -> booldownload(path) -> (bytes, content_type)
Important behavior differences:
- MinIO supports
download(...)for API media proxy routes. - Bunny does not support direct download in this adapter and raises
NotImplementedError; callers should use signed CDN URLs fromget_url(...).
URL Behavior
Local/MinIO mode (STORAGE_PROVIDER=local)
get_url(path)returns API-proxied URLs under/media/....- Browser requests go through the API media router.
- Media router validates DB ownership/existence, then streams bytes from storage.
Bunny mode (STORAGE_PROVIDER=bunny)
get_url(path)returns a signed Bunny CDN URL.- Signature uses token auth key + path + expiry (currently 1 hour).
- Browser requests go directly to Bunny CDN (no API proxy hop).
Configuration
Local/MinIO settings
STORAGE_PROVIDER=localSTORAGE_ENDPOINT_URL(for Docker dev:http://storage:9000)STORAGE_ACCESS_KEYSTORAGE_SECRET_KEYSTORAGE_BUCKETAPI_BASE_URL(used to build/media/...URLs)
On startup, MinioClient.ensure_bucket_exists() is called.
Bunny settings
STORAGE_PROVIDER=bunnyBUNNY_ZONEBUNNY_API_KEYBUNNY_CDN_BASE_URLBUNNY_TOKEN_AUTH_KEYBUNNY_STORAGE_ENDPOINT
On startup, Bunny client runs list_directory("") as a connection test.
Where Storage Is Used
- BFF routers call
get_storage_client().get_url(...)to expose audio URLs. - Media router calls
get_storage_client().download(...)to stream files for/media/...routes.
Practically:
- In local mode,
/media/...endpoints are expected and functional. - In Bunny mode, clients should consume returned CDN URLs directly.
Operational Notes
- Upload content type is currently fixed to
audio/wavin both adapters. - Bunny signed URL expiry is
_SIGNED_URL_EXPIRY_SECONDS = 3600. - The storage client is per-process; each API process initialises its own instance at boot.