| package redis |
| |
| import ( |
| "context" |
| "crypto/tls" |
| "net" |
| "time" |
| ) |
| |
| // 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. |
| |
| Dialer func(ctx context.Context, network, addr string) (net.Conn, error) |
| OnConnect func(ctx context.Context, cn *Conn) error |
| |
| Username string |
| Password string |
| SentinelPassword string |
| |
| MaxRetries int |
| MinRetryBackoff time.Duration |
| MaxRetryBackoff time.Duration |
| |
| DialTimeout time.Duration |
| ReadTimeout time.Duration |
| WriteTimeout time.Duration |
| |
| PoolSize int |
| MinIdleConns int |
| MaxConnAge time.Duration |
| PoolTimeout time.Duration |
| IdleTimeout time.Duration |
| IdleCheckFrequency time.Duration |
| |
| TLSConfig *tls.Config |
| |
| // Only cluster clients. |
| |
| MaxRedirects int |
| ReadOnly bool |
| RouteByLatency bool |
| RouteRandomly bool |
| |
| // The sentinel master name. |
| // Only failover clients. |
| MasterName string |
| } |
| |
| // Cluster returns cluster options created from the universal options. |
| func (o *UniversalOptions) Cluster() *ClusterOptions { |
| if len(o.Addrs) == 0 { |
| o.Addrs = []string{"127.0.0.1:6379"} |
| } |
| |
| return &ClusterOptions{ |
| Addrs: o.Addrs, |
| Dialer: o.Dialer, |
| OnConnect: o.OnConnect, |
| |
| Username: o.Username, |
| Password: o.Password, |
| |
| MaxRedirects: o.MaxRedirects, |
| ReadOnly: o.ReadOnly, |
| RouteByLatency: o.RouteByLatency, |
| RouteRandomly: o.RouteRandomly, |
| |
| MaxRetries: o.MaxRetries, |
| MinRetryBackoff: o.MinRetryBackoff, |
| MaxRetryBackoff: o.MaxRetryBackoff, |
| |
| DialTimeout: o.DialTimeout, |
| ReadTimeout: o.ReadTimeout, |
| WriteTimeout: o.WriteTimeout, |
| PoolSize: o.PoolSize, |
| MinIdleConns: o.MinIdleConns, |
| MaxConnAge: o.MaxConnAge, |
| PoolTimeout: o.PoolTimeout, |
| IdleTimeout: o.IdleTimeout, |
| IdleCheckFrequency: o.IdleCheckFrequency, |
| |
| TLSConfig: o.TLSConfig, |
| } |
| } |
| |
| // Failover returns failover options created from the universal options. |
| func (o *UniversalOptions) Failover() *FailoverOptions { |
| if len(o.Addrs) == 0 { |
| o.Addrs = []string{"127.0.0.1:26379"} |
| } |
| |
| return &FailoverOptions{ |
| SentinelAddrs: o.Addrs, |
| MasterName: o.MasterName, |
| |
| Dialer: o.Dialer, |
| OnConnect: o.OnConnect, |
| |
| DB: o.DB, |
| Username: o.Username, |
| Password: o.Password, |
| SentinelPassword: o.SentinelPassword, |
| |
| MaxRetries: o.MaxRetries, |
| MinRetryBackoff: o.MinRetryBackoff, |
| MaxRetryBackoff: o.MaxRetryBackoff, |
| |
| DialTimeout: o.DialTimeout, |
| ReadTimeout: o.ReadTimeout, |
| WriteTimeout: o.WriteTimeout, |
| |
| PoolSize: o.PoolSize, |
| MinIdleConns: o.MinIdleConns, |
| MaxConnAge: o.MaxConnAge, |
| PoolTimeout: o.PoolTimeout, |
| IdleTimeout: o.IdleTimeout, |
| IdleCheckFrequency: o.IdleCheckFrequency, |
| |
| TLSConfig: o.TLSConfig, |
| } |
| } |
| |
| // Simple returns basic options created from the universal options. |
| func (o *UniversalOptions) Simple() *Options { |
| addr := "127.0.0.1:6379" |
| if len(o.Addrs) > 0 { |
| addr = o.Addrs[0] |
| } |
| |
| return &Options{ |
| Addr: addr, |
| Dialer: o.Dialer, |
| OnConnect: o.OnConnect, |
| |
| DB: o.DB, |
| Username: o.Username, |
| Password: o.Password, |
| |
| MaxRetries: o.MaxRetries, |
| MinRetryBackoff: o.MinRetryBackoff, |
| MaxRetryBackoff: o.MaxRetryBackoff, |
| |
| DialTimeout: o.DialTimeout, |
| ReadTimeout: o.ReadTimeout, |
| WriteTimeout: o.WriteTimeout, |
| |
| PoolSize: o.PoolSize, |
| MinIdleConns: o.MinIdleConns, |
| MaxConnAge: o.MaxConnAge, |
| PoolTimeout: o.PoolTimeout, |
| IdleTimeout: o.IdleTimeout, |
| IdleCheckFrequency: o.IdleCheckFrequency, |
| |
| TLSConfig: o.TLSConfig, |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| // 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. |
| type UniversalClient interface { |
| Cmdable |
| Context() context.Context |
| AddHook(Hook) |
| 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 |
| Close() error |
| PoolStats() *PoolStats |
| } |
| |
| var ( |
| _ UniversalClient = (*Client)(nil) |
| _ UniversalClient = (*ClusterClient)(nil) |
| _ UniversalClient = (*Ring)(nil) |
| ) |
| |
| // 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()) |
| } else if len(opts.Addrs) > 1 { |
| return NewClusterClient(opts.Cluster()) |
| } |
| return NewClient(opts.Simple()) |
| } |