Go API Documentation

github.com/TykTechnologies/tyk/storage

No package summary is available.

Package

Files: 7. Third party imports: 2. Imports from organisation: 8. Tests: 0. Benchmarks: 0.

Constants

const (
	HashSha256	= crypto.HashSha256
	HashMurmur32	= crypto.HashMurmur32
	HashMurmur64	= crypto.HashMurmur64
	HashMurmur128	= crypto.HashMurmur128
)
const (
	// DefaultConn is the default connection type. Not analytics and Not cache.
	DefaultConn	= "default"
	// CacheConn is the cache connection type
	CacheConn	= "cache"
	// AnalyticsConn is the analytics connection type
	AnalyticsConn	= "analytics"
)
const (
	resourceOauthClient	= "OauthClient"
	resourceCertificate	= "Certificate"
	resourceApiKey		= "ApiKey"
	resourceKey		= "Key"
)

Vars

ErrKeyNotFound is a standard error for when a key is not found in the storage engine

var ErrKeyNotFound = errors.New("key not found")
var ErrMDCBConnectionLost = errors.New("mdcb connection is lost")
var (
	HashStr	= crypto.HashStr
	HashKey	= crypto.HashKey
)
var (
	GenerateToken	= crypto.GenerateToken
	TokenHashAlgo	= crypto.TokenHashAlgo
	TokenID		= crypto.TokenID
	TokenOrg	= crypto.TokenOrg
)
var (
	// ErrRedisIsDown is returned when we can't communicate with redis
	ErrRedisIsDown	= errors.New("storage: Redis is either down or was not configured")

	// ErrStorageConn is returned when we can't get a connection from the ConnectionHandler
	ErrStorageConn	= fmt.Errorf("Error trying to get singleton instance: %w", ErrRedisIsDown)
)
var log = logger.Get()

Types

AnalyticsHandler

This type doesn't have documentation.

Field name Field type Comment
type

any

No comment on field.
type AnalyticsHandler interface {
	Connect() bool
	AppendToSetPipelined(string, [][]byte)
	GetAndDeleteSet(string) []interface{}
	SetExp(string, int64) error	// Set key expiration
	GetExp(string) (int64, error)	// Returns expiry of a key
}

ConnectionHandler

ConnectionHandler is a wrapper around the storage connection. It allows to dynamically enable/disable talking with storage and mantain a connection map to different storage types.

Field name Field type Comment
connections

map[string]model.Connector

No comment on field.
connectionsMu

*sync.RWMutex

No comment on field.
storageUp

atomic.Value

No comment on field.
disableStorage

atomic.Value

No comment on field.
ctx

context.Context

No comment on field.
reconnect

chan struct{}

No comment on field.
type ConnectionHandler struct {
	connections	map[string]model.Connector
	connectionsMu	*sync.RWMutex

	storageUp	atomic.Value
	disableStorage	atomic.Value

	ctx		context.Context
	reconnect	chan struct{}
}

DummyStorage

DummyStorage is a simple in-memory storage structure used for testing or demonstration purposes. It simulates a storage system.

Field name Field type Comment
Data

map[string]string

No comment on field.
IndexList

map[string][]string

No comment on field.
type DummyStorage struct {
	Data		map[string]string
	IndexList	map[string][]string
}

Handler

Handler is a standard interface to a storage backend, used by AuthorisationManager to read and write key values to the backend

Field name Field type Comment
type

any

No comment on field.
type Handler interface {
	GetKey(string) (string, error)	// Returned string is expected to be a JSON object (user.SessionState)
	GetMultiKey([]string) ([]string, error)
	GetRawKey(string) (string, error)
	SetKey(string, string, int64) error	// Second input string is expected to be a JSON object (user.SessionState)
	SetRawKey(string, string, int64) error
	SetExp(string, int64) error	// Set key expiration
	GetExp(string) (int64, error)	// Returns expiry of a key
	GetKeys(string) []string
	DeleteKey(string) bool
	DeleteAllKeys() bool
	DeleteRawKey(string) bool
	DeleteRawKeys([]string) bool
	Connect() bool
	GetKeysAndValues() map[string]string
	GetKeysAndValuesWithFilter(string) map[string]string
	DeleteKeys([]string) bool
	Decrement(string)
	IncrememntWithExpire(string, int64) int64
	SetRollingWindow(key string, per int64, val string, pipeline bool) (int, []interface{})
	GetRollingWindow(key string, per int64, pipeline bool) (int, []interface{})
	GetSet(string) (map[string]string, error)
	AddToSet(string, string)
	GetAndDeleteSet(string) []interface{}
	RemoveFromSet(string, string)
	DeleteScanMatch(string) bool
	GetKeyPrefix() string
	AddToSortedSet(string, string, float64)
	GetSortedSetRange(string, string, string) ([]string, []float64, error)
	RemoveSortedSetRange(string, string, string) error
	GetListRange(string, int64, int64) ([]string, error)
	RemoveFromList(string, string) error
	AppendToSet(string, string)
	Exists(string) (bool, error)
}

MdcbStorage

This type doesn't have documentation.

Field name Field type Comment
local

Handler

No comment on field.
rpc

Handler

No comment on field.
logger

*logrus.Entry

No comment on field.
OnRPCCertPull

func(key string, val string) error

No comment on field.
type MdcbStorage struct {
	local		Handler
	rpc		Handler
	logger		*logrus.Entry
	OnRPCCertPull	func(key string, val string) error
}

RedisCluster

RedisCluster is a storage manager that uses the redis database.

Field name Field type Comment
KeyPrefix

string

No comment on field.
HashKeys

bool

No comment on field.
IsCache

bool

No comment on field.
IsAnalytics

bool

No comment on field.
ConnectionHandler

*ConnectionHandler

No comment on field.
RedisController

*RedisController

RedisController must remain for compatibility with goplugins

storageMu

sync.Mutex

No comment on field.
kvStorage

model.KeyValue

No comment on field.
flusherStorage

model.Flusher

No comment on field.
queueStorage

model.Queue

No comment on field.
listStorage

model.List

No comment on field.
setStorage

model.Set

No comment on field.
sortedSetStorage

model.SortedSet

No comment on field.
type RedisCluster struct {
	KeyPrefix	string
	HashKeys	bool
	IsCache		bool
	IsAnalytics	bool

	ConnectionHandler	*ConnectionHandler
	// RedisController must remain for compatibility with goplugins
	RedisController	*RedisController

	storageMu		sync.Mutex
	kvStorage		model.KeyValue
	flusherStorage		model.Flusher
	queueStorage		model.Queue
	listStorage		model.List
	setStorage		model.Set
	sortedSetStorage	model.SortedSet
}

RedisController

RedisController acts as a shim to provide backward compatibility for Go plugins users. It facilitates connecting to Redis using Tyk's storage package in a way that doesn't break existing implementations. changes here are sensible

Field name Field type Comment
connection

*ConnectionHandler

No comment on field.
type RedisController struct {
	connection *ConnectionHandler
}

Functions

func NewConnectionHandler

NewConnectionHandler creates a new connection handler not connected

func NewConnectionHandler(ctx context.Context) *ConnectionHandler {
	return &ConnectionHandler{
		ctx:		ctx,
		reconnect:	make(chan struct{}, 1),
		connections:	make(map[string]model.Connector),
		connectionsMu:	&sync.RWMutex{},
	}
}

Cognitive complexity: 3, Cyclomatic complexity: 1

Uses: model.Connector, sync.RWMutex.

func NewConnector

NewConnector creates a new storage connection.

