package session import ( "bytes" "encoding/gob" "log/slog" "go.etcd.io/bbolt" ) func NewBoltStore(db *bbolt.DB, bucketName []byte) Store { return &BoltStore{ db: db, bucketName: bucketName, } } type BoltStore struct { db *bbolt.DB bucketName []byte } func (s *BoltStore) Load(sessionID string) Values { v := Values{} 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.Warn("failed load session", slog.Any("error", err)) } return v } func (s *BoltStore) Save(sessionID string, value Values) 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(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)) }) }