Дельта android-live-albums: android-client (+3 требования: живое обновление списка, догон при переподключении, потеря доступа) и realtime (порядок списка теперь правило отображения клиента). Дельта fix-album-cover-readiness: realtime (+1 требование: album.updated при готовности вариантов фото-обложки).
5.1 KiB
Design
Context
См. proposal.md — мотивация. Что важно для подхода:
- Ссылки на обложку формируются из
photo_objects(ролиthumb/medium), которые заполняются асинхронно, поэтому в объекте альбома (Store.GetByIDджойнит обложку) они появляются не в момент загрузки, а когда варианты готовы. - Загрузка фото вызывает
SetCoverIfEmpty, то есть первое фото становится обложкой ещё до генерации вариантов, аNotifyAlbumChangedна этом шаге публикуетalbum.updatedуже сcover_photo_id, но с пустыми ссылками. - Готовность вариантов обрабатывает
Worker.notify(internal/photos/worker.go): он публикует толькоphoto.updatedв канал альбома и персональные потоки не трогает. albums.Serviceуже умеет перечитать альбом, обогатить обложку (attachCover) и веерно опубликоватьalbum.updated(NotifyAlbumChanged→PublishAlbumTo).
Goals / Non-Goals
Goals:
- Доставить актуальную ссылку на обложку в персональные потоки, когда она появляется.
- Не увеличивать поток событий при массовой загрузке.
Non-Goals:
- Менять контракт
photo.updatedв канале альбома (открытый экран закрывает свой случай сам). - Клиентские обходные пути (рефетч списка по таймеру и т.п.).
- Синхронная генерация вариантов при загрузке.
Decisions
1. Публикует albums.Service, а не воркер.
Решение «объект альбома изменился» принимает владелец альбомов: добавляется
NotifyCoverReady(ctx, albumID, photoID), который перечитывает альбом и публикует
album.updated, только если cover_photo_id == photoID (иначе no-op), переиспользуя
NotifyAlbumChanged. Воркер остаётся про фото и лишь сообщает о готовности.
Альтернатива — строить album.updated прямо в воркере: тогда photos пришлось бы знать
форму объекта альбома, обложку и аудиторию.
2. Условие — совпадение с текущей обложкой.
Готовность вариантов обычного фото объект альбома не меняет. Без условия пришлось бы на
каждое фото перечитывать альбом и веерно публиковать album.updated всем участникам — лишняя
нагрузка при массовой загрузке и лишние события клиентам.
Альтернатива — «публиковать всегда»: проще, но шумно; отвергнуто.
3. Проверка по cover_photo_id, а не по «в альбоме ещё нет ссылки на обложку».
Так закрываются оба сценария: и автопоставленная обложка первой загрузкой, и явная установка
обложки на фото, варианты которого ещё не готовы.
Risks / Trade-offs
- Двойное чтение альбома (
GetByIDдля проверки обложки и внутриPublishAlbumTo) → дополнительное чтение точечное (только для готовности вариантов фото-обложки), принято; при необходимости схлопывается в один публикующий вызов. - Гонка со сменой обложки между публикацией
photo.createdи готовностью вариантов → проверка по актуальномуcover_photo_idотсекает лишнюю публикацию, а новая обложка получит своё событие при готовности её вариантов. - Аудитория недоступна (ошибка в
members.Audience) → событие не публикуется; клиент догоняет состояние при переподключении (refresh) — существующее поведение веера.
Migration Plan
Изменение аддитивное: схема и API не меняются, нужен только перезапуск бэкенда (логика и статика в одном бинарнике). Откат — предыдущий бинарник.