func NewConnector(connType string, conf config.Config) (model.Connector, error) {
	cfg := conf.Storage
	if connType == CacheConn && conf.EnableSeperateCacheStore {
		cfg = conf.CacheStorage
	} else if connType == AnalyticsConn && conf.EnableAnalytics && conf.EnableSeperateAnalyticsStore {
		cfg = conf.AnalyticsStorage
	}
	log.Debug("Creating new " + connType + " Storage connection")

	// poolSize applies per cluster node and not for the whole cluster.
	poolSize := 500
	if cfg.MaxActive > 0 {
		poolSize = cfg.MaxActive
	}

	timeout := 5
	if cfg.Timeout > 0 {
		timeout = cfg.Timeout
	}

	opts := []model.Option{}
	optsR := model.RedisOptions{
		Username:		cfg.Username,
		Password:		cfg.Password,
		Host:			cfg.Host,
		Port:			cfg.Port,
		Timeout:		timeout,
		Hosts:			cfg.Hosts,
		Addrs:			cfg.Addrs,
		MasterName:		cfg.MasterName,
		SentinelPassword:	cfg.SentinelPassword,
		Database:		cfg.Database,
		MaxActive:		poolSize,
		EnableCluster:		cfg.EnableCluster,
	}
	opts = append(opts, model.WithRedisConfig(&optsR))

	if cfg.UseSSL {
		tls := model.TLS{
			Enable:			cfg.UseSSL,
			InsecureSkipVerify:	cfg.SSLInsecureSkipVerify,
			CAFile:			cfg.CAFile,
			CertFile:		cfg.CertFile,
			KeyFile:		cfg.KeyFile,
			MinVersion:		cfg.TLSMinVersion,
			MaxVersion:		cfg.TLSMaxVersion,
		}
		opts = append(opts, model.WithTLS(&tls))
	}

	return connector.NewConnector(model.RedisV9Type, opts...)
}

Cognitive complexity: 13, Cyclomatic complexity: 9

Uses: connector.NewConnector, model.Option, model.RedisOptions, model.RedisV9Type, model.TLS, model.WithRedisConfig, model.WithTLS.

func NewDummyStorage

NewDummyStorage creates and returns a new instance of DummyStorage.

