Plan stuff. Log stuff.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

197 lines
4.2 KiB

package bolt
import (
"context"
"github.com/gisle/stufflog/database/repositories"
"github.com/gisle/stufflog/models"
"github.com/gisle/stufflog/slerrors"
"github.com/vmihailenco/msgpack/v4"
"go.etcd.io/bbolt"
)
var bnUserSessions = []byte("UserSession")
type userSessionRepository struct {
userIdIdx *index
db *bbolt.DB
}
func (r *userSessionRepository) FindID(ctx context.Context, id string) (*models.UserSession, error) {
session := new(models.UserSession)
err := r.db.View(func(tx *bbolt.Tx) error {
value := tx.Bucket(bnUserSessions).Get(unsafeStringToBytes(id))
if value == nil {
return slerrors.NotFound("Session")
}
err := msgpack.Unmarshal(value, session)
if err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return session, nil
}
func (r *userSessionRepository) List(ctx context.Context) ([]*models.UserSession, error) {
sessions := make([]*models.UserSession, 0, 16)
err := r.db.View(func(tx *bbolt.Tx) error {
cursor := tx.Bucket(bnUserSessions).Cursor()
for key, value := cursor.First(); key != nil; key, value = cursor.Next() {
session := new(models.UserSession)
err := msgpack.Unmarshal(value, session)
if err != nil {
return err
}
sessions = append(sessions, session)
}
return nil
})
if err != nil {
return nil, err
}
return sessions, nil
}
func (r *userSessionRepository) ListUser(ctx context.Context, user models.User) ([]*models.UserSession, error) {
var sessions []*models.UserSession
err := r.db.View(func(tx *bbolt.Tx) error {
bucket := tx.Bucket(bnUserSessions)
ids, err := r.userIdIdx.WithTx(tx).Get(user.ID)
if err != nil {
return err
}
sessions = make([]*models.UserSession, len(ids))
for i, id := range ids {
value := bucket.Get(id)
session := new(models.UserSession)
err := msgpack.Unmarshal(value, session)
if err != nil {
return err
}
sessions[i] = session
}
return nil
})
if err != nil {
return nil, err
}
return sessions, nil
}
func (r *userSessionRepository) Save(ctx context.Context, session models.UserSession) error {
value, err := msgpack.Marshal(&session)
if err != nil {
return err
}
return r.db.Update(func(tx *bbolt.Tx) error {
err := tx.Bucket(bnUserSessions).Put(unsafeStringToBytes(session.ID), value)
if err != nil {
return err
}
err = r.userIdIdx.WithTx(tx).Set(unsafeStringToBytes(session.ID), session.UserID)
if err != nil {
return err
}
return nil
})
}
func (r *userSessionRepository) Remove(ctx context.Context, session models.UserSession) error {
return r.db.Update(func(tx *bbolt.Tx) error {
err := tx.Bucket(bnUserSessions).Delete(unsafeStringToBytes(session.ID))
if err != nil {
return err
}
err = r.userIdIdx.WithTx(tx).Set(unsafeStringToBytes(session.ID))
if err != nil {
return err
}
return nil
})
}
func (r *userSessionRepository) RemoveUser(ctx context.Context, user models.User) error {
return r.db.Update(func(tx *bbolt.Tx) error {
bucket := tx.Bucket(bnUserSessions)
ids, err := r.userIdIdx.WithTx(tx).Get(user.ID)
if err != nil {
return err
}
for _, id := range ids {
err := bucket.Delete(id)
if err != nil {
return err
}
}
return nil
})
}
func (r *userSessionRepository) reindex() error {
return r.db.Update(func(tx *bbolt.Tx) error {
cursor := tx.Bucket(bnUserSessions).Cursor()
err := r.userIdIdx.Reset(tx)
if err != nil {
return err
}
userIdIdxTx := r.userIdIdx.WithTx(tx)
for key, value := cursor.First(); key != nil; key, value = cursor.Next() {
session := new(models.UserSession)
err := msgpack.Unmarshal(value, session)
if err != nil {
return err
}
err = userIdIdxTx.Set(unsafeStringToBytes(session.ID), session.UserID)
if err != nil {
return err
}
}
return nil
})
}
func newUserSessionRepository(db *bbolt.DB) (repositories.UserSessionRepository, error) {
err := db.Update(func(tx *bbolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(bnUserSessions)
return err
})
if err != nil {
return nil, err
}
idx, err := newModelIndex(db, "UserSession", "UserID")
if err != nil {
return nil, err
}
return &userSessionRepository{
db: db,
userIdIdx: idx,
}, nil
}