redis/universal.go

232 lines
6.0 KiB
Go
Raw Permalink 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
// ClientName will execute the `CLIENT SETNAME ClientName` command for each conn.
ClientName string
2017-02-17 13:12:06 +03:00
// 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
2023-05-16 17:02:22 +03:00
Protocol int
Username string
Password string
SentinelUsername string
SentinelPassword string
2020-06-10 10:36:22 +03:00
MaxRetries int
MinRetryBackoff time.Duration
MaxRetryBackoff time.Duration
DialTimeout time.Duration
ReadTimeout time.Duration
WriteTimeout time.Duration
ContextTimeoutEnabled bool
2020-06-10 10:36:22 +03:00
// PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO).
PoolFIFO bool
PoolSize int
PoolTimeout time.Duration
MinIdleConns int
MaxIdleConns int
ConnMaxIdleTime time.Duration
ConnMaxLifetime 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.
2021-04-08 10:02:22 +03:00
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,
ClientName: o.ClientName,
Dialer: o.Dialer,
OnConnect: o.OnConnect,
2023-05-16 17:02:22 +03:00
Protocol: o.Protocol,
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,
ContextTimeoutEnabled: o.ContextTimeoutEnabled,
PoolFIFO: o.PoolFIFO,
PoolSize: o.PoolSize,
PoolTimeout: o.PoolTimeout,
MinIdleConns: o.MinIdleConns,
MaxIdleConns: o.MaxIdleConns,
ConnMaxIdleTime: o.ConnMaxIdleTime,
ConnMaxLifetime: o.ConnMaxLifetime,
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,
ClientName: o.ClientName,
2019-05-18 14:00:07 +03:00
Dialer: o.Dialer,
OnConnect: o.OnConnect,
DB: o.DB,
2023-05-16 17:02:22 +03:00
Protocol: o.Protocol,
Username: o.Username,
Password: o.Password,
SentinelUsername: o.SentinelUsername,
SentinelPassword: o.SentinelPassword,
MaxRetries: o.MaxRetries,
MinRetryBackoff: o.MinRetryBackoff,
MaxRetryBackoff: o.MaxRetryBackoff,
DialTimeout: o.DialTimeout,
ReadTimeout: o.ReadTimeout,
WriteTimeout: o.WriteTimeout,
ContextTimeoutEnabled: o.ContextTimeoutEnabled,
2017-02-17 13:12:06 +03:00
PoolFIFO: o.PoolFIFO,
PoolSize: o.PoolSize,
PoolTimeout: o.PoolTimeout,
MinIdleConns: o.MinIdleConns,
MaxIdleConns: o.MaxIdleConns,
ConnMaxIdleTime: o.ConnMaxIdleTime,
ConnMaxLifetime: o.ConnMaxLifetime,
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,
ClientName: o.ClientName,
Dialer: o.Dialer,
OnConnect: o.OnConnect,
DB: o.DB,
2023-05-16 17:02:22 +03:00
Protocol: o.Protocol,
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,
ContextTimeoutEnabled: o.ContextTimeoutEnabled,
2017-02-17 13:12:06 +03:00
PoolFIFO: o.PoolFIFO,
PoolSize: o.PoolSize,
PoolTimeout: o.PoolTimeout,
MinIdleConns: o.MinIdleConns,
MaxIdleConns: o.MaxIdleConns,
ConnMaxIdleTime: o.ConnMaxIdleTime,
ConnMaxLifetime: o.ConnMaxLifetime,
TLSConfig: o.TLSConfig,
2017-02-17 13:12:06 +03:00
}
}
// --------------------------------------------------------------------
// UniversalClient is an abstract client which - based on the provided options -
2021-04-08 10:02:22 +03:00
// represents either a ClusterClient, a FailoverClient, or a single-node Client.
// This can be useful for testing cluster-specific applications locally or having different
// clients in different environments.
2017-02-17 13:12:06 +03:00
type UniversalClient interface {
Cmdable
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
2022-08-03 18:10:03 +03:00
SSubscribe(ctx context.Context, channels ...string) *PubSub
2017-02-17 13:12:06 +03:00
Close() error
2020-09-29 19:08:01 +03:00
PoolStats() *PoolStats
2017-02-17 13:12:06 +03:00
}
2020-07-16 09:52:07 +03:00
var (
_ UniversalClient = (*Client)(nil)
_ UniversalClient = (*ClusterClient)(nil)
_ UniversalClient = (*Ring)(nil)
)
2017-09-25 11:48:44 +03:00
2021-04-08 10:02:22 +03:00
// NewUniversalClient returns a new multi client. The type of the returned client depends
// on the following conditions:
2017-02-17 13:12:06 +03:00
//
2021-04-08 10:02:22 +03:00
// 1. If the MasterName option is specified, a sentinel-backed FailoverClient is returned.
// 2. if the number of Addrs is two or more, a ClusterClient is returned.
// 3. Otherwise, a single-node Client is returned.
2017-02-17 13:12:06 +03:00
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
}