chore(openspec): архивировать android-live-albums и fix-album-cover-readiness

Дельта android-live-albums: android-client (+3 требования: живое обновление
списка, догон при переподключении, потеря доступа) и realtime (порядок списка
теперь правило отображения клиента).

Дельта fix-album-cover-readiness: realtime (+1 требование: album.updated при
готовности вариантов фото-обложки).
This commit is contained in:
iu
2026-10-16 12:48:32 +03:00
parent d0d6362a01
commit 14db79632a
13 changed files with 521 additions and 1 deletions
@@ -0,0 +1,38 @@
# Tasks
## 1. Клиент персонального потока
- [x] 1.1 Добавить в `GaloApi` запрос персонального потока (`api/sse/me`, `Accept: text/event-stream`); проверить request-тестом, что URL собран от базового адреса и заголовок выставлен
- [x] 1.2 Добавить парсер событий жизненного цикла альбома (`album.created`, `album.updated`, `album.deleted` -> типы с объектом/идентификатором; `notification` и неизвестные -> игнорировать); проверить unit-тестами на каждый тип, на неизвестный тип и на битый JSON
- [x] 1.3 Добавить `PersonalSseClient` по образцу `AlbumSseClient` (backoff, событие `Reconnected` после разрыва); проверить тестом: события доходят в порядке получения, после разрыва приходит `Reconnected`
- [x] 1.4 Проверить завершение соединения при отмене коллектора (отменяется ли `EventSource`, когда поток перестают собирать), при необходимости закрывать его в `finally`/`invokeOnClose`; проверить тестом, что после отмены поток не переоткрывается
## 2. Применение событий к кэшу
- [x] 2.1 Вывести удаление в `AlbumLocalSource` (`deleteByIds`) и `PhotoLocalSource` (очистка фото альбома); проверить тестами локального источника, что записи удаляются
- [x] 2.2 Добавить в `AlbumRepository` применение событий: `album.created`/`album.updated` заменяют альбом, `album.deleted` удаляет альбом вместе с его фото; проверить тестами на фейках: обновлённый объект виден из `observeAlbums`, удалённый исчезает вместе со своими фото
- [x] 2.3 Связать клиент персонального потока с репозиторием в `AppContainer` и обработчиком событий; проверить тестом, что событие из потока меняет то, что отдаёт `observeAlbums`
## 3. Подписка на время сессии
- [x] 3.1 Подписаться на персональный поток в `AlbumsViewModel` и завершать подписку при уничтожении ViewModel; проверить тестом, что подписка создаётся один раз и не пересоздаётся при повторном обращении к состоянию
- [x] 3.2 На `Reconnected` вызывать `albumRepository.refresh()`; проверить тестом, что альбом, удалённый на сервере за время разрыва, исчезает из кэша после догона
- [x] 3.3 Обновить `android/README.md`, раздел «Live updates»: персональный поток, обновление списка и потеря доступа; проверить, что описанный эндпоинт совпадает с реализованным запросом
## 4. Потеря доступа к альбому
- [x] 4.1 Отслеживать в `AlbumViewModel` факт «альбом уже был показан» и отдавать сигнал потери доступа при переходе «ненулевой -> отсутствует»; проверить unit-тестами оба случая: был и исчез — сигнал есть, не было изначально (нет кэша, нет сети) — сигнала нет
- [x] 4.2 По сигналу потери доступа экран альбома возвращается к списку; проверить Compose-тестом (Robolectric), что экран инициирует возврат, а список больше не содержит альбом
- [x] 4.3 Проверить сценарий исключения участника: `album.deleted` приходит только личным потоком, альбом исчезает из списка и открытый экран уходит назад
## 5. Интеграционная проверка
- [x] 5.1 Прогнать сквозной сценарий на двух аккаунтах против локального сервера: создание, переименование, смена обложки, удаление альбома и исключение участника — список и открытый экран обновляются без ручного обновления; приложить результат (шаги и наблюдение)
- [x] 5.2 Проверить поведение при истечении токена в долгоживущем потоке: соединение восстанавливается после обновления токена; если нет — зафиксировать ограничение в README
- [x] 5.3 Прогнать на финальной ревизии `cd android && ./gradlew test` и `cd android && ./gradlew :app:assembleDebug`; зафиксировать, что обе команды проходят
- [x] 5.4 Прогонять unit-тесты только на debug-варианте (тестовая активность Compose приходит из debug-зависимости `ui-test-manifest`), чтобы `cd android && ./gradlew test` проходил без тестовой активности в release-манифесте; проверить `./gradlew test`, `:app:assembleDebug` и `:app:assembleRelease`
## Workflow follow-up
- Заархивировать change после прохождения ревью проекта (`openspec archive android-live-albums`).
- Проверить, что после архивации требования вошли в `openspec/specs/android-client/spec.md` и `openspec/specs/realtime/spec.md`, а `openspec validate --strict android-live-albums` не выдаёт ошибок.