- move change media-object-layer to openspec/changes/archive/2026-10-10-media-object-layer - add main spec specs/media-objects (opaque keys, object journal, shared objects, reference-based GC, lifecycle recovery, variant generation queue) - update specs/photos deletion requirement to place photos in the trash without deleting storage objects
4.8 KiB
4.8 KiB
Tasks
1. Схема и миграции
- 1.1 Добавить миграцию, создающую
objects,photo_objects(PKphoto_id,role, индексobject_id) иvariant_jobs; проверить, чтоmake migrateприменяется и таблицы видны в БД - 1.2 Добавить миграцию, удаляющую
photos.storage_key,photos.thumb_key,photos.preview_key,photos.size,photos.width,photos.height,photos.mime_type; проверить, что up и down миграции проходят в обе стороны без ошибок
2. Слой хранения
- 2.1 Удалить
DeletePrefixизinternal/storage/storage.go; проверитьgo build ./...и отсутствие вызовов метода в коде - 2.2 Ввести хелпер ключа объекта вида
objects/{id}/{role}.{ext}без идентификатора альбома; покрыть юнит-тестом, что ключ не содержит album_id
3. Метаданные объектов
- 3.1 Реализовать стор объектов: создание
pending, активацияready, пометкаdeleting, удаление строки, выборкаpendingстарше порога; покрыть тестами переходы состояний - 3.2 Реализовать привязку
photo_objectsс блокировкой объектаFOR UPDATEи отказом приstate != 'ready'; тест на повторную привязку одного объекта к двум фото - 3.3 Реализовать запрос GC (объекты
readyбез связок) и тесты сценариев «последняя ссылка удалена» и «остались ссылки»
4. Сервис фото
- 4.1 Переписать
Upload: строка объектаpending→ S3 Put →ready→ привязкаoriginal+ задание вvariant_jobs; тест, что загрузка даёт фото с URL оригинала и ключом без альбома - 4.2 Переписать
List/Get/attachURLsна вывод ключей иsize/width/height/mime_typeджойном к объекту-оригиналу; тест, что JSON-поля и URL присутствуют как раньше - 4.3 Переписать
CopyBatch/MoveBatchна работу только через связки; тест, что объекты хранилища не меняются и делятся между фото - 4.4 Переписать
PermanentDelete: удалить связки и пометить осиротевшие объектыdeleting; тест, что объект с нулём ссылок становится кандидатом на GC - 4.5 Убрать обращения к удалённым колонкам во всех запросах и моделях; проверить
go build ./...и прохождениеinternal/repoтестов
5. Фоновый воркер
- 5.1 Реализовать цикл забора
variant_jobsчерезFOR UPDATE SKIP LOCKED, генерацию thumb/preview, привязку и публикацию SSE; тест обработки задания и повтора при ошибке - 5.2 Реализовать в воркере удаление
deleting(с повторной проверкой нуля ссылок) и досасывание зависшихpending; тест повторной попытки S3 Delete и очисткиpending - 5.3 Встроить старт/останов воркера в жизненный цикл приложения; проверить, что сервер запускается и воркер выполняет петлю (по логам/интеграционному тесту)
6. Интеграция и документация
- 6.1 Перевести обложку альбома (
CoverThumbKey) на вывод черезphoto_objects+objects; тест, что список альбомов отдаёт URL обложки - 6.2 Обновить
project.md§10 (структура в S3 и слои); проверить, что описание совпадает с реализованными ключами - 6.3 Сквозная проверка: загрузка → генерация вариантов → копирование между альбомами (0 операций S3) → перенос → окончательное удаление → сборка объектов; проверить, что объекты удаляются только при нуле ссылок