func NewDummyStorage() *DummyStorage {
	return &DummyStorage{
		Data:		make(map[string]string),
		IndexList:	make(map[string][]string),
	}
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func NewMdcbStorage

func NewMdcbStorage(local, rpc Handler, log *logrus.Entry, OnRPCCertPull func(key string, val string) error) *MdcbStorage {
	return &MdcbStorage{
		local:		local,
		rpc:		rpc,
		logger:		log,
		OnRPCCertPull:	OnRPCCertPull,
	}
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func NewRedisController

NewRedisController initializes a new RedisController. This method ensures Go plugins can connect to Redis leveraging Tyk's internal storage mechanisms with minimal changes to their code.

func NewRedisController(ctx context.Context) *RedisController {
	return &RedisController{
		connection: NewConnectionHandler(ctx),
	}
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (*ConnectionHandler) Connect

Connect starts a go routine that periodically tries to connect to storage.

onConnect will be called when we have established a successful storage reconnection

func (rc *ConnectionHandler) Connect(ctx context.Context, onConnect func(), conf *config.Config) {
	err := rc.initConnection(*conf)
	if err != nil {
		log.WithError(err).Error("Could not initialize connection to Redis cluster")
		return
	}

	// First time connecting to the clusters. We need this for the first connection (and avoid waiting 1second for the rc.statusCheck loop).
	for connTyp, connection := range rc.connections {
		if connection == nil {
			log.Warn("connection" + connTyp + " is nil")
		}
		err := backoff.Retry(func() error { return connection.Ping(ctx) }, getExponentialBackoff())
		if err != nil {
			log.WithError(err).Errorf("Could not connect to Redis cluster after many attempts. Host(s): %v", getRedisAddrs(conf.Storage))
		}
	}

	rc.storageUp.Store(true)
	go rc.recoverLoop(ctx, onConnect)

	// We need the ticker to constantly checking the connection status of Redis. If Redis gets down and up again, we should be able to recover.
	go rc.statusCheck(ctx)
}

Cognitive complexity: 10, Cyclomatic complexity: 5

Uses: backoff.Retry.

func (*ConnectionHandler) Connected

Connected returns true if we are connected to redis

func (rc *ConnectionHandler) Connected() bool {
	v := rc.storageUp.Load()
	if v != nil {
		return v.(bool)
	}
	return false
}

Cognitive complexity: 2, Cyclomatic complexity: 2

func (*ConnectionHandler) DisableStorage

DisableStorage allows to dynamically enable/disable talking with storage

func (rc *ConnectionHandler) DisableStorage(setStorageDown bool) {
	if setStorageDown {
		// we make sure x set that redis is down
		rc.disableStorage.Store(true)
		rc.storageUp.Store(false)
		return
	}

	rc.disableStorage.Store(false)
	rc.storageUp.Store(false)

	ctx, cancel := context.WithTimeout(rc.ctx, 5*time.Second)
	defer cancel()

	if !rc.WaitConnect(ctx) {
		panic("Can't reconnect to redis after disable")
	}
	rc.reconnect <- struct{}{}
}

Cognitive complexity: 6, Cyclomatic complexity: 3

Uses: context.WithTimeout, time.Second.

func (*ConnectionHandler) Disconnect

Disconnect closes the connection to the storage

func (rc *ConnectionHandler) Disconnect() error {
	for _, v := range rc.connections {
		if v != nil {
			if err := v.Disconnect(context.Background()); err != nil {
				return err
			}
		}
	}
	return nil
}

Cognitive complexity: 7, Cyclomatic complexity: 4

Uses: context.Background.

func (*ConnectionHandler) WaitConnect

WaitConnect waits until we are connected to the storage

func (rc *ConnectionHandler) WaitConnect(ctx context.Context) bool {
	for {
		select {
		case <-ctx.Done():
			return false
		default:
			if rc.Connected() {
				return true
			}

			time.Sleep(10 * time.Millisecond)
		}
	}
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: time.Millisecond, time.Sleep.

func (*DummyStorage) AddToSet

AddToSet adds a value to a set associated with a key in DummyStorage; implementation pending.

func (s *DummyStorage) AddToSet(string, string) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) AddToSortedSet

AddToSortedSet inserts a value with a score into a sorted set in DummyStorage; implementation pending.

func (s *DummyStorage) AddToSortedSet(string, string, float64) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) AppendToSet

AppendToSet adds a new value to the end of a list associated with a key in DummyStorage.

func (s *DummyStorage) AppendToSet(keyName string, value string) {
	s.IndexList[keyName] = append(s.IndexList[keyName], value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) Connect

Connect establishes a connection to the storage backend; not currently implemented.

func (s *DummyStorage) Connect() bool {
	return true
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) Decrement

Decrement reduces the value of a specified key in DummyStorage; implementation pending.

func (s *DummyStorage) Decrement(string) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) DeleteAllKeys

DeleteAllKeys removes all keys and their associated data from the DummyStorage. This method is intended to provide a way to clear the entire storage, which can be particularly useful in testing scenarios to ensure a clean state before tests.

func (s *DummyStorage) DeleteAllKeys() bool {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) DeleteKey

DeleteKey removes a specified key from DummyStorage, returning true if successful.

func (s *DummyStorage) DeleteKey(key string) bool {
	if _, ok := s.Data[key]; !ok {
		return false
	}

	delete(s.Data, key)
	return true
}

Cognitive complexity: 2, Cyclomatic complexity: 2

func (*DummyStorage) DeleteKeys

DeleteKeys removes a list of keys from DummyStorage, returning a success status; not yet implemented.

func (s *DummyStorage) DeleteKeys([]string) bool {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) DeleteRawKey

DeleteRawKey removes a specified key from DummyStorage, returning success status; not yet implemented.

func (s *DummyStorage) DeleteRawKey(string) bool {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) DeleteRawKeys

DeleteRawKeys removes a set of raw keys from DummyStorage, returning success status; not yet implemented.

func (s *DummyStorage) DeleteRawKeys([]string) bool	{ panic("implement me") }

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) DeleteScanMatch

DeleteScanMatch deletes keys matching a pattern from DummyStorage, returning true if successful.

func (s *DummyStorage) DeleteScanMatch(pattern string) bool {
	if pattern == "*" {
		s.Data = make(map[string]string)
		return true
	}

	return false
}

Cognitive complexity: 2, Cyclomatic complexity: 2

func (*DummyStorage) Exists

Exists checks if a key exists in either the IndexList or Data in DummyStorage; returns true if found.

func (s *DummyStorage) Exists(keyName string) (bool, error) {
	_, existIndex := s.IndexList[keyName]
	_, existRaw := s.Data[keyName]
	return existIndex || existRaw, nil
}

Cognitive complexity: 0, Cyclomatic complexity: 2

func (*DummyStorage) GetAndDeleteSet

GetAndDeleteSet retrieves and then deletes a set associated with a key in DummyStorage; not implemented.

func (s *DummyStorage) GetAndDeleteSet(string) []interface{} {
	panic("implement me")
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (*DummyStorage) GetExp

GetExp retrieves the expiration time of a specific key from the DummyStorage. This method accepts a string parameter representing the key and returns an int64 which is the expiration time associated with that key, along with an error.

func (s *DummyStorage) GetExp(string) (int64, error) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) GetKey

GetKey retrieves the value for a given key from DummyStorage, or an error if not found.

func (s *DummyStorage) GetKey(key string) (string, error) {
	if value, ok := s.Data[key]; ok {
		return value, nil
	}

	return "", errors.New("Not found")
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: errors.New.

func (*DummyStorage) GetKeyPrefix

GetKeyPrefix returns the prefix used for keys in DummyStorage; not yet implemented.

func (s *DummyStorage) GetKeyPrefix() string {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) GetKeys

GetKeys retrieves all keys matching a specified pattern from DummyStorage; currently supports only '*'.

func (s *DummyStorage) GetKeys(pattern string) (keys []string) {
	if pattern != "*" {
		return nil
	}

	for k := range s.Data {
		keys = append(keys, k)
	}

	return keys
}

Cognitive complexity: 5, Cyclomatic complexity: 3

func (*DummyStorage) GetKeysAndValues

GetKeysAndValues retrieves all key-value pairs from DummyStorage; currently not implemented.

func (s *DummyStorage) GetKeysAndValues() map[string]string {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) GetKeysAndValuesWithFilter

GetKeysAndValuesWithFilter fetches key-value pairs matching a filter from DummyStorage; not implemented.

func (s *DummyStorage) GetKeysAndValuesWithFilter(string) map[string]string {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) GetListRange

GetListRange retrieves a range of list elements from DummyStorage for a specified key; returns an error if not found.

func (s *DummyStorage) GetListRange(keyName string, _, _ int64) ([]string, error) {
	for key := range s.IndexList {
		if key == keyName {
			return s.IndexList[key], nil
		}
	}
	return []string{}, nil
}

Cognitive complexity: 6, Cyclomatic complexity: 3

func (*DummyStorage) GetMultiKey

GetMultiKey retrieves multiple values from the DummyStorage based on a slice of keys. It returns a slice of strings containing the values corresponding to each provided key, and an error if the operation cannot be completed.

func (s *DummyStorage) GetMultiKey(keys []string) ([]string, error) {
	var values []string
	for _, key := range keys {
		value, ok := s.Data[key]
		if !ok {
			return nil, fmt.Errorf("key not found: %s", key)
		}
		values = append(values, value)
	}
	return values, nil
}

Cognitive complexity: 5, Cyclomatic complexity: 3

Uses: fmt.Errorf.

func (*DummyStorage) GetRawKey

GetRawKey retrieves the value associated with a given key from the DummyStorage. The method accepts a single string as the key and returns the corresponding string value. An error is also returned to indicate whether the retrieval was successful. Currently, this method is not implemented and will cause a panic if invoked.

func (s *DummyStorage) GetRawKey(key string) (string, error) {
	value, ok := s.Data[key]
	if !ok {
		return "", fmt.Errorf("key not found: %s", key)
	}
	return value, nil
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: fmt.Errorf.

func (*DummyStorage) GetRollingWindow

GetRollingWindow retrieves data for a specified rolling window; currently not implemented.

func (s *DummyStorage) GetRollingWindow(string, int64, bool) (int, []interface{}) {
	panic("implement me")
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (*DummyStorage) GetSet

GetSet retrieves a set of values associated with a key in DummyStorage; not yet implemented.

func (s *DummyStorage) GetSet(string) (map[string]string, error) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) GetSortedSetRange

GetSortedSetRange retrieves a range of values and scores from a sorted set in DummyStorage; not implemented.

func (s *DummyStorage) GetSortedSetRange(string, string, string) ([]string, []float64, error) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) IncrememntWithExpire

IncrememntWithExpire increments the value of a key and sets an expiry; not yet implemented.

func (s *DummyStorage) IncrememntWithExpire(string, int64) int64 {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) RemoveFromList

RemoveFromList eliminates a specific value from a list within DummyStorage; always returns nil.

func (s *DummyStorage) RemoveFromList(keyName, value string) error {
	for key, keyList := range s.IndexList {
		if key == keyName {
			new := keyList[:]
			newL := 0
			for _, e := range new {
				if e == value {
					continue
				}

				new[newL] = e
				newL++
			}
			new = new[:newL]
			s.IndexList[key] = new
		}
	}

	return nil
}

Cognitive complexity: 10, Cyclomatic complexity: 5

func (*DummyStorage) RemoveFromSet

RemoveFromSet deletes a specific value from a set in DummyStorage; currently not implemented.

func (s *DummyStorage) RemoveFromSet(string, string) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) RemoveSortedSetRange

RemoveSortedSetRange deletes a range of values from a sorted set in DummyStorage; yet to be implemented.

func (s *DummyStorage) RemoveSortedSetRange(string, string, string) error {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) SetExp

SetExp updates the expiration time of a specific key in the DummyStorage. This method accepts two parameters: a string representing the key, and an int64 indicating the new expiration time.

func (s *DummyStorage) SetExp(string, int64) error {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) SetKey

SetKey assigns a value to a key in DummyStorage with an expiration time; returns nil for success.

func (s *DummyStorage) SetKey(key, value string, _ int64) error {
	s.Data[key] = value
	return nil
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) SetRawKey

SetRawKey stores a value with a specified key in the DummyStorage. It takes three parameters: the key and value as strings, and an expiry time as int64. The expiry time could be used to simulate time-sensitive data storage or caching behavior. Currently, this method is not implemented and will trigger a panic if it is called. TODO: Proper implementation is needed for this method to handle data storage, or manage

func (s *DummyStorage) SetRawKey(string, string, int64) error {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*DummyStorage) SetRollingWindow

SetRollingWindow sets a rolling window for a key with specified parameters; implementation pending.

func (s *DummyStorage) SetRollingWindow(string, int64, string, bool) (int, []interface{}) {
	panic("implement me")
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (*RedisCluster) AddToSet

func (r *RedisCluster) AddToSet(keyName, value string) {
	log.Debug("Pushing to raw key set: ", keyName)
	log.Debug("Pushing to fixed key set: ", r.fixKey(keyName))
	storage, err := r.set()
	if err != nil {
		log.Error(err)
		return
	}

	err = storage.AddMember(context.Background(), r.fixKey(keyName), value)
	if err != nil {
		log.Error("Error trying to append to set: ", err)
	}
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) AddToSortedSet

AddToSortedSet adds value with given score to sorted set identified by keyName

func (r *RedisCluster) AddToSortedSet(keyName, value string, score float64) {
	fixedKey := r.fixKey(keyName)
	logEntry := logrus.Fields{
		"keyName":	keyName,
		"fixedKey":	fixedKey,
	}
	log.WithFields(logEntry).Debug("Pushing raw key to sorted set")

	storage, err := r.sortedSet()
	if err != nil {
		log.Error(err)
		return
	}

	_, err = storage.AddScoredMember(context.Background(), fixedKey, value, score)
	if err != nil {
		log.WithFields(logEntry).WithError(err).Error("ZADD command failed")
	}
}

Cognitive complexity: 5, Cyclomatic complexity: 3

Uses: context.Background, logrus.Fields.

func (*RedisCluster) AppendToSet

func (r *RedisCluster) AppendToSet(keyName, value string) {
	fixedKey := r.fixKey(keyName)
	log.WithField("keyName", keyName).Debug("Pushing to raw key list")
	log.WithField("fixedKey", fixedKey).Debug("Appending to fixed key list")
	storage, err := r.list()
	if err != nil {
		log.Error(err)
		return
	}

	err = storage.Append(context.Background(), false, fixedKey, []byte(value))
	if err != nil {
		log.WithError(err).Error("Error trying to append to set keys")
	}
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) AppendToSetPipelined

func (r *RedisCluster) AppendToSetPipelined(key string, values [][]byte) {
	if len(values) == 0 {
		return
	}

	fixedKey := r.fixKey(key)
	storage, err := r.list()
	if err != nil {
		log.Error(err)
		return
	}

	err = storage.Append(context.Background(), true, fixedKey, values...)
	if err != nil {
		log.WithError(err).Error("Error trying to append to set keys")
	}
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: context.Background.

func (*RedisCluster) Client

Client will return a redis v8 RedisClient. This function allows implementation using the old storage clients.

func (r *RedisCluster) Client() (redis.UniversalClient, error) {
	if err := r.up(); err != nil {
		return nil, err
	}

	conn := r.getConnectionHandler().getConnection(r.IsCache, r.IsAnalytics)
	if conn == nil {
		return nil, ErrStorageConn
	}

	var client redis.UniversalClient

	if ok := conn.As(&client); !ok {
		return nil, errors.New("error converting connection to redis client")
	}

	return client, nil
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: errors.New, redis.UniversalClient.

func (*RedisCluster) Connect

Connect will establish a connection this is always true because we are dynamically using redis

func (r *RedisCluster) Connect() bool {
	return r.getConnectionHandler().Connected()
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisCluster) ControllerInitiated

func (r *RedisCluster) ControllerInitiated() bool {
	return r.getConnectionHandler() != nil
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisCluster) Decrement

Decrement will decrement a key in redis

func (r *RedisCluster) Decrement(keyName string) {
	keyName = r.fixKey(keyName)
	// log.Debug("Decrementing key: ", keyName)
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return
	}

	_, err = storage.Decrement(context.Background(), keyName)
	if err != nil {
		log.Error("Error trying to decrement value:", err)
	}
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) DeleteAllKeys

DeleteAllKeys will remove all keys from the database.

func (r *RedisCluster) DeleteAllKeys() bool {
	storage, err := r.flusher()
	if err != nil {
		log.Error(err)
		return false
	}

	err = storage.FlushAll(context.Background())
	if err != nil {
		log.WithError(err).Error("Error trying to delete keys")
		return false
	}

	return true
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) DeleteKey

DeleteKey will remove a key from the database

func (r *RedisCluster) DeleteKey(keyName string) bool {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return false
	}

	exist, err := storage.Exists(context.Background(), r.fixKey(keyName))
	if err != nil || !exist {
		return false
	}

	err = storage.Delete(context.Background(), r.fixKey(keyName))
	if err != nil {
		log.WithError(err).Error("Error trying to delete key")
		return false
	}

	return true
}

Cognitive complexity: 6, Cyclomatic complexity: 5

Uses: context.Background.

func (*RedisCluster) DeleteKeys

DeleteKeys will remove a group of keys in bulk

func (r *RedisCluster) DeleteKeys(keys []string) bool {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return false
	}

	for i, v := range keys {
		keys[i] = r.fixKey(v)
	}

	deleted, err := storage.DeleteKeys(context.Background(), keys)
	if err != nil {
		log.WithError(err).Error("Error trying to delete keys ")
		return false
	}
	return deleted > 0
}

Cognitive complexity: 7, Cyclomatic complexity: 4

Uses: context.Background.

func (*RedisCluster) DeleteRawKey

DeleteKey will remove a key from the database without prefixing, assumes user knows what they are doing

func (r *RedisCluster) DeleteRawKey(keyName string) bool {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return false
	}

	err = storage.Delete(context.Background(), keyName)
	if err != nil {
		log.WithError(err).Error("Error trying to delete raw key")
		return false
	}
	return true
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) DeleteRawKeys

