- realtime: личный поток несёт события жизненного цикла альбома и изменения счётчика фото; добавлены требования о жизненном цикле, получателях, форме payload'а, догоне и потере доступа - albums: photos_count считает только фото вне корзины
8.3 KiB
Proposal
Why
Real-time сейчас работает только для открытого альбома: события изменений альбома публикуются
в канал конкретного альбома, поэтому у пользователя, который не смотрит этот альбом, список
альбомов (рейл, главная) остаётся устаревшим до перезагрузки страницы. Персональный поток
GET /api/sse/me существует, но не несёт событий жизненного цикла альбома, и ни один клиент
в него не подписан — то есть создание, переименование, смена обложки, изменение состава
участников и удаление альбома не доходят до тех, кого они касаются.
Отдельно устаревает состав фото: загрузка, перемещение, копирование, восстановление и удаление
фото не публикуют событие альбома, поэтому счётчик photos_count и обложка на карточках не
обновляются, а открытая страница альбома у других клиентов не показывает загруженное фото
(Upload не публикует photo.created, хотя способность realtime это требует).
What Changes
- Персональный поток
GET /api/sse/meначинает нести события жизненного цикла альбома:album.createdиalbum.updatedс полным объектом альбома в той же форме, что отдаётGET /api/albums, иalbum.deletedс{id}. - Получатели события — пользователи, для которых альбом входит в список доступных: владелец
(
albums.owner_id) и участники (album_members); событие доставляется веером по личным каналам. - Публикации добавляются в: создание альбома, принятие инвайта, изменение названия/описания/ обложки, смену роли, исключение участника и выход, удаление альбома.
- Список альбомов обновляется и при изменении состава фото: загрузка, перемещение,
копирование, восстановление, перевод в корзину и окончательное удаление публикуют
album.updatedв личные потоки владельца и участников, поэтомуphotos_countи обложка на карточках становятся актуальными без перезагрузки. - Загрузка фото публикует
photo.createdв канал альбома, поэтому открытая страница альбома у других клиентов добавляет новое фото; готовность вариантов по-прежнему приходит какphoto.updatedи обновляет фото на месте. - Web-клиент подписывается на
/api/sse/meна уровне layout'а приложения и применяет события к стору списка альбомов (upsert/remove) без повторного запроса; при переподключении догоняет состояние черезGET /api/albums. - Открытая страница альбома начинает обрабатывать
album.deleted(сейчас обрабатывается толькоalbum.updated, поэтому удалённый альбом продолжает отображаться у участников). - Контракт существующих пер-альбомных событий (
photo.*,like.*,comment.created,member.*,album.updated) и REST не меняется:Uploadначинает публиковать уже предусмотренный контрактомphoto.created, остальное — аддитивно.
Не входит в этап (осознанно отложено): персистентный центр уведомлений (колокольчик,
список непрочитанных, новые типы в таблице notifications); Android-клиент (личный поток
остаётся совместимым, подключение мобильного клиента — отдельный шаг); принудительный обрыв
пер-альбомного SSE у исключённого участника.
Capabilities
New Capabilities
Нет — поведение описывает расширение существующей способности realtime, отдельная
способность не вводится.
Modified Capabilities
realtime: персональный поток обязан нести события жизненного цикла альбома с полным payload'ом; определяются получатели события, поведение клиента при получении (обновление или удаление альбома в списке без запроса) и догон состояния при переподключении. Дополнительно определяются события при изменении состава фото: список альбомов обновляется в реальном времени, а загрузка фото публикуетphoto.created.albums: уточняется счётчикphotos_count— он считает только доступные в альбоме фото (вне корзины), чтобы совпадать с сеткой и корректно меняться при переводе в корзину и восстановлении.
Impact
- Код (backend):
internal/sse(веер по личным каналам),internal/albums/service.go(Create/Update/Delete, рассылкаalbum.updatedполучателям),internal/members/service.go(Accept/ChangeRole/Remove),internal/photos/service.go(загрузка/удаление/перемещение/ копирование/восстановление фото публикуютphoto.createdиalbum.updated), точка сборкиinternal/app/app.goиcmd/server/main.go— если для веера потребуется новый интерфейс-резолвер аудитории альбома. - Код (frontend):
routes/(app)/+layout.svelte(единая подписка на/api/sse/me),lib/stores/albums.svelte.ts(upsert/remove/load как обработчики событий),routes/(app)/albums/[id]/+page.svelte(обработкаalbum.deleted),lib/sse.ts— список известных событий. - API: новых HTTP-эндпоинтов нет; существующий
GET /api/sse/meначинает отдавать дополнительные типы событий. Для старых клиентов изменение аддитивное. - Не затрагивается:
notifications(персистентные уведомления остаются как есть),android-client(требование live-обновлений там и так ограничено активным экраном альбома), схема БД, миграции, зависимости. - Известное ограничение, фиксируемое отдельной задачей: доступ к пер-альбомному SSE проверяется только при подключении, поэтому исключённый участник продолжает получать события альбома до разрыва соединения.