func withRetry( b *sarama.Broker, cfg *sarama.Config, f func() error, ) error { var err error for max := 0; max < cfg.Metadata.Retry.Max; max++ { if ok, _ := b.Connected(); !ok { if err = b.Open(cfg); err == nil { err = f() } } else { err = f() } if err == nil { return nil } retry, reconnect := checkRetryQuery(err) if !retry { return err } time.Sleep(cfg.Metadata.Retry.Backoff) if reconnect { closeBroker(b) } } return err }
// Connects to the broker that handles all produce and consume // requests for the given chain (Partition Leader Replica) func newBroker(brokers []string, cp ChainPartition) (Broker, error) { var candidateBroker, connectedBroker, leaderBroker *sarama.Broker // Connect to one of the given brokers for _, hostPort := range brokers { candidateBroker = sarama.NewBroker(hostPort) if err := candidateBroker.Open(nil); err != nil { logger.Warningf("Failed to connect to broker %s: %s", hostPort, err) continue } if connected, err := candidateBroker.Connected(); !connected { logger.Warningf("Failed to connect to broker %s: %s", hostPort, err) continue } connectedBroker = candidateBroker break } if connectedBroker == nil { return nil, fmt.Errorf("Failed to connect to any of the given brokers (%v) for metadata request", brokers) } logger.Debugf("Connected to broker %s", connectedBroker.Addr()) // Get metadata for the topic that corresponds to this chain metadata, err := connectedBroker.GetMetadata(&sarama.MetadataRequest{Topics: []string{cp.Topic()}}) if err != nil { return nil, fmt.Errorf("Failed to get metadata for topic %s: %s", cp, err) } // Get the leader broker for this chain partition if (cp.Partition() >= 0) && (cp.Partition() < int32(len(metadata.Topics[0].Partitions))) { leaderBrokerID := metadata.Topics[0].Partitions[cp.Partition()].Leader logger.Debugf("Leading broker for chain %s is broker ID %d", cp, leaderBrokerID) for _, availableBroker := range metadata.Brokers { if availableBroker.ID() == leaderBrokerID { leaderBroker = availableBroker break } } } if leaderBroker == nil { return nil, fmt.Errorf("Can't find leader for chain %s", cp) } // Connect to broker if err := leaderBroker.Open(nil); err != nil { return nil, fmt.Errorf("Failed to connect ho Kafka broker: %s", err) } if connected, err := leaderBroker.Connected(); !connected { return nil, fmt.Errorf("Failed to connect to Kafka broker: %s", err) } return &brokerImpl{broker: leaderBroker}, nil }