func (r *RedisCluster) DeleteRawKeys(keys []string) bool {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return false
	}

	deleted, err := storage.DeleteKeys(context.Background(), keys)
	if err != nil {
		log.WithError(err).Error("Error trying to delete keys ")
		return false
	}
	return deleted > 0
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) DeleteScanMatch

DeleteKeys will remove a group of keys in bulk

func (r *RedisCluster) DeleteScanMatch(pattern string) bool {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return false
	}
	log.Debug("Deleting: ", pattern)

	_, err = storage.DeleteScanMatch(context.Background(), pattern)
	if err != nil {
		log.WithError(err).Error("Error trying to delete key pattern ", pattern)
		return false
	}
	return true
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) Exists

Exists check if keyName exists

func (r *RedisCluster) Exists(keyName string) (bool, error) {
	fixedKey := r.fixKey(keyName)
	log.WithField("keyName", fixedKey).Debug("Checking if exists")

	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return false, err
	}

	exists, err := storage.Exists(context.Background(), fixedKey)
	if err != nil {
		log.Error("Error trying to check if key exists: ", err)
		return false, err
	}
	return exists, nil
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) GetAndDeleteSet

func (r *RedisCluster) GetAndDeleteSet(keyName string) []interface{} {
	storage, err := r.list()
	if err != nil {
		log.Error(err)
		return nil
	}

	log.Debug("Getting raw key set: ", keyName)
	log.Debug("keyName is: ", keyName)
	fixedKey := r.fixKey(keyName)
	log.Debug("Fixed keyname is: ", fixedKey)

	values, err := storage.Pop(context.Background(), fixedKey, -1)
	if err != nil {
		log.Error("Multi command failed: ", err)
		return nil
	}

	if len(values) == 0 {
		return []interface{}{}
	}

	result := make([]interface{}, len(values))
	for i, v := range values {
		result[i] = v
	}

	return result
}

Cognitive complexity: 13, Cyclomatic complexity: 5

Uses: context.Background.

func (*RedisCluster) GetExp

func (r *RedisCluster) GetExp(keyName string) (int64, error) {
	return r.GetKeyTTL(keyName)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisCluster) GetKey

GetKey will retrieve a key from the database

func (r *RedisCluster) GetKey(keyName string) (string, error) {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return "", err
	}

	value, err := storage.Get(context.Background(), r.fixKey(keyName))
	if err != nil {
		if !errors.Is(err, redis.Nil) {
			log.Debug("Error trying to get value:", err)
		}
		return "", ErrKeyNotFound
	}

	return value, nil
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: context.Background, errors.Is, redis.Nil.

func (*RedisCluster) GetKeyPrefix

GetPrefix returns storage key prefix

func (r *RedisCluster) GetKeyPrefix() string {
	return r.KeyPrefix
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisCluster) GetKeyTTL

func (r *RedisCluster) GetKeyTTL(keyName string) (ttl int64, err error) {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return 0, err
	}

	return storage.TTL(context.Background(), r.fixKey(keyName))
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: context.Background.

func (*RedisCluster) GetKeys

GetKeys will return all keys according to the filter (filter is a prefix - e.g. tyk.keys.*)

func (r *RedisCluster) GetKeys(filter string) []string {
	filterHash := ""
	if filter != "" {
		filterHash = r.hashKey(filter)
	}

	searchStr := r.KeyPrefix + filterHash + "*"
	log.Debug("[STORE] Getting list by: ", searchStr)

	sessions, err := r.ScanKeys(searchStr)
	if err != nil {
		log.Error("Error while fetching keys:", err)
		return nil
	}

	for i, v := range sessions {
		sessions[i] = r.cleanKey(v)
	}

	return sessions
}

Cognitive complexity: 7, Cyclomatic complexity: 4

func (*RedisCluster) GetKeysAndValues

GetKeysAndValues will return all keys and their values - not to be used lightly

func (r *RedisCluster) GetKeysAndValues() map[string]string {
	return r.GetKeysAndValuesWithFilter("")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisCluster) GetKeysAndValuesWithFilter

GetKeysAndValuesWithFilter will return all keys and their values with a filter

func (r *RedisCluster) GetKeysAndValuesWithFilter(filter string) map[string]string {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return nil
	}

	if filter != "" && !strings.Contains(filter, r.KeyPrefix) {
		filter = r.KeyPrefix + filter
	}

	keysAndValues, err := storage.GetKeysAndValuesWithFilter(context.Background(), filter)
	if err != nil {
		log.Error("Error trying to get client keys: ", err)
		return nil
	}

	m := make(map[string]string)
	for key, value := range keysAndValues {
		m[r.cleanKey(key)] = fmt.Sprint(value)
	}

	return m
}

Cognitive complexity: 9, Cyclomatic complexity: 6

Uses: context.Background, fmt.Sprint, strings.Contains.

func (*RedisCluster) GetListRange

GetListRange gets range of elements of list identified by keyName

func (r *RedisCluster) GetListRange(keyName string, from, to int64) ([]string, error) {
	fixedKey := r.fixKey(keyName)
	logEntry := logrus.Fields{
		"keyName":	keyName,
		"fixedKey":	fixedKey,
		"from":		from,
		"to":		to,
	}
	log.WithFields(logEntry).Debug("Getting list range")

	storage, err := r.list()
	if err != nil {
		log.Error(err)
		return []string{}, err
	}

	elements, err := storage.Range(context.Background(), fixedKey, from, to)
	if err != nil {
		log.WithFields(logEntry).WithError(err).Error("LRANGE command failed")
		return nil, err
	}

	return elements, nil
}

Cognitive complexity: 6, Cyclomatic complexity: 3

