mirror of
https://github.com/kataras/iris.git
synced 2025-12-26 14:27:04 +00:00
add two new examples and share the app's specific logger instance with sessions databases and APIBuilder
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/v12/context"
|
||||
"github.com/kataras/iris/v12/sessions"
|
||||
|
||||
"github.com/dgraph-io/badger/v2"
|
||||
@@ -26,6 +27,7 @@ type Database struct {
|
||||
// it's initialized at `New` or `NewFromDB`.
|
||||
// Can be used to get stats.
|
||||
Service *badger.DB
|
||||
logger *golog.Logger
|
||||
|
||||
closed uint32 // if 1 is closed.
|
||||
}
|
||||
@@ -53,11 +55,12 @@ func New(directoryPath string) (*Database, error) {
|
||||
}
|
||||
|
||||
opts := badger.DefaultOptions(directoryPath)
|
||||
opts.Logger = golog.Default.Child("[sessionsdb.badger]").DisableNewLine()
|
||||
badgerLogger := context.DefaultLogger("sessionsdb.badger").DisableNewLine()
|
||||
opts.Logger = badgerLogger
|
||||
|
||||
service, err := badger.Open(opts)
|
||||
if err != nil {
|
||||
golog.Errorf("unable to initialize the badger-based session database: %v", err)
|
||||
badgerLogger.Errorf("unable to initialize the badger-based session database: %v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -72,6 +75,12 @@ func NewFromDB(service *badger.DB) *Database {
|
||||
return db
|
||||
}
|
||||
|
||||
// SetLogger sets the logger once before server ran.
|
||||
// By default the Iris one is injected.
|
||||
func (db *Database) SetLogger(logger *golog.Logger) {
|
||||
db.logger = logger
|
||||
}
|
||||
|
||||
// Acquire receives a session's lifetime from the database,
|
||||
// if the return value is LifeTime{} then the session manager sets the life time based on the expiration duration lives in configuration.
|
||||
func (db *Database) Acquire(sid string, expires time.Duration) sessions.LifeTime {
|
||||
@@ -94,7 +103,7 @@ func (db *Database) Acquire(sid string, expires time.Duration) sessions.LifeTime
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
golog.Error(err)
|
||||
db.logger.Error(err)
|
||||
}
|
||||
|
||||
return sessions.LifeTime{} // session manager will handle the rest.
|
||||
@@ -118,10 +127,10 @@ func makeKey(sid, key string) []byte {
|
||||
|
||||
// Set sets a key value of a specific session.
|
||||
// Ignore the "immutable".
|
||||
func (db *Database) Set(sid string, lifetime sessions.LifeTime, key string, value interface{}, immutable bool) {
|
||||
func (db *Database) Set(sid string, lifetime *sessions.LifeTime, key string, value interface{}, immutable bool) {
|
||||
valueBytes, err := sessions.DefaultTranscoder.Marshal(value)
|
||||
if err != nil {
|
||||
golog.Error(err)
|
||||
db.logger.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -131,7 +140,7 @@ func (db *Database) Set(sid string, lifetime sessions.LifeTime, key string, valu
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
golog.Error(err)
|
||||
db.logger.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +158,7 @@ func (db *Database) Get(sid string, key string) (value interface{}) {
|
||||
})
|
||||
|
||||
if err != nil && err != badger.ErrKeyNotFound {
|
||||
golog.Error(err)
|
||||
db.logger.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -189,7 +198,7 @@ func (db *Database) Visit(sid string, cb func(key string, value interface{})) {
|
||||
return sessions.DefaultTranscoder.Unmarshal(valueBytes, &value)
|
||||
})
|
||||
if err != nil {
|
||||
golog.Errorf("[sessionsdb.badger.Visit] %v", err)
|
||||
db.logger.Errorf("[sessionsdb.badger.Visit] %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -231,7 +240,7 @@ func (db *Database) Delete(sid string, key string) (deleted bool) {
|
||||
txn := db.Service.NewTransaction(true)
|
||||
err := txn.Delete(makeKey(sid, key))
|
||||
if err != nil {
|
||||
golog.Error(err)
|
||||
db.logger.Error(err)
|
||||
return false
|
||||
}
|
||||
return txn.Commit() == nil
|
||||
@@ -250,7 +259,7 @@ func (db *Database) Clear(sid string) {
|
||||
for iter.Rewind(); iter.ValidForPrefix(prefix); iter.Next() {
|
||||
key := iter.Item().Key()
|
||||
if err := txn.Delete(key); err != nil {
|
||||
golog.Warnf("Database.Clear: %s: %v", key, err)
|
||||
db.logger.Warnf("Database.Clear: %s: %v", key, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -264,10 +273,10 @@ func (db *Database) Release(sid string) {
|
||||
// and remove the $sid.
|
||||
txn := db.Service.NewTransaction(true)
|
||||
if err := txn.Delete([]byte(sid)); err != nil {
|
||||
golog.Warnf("Database.Release.Delete: %s: %v", sid, err)
|
||||
db.logger.Warnf("Database.Release.Delete: %s: %v", sid, err)
|
||||
}
|
||||
if err := txn.Commit(); err != nil {
|
||||
golog.Debugf("Database.Release.Commit: %s: %v", sid, err)
|
||||
db.logger.Debugf("Database.Release.Commit: %s: %v", sid, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +291,7 @@ func closeDB(db *Database) error {
|
||||
}
|
||||
err := db.Service.Close()
|
||||
if err != nil {
|
||||
golog.Warnf("closing the badger connection: %v", err)
|
||||
db.logger.Warnf("closing the badger connection: %v", err)
|
||||
} else {
|
||||
atomic.StoreUint32(&db.closed, 1)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ type Database struct {
|
||||
// it's initialized at `New` or `NewFromDB`.
|
||||
// Can be used to get stats.
|
||||
Service *bolt.DB
|
||||
logger *golog.Logger
|
||||
}
|
||||
|
||||
var errPathMissing = errors.New("path is required")
|
||||
@@ -91,7 +92,7 @@ func (db *Database) getBucketForSession(tx *bolt.Tx, sid string) *bolt.Bucket {
|
||||
if b == nil {
|
||||
// session does not exist, it shouldn't happen, session bucket creation happens once at `Acquire`,
|
||||
// no need to accept the `bolt.bucket.CreateBucketIfNotExists`'s performance cost.
|
||||
golog.Debugf("unreachable session access for '%s'", sid)
|
||||
db.logger.Debugf("unreachable session access for '%s'", sid)
|
||||
}
|
||||
|
||||
return b
|
||||
@@ -122,20 +123,20 @@ func (db *Database) cleanup() error {
|
||||
if bExp := b.Bucket(expirationName); bExp != nil { // has expiration.
|
||||
_, expValue := bExp.Cursor().First() // the expiration bucket contains only one key(we don't care, see `Acquire`) value(time.Time) pair.
|
||||
if expValue == nil {
|
||||
golog.Debugf("cleanup: expiration is there but its value is empty '%s'", v) // should never happen.
|
||||
db.logger.Debugf("cleanup: expiration is there but its value is empty '%s'", v) // should never happen.
|
||||
continue
|
||||
}
|
||||
|
||||
var expirationTime time.Time
|
||||
if err := sessions.DefaultTranscoder.Unmarshal(expValue, &expirationTime); err != nil {
|
||||
golog.Debugf("cleanup: unable to retrieve expiration value for '%s'", v)
|
||||
db.logger.Debugf("cleanup: unable to retrieve expiration value for '%s'", v)
|
||||
continue
|
||||
}
|
||||
|
||||
if expirationTime.Before(time.Now()) {
|
||||
// expired, delete the expiration bucket.
|
||||
if err := b.DeleteBucket(expirationName); err != nil {
|
||||
golog.Debugf("cleanup: unable to destroy a session '%s'", bsid)
|
||||
db.logger.Debugf("cleanup: unable to destroy a session '%s'", bsid)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -149,6 +150,12 @@ func (db *Database) cleanup() error {
|
||||
})
|
||||
}
|
||||
|
||||
// SetLogger sets the logger once before server ran.
|
||||
// By default the Iris one is injected.
|
||||
func (db *Database) SetLogger(logger *golog.Logger) {
|
||||
db.logger = logger
|
||||
}
|
||||
|
||||
var expirationKey = []byte("exp") // it can be random.
|
||||
|
||||
// Acquire receives a session's lifetime from the database,
|
||||
@@ -166,14 +173,14 @@ func (db *Database) Acquire(sid string, expires time.Duration) (lifetime session
|
||||
// don't return a lifetime, let it empty, session manager will do its job.
|
||||
b, err = root.CreateBucket(name)
|
||||
if err != nil {
|
||||
golog.Debugf("unable to create a session bucket for '%s': %v", sid, err)
|
||||
db.logger.Debugf("unable to create a session bucket for '%s': %v", sid, err)
|
||||
return err
|
||||
}
|
||||
|
||||
expirationTime := time.Now().Add(expires)
|
||||
timeBytes, err := sessions.DefaultTranscoder.Marshal(expirationTime)
|
||||
if err != nil {
|
||||
golog.Debugf("unable to set an expiration value on session expiration bucket for '%s': %v", sid, err)
|
||||
db.logger.Debugf("unable to set an expiration value on session expiration bucket for '%s': %v", sid, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -194,7 +201,7 @@ func (db *Database) Acquire(sid string, expires time.Duration) (lifetime session
|
||||
|
||||
var expirationTime time.Time
|
||||
if err = sessions.DefaultTranscoder.Unmarshal(expValue, &expirationTime); err != nil {
|
||||
golog.Debugf("acquire: unable to retrieve expiration value for '%s', value was: '%s': %v", sid, expValue, err)
|
||||
db.logger.Debugf("acquire: unable to retrieve expiration value for '%s', value was: '%s': %v", sid, expValue, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -207,7 +214,7 @@ func (db *Database) Acquire(sid string, expires time.Duration) (lifetime session
|
||||
return
|
||||
})
|
||||
if err != nil {
|
||||
golog.Debugf("unable to acquire session '%s': %v", sid, err)
|
||||
db.logger.Debugf("unable to acquire session '%s': %v", sid, err)
|
||||
return sessions.LifeTime{}
|
||||
}
|
||||
|
||||
@@ -227,7 +234,7 @@ func (db *Database) OnUpdateExpiration(sid string, newExpires time.Duration) err
|
||||
root := db.getBucket(tx)
|
||||
b := root.Bucket(expirationName)
|
||||
if b == nil {
|
||||
// golog.Debugf("tried to reset the expiration value for '%s' while its configured lifetime is unlimited or the session is already expired and not found now", sid)
|
||||
// db.logger.Debugf("tried to reset the expiration value for '%s' while its configured lifetime is unlimited or the session is already expired and not found now", sid)
|
||||
return sessions.ErrNotFound
|
||||
}
|
||||
|
||||
@@ -235,7 +242,7 @@ func (db *Database) OnUpdateExpiration(sid string, newExpires time.Duration) err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
golog.Debugf("unable to reset the expiration value for '%s': %v", sid, err)
|
||||
db.logger.Debugf("unable to reset the expiration value for '%s': %v", sid, err)
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -247,10 +254,10 @@ func makeKey(key string) []byte {
|
||||
|
||||
// Set sets a key value of a specific session.
|
||||
// Ignore the "immutable".
|
||||
func (db *Database) Set(sid string, lifetime sessions.LifeTime, key string, value interface{}, immutable bool) {
|
||||
func (db *Database) Set(sid string, _ *sessions.LifeTime, key string, value interface{}, immutable bool) {
|
||||
valueBytes, err := sessions.DefaultTranscoder.Marshal(value)
|
||||
if err != nil {
|
||||
golog.Debug(err)
|
||||
db.logger.Debug(err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -268,7 +275,7 @@ func (db *Database) Set(sid string, lifetime sessions.LifeTime, key string, valu
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
golog.Debug(err)
|
||||
db.logger.Debug(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +295,7 @@ func (db *Database) Get(sid string, key string) (value interface{}) {
|
||||
return sessions.DefaultTranscoder.Unmarshal(valueBytes, &value)
|
||||
})
|
||||
if err != nil {
|
||||
golog.Debugf("session '%s' key '%s' cannot be retrieved: %v", sid, key, err)
|
||||
db.logger.Debugf("session '%s' key '%s' cannot be retrieved: %v", sid, key, err)
|
||||
}
|
||||
|
||||
return
|
||||
@@ -305,7 +312,7 @@ func (db *Database) Visit(sid string, cb func(key string, value interface{})) {
|
||||
return b.ForEach(func(k []byte, v []byte) error {
|
||||
var value interface{}
|
||||
if err := sessions.DefaultTranscoder.Unmarshal(v, &value); err != nil {
|
||||
golog.Debugf("unable to retrieve value of key '%s' of '%s': %v", k, sid, err)
|
||||
db.logger.Debugf("unable to retrieve value of key '%s' of '%s': %v", k, sid, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -315,7 +322,7 @@ func (db *Database) Visit(sid string, cb func(key string, value interface{})) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
golog.Debugf("Database.Visit: %s: %v", sid, err)
|
||||
db.logger.Debugf("Database.Visit: %s: %v", sid, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +339,7 @@ func (db *Database) Len(sid string) (n int) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
golog.Debugf("Database.Len: %s: %v", sid, err)
|
||||
db.logger.Debugf("Database.Len: %s: %v", sid, err)
|
||||
}
|
||||
|
||||
return
|
||||
@@ -366,7 +373,7 @@ func (db *Database) Clear(sid string) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
golog.Debugf("Database.Clear: %s: %v", sid, err)
|
||||
db.logger.Debugf("Database.Clear: %s: %v", sid, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +391,7 @@ func (db *Database) Release(sid string) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
golog.Debugf("Database.Release: %s: %v", sid, err)
|
||||
db.logger.Debugf("Database.Release: %s: %v", sid, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +403,7 @@ func (db *Database) Close() error {
|
||||
func closeDB(db *Database) error {
|
||||
err := db.Service.Close()
|
||||
if err != nil {
|
||||
golog.Warnf("closing the BoltDB connection: %v", err)
|
||||
db.logger.Warnf("closing the BoltDB connection: %v", err)
|
||||
}
|
||||
|
||||
return err
|
||||
|
||||
@@ -77,7 +77,8 @@ func DefaultConfig() Config {
|
||||
|
||||
// Database the redis back-end session database for the sessions.
|
||||
type Database struct {
|
||||
c Config
|
||||
c Config
|
||||
logger *golog.Logger
|
||||
}
|
||||
|
||||
var _ sessions.Database = (*Database)(nil)
|
||||
@@ -131,6 +132,12 @@ func (db *Database) Config() *Config {
|
||||
return &db.c // 6 Aug 2019 - keep that for no breaking change.
|
||||
}
|
||||
|
||||
// SetLogger sets the logger once before server ran.
|
||||
// By default the Iris one is injected.
|
||||
func (db *Database) SetLogger(logger *golog.Logger) {
|
||||
db.logger = logger
|
||||
}
|
||||
|
||||
// Acquire receives a session's lifetime from the database,
|
||||
// if the return value is LifeTime{} then the session manager sets the life time based on the expiration duration lives in configuration.
|
||||
func (db *Database) Acquire(sid string, expires time.Duration) sessions.LifeTime {
|
||||
@@ -140,7 +147,7 @@ func (db *Database) Acquire(sid string, expires time.Duration) sessions.LifeTime
|
||||
// fmt.Printf("db.Acquire expires: %s. Seconds: %v\n", expires, expires.Seconds())
|
||||
// not found, create an entry with ttl and return an empty lifetime, session manager will do its job.
|
||||
if err := db.c.Driver.Set(key, sid, int64(expires.Seconds())); err != nil {
|
||||
golog.Debug(err)
|
||||
db.logger.Debug(err)
|
||||
}
|
||||
|
||||
return sessions.LifeTime{} // session manager will handle the rest.
|
||||
@@ -168,17 +175,17 @@ func (db *Database) makeKey(sid, key string) string {
|
||||
|
||||
// Set sets a key value of a specific session.
|
||||
// Ignore the "immutable".
|
||||
func (db *Database) Set(sid string, lifetime sessions.LifeTime, key string, value interface{}, immutable bool) {
|
||||
func (db *Database) Set(sid string, lifetime *sessions.LifeTime, key string, value interface{}, immutable bool) {
|
||||
valueBytes, err := sessions.DefaultTranscoder.Marshal(value)
|
||||
if err != nil {
|
||||
golog.Error(err)
|
||||
db.logger.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// fmt.Println("database.Set")
|
||||
// fmt.Printf("lifetime.DurationUntilExpiration(): %s. Seconds: %v\n", lifetime.DurationUntilExpiration(), lifetime.DurationUntilExpiration().Seconds())
|
||||
if err = db.c.Driver.Set(db.makeKey(sid, key), valueBytes, int64(lifetime.DurationUntilExpiration().Seconds())); err != nil {
|
||||
golog.Debug(err)
|
||||
db.logger.Debug(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +203,7 @@ func (db *Database) get(key string, outPtr interface{}) error {
|
||||
}
|
||||
|
||||
if err = sessions.DefaultTranscoder.Unmarshal(data.([]byte), outPtr); err != nil {
|
||||
golog.Debugf("unable to unmarshal value of key: '%s': %v", key, err)
|
||||
db.logger.Debugf("unable to unmarshal value of key: '%s': %v", key, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -206,7 +213,7 @@ func (db *Database) get(key string, outPtr interface{}) error {
|
||||
func (db *Database) keys(sid string) []string {
|
||||
keys, err := db.c.Driver.GetKeys(db.makeKey(sid, ""))
|
||||
if err != nil {
|
||||
golog.Debugf("unable to get all redis keys of session '%s': %v", sid, err)
|
||||
db.logger.Debugf("unable to get all redis keys of session '%s': %v", sid, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -233,7 +240,7 @@ func (db *Database) Len(sid string) (n int) {
|
||||
func (db *Database) Delete(sid string, key string) (deleted bool) {
|
||||
err := db.c.Driver.Delete(db.makeKey(sid, key))
|
||||
if err != nil {
|
||||
golog.Error(err)
|
||||
db.logger.Error(err)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
@@ -243,7 +250,7 @@ func (db *Database) Clear(sid string) {
|
||||
keys := db.keys(sid)
|
||||
for _, key := range keys {
|
||||
if err := db.c.Driver.Delete(key); err != nil {
|
||||
golog.Debugf("unable to delete session '%s' value of key: '%s': %v", sid, key, err)
|
||||
db.logger.Debugf("unable to delete session '%s' value of key: '%s': %v", sid, key, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +263,7 @@ func (db *Database) Release(sid string) {
|
||||
// and remove the $sid.
|
||||
err := db.c.Driver.Delete(db.c.Prefix + sid)
|
||||
if err != nil {
|
||||
golog.Debugf("Database.Release.Driver.Delete: %s: %v", sid, err)
|
||||
db.logger.Debugf("Database.Release.Driver.Delete: %s: %v", sid, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user