redis/universal.go

202 lines
5.1 KiB
Go
Raw Normal View History

2017-02-17 13:12:06 +03:00
package redis
import (
"context"
"crypto/tls"
2019-05-18 14:00:07 +03:00
"net"
"time"
)
2017-02-17 13:12:06 +03:00
// UniversalOptions information is required by UniversalClient to establish
// connections.
type UniversalOptions struct {
// Either a single address or a seed list of host:port addresses
// of cluster/sentinel nodes.
Addrs []string
// Database to be selected after connecting to the server.
// Only single-node and failover clients.
DB int
// Common options.
2017-02-17 13:12:06 +03:00
2020-06-10 10:36:22 +03:00
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
OnConnect func(ctx context.Context, cn *Conn) error
Username string
Password string
MaxRetries int
MinRetryBackoff time.Duration
MaxRetryBackoff time.Duration
DialTimeout time.Duration
ReadTimeout time.Duration
WriteTimeout time.Duration
2017-02-17 13:12:06 +03:00
PoolSize int
MinIdleConns int
MaxConnAge time.Duration
2017-02-17 13:12:06 +03:00
PoolTimeout time.Duration
IdleTimeout time.Duration
IdleCheckFrequency time.Duration
2020-06-10 10:36:22 +03:00
TLSConfig *tls.Config
// Only cluster clients.
MaxRedirects int
ReadOnly bool
RouteByLatency bool
RouteRandomly bool
// The sentinel master name.
// Only failover clients.
MasterName string
2017-02-17 13:12:06 +03:00
}
// Cluster returns cluster options created from the universal options.
func (o *UniversalOptions) Cluster() *ClusterOptions {
2017-02-17 13:12:06 +03:00
if len(o.Addrs) == 0 {
o.Addrs = []string{"127.0.0.1:6379"}
}
return &ClusterOptions{
Addrs: o.Addrs,
2019-05-18 14:00:07 +03:00
Dialer: o.Dialer,
OnConnect: o.OnConnect,
2020-05-21 08:59:20 +03:00
Username: o.Username,
Password: o.Password,
2017-02-17 13:12:06 +03:00
MaxRedirects: o.MaxRedirects,
ReadOnly: o.ReadOnly,
RouteByLatency: o.RouteByLatency,
RouteRandomly: o.RouteRandomly,
MaxRetries: o.MaxRetries,
MinRetryBackoff: o.MinRetryBackoff,
MaxRetryBackoff: o.MaxRetryBackoff,
2017-02-17 13:12:06 +03:00
DialTimeout: o.DialTimeout,
ReadTimeout: o.ReadTimeout,
WriteTimeout: o.WriteTimeout,
PoolSize: o.PoolSize,
MinIdleConns: o.MinIdleConns,
MaxConnAge: o.MaxConnAge,
2017-02-17 13:12:06 +03:00
PoolTimeout: o.PoolTimeout,
IdleTimeout: o.IdleTimeout,
IdleCheckFrequency: o.IdleCheckFrequency,
TLSConfig: o.TLSConfig,
2017-02-17 13:12:06 +03:00
}
}
// Failover returns failover options created from the universal options.
func (o *UniversalOptions) Failover() *FailoverOptions {
2017-02-17 13:12:06 +03:00
if len(o.Addrs) == 0 {
o.Addrs = []string{"127.0.0.1:26379"}
}
return &FailoverOptions{
SentinelAddrs: o.Addrs,
MasterName: o.MasterName,
2019-05-18 14:00:07 +03:00
Dialer: o.Dialer,
OnConnect: o.OnConnect,
DB: o.DB,
2020-05-21 08:59:20 +03:00
Username: o.Username,
Password: o.Password,
MaxRetries: o.MaxRetries,
MinRetryBackoff: o.MinRetryBackoff,
MaxRetryBackoff: o.MaxRetryBackoff,
DialTimeout: o.DialTimeout,
ReadTimeout: o.ReadTimeout,
WriteTimeout: o.WriteTimeout,
2017-02-17 13:12:06 +03:00
PoolSize: o.PoolSize,
MinIdleConns: o.MinIdleConns,
MaxConnAge: o.MaxConnAge,
2017-02-17 13:12:06 +03:00
PoolTimeout: o.PoolTimeout,
IdleTimeout: o.IdleTimeout,
IdleCheckFrequency: o.IdleCheckFrequency,
TLSConfig: o.TLSConfig,
2017-02-17 13:12:06 +03:00
}
}
// Simple returns basic options created from the universal options.
func (o *UniversalOptions) Simple() *Options {
2017-02-17 13:12:06 +03:00
addr := "127.0.0.1:6379"
if len(o.Addrs) > 0 {
addr = o.Addrs[0]
}
return &Options{
Addr: addr,
2019-05-18 14:00:07 +03:00
Dialer: o.Dialer,
OnConnect: o.OnConnect,
DB: o.DB,
2020-05-21 08:59:20 +03:00
Username: o.Username,
Password: o.Password,
MaxRetries: o.MaxRetries,
MinRetryBackoff: o.MinRetryBackoff,
MaxRetryBackoff: o.MaxRetryBackoff,
DialTimeout: o.DialTimeout,
ReadTimeout: o.ReadTimeout,
WriteTimeout: o.WriteTimeout,
2017-02-17 13:12:06 +03:00
PoolSize: o.PoolSize,
MinIdleConns: o.MinIdleConns,
MaxConnAge: o.MaxConnAge,
2017-02-17 13:12:06 +03:00
PoolTimeout: o.PoolTimeout,
IdleTimeout: o.IdleTimeout,
IdleCheckFrequency: o.IdleCheckFrequency,
TLSConfig: o.TLSConfig,
2017-02-17 13:12:06 +03:00
}
}
// --------------------------------------------------------------------
// UniversalClient is an abstract client which - based on the provided options -
// can connect to either clusters, or sentinel-backed failover instances
// or simple single-instance servers. This can be useful for testing
// cluster-specific applications locally.
2017-02-17 13:12:06 +03:00
type UniversalClient interface {
Cmdable
Context() context.Context
2019-05-31 17:40:47 +03:00
AddHook(Hook)
2020-03-11 17:26:42 +03:00
Watch(ctx context.Context, fn func(*Tx) error, keys ...string) error
Do(ctx context.Context, args ...interface{}) *Cmd
Process(ctx context.Context, cmd Cmder) error
Subscribe(ctx context.Context, channels ...string) *PubSub
PSubscribe(ctx context.Context, channels ...string) *PubSub
2017-02-17 13:12:06 +03:00
Close() error
}
2017-09-25 11:48:44 +03:00
var _ UniversalClient = (*Client)(nil)
var _ UniversalClient = (*ClusterClient)(nil)
2019-05-31 17:40:47 +03:00
var _ UniversalClient = (*Ring)(nil)
2017-09-25 11:48:44 +03:00
2017-02-17 13:12:06 +03:00
// NewUniversalClient returns a new multi client. The type of client returned depends
// on the following three conditions:
//
// 1. if a MasterName is passed a sentinel-backed FailoverClient will be returned
// 2. if the number of Addrs is two or more, a ClusterClient will be returned
// 3. otherwise, a single-node redis Client will be returned.
func NewUniversalClient(opts *UniversalOptions) UniversalClient {
if opts.MasterName != "" {
return NewFailoverClient(opts.Failover())
2017-02-17 13:12:06 +03:00
} else if len(opts.Addrs) > 1 {
return NewClusterClient(opts.Cluster())
2017-02-17 13:12:06 +03:00
}
return NewClient(opts.Simple())
2017-02-17 13:12:06 +03:00
}