Uses: context.Background, logrus.Fields.

func (*RedisCluster) GetMultiKey

GetMultiKey gets multiple keys from the database

func (r *RedisCluster) GetMultiKey(keys []string) ([]string, error) {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return nil, err
	}

	keyNames := make([]string, len(keys))
	copy(keyNames, keys)
	for index, val := range keyNames {
		keyNames[index] = r.fixKey(val)
	}

	values, err := storage.GetMulti(context.Background(), keyNames)
	if err != nil {
		log.WithError(err).Debug("Error trying to get value")
		return nil, ErrKeyNotFound
	}
	result := make([]string, 0)
	for _, val := range values {
		strVal := fmt.Sprint(val)
		if strVal == "<nil>" {
			strVal = ""
		}
		result = append(result, strVal)
	}

	for _, val := range result {
		if val != "" {
			return result, nil
		}
	}

	return nil, ErrKeyNotFound
}

Cognitive complexity: 17, Cyclomatic complexity: 8

Uses: context.Background, fmt.Sprint.

func (*RedisCluster) GetRawKey

func (r *RedisCluster) GetRawKey(keyName string) (string, error) {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return "", err
	}

	value, err := storage.Get(context.Background(), keyName)
	if err != nil {
		if !errors.Is(err, redis.Nil) {
			log.Debug("Error trying to get value:", err)
		}
		return "", ErrKeyNotFound
	}

	return value, nil
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: context.Background, errors.Is, redis.Nil.

func (*RedisCluster) GetRollingWindow

func (r *RedisCluster) GetRollingWindow(keyName string, per int64, pipeline bool) (int, []interface{}) {
	now := time.Now()
	onePeriodAgo := now.Add(time.Duration(-1*per) * time.Second)

	singleton, err := r.Client()
	if err != nil {
		log.Error(err)
		return 0, nil
	}
	ctx := context.Background()

	var zrange *redis.StringSliceCmd

	pipeFn := func(pipe redis.Pipeliner) error {
		pipe.ZRemRangeByScore(ctx, keyName, "-inf", strconv.Itoa(int(onePeriodAgo.UnixNano())))
		zrange = pipe.ZRange(ctx, keyName, 0, -1)

		return nil
	}

	if pipeline {
		_, err = singleton.Pipelined(ctx, pipeFn)
	} else {
		_, err = singleton.TxPipelined(ctx, pipeFn)
	}
	if err != nil {
		log.Error("Multi command failed: ", err)
		return 0, nil
	}

	values := zrange.Val()

	// Check actual value
	if values == nil {
		return 0, nil
	}

	intVal := len(values)
	result := make([]interface{}, intVal)
	for i, v := range values {
		result[i] = v
	}

	log.Debug("Returned: ", intVal)

	return intVal, result
}

Cognitive complexity: 16, Cyclomatic complexity: 6

Uses: context.Background, redis.Pipeliner, redis.StringSliceCmd, strconv.Itoa, time.Duration, time.Now, time.Second.

func (*RedisCluster) GetSet

func (r *RedisCluster) GetSet(keyName string) (map[string]string, error) {
	log.Debug("Getting from key set: ", keyName)
	log.Debug("Getting from fixed key set: ", r.fixKey(keyName))
	storage, err := r.set()
	if err != nil {
		log.Error(err)
		return nil, err
	}

	members, err := storage.Members(context.Background(), r.fixKey(keyName))
	if err != nil {
		log.Error("Error trying to get key set:", err)
		return nil, err
	}

	result := make(map[string]string)
	for i, value := range members {
		result[strconv.Itoa(i)] = value
	}

	return result, nil
}

Cognitive complexity: 7, Cyclomatic complexity: 4

Uses: context.Background, strconv.Itoa.

func (*RedisCluster) GetSortedSetRange

GetSortedSetRange gets range of elements of sorted set identified by keyName

func (r *RedisCluster) GetSortedSetRange(keyName, scoreFrom, scoreTo string) ([]string, []float64, error) {
	fixedKey := r.fixKey(keyName)
	logEntry := logrus.Fields{
		"keyName":	keyName,
		"fixedKey":	fixedKey,
		"scoreFrom":	scoreFrom,
		"scoreTo":	scoreTo,
	}
	log.WithFields(logEntry).Debug("Getting sorted set range")

	storage, err := r.sortedSet()
	if err != nil {
		log.Error(err)
		return nil, nil, err
	}

	values, scores, err := storage.GetMembersByScoreRange(context.Background(), fixedKey, scoreFrom, scoreTo)
	if err != nil {
		log.WithFields(logEntry).WithError(err).Error("ZRANGEBYSCORE command failed")
		return nil, nil, err
	}

	if len(values) == 0 {
		return nil, nil, nil
	}

	elements := make([]string, len(values))

	for i, v := range values {
		elements[i] = fmt.Sprint(v)
	}

	return elements, scores, nil
}

Cognitive complexity: 10, Cyclomatic complexity: 5

Uses: context.Background, fmt.Sprint, logrus.Fields.

func (*RedisCluster) IncrememntWithExpire

IncrementWithExpire will increment a key in redis

func (r *RedisCluster) IncrememntWithExpire(keyName string, expire int64) int64 {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return 0
	}

	// This function uses a raw key, so we shouldn't call fixKey
	fixedKey := keyName

	val, err := storage.Increment(context.Background(), fixedKey)
	if err != nil {
		log.Error("Error trying to increment value:", err)
	} else {
		log.Debug("Incremented key: ", fixedKey, ", val is: ", val)
	}

	if val == 1 && expire > 0 {
		log.Debug("--> Setting Expire")
		err = storage.Expire(context.Background(), fixedKey, time.Duration(expire)*time.Second)
		if err != nil {
			log.Error("Error trying to set expire on key:", err)
		}
	}

	return val
}

Cognitive complexity: 10, Cyclomatic complexity: 6

Uses: context.Background, time.Duration, time.Second.

func (*RedisCluster) IsMemberOfSet

func (r *RedisCluster) IsMemberOfSet(keyName, value string) bool {
	storage, err := r.set()
	if err != nil {
		log.Error(err)
		return false
	}

	val, err := storage.IsMember(context.Background(), r.fixKey(keyName), value)
	if err != nil {
		log.Error("Error trying to check set member: ", err)
		return false
	}

	log.Debug("SISMEMBER", keyName, value, val, err)

	return val
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) Lock

Lock implements a distributed lock in a cluster.

func (r *RedisCluster) Lock(key string, timeout time.Duration) (bool, error) {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return false, err
	}

	set, err := storage.SetIfNotExist(context.Background(), key, "1", timeout)
	if err != nil {
		log.WithError(err).Error("Error trying to set value")
		return false, err
	}
	return set, nil
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) Publish

func (r *RedisCluster) Publish(channel, message string) error {
	storage, err := r.queue()
	if err != nil {
		log.Error(err)
		return err
	}

	_, err = storage.Publish(context.Background(), channel, message)
	if err != nil {
		log.Error("Error trying to publish message: ", err)
		return err
	}
	return nil
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) RemoveFromList

RemoveFromList delete an value from a list idetinfied with the keyName

func (r *RedisCluster) RemoveFromList(keyName, value string) error {
	fixedKey := r.fixKey(keyName)
	logEntry := logrus.Fields{
		"keyName":	keyName,
		"fixedKey":	fixedKey,
		"value":	value,
	}
	log.WithFields(logEntry).Debug("Removing value from list")
	storage, err := r.list()
	if err != nil {
		log.Error(err)
		return err
	}

	_, err = storage.Remove(context.Background(), fixedKey, 0, value)
	if err != nil {
		log.WithFields(logEntry).WithError(err).Error("LREM command failed")
		return err
	}

	return nil
}

Cognitive complexity: 5, Cyclomatic complexity: 3

Uses: context.Background, logrus.Fields.

func (*RedisCluster) RemoveFromSet

