owpengram-server/internal/app/stargifts/service.go

124 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package stargifts 实现 Star 礼物应用服务:礼物目录(从 seed 合成、懒加载缓存)+ peer 收到的
// 礼物实例 CRUD。扣费/退款/服务消息投递由 rpc 层编排(复用 Stars 账本 + SendPrivateText
// 本层只管目录与持久化。
package stargifts
import (
"context"
"sync"
"telesrv/internal/domain"
"telesrv/internal/store"
)
// CatalogProvider 合成礼物目录app/files 实现)。
type CatalogProvider interface {
BuildStarGiftCatalog(ctx context.Context) ([]domain.StarGift, error)
}
// Service 是 Star 礼物应用服务。
type Service struct {
store store.StarGiftStore
catalog CatalogProvider
mu sync.Mutex
built bool
gifts []domain.StarGift
byID map[int64]domain.StarGift
hash int
}
// NewService 创建 Star 礼物服务。
func NewService(st store.StarGiftStore, catalog CatalogProvider) *Service {
return &Service{store: st, catalog: catalog}
}
// ensureCatalog 懒加载并缓存目录(静态数据,构建一次)。
func (s *Service) ensureCatalog(ctx context.Context) error {
s.mu.Lock()
defer s.mu.Unlock()
if s.built {
return nil
}
gifts, err := s.catalog.BuildStarGiftCatalog(ctx)
if err != nil {
return err
}
s.gifts = gifts
s.byID = make(map[int64]domain.StarGift, len(gifts))
for _, g := range gifts {
s.byID[g.ID] = g
}
s.hash = domain.StarGiftCatalogHash(gifts)
s.built = true
return nil
}
// Catalog 返回礼物目录。
func (s *Service) Catalog(ctx context.Context) ([]domain.StarGift, error) {
if err := s.ensureCatalog(ctx); err != nil {
return nil, err
}
s.mu.Lock()
defer s.mu.Unlock()
out := make([]domain.StarGift, len(s.gifts))
copy(out, s.gifts)
return out, nil
}
// CatalogHash 返回目录 hashgetStarGifts NotModified 判定)。
func (s *Service) CatalogHash(ctx context.Context) (int, error) {
if err := s.ensureCatalog(ctx); err != nil {
return 0, err
}
s.mu.Lock()
defer s.mu.Unlock()
return s.hash, nil
}
// GiftByID 返回目录中指定礼物,不存在返回 ok=false。
func (s *Service) GiftByID(ctx context.Context, id int64) (domain.StarGift, bool, error) {
if err := s.ensureCatalog(ctx); err != nil {
return domain.StarGift{}, false, err
}
s.mu.Lock()
defer s.mu.Unlock()
g, ok := s.byID[id]
return g, ok, nil
}
// RecordSavedGift 持久化一条收到的礼物实例,返回行 id。
func (s *Service) RecordSavedGift(ctx context.Context, gift domain.SavedStarGift) (int64, error) {
return s.store.Create(ctx, gift)
}
// ListSaved 分页返回某 owner 收到的礼物。
func (s *Service) ListSaved(ctx context.Context, owner domain.Peer, excludeUnsaved bool, offset string, limit int) (domain.SavedStarGiftPage, error) {
if len(offset) > domain.MaxStarGiftsOffsetBytes {
offset = ""
}
if limit <= 0 || limit > domain.MaxSavedStarGiftsLimit {
limit = domain.MaxSavedStarGiftsLimit
}
return s.store.ListByOwner(ctx, owner, excludeUnsaved, offset, limit)
}
// GetSaved 按协议引用取礼物实例。
func (s *Service) GetSaved(ctx context.Context, ref domain.SavedStarGiftRef) (domain.SavedStarGift, bool, error) {
return s.store.GetByRef(ctx, ref)
}
// CountSaved 返回某 owner 展示在资料的礼物数full.stargifts_count
func (s *Service) CountSaved(ctx context.Context, owner domain.Peer) (int, error) {
return s.store.CountByOwner(ctx, owner)
}
// ToggleSaved 切换礼物在资料的展示saveStarGift
func (s *Service) ToggleSaved(ctx context.Context, ref domain.SavedStarGiftRef, unsaved bool) (bool, error) {
return s.store.SetUnsaved(ctx, ref, unsaved)
}
// Convert 把礼物标记为已转换convertStarGift返回该行供调用方据 ConvertStars 入账。
func (s *Service) Convert(ctx context.Context, ref domain.SavedStarGiftRef) (domain.SavedStarGift, error) {
return s.store.MarkConverted(ctx, ref)
}