@@ -124,6 +124,11 @@ type ClusterOptions struct {
124124
125125 // UnstableResp3 enables Unstable mode for Redis Search module with RESP3.
126126 UnstableResp3 bool
127+
128+ // FailingTimeoutSeconds is the timeout in seconds for marking a cluster node as failing.
129+ // When a node is marked as failing, it will be avoided for this duration.
130+ // Default is 15 seconds.
131+ FailingTimeoutSeconds int
127132}
128133
129134func (opt * ClusterOptions ) init () {
@@ -180,6 +185,10 @@ func (opt *ClusterOptions) init() {
180185 if opt .NewClient == nil {
181186 opt .NewClient = NewClient
182187 }
188+
189+ if opt .FailingTimeoutSeconds == 0 {
190+ opt .FailingTimeoutSeconds = 15
191+ }
183192}
184193
185194// ParseClusterURL parses a URL into ClusterOptions that can be used to connect to Redis.
@@ -284,6 +293,7 @@ func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, er
284293 o .PoolTimeout = q .duration ("pool_timeout" )
285294 o .ConnMaxLifetime = q .duration ("conn_max_lifetime" )
286295 o .ConnMaxIdleTime = q .duration ("conn_max_idle_time" )
296+ o .FailingTimeoutSeconds = q .int ("failing_timeout_seconds" )
287297
288298 if q .err != nil {
289299 return nil , q .err
@@ -330,20 +340,21 @@ func (opt *ClusterOptions) clientOptions() *Options {
330340 WriteTimeout : opt .WriteTimeout ,
331341 ContextTimeoutEnabled : opt .ContextTimeoutEnabled ,
332342
333- PoolFIFO : opt .PoolFIFO ,
334- PoolSize : opt .PoolSize ,
335- PoolTimeout : opt .PoolTimeout ,
336- MinIdleConns : opt .MinIdleConns ,
337- MaxIdleConns : opt .MaxIdleConns ,
338- MaxActiveConns : opt .MaxActiveConns ,
339- ConnMaxIdleTime : opt .ConnMaxIdleTime ,
340- ConnMaxLifetime : opt .ConnMaxLifetime ,
341- ReadBufferSize : opt .ReadBufferSize ,
342- WriteBufferSize : opt .WriteBufferSize ,
343- DisableIdentity : opt .DisableIdentity ,
344- DisableIndentity : opt .DisableIdentity ,
345- IdentitySuffix : opt .IdentitySuffix ,
346- TLSConfig : opt .TLSConfig ,
343+ PoolFIFO : opt .PoolFIFO ,
344+ PoolSize : opt .PoolSize ,
345+ PoolTimeout : opt .PoolTimeout ,
346+ MinIdleConns : opt .MinIdleConns ,
347+ MaxIdleConns : opt .MaxIdleConns ,
348+ MaxActiveConns : opt .MaxActiveConns ,
349+ ConnMaxIdleTime : opt .ConnMaxIdleTime ,
350+ ConnMaxLifetime : opt .ConnMaxLifetime ,
351+ ReadBufferSize : opt .ReadBufferSize ,
352+ WriteBufferSize : opt .WriteBufferSize ,
353+ DisableIdentity : opt .DisableIdentity ,
354+ DisableIndentity : opt .DisableIdentity ,
355+ IdentitySuffix : opt .IdentitySuffix ,
356+ FailingTimeoutSeconds : opt .FailingTimeoutSeconds ,
357+ TLSConfig : opt .TLSConfig ,
347358 // If ClusterSlots is populated, then we probably have an artificial
348359 // cluster whose nodes are not in clustering mode (otherwise there isn't
349360 // much use for ClusterSlots config). This means we cannot execute the
@@ -432,7 +443,7 @@ func (n *clusterNode) MarkAsFailing() {
432443}
433444
434445func (n * clusterNode ) Failing () bool {
435- const timeout = 15 // 15 seconds
446+ timeout := int64 ( n . Client . opt . FailingTimeoutSeconds )
436447
437448 failing := atomic .LoadUint32 (& n .failing )
438449 if failing == 0 {
0 commit comments