chore: refresh gramsrv public release

This commit is contained in:
A 2026-06-30 14:37:43 +08:00
parent 75cebe8dbf
commit 70b6820474
1274 changed files with 378751 additions and 59919 deletions

View file

@ -0,0 +1,76 @@
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()
}