Files
PrivateCaptcha/pkg/db/session.go
2025-09-14 14:41:29 +03:00

86 lines
2.2 KiB
Go

package db
import (
"context"
"log/slog"
"time"
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/common"
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/session"
)
const (
sessionBatchSize = 20
sessionCacheTTL = 1 * time.Hour
)
type SessionStore struct {
store Implementor
persistChan chan string
batchSize int
processCancel context.CancelFunc
persistKey session.SessionKey
}
func NewSessionStore(store Implementor, persistKey session.SessionKey) *SessionStore {
return &SessionStore{
store: store,
persistChan: make(chan string, sessionBatchSize),
batchSize: sessionBatchSize,
persistKey: persistKey,
processCancel: func() {},
}
}
func (ss *SessionStore) Start(ctx context.Context, interval time.Duration) {
var cancelCtx context.Context
cancelCtx, ss.processCancel = context.WithCancel(
context.WithValue(ctx, common.TraceIDContextKey, "persist_session"))
go common.ProcessBatchMap(cancelCtx, ss.persistChan, interval, ss.batchSize, ss.batchSize*100, ss.persistSessions)
}
var _ session.Store = (*SessionStore)(nil)
func (ss *SessionStore) Shutdown() {
slog.Debug("Shutting down persisting sessions")
ss.processCancel()
close(ss.persistChan)
}
func (ss *SessionStore) Init(ctx context.Context, session *session.Session) error {
return ss.store.Impl().CacheUserSession(ctx, session.Data())
}
func (ss *SessionStore) Read(ctx context.Context, sid string) (*session.Session, error) {
sd, err := ss.store.Impl().RetrieveUserSession(ctx, sid)
if err != nil {
if (err == ErrNegativeCacheHit) || (err == ErrCacheMiss) {
return nil, session.ErrSessionMissing
}
return nil, err
}
return session.NewSession(sd, ss), nil
}
func (ss *SessionStore) Update(sd *session.Session) error {
ss.persistChan <- sd.ID()
return nil
}
func (ss *SessionStore) TTL() time.Duration {
return sessionCacheTTL
}
func (ss *SessionStore) Destroy(ctx context.Context, sid string) error {
return ss.store.Impl().DeleteUserSession(ctx, sid)
}
func (ss *SessionStore) persistSessions(ctx context.Context, batch map[string]uint) error {
// we actually do not care if we failed to save sessions to cache
_ = ss.store.Impl().StoreUserSessions(ctx, batch, ss.persistKey, sessionCacheTTL)
return nil
}