Skip to content

Commit 428a0be

Browse files
committed
feat: add cache clear
1 parent 02c0ebb commit 428a0be

File tree

2 files changed

+59
-17
lines changed

2 files changed

+59
-17
lines changed

server/memorystore/providers/inmemory/stores/session_store.go

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package stores
22

33
import (
44
"fmt"
5+
"sort"
56
"strings"
67
"sync"
78
"time"
@@ -10,6 +11,8 @@ import (
1011
const (
1112
// Maximum entries to keep in session storage
1213
maxCacheSize = 1000
14+
// Cache clear interval
15+
clearInterval = 10 * time.Minute
1316
)
1417

1518
// SessionEntry is the struct for entry stored in store
@@ -20,30 +23,64 @@ type SessionEntry struct {
2023

2124
// SessionStore struct to store the env variables
2225
type SessionStore struct {
23-
mutex sync.Mutex
24-
store map[string]*SessionEntry
25-
itemsToEvict []string
26+
wg sync.WaitGroup
27+
mutex sync.RWMutex
28+
store map[string]*SessionEntry
29+
// stores expireTime: key to remove data when cache is full
30+
// map is sorted by key so older most entry can be deleted first
31+
keyIndex map[int64]string
32+
stop chan struct{}
2633
}
2734

2835
// NewSessionStore create a new session store
2936
func NewSessionStore() *SessionStore {
30-
return &SessionStore{
31-
mutex: sync.Mutex{},
32-
store: make(map[string]*SessionEntry),
37+
store := &SessionStore{
38+
mutex: sync.RWMutex{},
39+
store: make(map[string]*SessionEntry),
40+
keyIndex: make(map[int64]string),
41+
stop: make(chan struct{}),
42+
}
43+
store.wg.Add(1)
44+
go func() {
45+
defer store.wg.Done()
46+
store.clean()
47+
}()
48+
return store
49+
}
50+
51+
func (s *SessionStore) clean() {
52+
t := time.NewTicker(clearInterval)
53+
defer t.Stop()
54+
for {
55+
select {
56+
case <-s.stop:
57+
return
58+
case <-t.C:
59+
s.mutex.Lock()
60+
currentTime := time.Now().Unix()
61+
for k, v := range s.store {
62+
if v.ExpiresAt < currentTime {
63+
delete(s.store, k)
64+
delete(s.keyIndex, v.ExpiresAt)
65+
}
66+
}
67+
s.mutex.Unlock()
68+
}
3369
}
3470
}
3571

3672
// Get returns the value of the key in state store
3773
func (s *SessionStore) Get(key, subKey string) string {
38-
s.mutex.Lock()
39-
defer s.mutex.Unlock()
74+
s.mutex.RLock()
75+
defer s.mutex.RUnlock()
4076
currentTime := time.Now().Unix()
4177
k := fmt.Sprintf("%s:%s", key, subKey)
4278
if v, ok := s.store[k]; ok {
4379
if v.ExpiresAt > currentTime {
4480
return v.Value
4581
}
46-
s.itemsToEvict = append(s.itemsToEvict, k)
82+
// Delete expired items
83+
delete(s.store, k)
4784
}
4885
return ""
4986
}
@@ -54,17 +91,25 @@ func (s *SessionStore) Set(key string, subKey, value string, expiration int64) {
5491
defer s.mutex.Unlock()
5592
k := fmt.Sprintf("%s:%s", key, subKey)
5693
if _, ok := s.store[k]; !ok {
57-
s.store[k] = &SessionEntry{
58-
Value: value,
59-
ExpiresAt: expiration,
60-
// TODO add expire time
94+
// check if there is enough space in cache
95+
// else delete entries based on FIFO
96+
if len(s.store) == maxCacheSize {
97+
// remove older most entry
98+
sortedKeys := []int64{}
99+
for ik := range s.keyIndex {
100+
sortedKeys = append(sortedKeys, ik)
101+
}
102+
sort.Slice(sortedKeys, func(i, j int) bool { return sortedKeys[i] < sortedKeys[j] })
103+
itemToRemove := sortedKeys[0]
104+
delete(s.store, s.keyIndex[itemToRemove])
105+
delete(s.keyIndex, itemToRemove)
61106
}
62107
}
63108
s.store[k] = &SessionEntry{
64109
Value: value,
65110
ExpiresAt: expiration,
66-
// TODO add expire time
67111
}
112+
s.keyIndex[expiration] = k
68113
}
69114

70115
// RemoveAll all values for given key

server/memorystore/providers/redis/store.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,14 @@ func (c *provider) GetUserSession(userId, key string) (string, error) {
4242
func (c *provider) DeleteUserSession(userId, key string) error {
4343
if err := c.store.Del(c.ctx, fmt.Sprintf("%s:%s", userId, constants.TokenTypeSessionToken+"_"+key)).Err(); err != nil {
4444
log.Debug("Error deleting user session from redis: ", err)
45-
fmt.Println("Error deleting user session from redis: ", err, userId, constants.TokenTypeSessionToken, key)
4645
// continue
4746
}
4847
if err := c.store.Del(c.ctx, fmt.Sprintf("%s:%s", userId, constants.TokenTypeAccessToken+"_"+key)).Err(); err != nil {
4948
log.Debug("Error deleting user session from redis: ", err)
50-
fmt.Println("Error deleting user session from redis: ", err, userId, constants.TokenTypeAccessToken, key)
5149
// continue
5250
}
5351
if err := c.store.Del(c.ctx, fmt.Sprintf("%s:%s", userId, constants.TokenTypeRefreshToken+"_"+key)).Err(); err != nil {
5452
log.Debug("Error deleting user session from redis: ", err)
55-
fmt.Println("Error deleting user session from redis: ", err, userId, constants.TokenTypeRefreshToken, key)
5653
// continue
5754
}
5855
return nil

0 commit comments

Comments
 (0)