76 lines
2.2 KiB
Go
76 lines
2.2 KiB
Go
package rpc
|
|
|
|
import (
|
|
"time"
|
|
|
|
"telesrv/internal/readmodelcache"
|
|
)
|
|
|
|
// projectionCache 是 RPC 层 per-viewer TTL 投影缓存的统一核心,基于 readmodelcache.Cache。
|
|
// 4 个结构同形的投影缓存(userFull/peerSettings/channelFull/channelFullBot)收敛到它,
|
|
// 仅在键类型、值类型、clone、失效维度上不同;TTL 与时钟、LRU 单条驱逐、epoch 守卫均由原语承载。
|
|
//
|
|
// 这些投影走「外部构建再写回」模式(LoadEpoch → 在 handler 内构建 → StoreIfEpoch),而非
|
|
// GetOrLoad:投影需要 ctx、多次往返与富化,无法塞进单个 load 回调。epoch 守卫确保构建期间
|
|
// 到达的失效不会被 pre-invalidation 快照覆盖(避免陈旧 per-viewer 投影留满一个 TTL)。
|
|
type projectionCache[K comparable, V any] struct {
|
|
cache *readmodelcache.Cache[K, V]
|
|
}
|
|
|
|
func newProjectionCache[K comparable, V any](max int, ttl time.Duration, clock func() time.Time, clone func(V) V) *projectionCache[K, V] {
|
|
return &projectionCache[K, V]{
|
|
cache: readmodelcache.New[K, V](readmodelcache.Config[K, V]{
|
|
MaxEntries: max,
|
|
TTL: ttl,
|
|
Now: clock,
|
|
Clone: clone,
|
|
}),
|
|
}
|
|
}
|
|
|
|
// Lookup 返回缓存项(TTL 过期视为 miss);clone 由原语在返回边界完成。
|
|
func (c *projectionCache[K, V]) lookup(key K) (V, bool) {
|
|
if c == nil {
|
|
var zero V
|
|
return zero, false
|
|
}
|
|
return c.cache.Peek(key)
|
|
}
|
|
|
|
// storeIfEpoch 仅在 epoch 自 loadEpoch 以来未变时写回外部构建的值。
|
|
func (c *projectionCache[K, V]) storeIfEpoch(key K, v V, loadEpoch uint64) {
|
|
if c == nil {
|
|
return
|
|
}
|
|
c.cache.StoreIfEpoch(key, v, loadEpoch)
|
|
}
|
|
|
|
// LoadEpoch 在构建前快照 epoch,与 storeIfEpoch 配对实现外部构建路径的 epoch 守卫。
|
|
func (c *projectionCache[K, V]) LoadEpoch() uint64 {
|
|
if c == nil {
|
|
return 0
|
|
}
|
|
return c.cache.LoadEpoch()
|
|
}
|
|
|
|
func (c *projectionCache[K, V]) deleteKey(key K) {
|
|
if c == nil {
|
|
return
|
|
}
|
|
c.cache.Invalidate(key)
|
|
}
|
|
|
|
func (c *projectionCache[K, V]) deleteWhere(pred func(K) bool) {
|
|
if c == nil {
|
|
return
|
|
}
|
|
c.cache.InvalidateWhere(pred)
|
|
}
|
|
|
|
// Clear 清空缓存并自增 epoch(listener 重连兜底)。
|
|
func (c *projectionCache[K, V]) Clear() {
|
|
if c == nil {
|
|
return
|
|
}
|
|
c.cache.Flush()
|
|
}
|