func (r *RedisCluster) RemoveFromSet(keyName, value string) {
	log.Debug("Removing from raw key set: ", keyName)
	log.Debug("Removing from fixed key set: ", r.fixKey(keyName))
	storage, err := r.set()
	if err != nil {
		log.Error(err)
		return
	}

	err = storage.RemoveMember(context.Background(), r.fixKey(keyName), value)
	if err != nil {
		log.Error("Error trying to remove keys: ", err)
	}
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: context.Background.

func (*RedisCluster) RemoveSortedSetRange

RemoveSortedSetRange removes range of elements from sorted set identified by keyName

func (r *RedisCluster) RemoveSortedSetRange(keyName, scoreFrom, scoreTo string) error {
	fixedKey := r.fixKey(keyName)
	logEntry := logrus.Fields{
		"keyName":	keyName,
		"fixedKey":	fixedKey,
		"scoreFrom":	scoreFrom,
		"scoreTo":	scoreTo,
	}
	log.WithFields(logEntry).Debug("Removing sorted set range")

	storage, err := r.sortedSet()
	if err != nil {
		log.Error(err)
		return err
	}

	_, err = storage.RemoveMembersByScoreRange(context.Background(), fixedKey, scoreFrom, scoreTo)
	if err != nil {
		log.WithFields(logEntry).WithError(err).Error("ZREMRANGEBYSCORE command failed")
		return err
	}

	return nil
}

Cognitive complexity: 5, Cyclomatic complexity: 3

Uses: context.Background, logrus.Fields.

func (*RedisCluster) ScanKeys

ScanKeys will return all keys according to the pattern.

func (r *RedisCluster) ScanKeys(pattern string) ([]string, error) {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return nil, err
	}

	return storage.Keys(context.Background(), pattern)
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: context.Background.

func (*RedisCluster) SetExp

func (r *RedisCluster) SetExp(keyName string, timeout int64) error {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return err
	}

	return storage.Expire(context.Background(), r.fixKey(keyName), time.Duration(timeout)*time.Second)
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: context.Background, time.Duration, time.Second.

func (*RedisCluster) SetKey

SetKey will create (or update) a key value in the store

func (r *RedisCluster) SetKey(keyName, session string, timeout int64) error {
	return r.SetRawKey(r.fixKey(keyName), session, timeout)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisCluster) SetRawKey

func (r *RedisCluster) SetRawKey(keyName, session string, timeout int64) error {
	storage, err := r.kv()
	if err != nil {
		log.Error(err)
		return err
	}

	return storage.Set(context.Background(), keyName, session, time.Duration(timeout)*time.Second)
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: context.Background, time.Duration, time.Second.

func (*RedisCluster) SetRollingWindow

SetRollingWindow will append to a sorted set in redis and extract a timed window of values

func (r *RedisCluster) SetRollingWindow(keyName string, per int64, value_override string, pipeline bool) (int, []interface{}) {
	log.Debug("Incrementing raw key: ", keyName)
	log.Debug("keyName is: ", keyName)
	now := time.Now()
	log.Debug("Now is:", now)
	onePeriodAgo := now.Add(time.Duration(-1*per) * time.Second)
	log.Debug("Then is: ", onePeriodAgo)

	singleton, err := r.Client()
	if err != nil {
		log.Error(err)
		return 0, nil
	}

	ctx := context.Background()
	var zrange *redis.StringSliceCmd

	pipeFn := func(pipe redis.Pipeliner) error {
		pipe.ZRemRangeByScore(ctx, keyName, "-inf", strconv.Itoa(int(onePeriodAgo.UnixNano())))
		zrange = pipe.ZRange(ctx, keyName, 0, -1)

		element := redis.Z{
			Score: float64(now.UnixNano()),
		}

		if value_override != "-1" {
			element.Member = value_override
		} else {
			element.Member = strconv.Itoa(int(now.UnixNano()))
		}

		pipe.ZAdd(ctx, keyName, element)
		pipe.Expire(ctx, keyName, time.Duration(per)*time.Second)

		return nil
	}

	if pipeline {
		_, err = singleton.Pipelined(context.Background(), pipeFn)
	} else {
		_, err = singleton.TxPipelined(context.Background(), pipeFn)
	}

	if err != nil {
		log.Error("Multi command failed: ", err)
		return 0, nil
	}

	values := zrange.Val()

	// Check actual value
	if values == nil {
		return 0, nil
	}

	intVal := len(values)
	result := make([]interface{}, len(values))

	for i, v := range values {
		result[i] = v
	}

	log.Debug("Returned: ", intVal)

	return intVal, result
}

Cognitive complexity: 21, Cyclomatic complexity: 7

Uses: context.Background, redis.Pipeliner, redis.StringSliceCmd, redis.Z, strconv.Itoa, time.Duration, time.Now, time.Second.

func (*RedisCluster) StartPubSubHandler

StartPubSubHandler will listen for a signal and run the callback for every subscription and message event.

func (r *RedisCluster) StartPubSubHandler(ctx context.Context, channel string, callback func(interface{})) error {
	storage, err := r.queue()
	if err != nil {
		log.Error(err)
		return err
	}

	pubsub := storage.Subscribe(ctx, channel)
	defer pubsub.Close()

	for {
		select {
		case <-ctx.Done():
			return nil
		default:
			if err := r.handleReceive(ctx, pubsub.Receive, callback); err != nil {
				return err
			}
		}
	}
}

Cognitive complexity: 9, Cyclomatic complexity: 5

func (*RedisController) ConnectToRedis

ConnectToRedis sets up the connection to Redis using specified configuration. It abstracts the connection logic, allowing Go plugins to seamlessly integrate without direct interaction with the underlying storage logic.

func (rc *RedisController) ConnectToRedis(ctx context.Context, onReconnect func(), conf *config.Config) {
	rc.connection.Connect(ctx, onReconnect, conf)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisController) Connected

Connected checks the current state of the Redis connection, offering a simple interface for Go plugins to verify connectivity without delving into the specifics of the storage layer.

func (rc *RedisController) Connected() bool {
	return rc.connection.Connected()
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisController) DisableRedis

DisableRedis toggles the Redis connection's active status, providing a mechanism to dynamically manage the connection state in response to runtime conditions or configurations.

func (rc *RedisController) DisableRedis(setRedisDown bool) {
	rc.connection.DisableStorage(setRedisDown)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*RedisController) WaitConnect

WaitConnect blocks until a Redis connection is established, enabling Go plugins to wait for connectivity before proceeding with operations that require Redis access.

func (rc *RedisController) WaitConnect(ctx context.Context) bool {
	return rc.connection.WaitConnect(ctx)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) AddToSet

func (m MdcbStorage) AddToSet(key string, value string) {
	m.local.AddToSet(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) AddToSortedSet

func (m MdcbStorage) AddToSortedSet(string, string, float64) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) AppendToSet

func (m MdcbStorage) AppendToSet(key string, value string) {
	m.local.AppendToSet(key, value)
	m.rpc.AppendToSet(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) Connect

func (m MdcbStorage) Connect() bool {
	return m.local.Connect() && m.rpc.Connect()
}

Cognitive complexity: 0, Cyclomatic complexity: 2

func (MdcbStorage) Decrement

func (m MdcbStorage) Decrement(string) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) DeleteAllKeys

func (m MdcbStorage) DeleteAllKeys() bool {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) DeleteKey

func (m MdcbStorage) DeleteKey(key string) bool {
	deleteLocal := m.local.DeleteKey(key)
	deleteRPC := m.rpc.DeleteKey(key)

	return deleteLocal || deleteRPC
}

Cognitive complexity: 0, Cyclomatic complexity: 2

func (MdcbStorage) DeleteKeys

func (m MdcbStorage) DeleteKeys([]string) bool {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) DeleteRawKey

func (m MdcbStorage) DeleteRawKey(string) bool {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) DeleteRawKeys

func (m MdcbStorage) DeleteRawKeys([]string) bool	{ panic("implement me") }

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) DeleteScanMatch

func (m MdcbStorage) DeleteScanMatch(key string) bool {
	deleteLocal := m.local.DeleteScanMatch(key)
	deleteRPC := m.rpc.DeleteScanMatch(key)

	return deleteLocal || deleteRPC
}

Cognitive complexity: 0, Cyclomatic complexity: 2

func (MdcbStorage) Exists

func (m MdcbStorage) Exists(key string) (bool, error) {
	foundLocal, errLocal := m.local.Exists(key)
	foundRpc, errRpc := m.rpc.Exists(key)

	if errLocal != nil && errRpc != nil {
		return false, errors.New("cannot find key in storages")
	}

	return foundLocal && foundRpc, nil
}

Cognitive complexity: 2, Cyclomatic complexity: 4

Uses: errors.New.

func (MdcbStorage) GetAndDeleteSet

func (m MdcbStorage) GetAndDeleteSet(string) []interface{} {
	panic("implement me")
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (MdcbStorage) GetExp

func (m MdcbStorage) GetExp(string) (int64, error) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) GetKey

func (m MdcbStorage) GetKey(key string) (string, error) {
	if m.local != nil {
		val, err := m.getFromLocal(key)
		if err == nil {
			return val, nil
		}
		m.logger.Debugf("Key not present locally, pulling from rpc layer: %v", err)
	}

	return m.getFromRPCAndCache(key)
}

Cognitive complexity: 4, Cyclomatic complexity: 3

func (MdcbStorage) GetKeyPrefix

func (m MdcbStorage) GetKeyPrefix() string {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) GetKeys

func (m MdcbStorage) GetKeys(key string) []string {
	var val []string

	if m.local != nil {
		val = m.local.GetKeys(key)
		if len(val) == 0 {
			val = m.rpc.GetKeys(key)
		}
	} else {
		val = m.rpc.GetKeys(key)
	}
	return val
}

Cognitive complexity: 6, Cyclomatic complexity: 3

func (MdcbStorage) GetKeysAndValues

func (m MdcbStorage) GetKeysAndValues() map[string]string {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) GetKeysAndValuesWithFilter

func (m MdcbStorage) GetKeysAndValuesWithFilter(key string) map[string]string {
	return m.local.GetKeysAndValuesWithFilter(key)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) GetListRange

func (m MdcbStorage) GetListRange(key string, from int64, to int64) ([]string, error) {
	var val []string
	var err error

	if m.local == nil {
		return m.rpc.GetListRange(key, from, to)
	}

	val, err = m.local.GetListRange(key, from, to)
	if err != nil {
		val, err = m.rpc.GetListRange(key, from, to)
	}

	return val, err
}

Cognitive complexity: 4, Cyclomatic complexity: 3

func (MdcbStorage) GetMultiKey

GetMultiKey gets multiple keys from the MDCB layer

func (m MdcbStorage) GetMultiKey(keyNames []string) ([]string, error) {
	var err error
	var value string

	for _, key := range keyNames {
		value, err = m.GetKey(key)
		if err == nil {
			return []string{value}, nil
		}
	}

	return nil, err
}

Cognitive complexity: 6, Cyclomatic complexity: 3

func (MdcbStorage) GetRawKey

func (m MdcbStorage) GetRawKey(string) (string, error) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) GetRollingWindow

