You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
5.5 KiB

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