60 lines
1.8 KiB
Go
60 lines
1.8 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"telesrv/internal/domain"
|
|
"telesrv/internal/readmodelcache"
|
|
)
|
|
|
|
// storyPinnedAvailableCache 缓存 (viewer,peer)→是否有置顶故事,由统一缓存原语承载
|
|
// (LRU 单条驱逐 / epoch 守卫 / 内建 singleflight;纯 TTL,无版本闸门)。
|
|
type storyPinnedAvailableCache struct {
|
|
cache *readmodelcache.Cache[storyProjectionCacheKey, bool]
|
|
}
|
|
|
|
func newStoryPinnedAvailableCache(now func() time.Time) *storyPinnedAvailableCache {
|
|
return &storyPinnedAvailableCache{
|
|
cache: readmodelcache.New[storyProjectionCacheKey, bool](readmodelcache.Config[storyProjectionCacheKey, bool]{
|
|
MaxEntries: storyProjectionCacheMaxEntries,
|
|
TTL: storyPinnedStoriesCacheTTL,
|
|
Now: now,
|
|
}),
|
|
}
|
|
}
|
|
|
|
func (c *storyPinnedAvailableCache) getOrLoad(ctx context.Context, viewerUserID int64, peer domain.Peer, load func() (bool, error)) (bool, error) {
|
|
if c == nil || viewerUserID == 0 || peer.ID == 0 {
|
|
return load()
|
|
}
|
|
return c.cache.GetOrLoad(ctx, storyProjectionCacheKey{viewerUserID: viewerUserID, peer: peer}, load)
|
|
}
|
|
|
|
func (c *storyPinnedAvailableCache) Delete(viewerUserID int64, peer domain.Peer) {
|
|
if c == nil || viewerUserID == 0 || peer.ID == 0 {
|
|
return
|
|
}
|
|
c.cache.Invalidate(storyProjectionCacheKey{viewerUserID: viewerUserID, peer: peer})
|
|
}
|
|
|
|
func (c *storyPinnedAvailableCache) DeleteViewer(viewerUserID int64) {
|
|
if c == nil || viewerUserID == 0 {
|
|
return
|
|
}
|
|
c.cache.InvalidateWhere(func(k storyProjectionCacheKey) bool { return k.viewerUserID == viewerUserID })
|
|
}
|
|
|
|
func (c *storyPinnedAvailableCache) DeletePeer(peer domain.Peer) {
|
|
if c == nil || peer.ID == 0 {
|
|
return
|
|
}
|
|
c.cache.InvalidateWhere(func(k storyProjectionCacheKey) bool { return k.peer == peer })
|
|
}
|
|
|
|
func (c *storyPinnedAvailableCache) Flush() {
|
|
if c == nil {
|
|
return
|
|
}
|
|
c.cache.Flush()
|
|
}
|