gRPC

Features

gRPC extension capabilities

GRPC Interface

The extension exposes a comprehensive GRPC interface for server management:

type GRPC interface {
    RegisterService(desc *grpc.ServiceDesc, impl interface{}) error
    Start(ctx context.Context, addr string) error
    Stop(ctx context.Context) error
    GracefulStop(ctx context.Context) error
    AddUnaryInterceptor(interceptor grpc.UnaryServerInterceptor)
    AddStreamInterceptor(interceptor grpc.StreamServerInterceptor)
    RegisterHealthChecker(service string, checker HealthChecker)
    GetServer() *grpc.Server
    IsRunning() bool
    GetStats() ServerStats
    GetServices() []ServiceInfo
    Ping(ctx context.Context) error
}

Full gRPC Server

A production-ready gRPC server running on a dedicated TCP port with support for all four RPC types:

  • Unary -- single request, single response
  • Server streaming -- single request, stream of responses
  • Client streaming -- stream of requests, single response
  • Bidirectional streaming -- stream of requests and responses
// Register your protobuf service before app.Start()
server.RegisterService(&pb.MyService_ServiceDesc, &myServiceImpl{})

TLS and Mutual TLS

Serve over TLS with configurable certificate, key, and CA files. For zero-trust service-to-service authentication, enable client certificate verification:

forgeGrpc.NewExtension(
    forgeGrpc.WithTLS("server.crt", "server.key", "ca.crt"),
    forgeGrpc.WithClientAuth(true), // require client certificates (mTLS)
)

Health Checks

The standard grpc.health.v1.Health service is registered by default. Register service-specific health checkers:

type HealthChecker interface {
    Check(ctx context.Context) error
}

server.RegisterHealthChecker("my-service", &myChecker{})

Health probes check all registered services and report per-service status.

Server Reflection

Enabled by default for debugging with grpcurl, grpcui, and other reflection-aware tools:

# List services
grpcurl -plaintext localhost:50051 list

# Describe a service
grpcurl -plaintext localhost:50051 describe myapp.Greeter

# Call a method
grpcurl -plaintext -d '{"name":"Alice"}' localhost:50051 myapp.Greeter/SayHello

Interceptors

The extension automatically configures interceptor chains for both unary and streaming RPCs:

Built-in Interceptors

InterceptorPurpose
LoggingLogs every RPC call with method name, duration, and status code
MetricsEmits counters and histograms for RPC calls (request count, latency, errors)
TracingPropagates distributed trace context via OpenTelemetry
RecoveryCatches panics in handlers and returns gRPC Internal status instead of crashing

Custom Interceptors

Add your own interceptors:

// Unary interceptor
server.AddUnaryInterceptor(func(
    ctx context.Context, req interface{},
    info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
) (interface{}, error) {
    log.Printf("Method: %s", info.FullMethod)
    return handler(ctx, req)
})

// Stream interceptor
server.AddStreamInterceptor(func(
    srv interface{}, ss grpc.ServerStream,
    info *grpc.StreamServerInfo, handler grpc.StreamHandler,
) error {
    log.Printf("Stream: %s", info.FullMethod)
    return handler(srv, ss)
})

Keepalive

Configurable server keepalive parameters with enforcement policies for misbehaving clients:

  • Keepalive.Time -- ping interval for idle connections
  • Keepalive.Timeout -- wait time for ping response
  • Keepalive.MinTime -- minimum time between client pings (enforcement)
  • Keepalive.PermitWithoutStream -- allow pings even without active streams

Message Size Limits

Configurable maximum receive and send message sizes (default 4 MB each):

forgeGrpc.NewExtension(
    forgeGrpc.WithMaxMessageSize(16 * 1024 * 1024), // 16 MB
)

Concurrent Stream Limits

Cap the number of concurrent streams per connection with MaxConcurrentStreams to prevent resource exhaustion.

Service Info and Statistics

Query registered services and runtime stats:

// List registered services and methods
services := server.GetServices()
for _, svc := range services {
    fmt.Printf("Service: %s\n", svc.Name)
    for _, method := range svc.Methods {
        fmt.Printf("  %s (client_stream=%v, server_stream=%v)\n",
            method.Name, method.IsClientStream, method.IsServerStream)
    }
}

// Runtime statistics
stats := server.GetStats()
fmt.Printf("Connections: %d, RPCs started: %d, Failed: %d\n",
    stats.TotalConnections, stats.RPCsStarted, stats.RPCsFailed)

Sentinel Errors

ErrorMeaning
ErrNotStartedServer has not been started yet
ErrAlreadyStartedServer is already running
ErrServiceNotFoundRequested gRPC service not registered
ErrInvalidConfigConfiguration validation failed
ErrStartFailedServer failed to start (e.g. port in use)
ErrStopFailedGraceful shutdown failed
ErrHealthCheckFailedHealth check probe failed

How is this guide?

On this page