updated cache
This commit is contained in:
99
util/cache/cache.go
vendored
99
util/cache/cache.go
vendored
@@ -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
14
util/cache/structs.go
vendored
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user