diff --git a/README.md b/README.md index cf9253e..f46901a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -# redis - -> A redis-based session store +# Redis store for [Session](https://github.com/go-session/session) [![Build][Build-Status-Image]][Build-Status-Url] [![Coverage][Coverage-Image]][Coverage-Url] [![ReportCard][reportcard-image]][reportcard-url] [![GoDoc][godoc-image]][godoc-url] [![License][license-image]][license-url] diff --git a/options.go b/options.go index 0e22f20..972463b 100644 --- a/options.go +++ b/options.go @@ -88,3 +88,63 @@ func (o *Options) redisOptions() *redis.Options { TLSConfig: o.TLSConfig, } } + +// ClusterOptions are used to configure a cluster client and should be +// passed to NewClusterClient. +type ClusterOptions struct { + // A seed list of host:port addresses of cluster nodes. + Addrs []string + + // The maximum number of retries before giving up. Command is retried + // on network errors and MOVED/ASK redirects. + // Default is 8. + MaxRedirects int + + // Enables read-only commands on slave nodes. + ReadOnly bool + // Allows routing read-only commands to the closest master or slave node. + RouteByLatency bool + // Allows routing read-only commands to the random master or slave node. + RouteRandomly bool + + // Following options are copied from Options struct. + + OnConnect func(*redis.Conn) error + + MaxRetries int + MinRetryBackoff time.Duration + MaxRetryBackoff time.Duration + Password string + + DialTimeout time.Duration + ReadTimeout time.Duration + WriteTimeout time.Duration + + // PoolSize applies per cluster node and not for the whole cluster. + PoolSize int + PoolTimeout time.Duration + IdleTimeout time.Duration + IdleCheckFrequency time.Duration +} + +func (o *ClusterOptions) redisClusterOptions() *redis.ClusterOptions { + return &redis.ClusterOptions{ + Addrs: o.Addrs, + MaxRedirects: o.MaxRedirects, + ReadOnly: o.ReadOnly, + RouteByLatency: o.RouteByLatency, + RouteRandomly: o.RouteRandomly, + OnConnect: o.OnConnect, + MaxRetries: o.MaxRetries, + MinRetryBackoff: o.MinRetryBackoff, + MaxRetryBackoff: o.MaxRetryBackoff, + Password: o.Password, + DialTimeout: o.DialTimeout, + ReadTimeout: o.ReadTimeout, + WriteTimeout: o.WriteTimeout, + PoolSize: o.PoolSize, + PoolTimeout: o.PoolTimeout, + IdleTimeout: o.IdleTimeout, + IdleCheckFrequency: o.IdleCheckFrequency, + } +} diff --git a/redis.go b/redis.go index 775beb7..95e8b5d 100644 --- a/redis.go +++ b/redis.go @@ -18,11 +18,11 @@ var ( ) // NewRedisStore create an instance of a redis store -func NewRedisStore(opt *Options) session.ManagerStore { - if opt == nil { - panic("option cannot be nil") +func NewRedisStore(opts *Options) session.ManagerStore { + if opts == nil { + panic("options cannot be nil") } - return &managerStore{cli: redis.NewClient(opt.redisOptions())} + return &managerStore{cli: redis.NewClient(opts.redisOptions())} } // NewRedisStoreWithCli create an instance of a redis store @@ -37,8 +37,38 @@ func NewRedisStoreWithCli(cli *redis.Client) session.ManagerStore { } } +// NewRedisClusterStore create an instance of a redis cluster store +func NewRedisClusterStore(opts *ClusterOptions) session.ManagerStore { + if opts == nil { + panic("options cannot be nil") + } + return &managerStore{cli: redis.NewClusterClient(opts.redisClusterOptions())} +} + +// NewRedisClusterStoreWithCli create an instance of a redis cluster store +func NewRedisClusterStoreWithCli(cli *redis.ClusterClient) session.ManagerStore { + return &managerStore{ + cli: cli, + pool: sync.Pool{ + New: func() interface{} { + return newDefaultStore(cli) + }, + }, + } +} + +type clienter interface { + Get(key string) *redis.StringCmd + Set(key string, value interface{}, expiration time.Duration) *redis.StatusCmd + Expire(key string, expiration time.Duration) *redis.BoolCmd + Exists(keys ...string) *redis.IntCmd + TxPipeline() redis.Pipeliner + Del(keys ...string) *redis.IntCmd + Close() error +} + type managerStore struct { - cli *redis.Client + cli clienter pool sync.Pool } @@ -147,7 +177,7 @@ func (s *managerStore) Close() error { return s.cli.Close() } -func newDefaultStore(cli *redis.Client) *store { +func newDefaultStore(cli clienter) *store { return &store{ cli: cli, } @@ -159,7 +189,7 @@ type store struct { sid string expired int64 values map[string]interface{} - cli *redis.Client + cli clienter } func (s *store) reset(ctx context.Context, sid string, expired int64, values map[string]interface{}) {