func (m MdcbStorage) GetRollingWindow(key string, per int64, pipeline bool) (int, []interface{}) {
	panic("implement me")
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (MdcbStorage) GetSet

func (m MdcbStorage) GetSet(key string) (map[string]string, error) {
	val, err := m.local.GetSet(key)
	if err != nil {
		// try rpc
		val, err = m.rpc.GetSet(key)
	}
	return val, err
}

Cognitive complexity: 2, Cyclomatic complexity: 2

func (MdcbStorage) GetSortedSetRange

func (m MdcbStorage) GetSortedSetRange(string, string, string) ([]string, []float64, error) {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) IncrememntWithExpire

func (m MdcbStorage) IncrememntWithExpire(string, int64) int64 {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) RemoveFromList

func (m MdcbStorage) RemoveFromList(key string, value string) error {
	errLocal := m.local.RemoveFromList(key, value)
	errRpc := m.rpc.RemoveFromList(key, value)

	if errLocal != nil && errRpc != nil {
		return errors.New("cannot delete key in storages")
	}

	return nil
}

Cognitive complexity: 2, Cyclomatic complexity: 3

Uses: errors.New.

func (MdcbStorage) RemoveFromSet

func (m MdcbStorage) RemoveFromSet(key string, value string) {
	m.local.RemoveFromSet(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) RemoveSortedSetRange

func (m MdcbStorage) RemoveSortedSetRange(string, string, string) error {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) SetExp

func (m MdcbStorage) SetExp(string, int64) error {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) SetKey

func (m MdcbStorage) SetKey(key string, content string, TTL int64) error {
	// only set the value locally as rpc writtes is not allowed
	errLocal := m.local.SetKey(key, content, TTL)

	if errLocal != nil {
		return errors.New("cannot save key in local")
	}

	return nil
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: errors.New.

func (MdcbStorage) SetRawKey

func (m MdcbStorage) SetRawKey(string, string, int64) error {
	panic("implement me")
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (MdcbStorage) SetRollingWindow

func (m MdcbStorage) SetRollingWindow(key string, per int64, val string, pipeline bool) (int, []interface{}) {
	panic("implement me")
}

Cognitive complexity: 1, Cyclomatic complexity: 1

Private functions

func getExponentialBackoff

getExponentialBackoff returns a backoff.ExponentialBackOff with the following settings:

  • Multiplier: 2
  • MaxInterval: 10 seconds
  • MaxElapsedTime: 0 (no limit)

getExponentialBackoff () *backoff.ExponentialBackOff
References: backoff.NewExponentialBackOff, time.Second.

func getRedisAddrs

getRedisAddrs (conf config.StorageOptionsConf) []string

func getResourceType

getResourceType (key string) string
References: strings.Contains, strings.HasPrefix.

func enabled

enabled () bool

func getConnection

getConnection (isCache,isAnalytics bool) model.Connector

func initConnection

initConnection initializes the connection singletons.

initConnection (conf config.Config) error

func isConnected

isConnected (ctx context.Context, connType string) bool

func recoverLoop

recoverLoop (ctx context.Context, onReconnect func())

func statusCheck

statusCheck will check the storage status each second. This method will be constantly modifying the redisUp control flag.

statusCheck (ctx context.Context)
References: time.NewTicker, time.Second.

func cleanKey

cleanKey (keyName string) string
References: strings.Replace.

func fixKey

fixKey (keyName string) string

func flusher

flusher () (model.Flusher, error)
References: tempflusher.NewFlusher.

func getConnectionHandler

getConnectionHandler () *ConnectionHandler

func handleMessage

handleMessage (msg interface{}, err error, callback func(interface{})) error
References: redis.ErrClosed, strings.Contains.

func handleReceive

handleReceive is split from pubsub inner loop to inject fake receive function for code coverage tests.

handleReceive (ctx context.Context, receiveFn func(context.Context) (model.Message, error), callback func(interface{})) error

func hashKey

hashKey (in string) string

func kv

kv () (model.KeyValue, error)
References: tempkv.NewKeyValue.

func list

list () (model.List, error)
References: templist.NewList.

func queue

queue () (model.Queue, error)
References: tempqueue.NewQueue.

func set

set () (model.Set, error)
References: tempset.NewSet.

func sortedSet

sortedSet () (model.SortedSet, error)
References: tempsortedset.NewSortedSet.

func up

up () error

func cacheCertificate

cacheCertificate saves locally resourceCertificate after pull from rpc

cacheCertificate (key,val string) error

func cacheOAuthClient

cacheOAuthClient saved oauth data in local storage after pull from rpc

cacheOAuthClient (key,val string) error

func getFromLocal

getFromLocal get a key from local storage

getFromLocal (key string) (string, error)

func getFromRPCAndCache

getFromRPCAndCache pulls a resource from rpc and stores it in local redis for caching

getFromRPCAndCache (key string) (string, error)

func processResourceByType

processResourceByType based on the type of key it will trigger the proper caching mechanism

processResourceByType (key,val string) error


Tests

Files: 6. Third party imports: 4. Imports from organisation: 2. Tests: 97. Benchmarks: 0.

Vars

var notFoundKeyErr = errors.New("key not found")
var rc *ConnectionHandler

Types

testSetup

This type doesn't have documentation.

Field name Field type Comment
Logger

*logrus.Entry

No comment on field.
Local

*mock.MockHandler

No comment on field.
Remote

*mock.MockHandler

No comment on field.
MdcbStorage

*MdcbStorage

No comment on field.
CleanUp

func()

No comment on field.
type testSetup struct {
	Logger		*logrus.Entry
	Local		*mock.MockHandler
	Remote		*mock.MockHandler
	MdcbStorage	*MdcbStorage
	CleanUp		func()
}

Test functions

TestAddToSet

References: errors.New, mock.Anything, tempmocks.NewSet, testing.T.

TestAddToSortedSet

References: errors.New, mock.Anything, tempmocks.NewSortedSet, testing.T.

TestAppendToSet

References: errors.New, mock.Anything, tempmocks.NewList, testing.T.

TestAppendToSetPipelined

References: errors.New, mock.Anything, tempmocks.NewList, testing.T.

TestCacheCertificate

References: assert.Equal, assert.ErrorIs, assert.False, assert.NoError, assert.True, errors.New, testing.T.

TestCacheOAuthClient

References: assert.Error, assert.ErrorIs, assert.NoError, errors.New, gomock.Any, testing.T.

TestConnectToRedis

References: assert.NoError, assert.True, config.New, context.Background, context.WithCancel, time.Millisecond, time.Sleep.

TestConnectionHandler_Connect

References: assert.NoError, assert.True, config.New, context.Background, context.WithCancel, time.Millisecond, time.Sleep.

TestConnectionHandler_DisableStorage

References: assert.False, assert.True, context.Background.

TestConnectionHandler_Disconnect

References: assert.NoError, context.Background, tempmocks.NewConnector.

TestConnectionHandler_statusCheck

References: assert.True, context.Background, context.WithCancel, mock.Arguments, sync.WaitGroup, tempmocks.NewConnector.

TestDecrement

References: mock.Anything, tempmocks.NewKeyValue, testing.T.

TestDeleteAllKeys

References: assert.False, assert.True, errors.New, mock.Anything, tempmocks.NewFlusher, testing.T.

TestDeleteKey

References: assert.False, assert.True, errors.New, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestDeleteKeys

References: assert.False, assert.True, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestDeleteRawKey

References: assert.False, assert.True, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestDeleteRawKeys

References: assert.False, assert.True, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestDeleteScanMatch

References: assert.False, assert.True, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestDisableRedis

References: assert.False, assert.True, context.Background.

TestDummyStorage_AddToSet

TestDummyStorage_AddToSortedSet

TestDummyStorage_AppendToSet

References: reflect.DeepEqual, testing.T.

TestDummyStorage_Connect

References: assert.True.

TestDummyStorage_Decrement

TestDummyStorage_DeleteAllKeys

TestDummyStorage_DeleteKey

References: testing.T.

TestDummyStorage_DeleteKeys

TestDummyStorage_DeleteRawKey

TestDummyStorage_DeleteScanMatch

References: testing.T.

TestDummyStorage_Exists

References: testing.T.

TestDummyStorage_GetAndDeleteSet

TestDummyStorage_GetExp

TestDummyStorage_GetKey

References: testing.T.

TestDummyStorage_GetKeyPrefix

TestDummyStorage_GetKeys

References: reflect.DeepEqual, sort.Strings, testing.T.

TestDummyStorage_GetKeysAndValues

TestDummyStorage_GetKeysAndValuesWithFilter

TestDummyStorage_GetListRange

References: reflect.DeepEqual, testing.T.

TestDummyStorage_GetMultiKey

References: reflect.DeepEqual, testing.T.

TestDummyStorage_GetRawKey

References: testing.T.

TestDummyStorage_GetRollingWindow

TestDummyStorage_GetSet

TestDummyStorage_GetSortedSetRange

TestDummyStorage_IncrememntWithExpire

TestDummyStorage_RemoveFromList

References: reflect.DeepEqual, testing.T.

TestDummyStorage_RemoveFromSet

TestDummyStorage_RemoveSortedSetRange

TestDummyStorage_SetExp

TestDummyStorage_SetKey

References: testing.T.

TestDummyStorage_SetRawKey

TestDummyStorage_SetRollingWindow

TestExists

References: assert.Error, assert.False, assert.NoError, assert.True, errors.New, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetAndDeleteSet

References: assert.Equal, assert.Nil, errors.New, mock.Anything, tempmocks.NewList, testing.T.

TestGetExp

References: assert.Equal, assert.Error, assert.NoError, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetFromLocalStorage

References: assert.Equal, assert.ErrorIs, assert.Nil.

TestGetFromRPCAndCache

References: assert.Equal, assert.ErrorIs, assert.Nil, gomock.Any.

TestGetKey

References: assert.Equal, assert.Error, assert.NoError, errors.New, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetKeyPrefix

References: assert.Equal, testing.T.

TestGetKeyTTL

References: assert.Equal, assert.Error, assert.NoError, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetKeys

References: assert.Equal, errors.New, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetKeysAndValues

References: assert.Equal, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetKeysAndValuesWithFilter

References: assert.Equal, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetListRange

References: assert.Empty, assert.Equal, assert.Error, assert.Nil, assert.NoError, errors.New, mock.Anything, tempmocks.NewList, testing.T.

TestGetMultiKey

References: assert.Equal, assert.Error, assert.NoError, errors.New, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetRawKey

References: assert.Equal, assert.Error, assert.NoError, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestGetResourceType

References: testing.T.

TestGetSet

References: assert.Empty, assert.Equal, assert.Error, assert.Nil, assert.NoError, errors.New, mock.Anything, tempmocks.NewSet, testing.T.

TestGetSortedSetRange

References: assert.Empty, assert.Equal, assert.Error, assert.Nil, assert.NoError, errors.New, mock.Anything, tempmocks.NewSortedSet, testing.T.

TestHandleMessage

References: assert.Equal, assert.NoError, assert.True, errors.New, redis.ErrClosed, testing.T.

TestHandleReceive

References: assert.NoError, context.Background, context.Context, model.Message, testing.T.

TestIncrememntWithExpire

References: assert.Equal, mock.Anything, tempmocks.NewKeyValue, testing.T, time.Duration, time.Second.

TestInternalStorages

References: assert.Equal, assert.Error, assert.Nil, assert.NoError, assert.NotNil, context.Background, testing.T.

TestIsMemberOfSet

References: assert.False, assert.True, errors.New, mock.Anything, tempmocks.NewSet, testing.T.

TestLock

References: assert.Equal, assert.Error, assert.False, assert.NoError, assert.True, context.Background, errors.ErrUnsupported, mock.Anything, tempmocks.NewKeyValue, testing.T, time.Second.

TestMain

References: config.New, context.Background, context.WithTimeout, os.Exit, time.Second.

TestMdcbStorage_GetMultiKey

References: assert.Equal, context.Background, io.Discard, logrus.New, testing.T.

TestNewConnectionHandler

References: context.Background.

TestNewConnectorAnalyticsConn

References: assert.NoError, assert.NotNil, config.New.

TestNewConnectorCacheConn

References: assert.NoError, assert.NotNil, config.New.

TestNewConnectorDefaultConn

References: assert.NoError, assert.NotNil, config.New.

TestNewRedisController

References: context.Background.

TestProcessResourceByType

References: assert.Error, assert.ErrorIs, assert.NoError, errors.New, gomock.Any, mock.MockHandler, strings.HasPrefix, testing.T.

TestPublish

References: assert.Equal, assert.Error, assert.NoError, errors.New, mock.Anything, tempmocks.NewQueue, testing.T.

TestRecoverLoop

References: assert.Equal, assert.NoError, config.New, context.Background, sync.WaitGroup.

TestRedisAddressConfiguration

References: config.StorageOptionsConf, redis.UniversalOptions, testing.T.

TestRedisClusterGetConnectionHandler

References: context.Background, testing.T.

TestRedisClusterGetMultiKey

References: errors.Is.

TestRedisExpirationTime

References: assert.Equal, assert.True, context.Background.

TestRemoveFromList

References: assert.Error, assert.NoError, errors.New, mock.Anything, tempmocks.NewList, testing.T.

TestRemoveFromSet

References: errors.New, mock.Anything, tempmocks.NewSet, testing.T.

TestRemoveSortedSetRange

References: assert.Error, assert.NoError, errors.New, mock.Anything, tempmocks.NewSortedSet, testing.T.

TestScanKeys

References: assert.Equal, assert.Error, assert.Nil, assert.NoError, errors.New, mock.Anything, tempmocks.NewKeyValue, testing.T.

TestSetExp

References: assert.Equal, assert.Error, assert.NoError, mock.Anything, tempmocks.NewKeyValue, testing.T, time.Duration, time.Second.

TestSetKey

References: assert.Equal, assert.Error, assert.NoError, mock.Anything, tempmocks.NewKeyValue, testing.T, time.Duration, time.Second.

TestSetRawKey

References: assert.Equal, assert.Error, assert.NoError, mock.Anything, tempmocks.NewKeyValue, testing.T, time.Duration, time.Second.

TestStartPubSubHandler

References: assert.Equal, assert.Error, assert.Fail, assert.NoError, assert.True, context.Background, context.WithCancel, context.WithTimeout, errors.New, mock.Anything, model.Message, tempmocks.NewMessage, tempmocks.NewQueue, tempmocks.NewSubscription, testing.T, time.Millisecond.

Test_TokenOrg

References: testing.T.