fix(realtime): доставлять обложку альбома после готовности вариантов

Карточка альбома не получала ссылку на обложку: она появляется в объекте
альбома только после генерации thumb/medium, а событие об этом шаге в
персональные потоки не публиковалось — счётчик обновлялся, обложка нет.

- albums.Service.NotifyCoverReady публикует album.updated получателям, когда
  варианты готовы у фото, являющегося текущей обложкой (иначе no-op, чтобы
  массовая загрузка не рассылала событие на каждый файл)
- photos: порт AlbumAccess расширен, worker вызывает публикацию после
  photo.updated
- project.md §11/§12: триггер добавлен в контракт персонального потока
This commit is contained in:
iu
2026-10-16 12:47:50 +03:00
parent 742745e6aa
commit 44cb7c7d68
7 changed files with 129 additions and 11 deletions
+17
View File
@@ -80,6 +80,23 @@ func (s *Service) NotifyAlbumChanged(ctx context.Context, albumID string) {
s.PublishAlbumTo(ctx, albumID, EventAlbumUpdated, s.albumAudience(ctx, albumID))
}
// NotifyCoverReady republishes the album to personal streams when the photo that
// is currently its cover gains its variant URLs. The album object only carries a
// cover link once thumb/medium exist, so without this event an album card keeps
// showing a placeholder. Readiness of any other photo does not change the album
// object and is ignored, which keeps bulk uploads from fanning out an event per
// file.
func (s *Service) NotifyCoverReady(ctx context.Context, albumID, photoID string) {
a, err := s.store.GetByID(ctx, albumID)
if err != nil {
return
}
if a.CoverPhotoID == nil || *a.CoverPhotoID != photoID {
return
}
s.NotifyAlbumChanged(ctx, albumID)
}
// albumAudience resolves the users an album is visible to. Resolution failures
// are swallowed: a missed fan-out is recovered by the client's reconnect sync
// and must not fail the mutation that triggered it.