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.

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