mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
Update sessions/sessiondb/badger to its latest version and SessionController is able to initialize itself if session manager is not provided by the caller-dev.
Changes:
Update the badger database using transactions, as supported from yesterday via: 06242925c2
Add a custom `OnActivate` via mvc/activator/activate_listener.go, this can be used to perform any custom actions when the app registers the supported Controllers. See mvc/session_controller.go for the excellent use case.
errors.Reporter.AddErr returns true if the error is added to the stack, otherwise false
Former-commit-id: c896a2d186a4315643f3c5fdb4325f7ee48a9e0a
This commit is contained in:
parent
6925ed9b33
commit
4fb78bbcd9
File diff suppressed because one or more lines are too long
|
@ -23,7 +23,8 @@ func (u *VisitController) Get() {
|
||||||
u.Session.Set("visits", visits)
|
u.Session.Set("visits", visits)
|
||||||
|
|
||||||
// write the current, updated visits
|
// write the current, updated visits
|
||||||
u.Ctx.Writef("%d visits in %0.1f seconds", visits, time.Now().Sub(u.StartTime).Seconds())
|
u.Ctx.Writef("%d visit from my current session in %0.1f seconds of server's up-time",
|
||||||
|
visits, time.Now().Sub(u.StartTime).Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
BIN
_examples/sessions/database/badger/data/000000.vlog
Normal file
BIN
_examples/sessions/database/badger/data/000000.vlog
Normal file
Binary file not shown.
BIN
_examples/sessions/database/badger/data/000001.sst
Normal file
BIN
_examples/sessions/database/badger/data/000001.sst
Normal file
Binary file not shown.
BIN
_examples/sessions/database/badger/data/000002.sst
Normal file
BIN
_examples/sessions/database/badger/data/000002.sst
Normal file
Binary file not shown.
BIN
_examples/sessions/database/badger/data/000003.sst
Normal file
BIN
_examples/sessions/database/badger/data/000003.sst
Normal file
Binary file not shown.
BIN
_examples/sessions/database/badger/data/000004.sst
Normal file
BIN
_examples/sessions/database/badger/data/000004.sst
Normal file
Binary file not shown.
BIN
_examples/sessions/database/badger/data/MANIFEST
Normal file
BIN
_examples/sessions/database/badger/data/MANIFEST
Normal file
Binary file not shown.
|
@ -56,23 +56,33 @@ func NewReporter() *Reporter {
|
||||||
// AddErr adds an error to the error stack.
|
// AddErr adds an error to the error stack.
|
||||||
// if "err" is a StackError then
|
// if "err" is a StackError then
|
||||||
// each of these errors will be printed as individual.
|
// each of these errors will be printed as individual.
|
||||||
func (r *Reporter) AddErr(err error) {
|
//
|
||||||
|
// Returns true if this "err" is not nil and it's added to the reporter's stack.
|
||||||
|
func (r *Reporter) AddErr(err error) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if stackErr, ok := err.(StackError); ok {
|
if stackErr, ok := err.(StackError); ok {
|
||||||
r.addStack(stackErr.Stack())
|
r.addStack(stackErr.Stack())
|
||||||
return
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
r.wrapper = r.wrapper.AppendErr(err)
|
r.wrapper = r.wrapper.AppendErr(err)
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Add adds a formatted message as an error to the error stack.
|
// Add adds a formatted message as an error to the error stack.
|
||||||
func (r *Reporter) Add(format string, a ...interface{}) {
|
//
|
||||||
|
// Returns true if this "err" is not nil and it's added to the reporter's stack.
|
||||||
|
func (r *Reporter) Add(format string, a ...interface{}) bool {
|
||||||
|
|
||||||
|
if format == "" && len(a) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// usually used as: "module: %v", err so
|
// usually used as: "module: %v", err so
|
||||||
// check if the first argument is error and if that error is empty then don't add it.
|
// check if the first argument is error and if that error is empty then don't add it.
|
||||||
if len(a) > 0 {
|
if len(a) > 0 {
|
||||||
|
@ -81,7 +91,7 @@ func (r *Reporter) Add(format string, a ...interface{}) {
|
||||||
Error() string
|
Error() string
|
||||||
}); ok {
|
}); ok {
|
||||||
if e.Error() == "" {
|
if e.Error() == "" {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,6 +99,7 @@ func (r *Reporter) Add(format string, a ...interface{}) {
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
r.wrapper = r.wrapper.Append(format, a...)
|
r.wrapper = r.wrapper.Append(format, a...)
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe same as `Add` but if "err" is nil then it does nothing.
|
// Describe same as `Add` but if "err" is nil then it does nothing.
|
||||||
|
|
|
@ -545,12 +545,6 @@ func (api *APIBuilder) Controller(relativePath string, controller activator.Base
|
||||||
api.reporter.Add("%v for path: '%s'", err, relativePath)
|
api.reporter.Add("%v for path: '%s'", err, relativePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cInit, ok := controller.(interface {
|
|
||||||
Init(activator.RegisterFunc)
|
|
||||||
}); ok {
|
|
||||||
cInit.Init(registerFunc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,6 @@ import (
|
||||||
"github.com/kataras/iris/mvc"
|
"github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: When go 1.9 will be released
|
|
||||||
// split this file in order to separate the concepts.
|
|
||||||
//
|
|
||||||
// Files should change after go1.9 final release:
|
|
||||||
// README.md: Hello World with Go 1.9
|
|
||||||
// core/host/supervisor.go
|
|
||||||
// context.go
|
|
||||||
type (
|
type (
|
||||||
// Context is the midle-man server's "object" for the clients.
|
// Context is the midle-man server's "object" for the clients.
|
||||||
//
|
//
|
78
mvc/activator/activate_listener.go
Normal file
78
mvc/activator/activate_listener.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package activator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CallOnActivate simply calls the "controller"'s `OnActivate(*ActivatePayload)` function,
|
||||||
|
// if any.
|
||||||
|
//
|
||||||
|
// Look `activator.go#Register` and `ActivateListener` for more.
|
||||||
|
func CallOnActivate(controller interface{},
|
||||||
|
bindValues *[]interface{}, registerFunc RegisterFunc) {
|
||||||
|
|
||||||
|
if ac, ok := controller.(ActivateListener); ok {
|
||||||
|
p := &ActivatePayload{
|
||||||
|
BindValues: bindValues,
|
||||||
|
Handle: registerFunc,
|
||||||
|
}
|
||||||
|
ac.OnActivate(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActivateListener is an interface which should be declared
|
||||||
|
// on a Controller which needs to register or change the bind values
|
||||||
|
// that the caller-"user" has been passed to; via the `app.Controller`.
|
||||||
|
// If that interface is completed by a controller
|
||||||
|
// then the `OnActivate` function will be called ONCE, NOT in every request
|
||||||
|
// but ONCE at the application's lifecycle.
|
||||||
|
type ActivateListener interface {
|
||||||
|
// OnActivate accepts a pointer to the `ActivatePayload`.
|
||||||
|
//
|
||||||
|
// The `Controller` can make use of the `OnActivate` function
|
||||||
|
// to register custom routes
|
||||||
|
// or modify the provided values that will be binded to the
|
||||||
|
// controller later on.
|
||||||
|
//
|
||||||
|
// Look `ActivatePayload` for more.
|
||||||
|
OnActivate(*ActivatePayload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActivatePayload contains the necessary information and the ability
|
||||||
|
// to alt a controller's registration options, i.e the binder.
|
||||||
|
//
|
||||||
|
// With `ActivatePayload` the `Controller` can register custom routes
|
||||||
|
// or modify the provided values that will be binded to the
|
||||||
|
// controller later on.
|
||||||
|
type ActivatePayload struct {
|
||||||
|
BindValues *[]interface{}
|
||||||
|
Handle RegisterFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureBindValue will make sure that this "bindValue"
|
||||||
|
// will be registered to the controller's binder
|
||||||
|
// if its type is not already passed by the caller..
|
||||||
|
//
|
||||||
|
// For example, on `SessionController` it looks if *sessions.Sessions
|
||||||
|
// has been binded from the caller and if not then the "bindValue"
|
||||||
|
// will be binded and used as a default sessions manager instead.
|
||||||
|
//
|
||||||
|
// At general, if the caller has already provided a value with the same Type
|
||||||
|
// then the "bindValue" will be ignored and not be added to the controller's bind values.
|
||||||
|
//
|
||||||
|
// Returns true if the caller has NOT already provided a value with the same Type
|
||||||
|
// and "bindValue" is NOT ignored therefore is appended to the controller's bind values.
|
||||||
|
func (i *ActivatePayload) EnsureBindValue(bindValue interface{}) bool {
|
||||||
|
valueTyp := reflect.TypeOf(bindValue)
|
||||||
|
localBindValues := *i.BindValues
|
||||||
|
|
||||||
|
for _, bindedValue := range localBindValues {
|
||||||
|
// type already exists, remember: binding here is per-type.
|
||||||
|
if reflect.TypeOf(bindedValue) == valueTyp {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*i.BindValues = append(localBindValues, bindValue)
|
||||||
|
return true
|
||||||
|
}
|
|
@ -65,7 +65,6 @@ type BaseController interface {
|
||||||
|
|
||||||
// ActivateController returns a new controller type info description.
|
// ActivateController returns a new controller type info description.
|
||||||
func ActivateController(base BaseController, bindValues []interface{}) (TController, error) {
|
func ActivateController(base BaseController, bindValues []interface{}) (TController, error) {
|
||||||
|
|
||||||
// get and save the type.
|
// get and save the type.
|
||||||
typ := reflect.TypeOf(base)
|
typ := reflect.TypeOf(base)
|
||||||
if typ.Kind() != reflect.Ptr {
|
if typ.Kind() != reflect.Ptr {
|
||||||
|
@ -202,6 +201,8 @@ func RegisterMethodHandlers(t TController, registerFunc RegisterFunc) {
|
||||||
func Register(controller BaseController, bindValues []interface{},
|
func Register(controller BaseController, bindValues []interface{},
|
||||||
registerFunc RegisterFunc) error {
|
registerFunc RegisterFunc) error {
|
||||||
|
|
||||||
|
CallOnActivate(controller, &bindValues, registerFunc)
|
||||||
|
|
||||||
t, err := ActivateController(controller, bindValues)
|
t, err := ActivateController(controller, bindValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
"github.com/kataras/iris/mvc"
|
"github.com/kataras/iris/mvc"
|
||||||
|
"github.com/kataras/iris/mvc/activator"
|
||||||
|
|
||||||
"github.com/kataras/iris/core/router"
|
"github.com/kataras/iris/core/router"
|
||||||
"github.com/kataras/iris/httptest"
|
"github.com/kataras/iris/httptest"
|
||||||
|
@ -493,3 +494,33 @@ func TestControllerRelPathFromFunc(t *testing.T) {
|
||||||
e.GET("/anything/here").Expect().Status(httptest.StatusOK).
|
e.GET("/anything/here").Expect().Status(httptest.StatusOK).
|
||||||
Body().Equal("GET:/anything/here")
|
Body().Equal("GET:/anything/here")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testControllerActivateListener struct {
|
||||||
|
mvc.Controller
|
||||||
|
|
||||||
|
TitlePointer *testBindType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *testControllerActivateListener) OnActivate(p *activator.ActivatePayload) {
|
||||||
|
p.EnsureBindValue(&testBindType{
|
||||||
|
title: "default title",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *testControllerActivateListener) Get() {
|
||||||
|
c.Text = c.TitlePointer.title
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestControllerActivateListener(t *testing.T) {
|
||||||
|
app := iris.New()
|
||||||
|
app.Controller("/", new(testControllerActivateListener))
|
||||||
|
app.Controller("/manual", new(testControllerActivateListener), &testBindType{
|
||||||
|
title: "my title",
|
||||||
|
})
|
||||||
|
|
||||||
|
e := httptest.New(t, app)
|
||||||
|
e.GET("/").Expect().Status(httptest.StatusOK).
|
||||||
|
Body().Equal("default title")
|
||||||
|
e.GET("/manual").Expect().Status(httptest.StatusOK).
|
||||||
|
Body().Equal("my title")
|
||||||
|
}
|
||||||
|
|
19
mvc/go19.go
Normal file
19
mvc/go19.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package mvc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kataras/iris/mvc/activator"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ActivatePayload contains the necessary information and the ability
|
||||||
|
// to alt a controller's registration options, i.e the binder.
|
||||||
|
//
|
||||||
|
// With `ActivatePayload` the `Controller` can register custom routes
|
||||||
|
// or modify the provided values that will be binded to the
|
||||||
|
// controller later on.
|
||||||
|
//
|
||||||
|
// Look the `mvc/activator#ActivatePayload` for its implementation.
|
||||||
|
//
|
||||||
|
// A shortcut for the `mvc/activator#ActivatePayload`, useful when `OnActivate` is being used.
|
||||||
|
type ActivatePayload = activator.ActivatePayload
|
|
@ -2,9 +2,14 @@ package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
|
"github.com/kataras/iris/mvc/activator"
|
||||||
"github.com/kataras/iris/sessions"
|
"github.com/kataras/iris/sessions"
|
||||||
|
|
||||||
|
"github.com/kataras/golog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var defaultManager = sessions.New(sessions.Config{})
|
||||||
|
|
||||||
// SessionController is a simple `Controller` implementation
|
// SessionController is a simple `Controller` implementation
|
||||||
// which requires a binded session manager in order to give
|
// which requires a binded session manager in order to give
|
||||||
// direct access to the current client's session via its `Session` field.
|
// direct access to the current client's session via its `Session` field.
|
||||||
|
@ -15,21 +20,27 @@ type SessionController struct {
|
||||||
Session *sessions.Session
|
Session *sessions.Session
|
||||||
}
|
}
|
||||||
|
|
||||||
var managerMissing = "MVC SessionController: session manager field is nil, you have to bind it to a *sessions.Sessions"
|
// OnActivate called, once per application lifecycle NOT request,
|
||||||
|
// every single time the dev registers a specific SessionController-based controller.
|
||||||
|
// It makes sure that its "Manager" field is filled
|
||||||
|
// even if the caller didn't provide any sessions manager via the `app.Controller` function.
|
||||||
|
func (s *SessionController) OnActivate(p *activator.ActivatePayload) {
|
||||||
|
if p.EnsureBindValue(defaultManager) {
|
||||||
|
golog.Warnf(`MVC SessionController: couldn't find any "*sessions.Sessions" bindable value to fill the "Manager" field,
|
||||||
|
therefore this controller is using the default sessions manager instead.
|
||||||
|
Please refer to the documentation to learn how you can provide the session manager`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BeginRequest calls the Controller's BeginRequest
|
// BeginRequest calls the Controller's BeginRequest
|
||||||
// and tries to initialize the current user's Session.
|
// and tries to initialize the current user's Session.
|
||||||
func (s *SessionController) BeginRequest(ctx context.Context) {
|
func (s *SessionController) BeginRequest(ctx context.Context) {
|
||||||
s.Controller.BeginRequest(ctx)
|
s.Controller.BeginRequest(ctx)
|
||||||
if s.Manager == nil {
|
if s.Manager == nil {
|
||||||
ctx.Application().Logger().Errorf(managerMissing)
|
ctx.Application().Logger().Errorf(`MVC SessionController: sessions manager is nil, report this as a bug
|
||||||
|
because the SessionController should predict this on its activation state and use a default one automatically`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Session = s.Manager.Start(ctx)
|
s.Session = s.Manager.Start(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
Maybe add struct tags on `binder` for required binded values
|
|
||||||
in order to log error if some of the bindings are missing or leave that to the end-developers?
|
|
||||||
*/
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Database struct {
|
||||||
// Service is the underline badger database connection,
|
// Service is the underline badger database connection,
|
||||||
// it's initialized at `New` or `NewFromDB`.
|
// it's initialized at `New` or `NewFromDB`.
|
||||||
// Can be used to get stats.
|
// Can be used to get stats.
|
||||||
Service *badger.KV
|
Service *badger.DB
|
||||||
async bool
|
async bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func New(directoryPath string) (*Database, error) {
|
||||||
opts.Dir = directoryPath
|
opts.Dir = directoryPath
|
||||||
opts.ValueDir = directoryPath
|
opts.ValueDir = directoryPath
|
||||||
|
|
||||||
service, err := badger.NewKV(&opts)
|
service, err := badger.Open(&opts)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Errorf("unable to initialize the badger-based session database: %v", err)
|
golog.Errorf("unable to initialize the badger-based session database: %v", err)
|
||||||
|
@ -62,7 +62,7 @@ func New(directoryPath string) (*Database, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromDB same as `New` but accepts an already-created custom badger connection instead.
|
// NewFromDB same as `New` but accepts an already-created custom badger connection instead.
|
||||||
func NewFromDB(service *badger.KV) (*Database, error) {
|
func NewFromDB(service *badger.DB) (*Database, error) {
|
||||||
if service == nil {
|
if service == nil {
|
||||||
return nil, errors.New("underline database is missing")
|
return nil, errors.New("underline database is missing")
|
||||||
}
|
}
|
||||||
|
@ -75,30 +75,37 @@ func NewFromDB(service *badger.KV) (*Database, error) {
|
||||||
|
|
||||||
// Cleanup removes any invalid(have expired) session entries,
|
// Cleanup removes any invalid(have expired) session entries,
|
||||||
// it's being called automatically on `New` as well.
|
// it's being called automatically on `New` as well.
|
||||||
func (db *Database) Cleanup() error {
|
func (db *Database) Cleanup() (err error) {
|
||||||
rep := errors.NewReporter()
|
rep := errors.NewReporter()
|
||||||
|
|
||||||
iter := db.Service.NewIterator(badger.DefaultIteratorOptions)
|
txn := db.Service.NewTransaction(true)
|
||||||
|
defer txn.Commit(nil)
|
||||||
|
|
||||||
|
iter := txn.NewIterator(badger.DefaultIteratorOptions)
|
||||||
|
defer iter.Close()
|
||||||
|
|
||||||
for iter.Rewind(); iter.Valid(); iter.Next() {
|
for iter.Rewind(); iter.Valid(); iter.Next() {
|
||||||
// Remember that the contents of the returned slice should not be modified, and
|
// Remember that the contents of the returned slice should not be modified, and
|
||||||
// only valid until the next call to Next.
|
// only valid until the next call to Next.
|
||||||
item := iter.Item()
|
item := iter.Item()
|
||||||
err := item.Value(func(b []byte) error {
|
b, err := item.Value()
|
||||||
|
|
||||||
|
if rep.AddErr(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
storeDB, err := sessions.DecodeRemoteStore(b)
|
storeDB, err := sessions.DecodeRemoteStore(b)
|
||||||
if err != nil {
|
if rep.AddErr(err) {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if storeDB.Lifetime.HasExpired() {
|
if storeDB.Lifetime.HasExpired() {
|
||||||
err = db.Service.Delete(item.Key())
|
if err := txn.Delete(item.Key()); err != nil {
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
rep.AddErr(err)
|
rep.AddErr(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iter.Close()
|
|
||||||
return rep.Return()
|
return rep.Return()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,21 +119,28 @@ func (db *Database) Async(useGoRoutines bool) *Database {
|
||||||
// Load loads the sessions from the badger(key-value file-based) session storage.
|
// Load loads the sessions from the badger(key-value file-based) session storage.
|
||||||
func (db *Database) Load(sid string) (storeDB sessions.RemoteStore) {
|
func (db *Database) Load(sid string) (storeDB sessions.RemoteStore) {
|
||||||
bsid := []byte(sid)
|
bsid := []byte(sid)
|
||||||
iter := db.Service.NewIterator(badger.DefaultIteratorOptions)
|
|
||||||
defer iter.Close()
|
|
||||||
|
|
||||||
iter.Seek(bsid)
|
txn := db.Service.NewTransaction(false)
|
||||||
if !iter.Valid() {
|
defer txn.Discard()
|
||||||
|
|
||||||
|
item, err := txn.Get(bsid)
|
||||||
|
if err != nil {
|
||||||
|
// Key not found, don't report this, session manager will create a new session as it should.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
item := iter.Item()
|
|
||||||
item.Value(func(b []byte) (err error) {
|
b, err := item.Value()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
golog.Errorf("error while trying to get the serialized session(%s) from the remote store: %v", sid, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
storeDB, err = sessions.DecodeRemoteStore(b) // decode the whole value, as a remote store
|
storeDB, err = sessions.DecodeRemoteStore(b) // decode the whole value, as a remote store
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Errorf("error while trying to load from the remote store: %v", err)
|
golog.Errorf("error while trying to load from the remote store: %v", err)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,19 +169,28 @@ func (db *Database) sync(p sessions.SyncPayload) {
|
||||||
golog.Errorf("error while serializing the remote store: %v", err)
|
golog.Errorf("error while serializing the remote store: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// err = db.Service.Set(bsid, s, meta)
|
txn := db.Service.NewTransaction(true)
|
||||||
e := &badger.Entry{
|
|
||||||
Key: bsid,
|
err = txn.Set(bsid, s, 0x00)
|
||||||
Value: s,
|
|
||||||
}
|
|
||||||
err = db.Service.BatchSet([]*badger.Entry{e})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Errorf("error while writing the session(%s) to the database: %v", p.SessionID, err)
|
txn.Discard()
|
||||||
|
golog.Errorf("error while trying to save the session(%s) to the database: %v", p.SessionID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := txn.Commit(nil); err != nil { // Commit will call the Discard automatically.
|
||||||
|
golog.Errorf("error while committing the session(%s) changes to the database: %v", p.SessionID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) destroy(bsid []byte) error {
|
func (db *Database) destroy(bsid []byte) error {
|
||||||
return db.Service.Delete(bsid)
|
txn := db.Service.NewTransaction(true)
|
||||||
|
|
||||||
|
err := txn.Delete(bsid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return txn.Commit(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close shutdowns the badger connection.
|
// Close shutdowns the badger connection.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user