Публиковать 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) и применяет события к стору альбомов; страница альбома уходит при потере доступа
48 lines
1.2 KiB
Go
48 lines
1.2 KiB
Go
package sse
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// Publishing to a user with no subscription must be a no-op: it must neither
|
|
// panic nor register an empty subscription entry.
|
|
func TestPublishUserWithoutSubscriberIsNoop(t *testing.T) {
|
|
h := NewHub(4)
|
|
h.PublishUser("nobody", "album.created", map[string]string{"id": "a1"})
|
|
|
|
h.mu.RLock()
|
|
_, created := h.users["nobody"]
|
|
h.mu.RUnlock()
|
|
if created {
|
|
t.Fatalf("PublishUser created a subscription entry for an absent user")
|
|
}
|
|
}
|
|
|
|
// The personal and per-album channels are independent: a personal event must
|
|
// not leak into the album channel.
|
|
func TestPublishUserDoesNotReachAlbumChannel(t *testing.T) {
|
|
h := NewHub(4)
|
|
albumSub := h.SubscribeAlbum("a1")
|
|
defer albumSub.Close()
|
|
userSub := h.SubscribeUser("u1")
|
|
defer userSub.Close()
|
|
|
|
h.PublishUser("u1", "album.created", map[string]string{"id": "a1"})
|
|
|
|
select {
|
|
case ev := <-albumSub.Events():
|
|
t.Fatalf("album channel received personal event %q", ev.Type)
|
|
case <-time.After(50 * time.Millisecond):
|
|
}
|
|
|
|
select {
|
|
case ev := <-userSub.Events():
|
|
if ev.Type != "album.created" {
|
|
t.Fatalf("user event = %q, want album.created", ev.Type)
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatalf("personal subscriber did not receive the event")
|
|
}
|
|
}
|