openreplay/backend/pkg/db/cache/cache.go
Alexander 2abf063ba2
Sessions cache layer (#789)
* feat(backend/db): cache layer for sessions with auto deleting logic
2022-11-02 17:00:41 +01:00

73 lines
1.6 KiB
Go

package cache
import (
"log"
"openreplay/backend/pkg/db/postgres"
"openreplay/backend/pkg/db/types"
"sync"
"time"
)
type SessionMeta struct {
*types.Session
lastUse time.Time
}
type ProjectMeta struct {
*types.Project
expirationTime time.Time
}
type Cache interface {
SetSession(sess *types.Session)
HasSession(sessID uint64) bool
GetSession(sessionID uint64) (*types.Session, error)
GetProject(projectID uint32) (*types.Project, error)
GetProjectByKey(projectKey string) (*types.Project, error)
}
type cacheImpl struct {
conn *postgres.Conn
mutex sync.RWMutex
sessions map[uint64]*SessionMeta
projects map[uint32]*ProjectMeta
projectsByKeys sync.Map
projectExpirationTimeout time.Duration
}
func NewCache(conn *postgres.Conn, projectExpirationTimeoutMs int64) Cache {
newCache := &cacheImpl{
conn: conn,
sessions: make(map[uint64]*SessionMeta),
projects: make(map[uint32]*ProjectMeta),
projectExpirationTimeout: time.Duration(1000 * projectExpirationTimeoutMs),
}
go newCache.cleaner()
return newCache
}
func (c *cacheImpl) cleaner() {
cleanTick := time.Tick(time.Minute * 5)
for {
select {
case <-cleanTick:
c.clearCache()
}
}
}
func (c *cacheImpl) clearCache() {
c.mutex.Lock()
defer c.mutex.Unlock()
now := time.Now()
cacheSize := len(c.sessions)
deleted := 0
for id, sess := range c.sessions {
if now.Sub(sess.lastUse).Minutes() > 3 {
deleted++
delete(c.sessions, id)
}
}
log.Printf("cache cleaner: deleted %d/%d sessions", deleted, cacheSize)
}