github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/orderer/consensus/kafka/consenter.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package kafka
     8  
     9  import (
    10  	"github.com/Shopify/sarama"
    11  	"github.com/hechain20/hechain/common/flogging"
    12  	"github.com/hechain20/hechain/common/metrics"
    13  	"github.com/hechain20/hechain/orderer/common/localconfig"
    14  	"github.com/hechain20/hechain/orderer/consensus"
    15  	"github.com/hechain20/hechain/orderer/consensus/inactive"
    16  	"github.com/hyperledger/fabric-lib-go/healthz"
    17  	cb "github.com/hyperledger/fabric-protos-go/common"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  //go:generate counterfeiter -o mock/health_checker.go -fake-name HealthChecker . healthChecker
    22  
    23  // healthChecker defines the contract for health checker
    24  type healthChecker interface {
    25  	RegisterChecker(component string, checker healthz.HealthChecker) error
    26  }
    27  
    28  // New creates a Kafka-based consenter. Called by orderer's main.go.
    29  func New(config localconfig.Kafka, mp metrics.Provider, healthChecker healthChecker, icr InactiveChainRegistry, mkChain func(string)) (consensus.Consenter, *Metrics) {
    30  	if config.Verbose {
    31  		flogging.ActivateSpec(flogging.Global.Spec() + ":orderer.consensus.kafka.sarama=debug")
    32  	}
    33  
    34  	brokerConfig := newBrokerConfig(
    35  		config.TLS,
    36  		config.SASLPlain,
    37  		config.Retry,
    38  		config.Version,
    39  		defaultPartition)
    40  
    41  	metrics := NewMetrics(mp, brokerConfig.MetricRegistry)
    42  
    43  	return &consenterImpl{
    44  		mkChain:               mkChain,
    45  		inactiveChainRegistry: icr,
    46  		brokerConfigVal:       brokerConfig,
    47  		tlsConfigVal:          config.TLS,
    48  		retryOptionsVal:       config.Retry,
    49  		kafkaVersionVal:       config.Version,
    50  		topicDetailVal: &sarama.TopicDetail{
    51  			NumPartitions:     1,
    52  			ReplicationFactor: config.Topic.ReplicationFactor,
    53  		},
    54  		healthChecker: healthChecker,
    55  		metrics:       metrics,
    56  	}, metrics
    57  }
    58  
    59  // InactiveChainRegistry registers chains that are inactive
    60  type InactiveChainRegistry interface {
    61  	// TrackChain tracks a chain with the given name, and calls the given callback
    62  	// when this chain should be created.
    63  	TrackChain(chainName string, genesisBlock *cb.Block, createChain func())
    64  }
    65  
    66  // consenterImpl holds the implementation of type that satisfies the
    67  // consensus.Consenter interface --as the HandleChain contract requires-- and
    68  // the commonConsenter one.
    69  type consenterImpl struct {
    70  	mkChain               func(string)
    71  	brokerConfigVal       *sarama.Config
    72  	tlsConfigVal          localconfig.TLS
    73  	retryOptionsVal       localconfig.Retry
    74  	kafkaVersionVal       sarama.KafkaVersion
    75  	topicDetailVal        *sarama.TopicDetail
    76  	healthChecker         healthChecker
    77  	metrics               *Metrics
    78  	inactiveChainRegistry InactiveChainRegistry
    79  }
    80  
    81  // HandleChain creates/returns a reference to a consensus.Chain object for the
    82  // given set of support resources. Implements the consensus.Consenter
    83  // interface. Called by consensus.newChainSupport(), which is itself called by
    84  // multichannel.NewManagerImpl() when ranging over the ledgerFactory's
    85  // existingChains.
    86  func (consenter *consenterImpl) HandleChain(support consensus.ConsenterSupport, metadata *cb.Metadata) (consensus.Chain, error) {
    87  	// Check if this node was migrated from Raft
    88  	if consenter.inactiveChainRegistry != nil {
    89  		logger.Infof("This node was migrated from Kafka to Raft, skipping activation of Kafka chain")
    90  		consenter.inactiveChainRegistry.TrackChain(support.ChannelID(), support.Block(0), func() {
    91  			consenter.mkChain(support.ChannelID())
    92  		})
    93  		return &inactive.Chain{Err: errors.Errorf("channel %s is not serviced by me", support.ChannelID())}, nil
    94  	}
    95  
    96  	lastOffsetPersisted, lastOriginalOffsetProcessed, lastResubmittedConfigOffset := getOffsets(metadata.Value, support.ChannelID())
    97  	ch, err := newChain(consenter, support, lastOffsetPersisted, lastOriginalOffsetProcessed, lastResubmittedConfigOffset)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	consenter.healthChecker.RegisterChecker(ch.channel.String(), ch)
   102  	return ch, nil
   103  }
   104  
   105  // commonConsenter allows us to retrieve the configuration options set on the
   106  // consenter object. These will be common across all chain objects derived by
   107  // this consenter. They are set using local configuration settings. This
   108  // interface is satisfied by consenterImpl.
   109  type commonConsenter interface {
   110  	brokerConfig() *sarama.Config
   111  	retryOptions() localconfig.Retry
   112  	topicDetail() *sarama.TopicDetail
   113  	Metrics() *Metrics
   114  }
   115  
   116  func (consenter *consenterImpl) Metrics() *Metrics {
   117  	return consenter.metrics
   118  }
   119  
   120  func (consenter *consenterImpl) brokerConfig() *sarama.Config {
   121  	return consenter.brokerConfigVal
   122  }
   123  
   124  func (consenter *consenterImpl) retryOptions() localconfig.Retry {
   125  	return consenter.retryOptionsVal
   126  }
   127  
   128  func (consenter *consenterImpl) topicDetail() *sarama.TopicDetail {
   129  	return consenter.topicDetailVal
   130  }