Драйверы хранилища

Раздел для тех, кто разворачивает castbase у себя (владельцы инсталляции). Пользователю сервиса он не нужен.

Доменный код castbase не знает, где физически лежат файлы. Он работает с двумя портами; конкретное хранилище выбирается строкой DSN в окружении, а новое подключается без правки доменного кода.

Порт Где Что делает Настройка
MediaStorage ядро (PHP) оригиналы загруженных медиа MEDIA_STORAGE_DSN
PublicMediaHost вертикаль (Python) публичные URL, с которых площадка скачивает файл PUBLIC_MEDIA_DSN

В v1 есть драйверы: local:// (диск сервера) для оригиналов и rsync:// (внешний хост вне РФ, JPEG-конвертация, публичный URL по public_base) для публичной раздачи. Meta не скачивает медиа с российских хостов, поэтому публичный хост — вне РФ; файлы там автоматически удаляются через 7 дней.

Драйвер оригиналов (ядро, PHP)

Порт App\Media\Application\MediaStorage:

interface MediaStorage
{
    /** @param resource $stream читается до конца, закрывать его — забота вызывающего */
    public function put(string $key, $stream, string $mime): void;

    /** @return resource поток для чтения; вызывающий закрывает @throws MediaNotFound */
    public function readStream(string $key);

    /** Идемпотентно: удаление отсутствующего объекта — не ошибка. */
    public function delete(string $key): void;

    public function exists(string $key): bool;
}

Как подключить новый драйвер (например, S3):

  1. Класс в src/Media/Infrastructure/, реализующий MediaStorageDriver: scheme() возвращает схему DSN (s3), create($dsn) разбирает DSN и возвращает реализацию MediaStorage.
  2. Тег app.media_storage_driver ставится автоматически (autoconfigure): services.yaml править не нужно.
  3. В .env.local на сервере: MEDIA_STORAGE_DSN=s3://…. Доменный код и контроллеры не меняются.

Неверный DSN даёт InvalidMediaStorageDsn со списком известных схем. Образец — LocalMediaStorageDriver.

Драйвер публичного хоста (вертикаль, Python)

Хранилище выбирается DSN в PUBLIC_MEDIA_DSN; доменный код вертикали знает только порт PublicMediaHost.

  1. Класс-наследник castbase_kit.media.PublicMediaHost:
    • put(local_path, name) — положить файл под именем name, доступным на чтение по public_base/name;
    • purge(older_than) — удалить выложенное старше срока, вернуть число файлов;
    • @classmethod from_dsn(dsn, **options) — разобрать свой DSN (обязателен public_base, если URL не вычисляется иначе — тогда переопределите url_for).
  2. Зарегистрировать схему в default_registry(): registry.register("s3", S3MediaHost.from_dsn).
  3. Тест драйвера по образцу tests/test_media.py; внешние вызовы — через подменяемый runner или клиент.
  4. На сервере сменить PUBLIC_MEDIA_DSN. Деплой кода вертикали не нужен, если драйвер уже в kit.

Сам DSN в сообщения об ошибках не попадает (в нём могут быть ключи).

Что остаётся неизменным

Ядро отдаёт оригинал вертикали по подписанному внутреннему URL; вертикаль конвертирует картинки в JPEG, выкладывает через PublicMediaHost и удаляет через 7 дней. Новый драйвер заменяет только «где лежат байты».