Commit 979fe08f authored by Ajit Jagtap's avatar Ajit Jagtap
Browse files

Merge branch 'ab_Add_SessionMGRCache' into 'devbranch'

Add: Functionality to call session manager from bls.

Closes MKCLOS/coreosv3/corestudio#315

See merge request !170
parents cd392d95 a023f388
2 merge requests!173Mep release19032020,!170Add: Functionality to call session manager from bls.
Showing with 157 additions and 5 deletions
...@@ -18,6 +18,11 @@ var ( ...@@ -18,6 +18,11 @@ var (
) )
// Cacher provides access to underlying cache, make sure all caches implement these methods. // Cacher provides access to underlying cache, make sure all caches implement these methods.
//
// The return types of data can be different. Ex. In case of redis cache it is `string`. The caller needs to handle this with the help of Type() method.
//
// Ex.
// (Cacher{}).Type() == TypeRedisCache { // your implementation }
type Cacher interface { type Cacher interface {
// SET // SET
Set(key string, val interface{}) Set(key string, val interface{})
...@@ -34,6 +39,8 @@ type Cacher interface { ...@@ -34,6 +39,8 @@ type Cacher interface {
// GetItemsCount // GetItemsCount
GetItemsCount() int GetItemsCount() int
Type() int
} }
// GetCacheInstance returns a cache instance, panics if invalid cache type is provided // GetCacheInstance returns a cache instance, panics if invalid cache type is provided
......
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl" "corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
"github.com/go-redis/redis" "github.com/go-redis/redis"
"github.com/tidwall/gjson"
) )
const ( const (
...@@ -52,8 +51,9 @@ type RedisCache struct { ...@@ -52,8 +51,9 @@ type RedisCache struct {
Prefix string // this will be used for storing keys for provided project Prefix string // this will be used for storing keys for provided project
} }
// Setup - // Setup initializes redis cache for application. Must be called only once.
func (rc *RedisCache) Setup(addr, password, prefix string, db int, exp time.Duration) { func (rc *RedisCache) Setup(addr, password, prefix string, db int, exp time.Duration) {
if rc == nil { if rc == nil {
rc = new(RedisCache) rc = new(RedisCache)
} }
...@@ -84,6 +84,7 @@ func (rc *RedisCache) Setup(addr, password, prefix string, db int, exp time.Dura ...@@ -84,6 +84,7 @@ func (rc *RedisCache) Setup(addr, password, prefix string, db int, exp time.Dura
rc.keyStr = contcat(rc.Prefix, keySplitter) rc.keyStr = contcat(rc.Prefix, keySplitter)
rc.addPrefix = true rc.addPrefix = true
} }
} }
// Set marshalls provided value and stores against provided key. Errors will be logged to initialized logger. // Set marshalls provided value and stores against provided key. Errors will be logged to initialized logger.
...@@ -135,11 +136,11 @@ func (rc *RedisCache) Get(key string) (interface{}, bool) { ...@@ -135,11 +136,11 @@ func (rc *RedisCache) Get(key string) (interface{}, bool) {
// Get returns error if key is not present. // Get returns error if key is not present.
val, err := rc.cli.Get(rc.key(key)).Result() val, err := rc.cli.Get(rc.key(key)).Result()
if err != nil { if err != nil {
loggermdl.LogError("error getting key ", key, " error: ", err) loggermdl.LogError("error getting key", key, "from redis cache with error:", err)
return nil, false return nil, false
} }
return gjson.Parse(val).Value(), true return val, true
} }
// Delete - // Delete -
...@@ -202,3 +203,7 @@ func (rc *RedisCache) key(key string) string { ...@@ -202,3 +203,7 @@ func (rc *RedisCache) key(key string) string {
} }
return key return key
} }
func (rc *RedisCache) Type() int {
return TypeRedisCache
}
...@@ -19,11 +19,13 @@ type FastCacheHelper struct { ...@@ -19,11 +19,13 @@ type FastCacheHelper struct {
MaxEntries int MaxEntries int
} }
//Setup create new object of GC // Setup initializes fastcache cache for application. Must be called only once.
func (fastCacheHelper *FastCacheHelper) Setup(maxEntries int, expiration time.Duration, cleanupTime time.Duration) { func (fastCacheHelper *FastCacheHelper) Setup(maxEntries int, expiration time.Duration, cleanupTime time.Duration) {
fastCacheHelper.MaxEntries = maxEntries fastCacheHelper.MaxEntries = maxEntries
fastCacheHelper.Expiration = expiration fastCacheHelper.Expiration = expiration
fastCacheHelper.FastCache = cache.New(fastCacheHelper.Expiration, fastCacheHelper.CleanupTime) fastCacheHelper.FastCache = cache.New(fastCacheHelper.Expiration, fastCacheHelper.CleanupTime)
} }
// Get - // Get -
...@@ -65,3 +67,7 @@ func (fastCacheHelper *FastCacheHelper) Delete(key string) { ...@@ -65,3 +67,7 @@ func (fastCacheHelper *FastCacheHelper) Delete(key string) {
func (fastCacheHelper *FastCacheHelper) GetItemsCount() int { func (fastCacheHelper *FastCacheHelper) GetItemsCount() int {
return fastCacheHelper.FastCache.ItemCount() return fastCacheHelper.FastCache.ItemCount()
} }
func (fh *FastCacheHelper) Type() int {
return TypeFastCache
}
package sessionmanagermdl
import (
"coresls/servers/coresls/app/models"
"errors"
"time"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/cachemdl"
)
// Entry is a data to be stored against a key.
type Entry struct {
Data gjson.Result `json:"data,omitempty"`
Expiration int64 `json:"expiration,omitempty"`
ExpiredAT int64 `json:"expiredAt,omitempty"`
}
const (
// keys for the entry object
KEY_DATA = "data"
KEY_EXPIREDAT = "expiredAt"
KEY_EXPIRATION = "expiration"
)
var store cachemdl.Cacher
var ErrSessionNotFound = errors.New("SESSION_NOT_FOUND")
var ErrInvalidDataType = errors.New("INVALID_DATA_Type")
// InitSessionManagerCache initializes the cache with provided configuration. Need to provide a cache type to use.
func InitSessionManagerCache(chacheType int) {
cacheConfig := cachemdl.CacheConfig{
Type: chacheType,
RedisCache: &cachemdl.RedisCache{
Addr: "", // empty takes default redis address 6379
DB: models.RedisDBSessionManager,
Prefix: models.ProjectID,
},
FastCache: &cachemdl.FastCacheHelper{
CleanupTime: 60 * time.Minute,
MaxEntries: 1000,
Expiration: -1,
},
}
store = cachemdl.GetCacheInstance(&cacheConfig)
}
// NewEntry prepares the object required to store data in session.
//
// The `exp` field interprets time in seconds. Ex. For 5 seconds, set `5`
func NewEntry(val gjson.Result, exp int64) Entry {
duration := time.Duration(exp) * time.Second
deadLine := time.Now().Add(duration).Unix()
return Entry{
Data: val,
Expiration: exp,
ExpiredAT: deadLine,
}
}
// NewRedisEntry prepares the entry for redis cache. This is required because redis accepts a byte array.
func NewRedisEntry(entry Entry) string {
var data string
// the error can be ignored here as we have valid keys and data values
data, _ = sjson.Set(data, KEY_DATA, entry.Data.Value())
data, _ = sjson.Set(data, KEY_EXPIRATION, entry.Expiration)
data, _ = sjson.Set(data, KEY_EXPIREDAT, entry.ExpiredAT)
return data
}
// ToObject returns an cache entry as an object. It is better than sjson.Set() as we need to perform gjson.Parse().
func ToObject(entry Entry) map[string]interface{} {
return map[string]interface{}{
KEY_DATA: entry.Data.Value(),
KEY_EXPIRATION: entry.Expiration,
KEY_EXPIREDAT: entry.ExpiredAT,
}
}
// Store adds/ updates the entry against the provided key.
func Store(key string, entry Entry) {
duration := time.Duration(entry.Expiration) * time.Second
// if session manager uses redis cache, the data field (gjson.Result) is saved as is.
// This adds irrelevant fields in redis cache and we get them on retrieve operation.
// The following operation needs to be performed so that the data is marshaled correctly. Redis only accepts []byte{}.
if store.Type() == cachemdl.TypeRedisCache {
store.SetWithExpiration(key, NewRedisEntry(entry), duration)
return
}
store.SetWithExpiration(key, entry, duration)
}
// Retrieve returns the entry present against the provided key. If a key is not available or data stored is not of type gjson.Result, a non nil error will be returned
func Retrieve(key string) (Entry, error) {
data, ok := store.Get(key)
if !ok {
return Entry{}, ErrSessionNotFound
}
switch v := data.(type) {
case string: // for result from redis cache
res := gjson.Parse(v)
return Entry{
Data: res.Get(KEY_DATA),
Expiration: res.Get(KEY_EXPIRATION).Int(),
ExpiredAT: res.Get(KEY_EXPIREDAT).Int(),
}, nil
case Entry: // for result from fastcache
return v, nil
default:
return Entry{}, ErrInvalidDataType
}
}
// Delete removes the entry from session manager. If the key is not present, error `ErrSessionNotFound` will be thrown. Caller can ignore error if this is acceptable.
func Delete(key string) error {
_, ok := store.Get(key)
if !ok {
return ErrSessionNotFound
}
store.Delete(key)
return nil
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment