# media-objects Specification ## Purpose Физическое объектное хранилище с непрозрачными ключами и журналом объектов: привязка объектов к фото по ролям, совместное использование объектов несколькими фото и сборка мусора по отсутствию ссылок. ## Requirements ### Requirement: Непрозрачные ключи хранилища Слой хранения SHALL адресоваться непрозрачными ключами объектов, не содержащими идентификаторов сущностей метаданных (таких как альбом или фото); сопоставление ключей и сущностей SHALL храниться только в слое метаданных. #### Scenario: Ключ без альбома - **WHEN** система сохраняет объект в хранилище - **THEN** ключ объекта не содержит идентификатора альбома #### Scenario: Перенос не трогает ключи - **WHEN** фото переносится в другой альбом - **THEN** ключи его объектов остаются неизменными ### Requirement: Журнал объектов Каждый физический объект SHALL иметь ровно одну запись в слое метаданных с ключом, MIME-типом, размером, габаритами и состоянием; фото SHALL ссылаться на объекты по ролям original, thumb, medium, preview, playback, edit, edit_thumb, edit_medium и edit_preview. #### Scenario: Привязка ролей - **WHEN** фото загружено и обработано - **THEN** фото ссылается на объект-оригинал и, когда они готовы, на объекты thumb, medium и preview #### Scenario: Оригинал без вариантов - **WHEN** варианты ещё не сгенерированы - **THEN** фото доступно с оригиналом, а thumb, medium и preview отсутствуют #### Scenario: Привязка роли воспроизведения - **WHEN** видео обработано - **THEN** медиа ссылается на объект playback наряду с оригиналом и постером #### Scenario: Привязка отредактированной версии - **WHEN** фото отредактировано и отредактированная версия отрендерена - **THEN** фото ссылается на объекты edit, edit_thumb, edit_medium и edit_preview рядом с исходными вариантами ### Requirement: Совместные объекты Несколько фото SHALL иметь возможность ссылаться на один и тот же физический объект; перенос и копирование SHALL изменять только ссылки и SHALL не изменять объекты хранилища. Отредактированная версия SHALL создаваться и привязываться только к тому фото, чьи правки её породили, в отличие от обычных вариантов, которые разделяются копиями того же оригинала. Копирование SHALL NOT переносить отредактированную версию на копию: копия фото с правками SHALL показываться в исходном виде и SHALL NOT наследовать параметры правок. #### Scenario: Копирование - **WHEN** пользователь копирует фото в другой альбом - **THEN** создаётся новая запись, ссылающаяся на те же объекты, без операций с хранилищем #### Scenario: Перенос - **WHEN** пользователь переносит фото в другой альбом - **THEN** изменяется только привязка к альбому, объекты хранилища не меняются #### Scenario: Правка не распространяется на копии - **WHEN** фото скопировали в другой альбом, а затем отредактировали исходное фото - **THEN** отредактированные объекты привязаны только к отредактированному фото, а копия остаётся в исходном виде #### Scenario: Копия отредактированного фото - **WHEN** фото с уже отрендеренной отредактированной версией копируют в другой альбом - **THEN** копия не получает отредактированные объекты, показывается в исходном виде и не наследует параметры правок ### Requirement: Сборка мусора по ссылкам Объект хранилища SHALL удаляться только когда на него не ссылается ни одно фото и ни один аватар пользователя; удаление альбома и попадание фото в корзину SHALL сохранять объекты. #### Scenario: Последняя ссылка удалена - **WHEN** фото удаляется навсегда и больше ни одно фото не ссылается на его объекты - **THEN** объекты удаляются из хранилища #### Scenario: Остались ссылки - **WHEN** на объект ссылается другое фото - **THEN** объект сохраняется в хранилище #### Scenario: Удаление альбома - **WHEN** владелец удаляет альбом - **THEN** объекты хранилища не удаляются #### Scenario: Ссылка аватара - **WHEN** на объект ссылается аватар пользователя - **THEN** объект сохраняется в хранилище, пока ссылка существует ### Requirement: Устойчивость жизненного цикла объекта Объект SHALL иметь состояние жизненного цикла, и незавершённые операции SHALL самовосстанавливаться: неудачная загрузка не оставляет осиротевших объектов, а удаление объекта SHALL доводиться до конца после сбоя. #### Scenario: Сбой загрузки - **WHEN** запись объекта создана, но загрузка в хранилище не завершилась - **THEN** объект очищается без ручного вмешательства #### Scenario: Сбой удаления - **WHEN** удаление объекта из хранилища не удалось - **THEN** попытка повторяется до успешного удаления ### Requirement: Генерация вариантов Генерация вариантов SHALL выполняться через надёжную очередь заданий с однократным выполнением и повтором при сбое; готовый результат SHALL транслироваться подписчикам альбома. Очередь SHALL поддерживать настраиваемую пропускную способность, SHALL обрабатывать более свежие фото раньше остальных и SHALL различать короткие задания изображений и длительные задания видео. Рендер отредактированных версий SHALL использовать отдельную очередь, чтобы правки не блокировали генерацию обычных вариантов. #### Scenario: Повтор после рестарта - **WHEN** процесс перезапускается с незавершёнными заданиями - **THEN** генерация вариантов продолжается #### Scenario: Событие после генерации - **WHEN** варианты фото готовы - **THEN** подписчикам альбома публикуется событие обновления этого фото #### Scenario: Приоритет свежих фото - **WHEN** в очереди есть готовые к обработке задания разного возраста - **THEN** система обрабатывает более свежие фото раньше #### Scenario: Настраиваемая пропускная способность - **WHEN** задан уровень параллелизма генерации - **THEN** система обрабатывает варианты с этим уровнем параллелизма #### Scenario: Длительное задание видео - **WHEN** выполняется длительная подготовка видео - **THEN** задание удерживается на весь срок выполнения и не вытесняет генерацию вариантов изображений #### Scenario: Рендер правок не блокирует варианты - **WHEN** в фоне выполняется рендер отредактированной версии - **THEN** генерация обычных вариантов продолжается независимо от него ### Requirement: Аватар пользователя как объект журнала Аватар пользователя SHALL храниться как объект журнала, привязанный к пользователю по ролям, соответствующим нарезкам аватара. Замена и удаление аватара SHALL менять привязку, а объекты без ссылок SHALL освобождаться сборкой мусора. #### Scenario: Привязка аватара - **WHEN** пользователь устанавливает аватар - **THEN** объекты нарезок привязываются к пользователю по своим ролям #### Scenario: Замена аватара - **WHEN** пользователь заменяет аватар - **THEN** привязка указывает на новые объекты, а старые освобождаются сборкой мусора #### Scenario: Удаление аватара - **WHEN** пользователь удаляет аватар - **THEN** привязка снимается, и объекты аватара освобождаются сборкой мусора