github.com/koko1123/flow-go-1@v0.29.6/engine/access/state_stream/engine.go (about) 1 package state_stream 2 3 import ( 4 "fmt" 5 "net" 6 7 grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" 8 access "github.com/onflow/flow/protobuf/go/flow/executiondata" 9 "github.com/rs/zerolog" 10 "google.golang.org/grpc" 11 12 "github.com/koko1123/flow-go-1/engine/common/rpc" 13 "github.com/koko1123/flow-go-1/model/flow" 14 "github.com/koko1123/flow-go-1/module/component" 15 "github.com/koko1123/flow-go-1/module/executiondatasync/execution_data" 16 "github.com/koko1123/flow-go-1/module/irrecoverable" 17 "github.com/koko1123/flow-go-1/storage" 18 ) 19 20 // Config defines the configurable options for the ingress server. 21 type Config struct { 22 ListenAddr string 23 MaxExecutionDataMsgSize int // in bytes 24 RpcMetricsEnabled bool // enable GRPC metrics 25 } 26 27 // Engine exposes the server with the state stream API. 28 // By default, this engine is not enabled. 29 // In order to run this engine a port for the GRPC server to be served on should be specified in the run config. 30 type Engine struct { 31 *component.ComponentManager 32 log zerolog.Logger 33 backend *StateStreamBackend 34 server *grpc.Server 35 config Config 36 chain flow.Chain 37 handler *Handler 38 39 stateStreamGrpcAddress net.Addr 40 } 41 42 // New returns a new ingress server. 43 func NewEng( 44 config Config, 45 execDataStore execution_data.ExecutionDataStore, 46 headers storage.Headers, 47 seals storage.Seals, 48 results storage.ExecutionResults, 49 log zerolog.Logger, 50 chainID flow.ChainID, 51 apiRatelimits map[string]int, // the api rate limit (max calls per second) for each of the gRPC API e.g. Ping->100, GetExecutionDataByBlockID->300 52 apiBurstLimits map[string]int, // the api burst limit (max calls at the same time) for each of the gRPC API e.g. Ping->50, GetExecutionDataByBlockID->10 53 ) *Engine { 54 // create a GRPC server to serve GRPC clients 55 grpcOpts := []grpc.ServerOption{ 56 grpc.MaxRecvMsgSize(config.MaxExecutionDataMsgSize), 57 grpc.MaxSendMsgSize(config.MaxExecutionDataMsgSize), 58 } 59 60 var interceptors []grpc.UnaryServerInterceptor // ordered list of interceptors 61 // if rpc metrics is enabled, add the grpc metrics interceptor as a server option 62 if config.RpcMetricsEnabled { 63 interceptors = append(interceptors, grpc_prometheus.UnaryServerInterceptor) 64 } 65 66 if len(apiRatelimits) > 0 { 67 // create a rate limit interceptor 68 rateLimitInterceptor := rpc.NewRateLimiterInterceptor(log, apiRatelimits, apiBurstLimits).UnaryServerInterceptor 69 // append the rate limit interceptor to the list of interceptors 70 interceptors = append(interceptors, rateLimitInterceptor) 71 } 72 73 // add the logging interceptor, ensure it is innermost wrapper 74 interceptors = append(interceptors, rpc.LoggingInterceptor(log)...) 75 76 // create a chained unary interceptor 77 chainedInterceptors := grpc.ChainUnaryInterceptor(interceptors...) 78 grpcOpts = append(grpcOpts, chainedInterceptors) 79 80 server := grpc.NewServer(grpcOpts...) 81 82 backend := New(headers, seals, results, execDataStore) 83 84 e := &Engine{ 85 log: log.With().Str("engine", "state_stream_rpc").Logger(), 86 backend: backend, 87 server: server, 88 chain: chainID.Chain(), 89 config: config, 90 handler: NewHandler(backend, chainID.Chain()), 91 } 92 93 e.ComponentManager = component.NewComponentManagerBuilder(). 94 AddWorker(e.serve). 95 Build() 96 access.RegisterExecutionDataAPIServer(e.server, e.handler) 97 98 return e 99 } 100 101 // serve starts the gRPC server. 102 // When this function returns, the server is considered ready. 103 func (e *Engine) serve(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 104 e.log.Info().Str("state_stream_address", e.config.ListenAddr).Msg("starting grpc server on address") 105 l, err := net.Listen("tcp", e.config.ListenAddr) 106 if err != nil { 107 ctx.Throw(fmt.Errorf("error starting grpc server: %w", err)) 108 } 109 110 e.stateStreamGrpcAddress = l.Addr() 111 e.log.Debug().Str("state_stream_address", e.stateStreamGrpcAddress.String()).Msg("listening on port") 112 113 go func() { 114 ready() 115 err = e.server.Serve(l) 116 if err != nil { 117 ctx.Throw(fmt.Errorf("error trying to serve grpc server: %w", err)) 118 } 119 }() 120 121 <-ctx.Done() 122 e.server.GracefulStop() 123 }