gRPC Workflow
A step-by-step workflow for building a NestForge gRPC service with tonic, module providers, and optional microservice pattern dispatch.
This is the practical flow behind the maintained gRPC example:
- define the protobuf contract
- register app providers in
AppModule - implement the tonic service
- bootstrap with
NestForgeGrpcFactory - run and verify the service
Step 1: define the protobuf contract
Section titled “Step 1: define the protobuf contract”The gRPC example starts with a normal tonic layout:
proto/ greeter.protosrc/ grpc/ proto/ service.rsYour contract lives in proto/*.proto, and generated bindings are loaded through
tonic::include_proto!(...).
Step 2: register providers in the module
Section titled “Step 2: register providers in the module”The maintained example exports configuration and a pattern registry:
#[module( imports = [], controllers = [], providers = [load_app_config()?, load_grpc_patterns()?], exports = [AppConfig, GrpcPatterns])]pub struct AppModule;This matters because the gRPC transport itself is not where your application state
should live. The service resolves those providers through GrpcContext.
Step 3: implement the tonic service
Section titled “Step 3: implement the tonic service”The gRPC service stores GrpcContext:
#[derive(Clone)]pub struct GreeterGrpcService { ctx: GrpcContext,}
impl GreeterGrpcService { pub fn new(ctx: GrpcContext) -> Self { Self { ctx } }}Then each RPC handler can resolve providers from the NestForge container. In the example the handler delegates into a microservice pattern registry:
let patterns = self.ctx.resolve::<GrpcPatterns>()?;let payload = dispatch_grpc_message( &self.ctx, patterns.registry(), "hello.say", name, TransportMetadata::new().insert("service", "greeter"),).await?;This is the main design pattern to understand:
- tonic is the network edge
- NestForge DI provides application dependencies
- optional microservice patterns provide transport-neutral business logic
Step 4: bootstrap with NestForgeGrpcFactory
Section titled “Step 4: bootstrap with NestForgeGrpcFactory”The example bootstrap is:
NestForgeGrpcFactory::<AppModule>::create()? .with_addr("127.0.0.1:50051") .listen_with(|ctx, addr| async move { nestforge::tonic::transport::Server::builder() .add_service(GreeterServer::new(GreeterGrpcService::new(ctx))) .serve(addr) .await }) .await?;That is the workflow to follow for new services:
- create the NestForge gRPC factory
- choose the address
- construct the tonic server inside
listen_with(...) - inject the provided
GrpcContextinto the service
Step 5: run and verify
Section titled “Step 5: run and verify”Before running, make sure:
- the
grpcfeature is enabled - protobuf generation is wired through your build
protocis available in your environment
Then start the app and verify:
- the server binds on
127.0.0.1:50051 - the RPC handler resolves config or other providers
- the response payload matches the protobuf contract
Good first extension
Section titled “Good first extension”Once the basic service works, the next useful step is moving business behavior into a
MicroserviceRegistry so multiple transports can reuse it.
What to read next
Section titled “What to read next”For the reference overview, see gRPC.