feat(realtime): доставлять клиентам события жизненного цикла альбома и изменения состава фото
Публиковать album.created/updated/deleted и изменения состава фото в личный поток SSE, а также photo.created при загрузке, чтобы списки альбомов, счётчики и открытые страницы альбома обновлялись без перезагрузки. - members.Repository получил Audience (владелец + участники) для дешёвого веера - albums.Service рассылает события в личные потоки получателей, перечитывая альбом через GetByID и attachCover, чтобы payload совпадал с GET /api/albums - members.Service публикует при принятии инвайта, смене роли и исключении - photos.Service публикует photo.created при загрузке и album.updated при добавлении/копировании/перемещении/восстановлении/корзине/окончательном удалении - photos_count теперь считает фото вне корзины - web-клиент подписывается на /api/sse/me один раз на уровне layout'а (app) и применяет события к стору альбомов; страница альбома уходит при потере доступа
This commit is contained in:
+32
-3
@@ -443,8 +443,10 @@ colors: {
|
||||
- `DELETE /api/comments/:id`
|
||||
|
||||
### Real-time (SSE)
|
||||
- `GET /api/sse/albums/:id` — события альбома
|
||||
- `GET /api/sse/me` — персональный поток (приглашения, уведомления)
|
||||
- `GET /api/sse/albums/:id` — события открытого альбома (`photo.*`, `like.*`,
|
||||
`comment.created`, `member.*`, `album.updated`, `album.deleted`)
|
||||
- `GET /api/sse/me` — персональный поток: `notification` и события жизненного цикла
|
||||
альбома `album.created`, `album.updated`, `album.deleted`
|
||||
|
||||
## 12. SSE — детали реализации
|
||||
|
||||
@@ -455,6 +457,30 @@ data: {"id":"...","album_id":"...","thumb_url":"...","uploader":{...}}
|
||||
|
||||
```
|
||||
|
||||
### Персональный поток (`/api/sse/me`)
|
||||
Несёт события, адресованные конкретному пользователю:
|
||||
|
||||
| Событие | Когда | payload |
|
||||
|---|---|---|
|
||||
| `notification` | создано уведомление для пользователя | объект уведомления |
|
||||
| `album.created` | альбом появился в списке пользователя (он его создал или принял инвайт) | объект альбома |
|
||||
| `album.updated` | изменены название/описание/обложка, состав участников или состав фото | объект альбома |
|
||||
| `album.deleted` | альбом удалён владельцем или доступ отозван (исключение из участников) | `{"id":"..."}` |
|
||||
|
||||
Объект альбома в `album.created` и `album.updated` совпадает по полям с элементом
|
||||
ответа `GET /api/albums`: `id`, `owner_id`, `title`, `description`, `cover_photo_id`,
|
||||
`cover_thumb_url`, `cover_medium_url`, `photos_count`, `members_count`, `created_at`,
|
||||
`updated_at`. Событие рассылается веером по личным каналам владельца и каждого
|
||||
участника альбома; `album.deleted` при исключении участника получает только
|
||||
исключённый. Публикация аддитивна: клиенты, которые не знают новый тип события,
|
||||
его игнорируют, а пер-альбомный контракт (`album.updated`, `album.deleted`) сохранён.
|
||||
|
||||
Состав фото отражается в персональном потоке: загрузка, копирование, перемещение,
|
||||
восстановление, перевод в корзину и окончательное удаление публикуют `album.updated`
|
||||
получателям (в пер-альбомный канал `album.updated` по этим поводам не идёт — открытая
|
||||
страница узнаёт об изменениях из `photo.*`). `photos_count` считает только фото вне
|
||||
корзины и совпадает с числом фото в сетке альбома.
|
||||
|
||||
### Backend: hub на каналах
|
||||
- В памяти `map[albumID]map[clientID]chan Event`
|
||||
- Регистрация клиента при подключении, удаление при отключении
|
||||
@@ -481,7 +507,10 @@ X-Accel-Buffering: no
|
||||
|
||||
### Догон пропущенного
|
||||
`EventSource` не отправляет `Last-Event-ID` надёжно. Поэтому при переподключении
|
||||
клиент догоняет пропущенное через REST: `GET /api/albums/:id/photos?since=<last_event_time>`.
|
||||
клиент догоняет пропущенное через REST: `GET /api/albums/:id/photos?since=<last_event_time>`
|
||||
для открытого альбома и `GET /api/albums` для списка альбомов (персональный поток).
|
||||
Догон списка восстанавливает изменения, пропущенные за время разрыва, в том числе
|
||||
удаления: удалённый альбом в ответе уже не приходит.
|
||||
|
||||
### Ограничения SSE
|
||||
- Односторонний поток (server → client), действия клиента — обычные POST/PATCH/DELETE
|
||||
|
||||
Reference in New Issue
Block a user