iris/sessions/sessiondb/redis/database.go
corebreaker 0f1a265e5a Fix up for sessions
- Restore expiration state of the sessions
- Add APIs to modify expire date
- Free the timer for the session destroy task

Former-commit-id: 4d796a9efba2c37cd3750275ac62c068ceb82be8
2017-07-31 21:49:30 +03:00

107 lines
2.8 KiB
Go

package redis
import (
"time"
"bytes"
"encoding/gob"
"github.com/kataras/iris/sessions/sessiondb/redis/service"
)
// Database the redis back-end session database for the sessions.
type Database struct {
redis *service.Service
}
// New returns a new redis database.
func New(cfg ...service.Config) *Database {
return &Database{redis: service.New(cfg...)}
}
// Config returns the configuration for the redis server bridge, you can change them.
func (d *Database) Config() *service.Config {
return d.redis.Config
}
// Load loads the values to the underline.
func (d *Database) Load(sid string) (datas map[string]interface{}, expireDate *time.Time) {
values := make(map[string]interface{})
if !d.redis.Connected { //yes, check every first time's session for valid redis connection
d.redis.Connect()
_, err := d.redis.PingPong()
if err != nil {
if err != nil {
// don't use to get the logger, just prin these to the console... atm
///TODO: Find a way to use the iris' defined logger via an optional interface to Database.
// println("Redis Connection error on Connect: " + err.Error())
// println("But don't panic, auto-switching to memory store right now!")
}
}
}
//fetch the values from this session id and copy-> store them
val, err := d.redis.GetBytes(sid)
if err == nil {
// err removed because of previous TODO
DeserializeBytes(val, &values)
}
datas, _ = values["session-data"].(map[string]interface{})
dbExpireDateValue, exists := values["expire-date"]
if !exists {
return
}
expireDateValue, ok := dbExpireDateValue.(time.Time)
if !ok {
return
}
return datas, &expireDateValue
}
// serialize the values to be stored as strings inside the Redis, we panic at any serialization error here
func serialize(values map[string]interface{}) []byte {
val, err := SerializeBytes(values)
if err != nil {
return nil
}
return val
}
// Update updates the real redis store
func (d *Database) Update(sid string, newValues map[string]interface{}, expireDate *time.Time) {
if len(newValues) == 0 {
go d.redis.Delete(sid)
} else {
datas := map[string]interface{}{"session-data": newValues}
if expireDate != nil {
datas["expire-date"] = *expireDate
}
//set/update all the values
go d.redis.Set(sid, serialize(datas))
}
}
// SerializeBytes serializa bytes using gob encoder and returns them
func SerializeBytes(m interface{}) ([]byte, error) {
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
err := enc.Encode(m)
if err == nil {
return buf.Bytes(), nil
}
return nil, err
}
// DeserializeBytes converts the bytes to an object using gob decoder
func DeserializeBytes(b []byte, m interface{}) error {
dec := gob.NewDecoder(bytes.NewBuffer(b))
return dec.Decode(m) //no reference here otherwise doesn't work because of go remote object
}