Documentation
¶
Overview ¶
Package grpc provides an opinionated gRPC server wrapper that implements lifecycle.Runner. It standardises functional options, panic recovery, OpenTelemetry stats handler wiring, and a context-bounded graceful shutdown.
The package mirrors the API shape of core/http2 — same option-style, same Run/Shutdown contract, same registration pattern with app.App — so a service that uses both feels uniform.
Typical usage:
srv := grpc.NewServer(grpc.Config{Port: "50051"},
grpc.WithOtel(),
grpc.WithRecovery(),
)
srv.Mount(func(s *grpc.Server) {
pb.RegisterMyServiceServer(s, myImpl)
})
a := app.New()
a.Add(srv)
log.Fatal(a.Run())
Index ¶
- Variables
- type Config
- type Option
- func WithHealthService(checker lifecycle.Healthchecker) Option
- func WithListener(l net.Listener) Option
- func WithLogger(l *slog.Logger) Option
- func WithOtel() Option
- func WithRecovery() Option
- func WithServerOptions(opts ...grpc.ServerOption) Option
- func WithStatsHandler(h stats.Handler) Option
- func WithStreamInterceptor(interceptors ...grpc.StreamServerInterceptor) Option
- func WithUnaryInterceptor(interceptors ...grpc.UnaryServerInterceptor) Option
- type Server
Constants ¶
This section is empty.
Variables ¶
var ErrServerAlreadyStarted = errors.New("grpc: server already started")
ErrServerAlreadyStarted is returned by Server.Run if the server has already been started. A Server instance is single-use: the underlying grpc.Server cannot be reused after GracefulStop.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Port is the TCP port the listener binds to. Default: "50051".
Port string
// ShutdownTimeout caps the graceful shutdown phase. After it elapses,
// the server is force-stopped via grpc.Server.Stop. Default: 10s.
ShutdownTimeout time.Duration
}
Config holds the server's network and timeout settings. Both fields are optional — zero values are replaced with defaults in NewServer.
type Option ¶ added in v1.3.0
type Option func(*options)
Option configures a new Server. Mirrors the functional-options pattern used by http2.Server for symmetric setup.
func WithHealthService ¶ added in v1.3.0
func WithHealthService(checker lifecycle.Healthchecker) Option
WithHealthService registers a grpc.health.v1 service on the server that reports SERVING/NOT_SERVING based on the given Healthchecker (typically an *app.App).
Works with Envoy / k8s gRPC health probes. For HTTP-style probes use http2.WithHealthcheckFrom on the HTTP server instead.
func WithListener ¶ added in v1.3.0
WithListener overrides the default TCP listener. Useful for tests (net.Listen on :0, bufconn) or for exposing the server on a unix socket.
Promoted from a method to an option in v2 for consistency with http2.
func WithLogger ¶ added in v1.3.0
WithLogger attaches a *slog.Logger to the server. Used by the recovery interceptor and lifecycle events. Defaults to slog.Default() when omitted.
func WithOtel ¶ added in v1.3.0
func WithOtel() Option
WithOtel enables OpenTelemetry instrumentation by registering otelgrpc.NewServerHandler as a stats.Handler. Uses the global tracer and meter providers, so otel.Setup must have run and its Provider must be registered with app.App before NewServer is called.
Equivalent to: WithStatsHandler(otelgrpc.NewServerHandler()).
func WithRecovery ¶ added in v1.3.0
func WithRecovery() Option
WithRecovery installs panic-recovery interceptors for both unary and stream RPCs. A panic is logged with stack trace via the configured slog logger and returned to the client as codes.Internal.
Recommended for every production server.
func WithServerOptions ¶ added in v1.3.0
func WithServerOptions(opts ...grpc.ServerOption) Option
WithServerOptions passes arbitrary grpc.ServerOption values through. Escape hatch for keepalive, TLS credentials, message size limits, etc.
Composes with the typed With* options — both are applied to the same underlying *grpc.Server.
func WithStatsHandler ¶ added in v1.3.0
WithStatsHandler attaches a stats.Handler. Multiple calls accumulate and every handler receives every event, fanned out via an internal composite (see stats.go). This is preferable to passing multiple grpc.StatsHandler options directly, where ordering and override semantics are ambiguous.
func WithStreamInterceptor ¶ added in v1.3.0
func WithStreamInterceptor(interceptors ...grpc.StreamServerInterceptor) Option
WithStreamInterceptor appends stream interceptors. Chained in registration order via grpc.ChainStreamInterceptor. See WithUnaryInterceptor for ordering rules.
func WithUnaryInterceptor ¶ added in v1.3.0
func WithUnaryInterceptor(interceptors ...grpc.UnaryServerInterceptor) Option
WithUnaryInterceptor appends unary interceptors. Multiple calls accumulate and are chained in registration order via grpc.ChainUnaryInterceptor. This is the gRPC analogue of http2.Server.WithMiddleware.
Built-in interceptors (WithRecovery) are appended AFTER user interceptors so they sit innermost — closest to the handler — and catch panics from user-interceptor work.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server wraps a *grpc.Server with lifecycle methods. Implements lifecycle.Runner so it can be registered with app.App.
func NewServer ¶
NewServer constructs a Server with the given Config and options. Zero values in cfg are replaced with defaults. The returned *Server implements lifecycle.Runner — register it with app.App.
func (*Server) Mount ¶
Mount registers services on the underlying *grpc.Server. The provided callback receives the *grpc.Server so generated RegisterXxxServer functions can attach implementations.
Mount must be called before Run; calling concurrently with Run is undefined behavior.
func (*Server) Run ¶
Run blocks until ctx is cancelled or the server fails. On ctx cancellation, Shutdown is called with a fresh ShutdownTimeout context (NOT the already-cancelled ctx).
Implements lifecycle.Runner.
Run must be called at most once per Server instance — the underlying grpc.Server cannot be reused after GracefulStop. A second call returns ErrServerAlreadyStarted.