github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/access/rpc/engine_builder.go (about)

     1  package rpc
     2  
     3  import (
     4  	"fmt"
     5  
     6  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
     7  
     8  	"github.com/onflow/flow-go/access"
     9  	legacyaccess "github.com/onflow/flow-go/access/legacy"
    10  	"github.com/onflow/flow-go/consensus/hotstuff"
    11  	"github.com/onflow/flow-go/module"
    12  
    13  	accessproto "github.com/onflow/flow/protobuf/go/flow/access"
    14  	legacyaccessproto "github.com/onflow/flow/protobuf/go/flow/legacy/access"
    15  )
    16  
    17  type RPCEngineBuilder struct {
    18  	*Engine
    19  	me                   module.Local
    20  	finalizedHeaderCache module.FinalizedHeaderCache
    21  
    22  	// optional parameters, only one can be set during build phase
    23  	signerIndicesDecoder hotstuff.BlockSignerDecoder
    24  	rpcHandler           accessproto.AccessAPIServer // Use the parent interface instead of implementation, so that we can assign it to proxy.
    25  }
    26  
    27  // NewRPCEngineBuilder helps to build a new RPC engine.
    28  func NewRPCEngineBuilder(engine *Engine, me module.Local, finalizedHeaderCache module.FinalizedHeaderCache) *RPCEngineBuilder {
    29  	// the default handler will use the engine.backend implementation
    30  	return &RPCEngineBuilder{
    31  		Engine:               engine,
    32  		me:                   me,
    33  		finalizedHeaderCache: finalizedHeaderCache,
    34  	}
    35  }
    36  
    37  func (builder *RPCEngineBuilder) RpcHandler() accessproto.AccessAPIServer {
    38  	return builder.rpcHandler
    39  }
    40  
    41  // WithBlockSignerDecoder specifies that signer indices in block headers should be translated
    42  // to full node IDs with the given decoder.
    43  // Caution:
    44  // you can inject either a `BlockSignerDecoder` (via method `WithBlockSignerDecoder`)
    45  // or an `AccessAPIServer` (via method `WithNewHandler`); but not both. If both are
    46  // specified, the builder will error during the build step.
    47  //
    48  // Returns self-reference for chaining.
    49  func (builder *RPCEngineBuilder) WithBlockSignerDecoder(signerIndicesDecoder hotstuff.BlockSignerDecoder) *RPCEngineBuilder {
    50  	builder.signerIndicesDecoder = signerIndicesDecoder
    51  	return builder
    52  }
    53  
    54  // WithRpcHandler specifies that the given `AccessAPIServer` should be used for serving API queries.
    55  // Caution:
    56  // you can inject either a `BlockSignerDecoder` (via method `WithBlockSignerDecoder`)
    57  // or an `AccessAPIServer` (via method `WithRpcHandler`); but not both. If both are
    58  // specified, the builder will error during the build step.
    59  //
    60  // Returns self-reference for chaining.
    61  func (builder *RPCEngineBuilder) WithRpcHandler(handler accessproto.AccessAPIServer) *RPCEngineBuilder {
    62  	builder.rpcHandler = handler
    63  	return builder
    64  }
    65  
    66  // WithLegacy specifies that a legacy access API should be instantiated
    67  // Returns self-reference for chaining.
    68  func (builder *RPCEngineBuilder) WithLegacy() *RPCEngineBuilder {
    69  	// Register legacy gRPC handlers for backwards compatibility, to be removed at a later date
    70  	legacyaccessproto.RegisterAccessAPIServer(
    71  		builder.unsecureGrpcServer.Server,
    72  		legacyaccess.NewHandler(builder.backend, builder.chain),
    73  	)
    74  	legacyaccessproto.RegisterAccessAPIServer(
    75  		builder.secureGrpcServer.Server,
    76  		legacyaccess.NewHandler(builder.backend, builder.chain),
    77  	)
    78  	return builder
    79  }
    80  
    81  func (builder *RPCEngineBuilder) DefaultHandler(signerIndicesDecoder hotstuff.BlockSignerDecoder) *access.Handler {
    82  	if signerIndicesDecoder == nil {
    83  		return access.NewHandler(builder.Engine.backend, builder.Engine.chain, builder.finalizedHeaderCache, builder.me, builder.stateStreamConfig.MaxGlobalStreams)
    84  	} else {
    85  		return access.NewHandler(builder.Engine.backend, builder.Engine.chain, builder.finalizedHeaderCache, builder.me, builder.stateStreamConfig.MaxGlobalStreams, access.WithBlockSignerDecoder(signerIndicesDecoder))
    86  	}
    87  }
    88  
    89  // WithMetrics specifies the metrics should be collected.
    90  // Returns self-reference for chaining.
    91  func (builder *RPCEngineBuilder) WithMetrics() *RPCEngineBuilder {
    92  	// Not interested in legacy metrics, so initialize here
    93  	grpc_prometheus.EnableHandlingTimeHistogram()
    94  	grpc_prometheus.Register(builder.unsecureGrpcServer.Server)
    95  	grpc_prometheus.Register(builder.secureGrpcServer.Server)
    96  	return builder
    97  }
    98  
    99  func (builder *RPCEngineBuilder) Build() (*Engine, error) {
   100  	if builder.signerIndicesDecoder != nil && builder.rpcHandler != nil {
   101  		return nil, fmt.Errorf("only BlockSignerDecoder (via method `WithBlockSignerDecoder`) or AccessAPIServer (via method `WithNewHandler`) can be specified but not both")
   102  	}
   103  	rpcHandler := builder.rpcHandler
   104  	if rpcHandler == nil {
   105  		rpcHandler = builder.DefaultHandler(builder.signerIndicesDecoder)
   106  	}
   107  	accessproto.RegisterAccessAPIServer(builder.unsecureGrpcServer.Server, rpcHandler)
   108  	accessproto.RegisterAccessAPIServer(builder.secureGrpcServer.Server, rpcHandler)
   109  	return builder.Engine, nil
   110  }