blob: c89b3e5d7431cffcc32fa1ba88e9a7081503a686 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301package redis
2
3import (
4 "context"
5 "crypto/tls"
6 "net"
7 "time"
8)
9
10// UniversalOptions information is required by UniversalClient to establish
11// connections.
12type UniversalOptions struct {
13 // Either a single address or a seed list of host:port addresses
14 // of cluster/sentinel nodes.
15 Addrs []string
16
17 // Database to be selected after connecting to the server.
18 // Only single-node and failover clients.
19 DB int
20
21 // Common options.
22
23 Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
24 OnConnect func(ctx context.Context, cn *Conn) error
25
26 Username string
27 Password string
28 SentinelUsername string
29 SentinelPassword string
30
31 MaxRetries int
32 MinRetryBackoff time.Duration
33 MaxRetryBackoff time.Duration
34
35 DialTimeout time.Duration
36 ReadTimeout time.Duration
37 WriteTimeout time.Duration
38
39 // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO).
40 PoolFIFO bool
41
42 PoolSize int
43 MinIdleConns int
44 MaxConnAge time.Duration
45 PoolTimeout time.Duration
46 IdleTimeout time.Duration
47 IdleCheckFrequency time.Duration
48
49 TLSConfig *tls.Config
50
51 // Only cluster clients.
52
53 MaxRedirects int
54 ReadOnly bool
55 RouteByLatency bool
56 RouteRandomly bool
57
58 // The sentinel master name.
59 // Only failover clients.
60
61 MasterName string
62}
63
64// Cluster returns cluster options created from the universal options.
65func (o *UniversalOptions) Cluster() *ClusterOptions {
66 if len(o.Addrs) == 0 {
67 o.Addrs = []string{"127.0.0.1:6379"}
68 }
69
70 return &ClusterOptions{
71 Addrs: o.Addrs,
72 Dialer: o.Dialer,
73 OnConnect: o.OnConnect,
74
75 Username: o.Username,
76 Password: o.Password,
77
78 MaxRedirects: o.MaxRedirects,
79 ReadOnly: o.ReadOnly,
80 RouteByLatency: o.RouteByLatency,
81 RouteRandomly: o.RouteRandomly,
82
83 MaxRetries: o.MaxRetries,
84 MinRetryBackoff: o.MinRetryBackoff,
85 MaxRetryBackoff: o.MaxRetryBackoff,
86
87 DialTimeout: o.DialTimeout,
88 ReadTimeout: o.ReadTimeout,
89 WriteTimeout: o.WriteTimeout,
90 PoolFIFO: o.PoolFIFO,
91 PoolSize: o.PoolSize,
92 MinIdleConns: o.MinIdleConns,
93 MaxConnAge: o.MaxConnAge,
94 PoolTimeout: o.PoolTimeout,
95 IdleTimeout: o.IdleTimeout,
96 IdleCheckFrequency: o.IdleCheckFrequency,
97
98 TLSConfig: o.TLSConfig,
99 }
100}
101
102// Failover returns failover options created from the universal options.
103func (o *UniversalOptions) Failover() *FailoverOptions {
104 if len(o.Addrs) == 0 {
105 o.Addrs = []string{"127.0.0.1:26379"}
106 }
107
108 return &FailoverOptions{
109 SentinelAddrs: o.Addrs,
110 MasterName: o.MasterName,
111
112 Dialer: o.Dialer,
113 OnConnect: o.OnConnect,
114
115 DB: o.DB,
116 Username: o.Username,
117 Password: o.Password,
118 SentinelUsername: o.SentinelUsername,
119 SentinelPassword: o.SentinelPassword,
120
121 MaxRetries: o.MaxRetries,
122 MinRetryBackoff: o.MinRetryBackoff,
123 MaxRetryBackoff: o.MaxRetryBackoff,
124
125 DialTimeout: o.DialTimeout,
126 ReadTimeout: o.ReadTimeout,
127 WriteTimeout: o.WriteTimeout,
128
129 PoolFIFO: o.PoolFIFO,
130 PoolSize: o.PoolSize,
131 MinIdleConns: o.MinIdleConns,
132 MaxConnAge: o.MaxConnAge,
133 PoolTimeout: o.PoolTimeout,
134 IdleTimeout: o.IdleTimeout,
135 IdleCheckFrequency: o.IdleCheckFrequency,
136
137 TLSConfig: o.TLSConfig,
138 }
139}
140
141// Simple returns basic options created from the universal options.
142func (o *UniversalOptions) Simple() *Options {
143 addr := "127.0.0.1:6379"
144 if len(o.Addrs) > 0 {
145 addr = o.Addrs[0]
146 }
147
148 return &Options{
149 Addr: addr,
150 Dialer: o.Dialer,
151 OnConnect: o.OnConnect,
152
153 DB: o.DB,
154 Username: o.Username,
155 Password: o.Password,
156
157 MaxRetries: o.MaxRetries,
158 MinRetryBackoff: o.MinRetryBackoff,
159 MaxRetryBackoff: o.MaxRetryBackoff,
160
161 DialTimeout: o.DialTimeout,
162 ReadTimeout: o.ReadTimeout,
163 WriteTimeout: o.WriteTimeout,
164
165 PoolFIFO: o.PoolFIFO,
166 PoolSize: o.PoolSize,
167 MinIdleConns: o.MinIdleConns,
168 MaxConnAge: o.MaxConnAge,
169 PoolTimeout: o.PoolTimeout,
170 IdleTimeout: o.IdleTimeout,
171 IdleCheckFrequency: o.IdleCheckFrequency,
172
173 TLSConfig: o.TLSConfig,
174 }
175}
176
177// --------------------------------------------------------------------
178
179// UniversalClient is an abstract client which - based on the provided options -
180// represents either a ClusterClient, a FailoverClient, or a single-node Client.
181// This can be useful for testing cluster-specific applications locally or having different
182// clients in different environments.
183type UniversalClient interface {
184 Cmdable
185 Context() context.Context
186 AddHook(Hook)
187 Watch(ctx context.Context, fn func(*Tx) error, keys ...string) error
188 Do(ctx context.Context, args ...interface{}) *Cmd
189 Process(ctx context.Context, cmd Cmder) error
190 Subscribe(ctx context.Context, channels ...string) *PubSub
191 PSubscribe(ctx context.Context, channels ...string) *PubSub
192 Close() error
193 PoolStats() *PoolStats
194}
195
196var (
197 _ UniversalClient = (*Client)(nil)
198 _ UniversalClient = (*ClusterClient)(nil)
199 _ UniversalClient = (*Ring)(nil)
200)
201
202// NewUniversalClient returns a new multi client. The type of the returned client depends
203// on the following conditions:
204//
205// 1. If the MasterName option is specified, a sentinel-backed FailoverClient is returned.
206// 2. if the number of Addrs is two or more, a ClusterClient is returned.
207// 3. Otherwise, a single-node Client is returned.
208func NewUniversalClient(opts *UniversalOptions) UniversalClient {
209 if opts.MasterName != "" {
210 return NewFailoverClient(opts.Failover())
211 } else if len(opts.Addrs) > 1 {
212 return NewClusterClient(opts.Cluster())
213 }
214 return NewClient(opts.Simple())
215}