Files
backend/internal/service/channel_service.go
lafay a887e8ea23
All checks were successful
Build Backend / build (push) Successful in 13m4s
Build Backend / build-docker (push) Successful in 1m22s
feat(channel): enhance channel service with caching and repository updates
- Updated ChannelService to include caching for channel lists, improving performance and reducing database load.
- Introduced cache invalidation methods to ensure channel list consistency after modifications.
- Modified ChannelRepository to remove unused ListByIDs method, streamlining the repository interface.
- Updated wire generation to inject cache into ChannelService for enhanced functionality.
- Added new cache key constants for channel-related data management.
2026-03-25 01:03:34 +08:00

130 lines
3.3 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 service
import (
"time"
"carrot_bbs/internal/cache"
"carrot_bbs/internal/model"
"carrot_bbs/internal/repository"
)
// 频道全量列表缓存 TTL频道变更少可较长管理端写入后会主动失效
const channelAllListCacheTTL = 10 * time.Minute
type ChannelService interface {
ListActive() ([]*model.Channel, error)
ListAll() ([]*model.Channel, error)
MapByIDs(ids []string) (map[string]*model.Channel, error)
Create(name, slug, description string, sortOrder int, isActive bool) (*model.Channel, error)
Update(id, name, slug, description string, sortOrder int, isActive bool) (*model.Channel, error)
Delete(id string) error
}
type channelServiceImpl struct {
channelRepo *repository.ChannelRepository
cache cache.Cache
}
func NewChannelService(channelRepo *repository.ChannelRepository, c cache.Cache) ChannelService {
return &channelServiceImpl{channelRepo: channelRepo, cache: c}
}
func (s *channelServiceImpl) invalidateChannelListCache() {
if s.cache != nil {
cache.InvalidateChannelList(s.cache)
}
}
func (s *channelServiceImpl) listAllFromDB() ([]*model.Channel, error) {
return s.channelRepo.ListAll()
}
func (s *channelServiceImpl) ListAll() ([]*model.Channel, error) {
if s.cache == nil {
return s.listAllFromDB()
}
cs := cache.GetSettings()
return cache.GetOrLoadTyped(s.cache, cache.ChannelsAllListKey(), channelAllListCacheTTL, cs.JitterRatio, cs.NullTTL, s.listAllFromDB)
}
func (s *channelServiceImpl) ListActive() ([]*model.Channel, error) {
all, err := s.ListAll()
if err != nil {
return nil, err
}
out := make([]*model.Channel, 0, len(all))
for _, ch := range all {
if ch != nil && ch.IsActive {
c := *ch
out = append(out, &c)
}
}
return out, nil
}
// MapByIDs 始终基于全量频道列表Redis 命中则零 SQL否则一次 ListAll与 ListActive / 公开列表共用同一缓存快照。
func (s *channelServiceImpl) MapByIDs(ids []string) (map[string]*model.Channel, error) {
if len(ids) == 0 {
return nil, nil
}
all, err := s.ListAll()
if err != nil {
return nil, err
}
byID := make(map[string]*model.Channel, len(all))
for _, ch := range all {
if ch != nil {
byID[ch.ID] = ch
}
}
out := make(map[string]*model.Channel, len(ids))
for _, id := range ids {
if ch, ok := byID[id]; ok {
out[id] = ch
}
}
return out, nil
}
func (s *channelServiceImpl) Create(name, slug, description string, sortOrder int, isActive bool) (*model.Channel, error) {
channel := &model.Channel{
Name: name,
Slug: slug,
Description: description,
SortOrder: sortOrder,
IsActive: isActive,
}
if err := s.channelRepo.Create(channel); err != nil {
return nil, err
}
s.invalidateChannelListCache()
return channel, nil
}
func (s *channelServiceImpl) Update(id, name, slug, description string, sortOrder int, isActive bool) (*model.Channel, error) {
channel, err := s.channelRepo.GetByID(id)
if err != nil {
return nil, err
}
channel.Name = name
channel.Slug = slug
channel.Description = description
channel.SortOrder = sortOrder
channel.IsActive = isActive
if err := s.channelRepo.Update(channel); err != nil {
return nil, err
}
s.invalidateChannelListCache()
return channel, nil
}
func (s *channelServiceImpl) Delete(id string) error {
err := s.channelRepo.Delete(id)
if err != nil {
return err
}
s.invalidateChannelListCache()
return nil
}