diff --git a/src/session/session_manager.go b/src/session/session_manager.go index 488118e..38c83c2 100644 --- a/src/session/session_manager.go +++ b/src/session/session_manager.go @@ -7,7 +7,6 @@ import ( "astraltech.xyz/accountmanager/src/logging" "astraltech.xyz/accountmanager/src/store" - "astraltech.xyz/accountmanager/src/worker" ) const SessionCookieName = "session_token" @@ -39,10 +38,10 @@ func (manager *SessionManager) SetStoreType(storeType StoreType, params ...any) case InMemory: { manager.store = store.NewMemoryStore[*SessionData]() - worker.CreateWorker(time.Minute*5, func() { - inMemStore, _ := manager.store.(*store.MemoryStore[*SessionData]) - cleanupInMemoryStore(inMemStore) - }) + // worker.CreateWorker(time.Minute*5, func() { + // inMemStore, _ := manager.store.(*store.MemoryStore[*SessionData]) + // cleanupInMemoryStore(inMemStore) + // }) break } case Redis: @@ -70,7 +69,7 @@ func (manager *SessionManager) CreateSession(userID string) (cookie *http.Cookie CSRFToken: CSRFToken, ExpiresAt: time.Now().Add(time.Hour), } - err = manager.store.Create(token, &newSessionData) + err = manager.store.CreateExpiring(token, &newSessionData, time.Hour) if err != nil { return nil, err } @@ -110,22 +109,22 @@ func (manager *SessionManager) GetSession(r *http.Request) (*SessionData, error) return data, nil } -func cleanupInMemoryStore(m *store.MemoryStore[*SessionData]) { - logging.Debug("Cleaning up memory store sessions") - now := time.Now() +// func cleanupInMemoryStore(m *store.MemoryStore[*SessionData]) { +// logging.Debug("Cleaning up memory store sessions") +// now := time.Now() - m.Lock.Lock() - defer m.Lock.Unlock() +// m.Lock.Lock() +// defer m.Lock.Unlock() - deleted := 0 - for id, session := range m.Sessions { - if now.After(session.ExpiresAt) { - delete(m.Sessions, id) - deleted = deleted + 1 - } - } - logging.Infof("Cleaned up %d stale sessions", deleted) -} +// deleted := 0 +// for id, session := range m.Sessions { +// if now.After(session.ExpiresAt) { +// delete(m.Sessions, id) +// deleted = deleted + 1 +// } +// } +// logging.Infof("Cleaned up %d stale sessions", deleted) +// } func (manager *SessionManager) DeleteSession(sessionId string) error { return manager.store.Delete(sessionId) diff --git a/src/store/store.go b/src/store/store.go index 85d9194..2c3aff5 100644 --- a/src/store/store.go +++ b/src/store/store.go @@ -1,9 +1,14 @@ package store +import ( + "time" +) + // A simple key value store that can either just be single instance in memory or a redis server (for now) type KeyValueStore[Value any] interface { Create(key string, value Value) error + CreateExpiring(key string, value Value, ttl time.Duration) error Get(key string) (Value, error) Update(key string, session Value) error Delete(key string) error diff --git a/src/store/store_in_memory.go b/src/store/store_in_memory.go index 816cbaf..dcd6c57 100644 --- a/src/store/store_in_memory.go +++ b/src/store/store_in_memory.go @@ -2,60 +2,77 @@ package store import ( "sync" + "time" "astraltech.xyz/accountmanager/src/logging" ) +type ValueEntry[Value any] struct { + value Value + expiry time.Time +} + type MemoryStore[Value any] struct { - Sessions map[string]Value - Lock sync.RWMutex + Keys map[string]ValueEntry[Value] + + Lock sync.RWMutex } func NewMemoryStore[Value any]() *MemoryStore[Value] { logging.Debug("Creating new in memory session store") store := &MemoryStore[Value]{ - Sessions: make(map[string]Value), + Keys: make(map[string]ValueEntry[Value]), } return store } -func (m *MemoryStore[Value]) Create(key string, session Value) (err error) { +func (m *MemoryStore[Value]) CreateExpiring(key string, value Value, duration time.Duration) error { hashedkey := HashKey(key) m.Lock.Lock() defer m.Lock.Unlock() - _, exist := m.Sessions[hashedkey] + _, exist := m.Keys[hashedkey] if exist { return ErrKeyAlreadyExists } - m.Sessions[hashedkey] = session + m.Keys[hashedkey] = ValueEntry[Value]{ + value: value, + expiry: time.Now().Add(duration), + } return nil } +func (m *MemoryStore[Value]) Create(key string, session Value) error { + return m.CreateExpiring(key, session, 0) +} + func (m *MemoryStore[Value]) Get(key string) (Value, error) { - var data Value + var data ValueEntry[Value] m.Lock.RLock() hashedkey := HashKey(key) - data, exists := m.Sessions[hashedkey] + data, exists := m.Keys[hashedkey] m.Lock.RUnlock() if exists == false { - return data, ErrKeyNotFound + return data.value, ErrKeyNotFound } - return data, nil + return data.value, nil } -func (m *MemoryStore[Value]) Update(sessionID string, session Value) error { +func (m *MemoryStore[Value]) Update(sessionID string, value Value) error { hashedkey := HashKey(sessionID) m.Lock.Lock() defer m.Lock.Unlock() - _, exist := m.Sessions[hashedkey] + current_key, exist := m.Keys[hashedkey] if !exist { return ErrKeyNotFound } - m.Sessions[hashedkey] = session + m.Keys[hashedkey] = ValueEntry[Value]{ + value: value, + expiry: current_key.expiry, + } return nil } @@ -64,10 +81,10 @@ func (m *MemoryStore[Value]) Delete(sessionID string) error { m.Lock.Lock() defer m.Lock.Unlock() - _, exist := m.Sessions[hashedkey] + _, exist := m.Keys[hashedkey] if !exist { return ErrKeyNotFound } - delete(m.Sessions, hashedkey) + delete(m.Keys, hashedkey) return nil } diff --git a/src/store/store_redis.go b/src/store/store_redis.go index bf09ba5..dede1fc 100644 --- a/src/store/store_redis.go +++ b/src/store/store_redis.go @@ -43,8 +43,7 @@ func NewRedisStore[Value any](redis_server string, prefix string) *RedisStore[Va } return store } - -func (m *RedisStore[Value]) Create(key string, value Value) (err error) { +func (m *RedisStore[Value]) CreateExpiring(key string, value Value, ttl time.Duration) error { hashedSession := m.RedisHash(key) data, err := json.Marshal(value) @@ -52,7 +51,7 @@ func (m *RedisStore[Value]) Create(key string, value Value) (err error) { return ErrKeyBackend } - created, err := m.client.SetNX(m.ctx, hashedSession, data, time.Hour).Result() + created, err := m.client.SetNX(m.ctx, hashedSession, data, ttl).Result() if err != nil { logging.Error(err.Error()) return ErrKeyBackend @@ -63,6 +62,9 @@ func (m *RedisStore[Value]) Create(key string, value Value) (err error) { } return nil } +func (m *RedisStore[Value]) Create(key string, value Value) error { + return m.CreateExpiring(key, value, 0) +} func (m *RedisStore[Value]) Get(sessionID string) (Value, error) { hashed := m.RedisHash(sessionID) var session_data Value