NewFailoverClient returns a Redis client that uses Redis Sentinel for automatic failover. It's safe for concurrent use by multiple goroutines. Passing nil FailoverOptions will cause a panic.
(failoverOpt *FailoverOptions)
| 507 | // goroutines. |
| 508 | // Passing nil FailoverOptions will cause a panic. |
| 509 | func NewFailoverClient(failoverOpt *FailoverOptions) *Client { |
| 510 | if failoverOpt == nil { |
| 511 | panic("redis: NewFailoverClient nil options") |
| 512 | } |
| 513 | |
| 514 | if failoverOpt.RouteByLatency { |
| 515 | panic("to route commands by latency, use NewFailoverClusterClient") |
| 516 | } |
| 517 | if failoverOpt.RouteRandomly { |
| 518 | panic("to route commands randomly, use NewFailoverClusterClient") |
| 519 | } |
| 520 | |
| 521 | sentinelAddrs := make([]string, len(failoverOpt.SentinelAddrs)) |
| 522 | copy(sentinelAddrs, failoverOpt.SentinelAddrs) |
| 523 | |
| 524 | rand.Shuffle(len(sentinelAddrs), func(i, j int) { |
| 525 | sentinelAddrs[i], sentinelAddrs[j] = sentinelAddrs[j], sentinelAddrs[i] |
| 526 | }) |
| 527 | |
| 528 | failover := &sentinelFailover{ |
| 529 | opt: failoverOpt, |
| 530 | sentinelAddrs: sentinelAddrs, |
| 531 | } |
| 532 | |
| 533 | opt := failoverOpt.clientOptions() |
| 534 | opt.Dialer = masterReplicaDialer(failover) |
| 535 | opt.init() |
| 536 | |
| 537 | rdb := &Client{ |
| 538 | baseClient: &baseClient{ |
| 539 | opt: opt, |
| 540 | onClose: &onCloseHooks{}, |
| 541 | }, |
| 542 | } |
| 543 | rdb.init() |
| 544 | |
| 545 | // Initialize push notification processor using shared helper |
| 546 | // Use void processor by default for RESP2 connections |
| 547 | rdb.pushProcessor = initializePushProcessor(opt) |
| 548 | |
| 549 | // Generate unique pool names for metrics |
| 550 | uniqueID := generateUniqueID() |
| 551 | mainPoolName := opt.Addr + "_" + uniqueID |
| 552 | pubsubPoolName := opt.Addr + "_" + uniqueID + "_pubsub" |
| 553 | |
| 554 | var err error |
| 555 | rdb.connPool, err = newConnPool(opt, rdb.dialHook, mainPoolName) |
| 556 | if err != nil { |
| 557 | panic(fmt.Errorf("redis: failed to create connection pool: %w", err)) |
| 558 | } |
| 559 | rdb.pubSubPool, err = newPubSubPool(opt, rdb.dialHook, pubsubPoolName) |
| 560 | if err != nil { |
| 561 | panic(fmt.Errorf("redis: failed to create pubsub pool: %w", err)) |
| 562 | } |
| 563 | |
| 564 | rdb.onClose.register(onCloseHookIDSentinelFailover, failover.Close) |
| 565 | |
| 566 | failover.mu.Lock() |
no test coverage detected