Skip to content

Commit f7a6e97

Browse files
author
Runze Cui
committed
Check CB Open and init connection for resolve hystrix attempt
1 parent 346434d commit f7a6e97

File tree

2 files changed

+63
-41
lines changed

2 files changed

+63
-41
lines changed

options.go

+32-23
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ type Limiter interface {
2525
// Execute allow a customised wrapper around the actual execution.
2626
// this is useful for most common circuit breaker implementation
2727
Execute(func() error) error
28+
// IsCBOpen return whether CB is open
29+
// this is useful for implementing additional logic bypass nested hystrix
30+
IsCBOpen() bool
2831
// ReportResult reports the result of the previously allowed operation.
2932
// nil indicates a success, non-nil error usually indicates a failure.
3033
ReportResult(result error)
@@ -205,32 +208,38 @@ func (opt *Options) clone() *Options {
205208
// Scheme is required.
206209
// There are two connection types: by tcp socket and by unix socket.
207210
// Tcp connection:
208-
// redis://<user>:<password>@<host>:<port>/<db_number>
211+
//
212+
// redis://<user>:<password>@<host>:<port>/<db_number>
213+
//
209214
// Unix connection:
210-
// unix://<user>:<password>@</path/to/redis.sock>?db=<db_number>
215+
//
216+
// unix://<user>:<password>@</path/to/redis.sock>?db=<db_number>
217+
//
211218
// Most Option fields can be set using query parameters, with the following restrictions:
212-
// - field names are mapped using snake-case conversion: to set MaxRetries, use max_retries
213-
// - only scalar type fields are supported (bool, int, time.Duration)
214-
// - for time.Duration fields, values must be a valid input for time.ParseDuration();
215-
// additionally a plain integer as value (i.e. without unit) is intepreted as seconds
216-
// - to disable a duration field, use value less than or equal to 0; to use the default
217-
// value, leave the value blank or remove the parameter
218-
// - only the last value is interpreted if a parameter is given multiple times
219-
// - fields "network", "addr", "username" and "password" can only be set using other
220-
// URL attributes (scheme, host, userinfo, resp.), query paremeters using these
221-
// names will be treated as unknown parameters
222-
// - unknown parameter names will result in an error
219+
// - field names are mapped using snake-case conversion: to set MaxRetries, use max_retries
220+
// - only scalar type fields are supported (bool, int, time.Duration)
221+
// - for time.Duration fields, values must be a valid input for time.ParseDuration();
222+
// additionally a plain integer as value (i.e. without unit) is intepreted as seconds
223+
// - to disable a duration field, use value less than or equal to 0; to use the default
224+
// value, leave the value blank or remove the parameter
225+
// - only the last value is interpreted if a parameter is given multiple times
226+
// - fields "network", "addr", "username" and "password" can only be set using other
227+
// URL attributes (scheme, host, userinfo, resp.), query paremeters using these
228+
// names will be treated as unknown parameters
229+
// - unknown parameter names will result in an error
230+
//
223231
// Examples:
224-
// redis://user:password@localhost:6789/3?dial_timeout=3&db=1&read_timeout=6s&max_retries=2
225-
// is equivalent to:
226-
// &Options{
227-
// Network: "tcp",
228-
// Addr: "localhost:6789",
229-
// DB: 1, // path "/3" was overridden by "&db=1"
230-
// DialTimeout: 3 * time.Second, // no time unit = seconds
231-
// ReadTimeout: 6 * time.Second,
232-
// MaxRetries: 2,
233-
// }
232+
//
233+
// redis://user:password@localhost:6789/3?dial_timeout=3&db=1&read_timeout=6s&max_retries=2
234+
// is equivalent to:
235+
// &Options{
236+
// Network: "tcp",
237+
// Addr: "localhost:6789",
238+
// DB: 1, // path "/3" was overridden by "&db=1"
239+
// DialTimeout: 3 * time.Second, // no time unit = seconds
240+
// ReadTimeout: 6 * time.Second,
241+
// MaxRetries: 2,
242+
// }
234243
func ParseURL(redisURL string) (*Options, error) {
235244
u, err := url.Parse(redisURL)
236245
if err != nil {

redis.go

+31-18
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,19 @@ func (c *baseClient) withConn(
265265
return err
266266
}
267267

268+
// Request is allowed occasionally to close the cb and cb is still in open state
269+
// Init the connection to avoid nested hystrix call during connection establishment
270+
if limiter.IsCBOpen() {
271+
cn, err := c.getConn(ctx)
272+
if err != nil {
273+
return err
274+
}
275+
276+
defer func() {
277+
c.releaseConn(ctx, cn, err)
278+
}()
279+
}
280+
268281
err := limiter.Execute(func() error {
269282
return c._withConn(ctx, fn)
270283
})
@@ -668,26 +681,26 @@ func (c *Client) pubSub() *PubSub {
668681
// subscription may not be active immediately. To force the connection to wait,
669682
// you may call the Receive() method on the returned *PubSub like so:
670683
//
671-
// sub := client.Subscribe(queryResp)
672-
// iface, err := sub.Receive()
673-
// if err != nil {
674-
// // handle error
675-
// }
684+
// sub := client.Subscribe(queryResp)
685+
// iface, err := sub.Receive()
686+
// if err != nil {
687+
// // handle error
688+
// }
676689
//
677-
// // Should be *Subscription, but others are possible if other actions have been
678-
// // taken on sub since it was created.
679-
// switch iface.(type) {
680-
// case *Subscription:
681-
// // subscribe succeeded
682-
// case *Message:
683-
// // received first message
684-
// case *Pong:
685-
// // pong received
686-
// default:
687-
// // handle error
688-
// }
690+
// // Should be *Subscription, but others are possible if other actions have been
691+
// // taken on sub since it was created.
692+
// switch iface.(type) {
693+
// case *Subscription:
694+
// // subscribe succeeded
695+
// case *Message:
696+
// // received first message
697+
// case *Pong:
698+
// // pong received
699+
// default:
700+
// // handle error
701+
// }
689702
//
690-
// ch := sub.Channel()
703+
// ch := sub.Channel()
691704
func (c *Client) Subscribe(ctx context.Context, channels ...string) *PubSub {
692705
pubsub := c.pubSub()
693706
if len(channels) > 0 {

0 commit comments

Comments
 (0)