updated cache

This commit is contained in:
2025-12-01 21:12:46 +01:00
parent 925dc319e8
commit 2372da942a
2 changed files with 67 additions and 46 deletions

99
util/cache/cache.go vendored
View File

@@ -1,70 +1,91 @@
package cache package cache
import "sync"
type Cache struct {
mu sync.RWMutex
s2c map[string]string
c2s map[string]string
}
func NewCache() *Cache { func NewCache() *Cache {
return &Cache{ c := &Cache{}
c.state.Store(&mappings{
s2c: make(map[string]string), s2c: make(map[string]string),
c2s: make(map[string]string), c2s: make(map[string]string),
} })
return c
} }
// Set creates or overwrites the pair a -> b and b -> a.
// It ensures any previous mappings involving a or b are removed first.
func (c *Cache) Set(serverId, channelId string) { func (c *Cache) Set(serverId, channelId string) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
if old, ok := c.s2c[serverId]; ok && old != channelId { current := c.state.Load()
delete(c.c2s, old) next := current.clone()
if oldCh, ok := next.s2c[serverId]; ok && oldCh != channelId {
delete(next.c2s, oldCh)
}
if oldSrv, ok := next.c2s[channelId]; ok && oldSrv != serverId {
delete(next.s2c, oldSrv)
} }
if old, ok := c.c2s[channelId]; ok && old != serverId { next.s2c[serverId] = channelId
delete(c.s2c, old) next.c2s[channelId] = serverId
}
c.s2c[serverId] = channelId c.state.Store(next)
c.c2s[channelId] = serverId
} }
func (c *Cache) GetByServerId(serverId string) (string, bool) { func (c *Cache) GetByServerId(serverId string) (string, bool) {
c.mu.RLock() m := c.state.Load()
defer c.mu.RUnlock() val, ok := m.s2c[serverId]
return val, ok
cId, ok := c.s2c[serverId]
return cId, ok
} }
func (c *Cache) GetByChannelId(channelId string) (string, bool) { func (c *Cache) GetByChannelId(channelId string) (string, bool) {
c.mu.RLock() m := c.state.Load()
defer c.mu.RUnlock() val, ok := m.c2s[channelId]
return val, ok
sId, ok := c.c2s[channelId]
return sId, ok
} }
func (c *Cache) RemoveByServerId(serverId string) { func (c *Cache) RemoveByServerId(serverId string) {
c.mu.RLock() c.mu.Lock()
defer c.mu.RUnlock() defer c.mu.Unlock()
if channelId, ok := c.s2c[serverId]; ok { current := c.state.Load()
delete(c.s2c, serverId) if _, ok := current.s2c[serverId]; !ok {
delete(c.c2s, channelId) return
} }
next := current.clone()
if channelId, ok := next.s2c[serverId]; ok {
delete(next.s2c, serverId)
delete(next.c2s, channelId)
}
c.state.Store(next)
} }
func (c *Cache) RemoveByChannelId(channelId string) { func (c *Cache) RemoveByChannelId(channelId string) {
c.mu.RLock() c.mu.Lock()
defer c.mu.RUnlock() defer c.mu.Unlock()
if serverId, ok := c.s2c[channelId]; ok { current := c.state.Load()
delete(c.c2s, channelId) if _, ok := current.c2s[channelId]; !ok {
delete(c.s2c, serverId) return
} }
next := current.clone()
if serverId, ok := next.c2s[channelId]; ok {
delete(next.c2s, channelId)
delete(next.s2c, serverId)
}
c.state.Store(next)
}
func (m *mappings) clone() *mappings {
newM := &mappings{
s2c: make(map[string]string, len(m.s2c)),
c2s: make(map[string]string, len(m.c2s)),
}
for k, v := range m.s2c {
newM.s2c[k] = v
}
for k, v := range m.c2s {
newM.c2s[k] = v
}
return newM
} }

14
util/cache/structs.go vendored
View File

@@ -2,15 +2,15 @@ package cache
import ( import (
"sync" "sync"
"sync/atomic"
) )
type ShardedCache struct { type Cache struct {
shards []*shard mu sync.Mutex
shardMask uint32 state atomic.Pointer[mappings]
} }
type shard struct { type mappings struct {
mu sync.RWMutex s2c map[string]string
s2c map[string]string // serverId -> channelId c2s map[string]string
c2s map[string]string // channelId -> serverId
} }