2024-07-29 02:38:17 +03:00
|
|
|
package session
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/gob"
|
|
|
|
"log/slog"
|
|
|
|
|
|
|
|
"go.etcd.io/bbolt"
|
|
|
|
)
|
|
|
|
|
2024-07-29 02:46:54 +03:00
|
|
|
func NewBoltStore(db *bbolt.DB, bucketName []byte) Store {
|
2024-07-29 02:38:17 +03:00
|
|
|
return &BoltStore{
|
|
|
|
db: db,
|
|
|
|
bucketName: bucketName,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type BoltStore struct {
|
|
|
|
db *bbolt.DB
|
|
|
|
bucketName []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *BoltStore) Load(ctx context.Context, sessionID string) Value {
|
|
|
|
v := Value{}
|
|
|
|
err := s.db.View(func(tx *bbolt.Tx) error {
|
|
|
|
bucket := tx.Bucket(s.bucketName)
|
|
|
|
if bucket == nil {
|
|
|
|
// no bucket -- normal situation
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
vb := bucket.Get([]byte(sessionID))
|
|
|
|
if vb == nil {
|
|
|
|
// no session -- no error
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
rdr := bytes.NewBuffer(vb)
|
|
|
|
|
|
|
|
return gob.NewDecoder(rdr).Decode(&v)
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
slog.WarnContext(ctx, "failed load session", slog.Any("error", err))
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *BoltStore) Save(ctx context.Context, sessionID string, value Value) error {
|
|
|
|
return s.db.Update(func(tx *bbolt.Tx) error {
|
|
|
|
bucket, err := tx.CreateBucketIfNotExists(s.bucketName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
wrt := bytes.NewBuffer([]byte{})
|
|
|
|
if err := gob.NewEncoder(wrt).Encode(value); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return bucket.Put([]byte(sessionID), wrt.Bytes())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *BoltStore) Remove(ctx context.Context, sessionID string) error {
|
|
|
|
return s.db.Update(func(tx *bbolt.Tx) error {
|
|
|
|
bucket, err := tx.CreateBucketIfNotExists(s.bucketName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return bucket.Delete([]byte(sessionID))
|
|
|
|
})
|
|
|
|
}
|