Hermes/src/core/repos/cache_inmem.go

100 lines
1.6 KiB
Go

package repos
import (
"sync"
"time"
)
type Cache[K comparable, V any] interface {
Get(key K) (V, bool)
Set(key K, value V, ttlSeconds int)
Del(key K)
CheckExpired()
}
func NewCacheInmem[K comparable, V any](ttlSeconds int) Cache[K, V] {
return &cacheInmem[K, V]{
m: &sync.Mutex{},
data: map[K]*cacheInmemItem[V]{},
ttlSeconds: ttlSeconds,
}
}
type cacheInmemItem[T any] struct {
Value T
Ttl int64
Expiration int64
}
type cacheInmem[K comparable, V any] struct {
m *sync.Mutex
data map[K]*cacheInmemItem[V]
ttlSeconds int
}
func (c *cacheInmem[K, V]) Get(key K) (V, bool) {
c.m.Lock()
defer c.m.Unlock()
item, ok := c.data[key]
if !ok {
var v V
return v, false
}
timestamp := time.Now().Unix()
if item.Expiration > timestamp {
item.Expiration = timestamp + item.Ttl
return item.Value, true
}
delete(c.data, key)
var v V
return v, false
}
func (c *cacheInmem[K, V]) Set(key K, value V, ttlSeconds int) {
c.m.Lock()
defer c.m.Unlock()
ttl := int64(c.ttlSeconds)
expiration := time.Now().Unix() + ttl
item := &cacheInmemItem[V]{
Value: value,
Ttl: ttl,
Expiration: expiration,
}
c.data[key] = item
}
func (c *cacheInmem[K, V]) Del(key K) {
c.m.Lock()
defer c.m.Unlock()
delete(c.data, key)
}
func (c *cacheInmem[K, V]) CheckExpired() {
if len(c.data) == 0 {
return
}
c.m.Lock()
defer c.m.Unlock()
itemsToProcess := 1000
for key, item := range c.data {
timestamp := time.Now().Unix()
if item.Expiration <= timestamp {
delete(c.data, key)
}
itemsToProcess--
if itemsToProcess <= 0 {
return
}
}
}