github.com/onflow/flow-go@v0.33.17/engine/access/rpc/backend/node_selector.go (about) 1 package backend 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/flow-go/model/flow" 7 ) 8 9 // maxNodesCnt is the maximum number of nodes that will be contacted to complete an API request. 10 const maxNodesCnt = 3 11 12 // NodeSelector is an interface that represents the ability to select node identities that the access node is trying to reach. 13 // It encapsulates the internal logic of node selection and provides a way to change implementations for different types 14 // of nodes. Implementations of this interface should define the Next method, which returns the next node identity to be 15 // selected. HasNext checks if there is next node available. 16 type NodeSelector interface { 17 Next() *flow.Identity 18 HasNext() bool 19 } 20 21 // NodeSelectorFactory is a factory for creating node selectors based on factory configuration and node type. 22 // Supported configurations: 23 // circuitBreakerEnabled = true - nodes will be pseudo-randomly sampled and picked in-order. 24 // circuitBreakerEnabled = false - nodes will be picked from proposed list in-order without any changes. 25 type NodeSelectorFactory struct { 26 circuitBreakerEnabled bool 27 } 28 29 // SelectNodes selects the configured number of node identities from the provided list of nodes 30 // and returns the node selector to iterate through them. 31 func (n *NodeSelectorFactory) SelectNodes(nodes flow.IdentityList) (NodeSelector, error) { 32 var err error 33 // If the circuit breaker is disabled, the legacy logic should be used, which selects only a specified number of nodes. 34 if !n.circuitBreakerEnabled { 35 nodes, err = nodes.Sample(maxNodesCnt) 36 if err != nil { 37 return nil, fmt.Errorf("sampling failed: %w", err) 38 } 39 } 40 41 return NewMainNodeSelector(nodes), nil 42 } 43 44 // MainNodeSelector is a specific implementation of the node selector. 45 // Which performs in-order node selection using fixed list of pre-defined nodes. 46 type MainNodeSelector struct { 47 nodes flow.IdentityList 48 index int 49 } 50 51 var _ NodeSelector = (*MainNodeSelector)(nil) 52 53 func NewMainNodeSelector(nodes flow.IdentityList) *MainNodeSelector { 54 return &MainNodeSelector{nodes: nodes, index: 0} 55 } 56 57 // HasNext returns true if next node is available. 58 func (e *MainNodeSelector) HasNext() bool { 59 return e.index < len(e.nodes) 60 } 61 62 // Next returns the next node in the selector. 63 func (e *MainNodeSelector) Next() *flow.Identity { 64 if e.index < len(e.nodes) { 65 next := e.nodes[e.index] 66 e.index++ 67 return next 68 } 69 return nil 70 }