Documentation
¶
Overview ¶
Package service provides abstractions for microservice lifecycle management. It supports unified lifecycle for HTTP and gRPC servers with graceful shutdown, signal handling, and cleanup hooks.
Example usage:
// Create HTTP service
httpSvc := service.NewHTTPService("my-service", ":8080", handler,
service.WithReadTimeout(10*time.Second),
service.WithShutdownTimeout(30*time.Second),
)
// Start service
if err := httpSvc.Start(ctx); err != nil {
log.Fatal(err)
}
// Wait for shutdown signal
service.WaitForShutdown(ctx, httpSvc)
Index ¶
- func WaitForShutdown(ctx context.Context, services ...Service)
- func WaitForShutdownWithConfig(ctx context.Context, cfg ShutdownConfig, services ...Service)
- func WithShutdownHandler(ctx context.Context, svc Service) error
- type Bootstrap
- type BootstrapOption
- type CleanupFunc
- type CleanupHandler
- type GRPCService
- type GRPCServiceOption
- type HTTPService
- type HTTPServiceOption
- type Service
- type ShutdownConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func WaitForShutdown ¶
WaitForShutdown blocks until a shutdown signal is received, then gracefully stops the provided services. It handles SIGINT and SIGTERM by default.
Services are stopped in the order provided. If a service fails to stop within the timeout, the error is logged but shutdown continues for remaining services.
Example:
httpSvc := service.NewHTTPService("api", ":8080", handler)
if err := httpSvc.Start(ctx); err != nil {
log.Fatal(err)
}
// Block until shutdown signal
service.WaitForShutdown(ctx, httpSvc)
func WaitForShutdownWithConfig ¶
func WaitForShutdownWithConfig(ctx context.Context, cfg ShutdownConfig, services ...Service)
WaitForShutdownWithConfig is like WaitForShutdown but accepts custom shutdown configuration.
Example:
cfg := service.ShutdownConfig{
Timeout: 60 * time.Second,
Signals: []os.Signal{syscall.SIGTERM},
}
service.WaitForShutdownWithConfig(ctx, cfg, httpSvc, grpcSvc)
func WithShutdownHandler ¶
WithShutdownHandler wraps a service with automatic signal-based shutdown. It starts the service and blocks until a shutdown signal is received.
Example:
svc := service.NewHTTPService("api", ":8080", handler)
if err := service.WithShutdownHandler(ctx, svc); err != nil {
log.Fatal(err)
}
Types ¶
type Bootstrap ¶
type Bootstrap struct {
Config *config.Config
Logger *logging.Logger
TracerProvider *sdktrace.TracerProvider
// contains filtered or unexported fields
}
Bootstrap represents initialized infrastructure components. It provides convenient access to all observability components.
func NewBootstrap ¶
func NewBootstrap(ctx context.Context, cfg *config.Config, opts ...BootstrapOption) (*Bootstrap, error)
NewBootstrap initializes all observability components from configuration. It creates logger, metrics, and tracing infrastructure in the correct order with appropriate error handling.
Example:
cfg := config.MustLoad("config.yaml", "MYAPP")
bootstrap, err := service.NewBootstrap(ctx, cfg)
if err != nil {
log.Fatal(err)
}
defer bootstrap.Cleanup(ctx)
// Use bootstrap.Logger, bootstrap.Tracer, etc.
func (*Bootstrap) AddCleanup ¶
AddCleanup adds a cleanup function to be executed during Cleanup. Cleanup functions are executed in reverse order (LIFO).
Example:
bootstrap.AddCleanup(func(ctx context.Context) error {
return db.Close()
})
type BootstrapOption ¶
type BootstrapOption func(*bootstrapConfig)
BootstrapOption is a functional option for configuring bootstrap behavior.
func WithoutLogger ¶
func WithoutLogger() BootstrapOption
WithoutLogger disables logger initialization during bootstrap. This is rarely needed but can be useful for testing.
func WithoutMetrics ¶
func WithoutMetrics() BootstrapOption
WithoutMetrics disables metrics initialization during bootstrap.
func WithoutTracing ¶
func WithoutTracing() BootstrapOption
WithoutTracing disables tracing initialization during bootstrap.
type CleanupFunc ¶
CleanupFunc represents a cleanup function to be executed during shutdown.
type CleanupHandler ¶
type CleanupHandler struct {
// contains filtered or unexported fields
}
CleanupHandler manages cleanup functions that should be executed during shutdown. Cleanup functions are executed in LIFO order (last registered, first executed).
func NewCleanupHandler ¶
func NewCleanupHandler() *CleanupHandler
NewCleanupHandler creates a new cleanup handler.
func (*CleanupHandler) Execute ¶
func (h *CleanupHandler) Execute(ctx context.Context) error
Execute runs all registered cleanup functions in reverse order (LIFO). It continues executing cleanup functions even if some fail, collecting all errors. Returns the first error encountered, but logs all errors.
func (*CleanupHandler) Register ¶
func (h *CleanupHandler) Register(fn CleanupFunc)
Register adds a cleanup function to be executed during shutdown. Cleanup functions are executed in reverse order (LIFO).
Example:
cleanup := service.NewCleanupHandler()
cleanup.Register(func(ctx context.Context) error {
return db.Close()
})
cleanup.Register(func(ctx context.Context) error {
return cache.Close()
})
defer cleanup.Execute(ctx)
type GRPCService ¶
type GRPCService struct {
// contains filtered or unexported fields
}
GRPCService implements the Service interface for gRPC servers. It manages the lifecycle of a gRPC server with graceful shutdown.
func NewGRPCService ¶
func NewGRPCService(name, addr string, registerFunc func(*grpc.Server), opts ...GRPCServiceOption) *GRPCService
NewGRPCService creates a new gRPC service with the provided configuration. The registerFunc is called with the gRPC server to register service implementations.
Example:
svc := service.NewGRPCService("grpc-server", ":9090",
func(s *grpc.Server) {
pb.RegisterMyServiceServer(s, &myServiceImpl{})
},
service.WithReflection(true),
service.WithGRPCShutdownTimeout(30*time.Second),
)
func NewGRPCServiceWithServer ¶
func NewGRPCServiceWithServer(name, addr string, server *grpc.Server, opts ...GRPCServiceOption) *GRPCService
NewGRPCServiceWithServer creates a new gRPC service using an existing gRPC server. This is useful when you need to configure the gRPC server with specific interceptors or other options before creating the service.
Example:
grpcServer := grpc.NewServer(
grpc.UnaryInterceptor(myInterceptor),
)
svc := service.NewGRPCServiceWithServer("grpc-server", ":9090", grpcServer,
service.WithGRPCShutdownTimeout(30*time.Second),
)
func (*GRPCService) Health ¶
func (s *GRPCService) Health() error
Health checks if the gRPC server is running. Returns nil if healthy, error if not running.
func (*GRPCService) Server ¶
func (s *GRPCService) Server() *grpc.Server
Server returns the underlying gRPC server. This is useful for testing or advanced configuration.
type GRPCServiceOption ¶
type GRPCServiceOption func(*GRPCService)
GRPCServiceOption is a functional option for configuring a GRPCService.
func WithGRPCShutdownTimeout ¶
func WithGRPCShutdownTimeout(timeout time.Duration) GRPCServiceOption
WithGRPCShutdownTimeout sets the graceful shutdown timeout for the gRPC server.
func WithReflection ¶
func WithReflection(enable bool) GRPCServiceOption
WithReflection enables gRPC reflection for the server. This allows tools like grpcurl to introspect the service.
type HTTPService ¶
type HTTPService struct {
// contains filtered or unexported fields
}
HTTPService implements the Service interface for HTTP servers. It manages the lifecycle of an HTTP server with graceful shutdown.
func NewHTTPService ¶
func NewHTTPService(name, addr string, handler http.Handler, opts ...HTTPServiceOption) *HTTPService
NewHTTPService creates a new HTTP service with the provided configuration. The handler will be invoked for all incoming HTTP requests.
Example:
mux := http.NewServeMux()
mux.HandleFunc("/health", healthHandler)
svc := service.NewHTTPService("api-server", ":8080", mux,
service.WithShutdownTimeout(30*time.Second),
)
func (*HTTPService) Health ¶
func (s *HTTPService) Health() error
Health checks if the HTTP server is running. Returns nil if healthy, error if not running.
type HTTPServiceOption ¶
type HTTPServiceOption func(*HTTPService)
HTTPServiceOption is a functional option for configuring an HTTPService.
func WithMaxHeaderBytes ¶
func WithMaxHeaderBytes(bytes int) HTTPServiceOption
WithMaxHeaderBytes sets the maximum header bytes for the HTTP server.
func WithReadTimeout ¶
func WithReadTimeout(timeout time.Duration) HTTPServiceOption
WithReadTimeout sets the HTTP server read timeout.
func WithShutdownTimeout ¶
func WithShutdownTimeout(timeout time.Duration) HTTPServiceOption
WithShutdownTimeout sets the graceful shutdown timeout.
func WithWriteTimeout ¶
func WithWriteTimeout(timeout time.Duration) HTTPServiceOption
WithWriteTimeout sets the HTTP server write timeout.
type Service ¶
type Service interface {
// Start starts the service and blocks until the service is ready.
// Returns an error if the service fails to start.
// The context can be used to cancel startup if needed.
Start(ctx context.Context) error
// Stop gracefully stops the service, waiting for in-flight requests to complete.
// Returns an error if the service fails to stop within the timeout.
// The context deadline determines how long to wait for graceful shutdown.
Stop(ctx context.Context) error
// Name returns the name of the service for logging and identification.
Name() string
// Health performs a health check on the service.
// Returns nil if the service is healthy, or an error describing the problem.
Health() error
}
Service represents a service that can be started, stopped, and health-checked. It provides a unified interface for HTTP and gRPC servers.
type ShutdownConfig ¶
type ShutdownConfig struct {
// Timeout is the maximum time to wait for graceful shutdown.
// After this timeout, services are forcefully stopped.
Timeout time.Duration
// Signals is the list of OS signals that trigger shutdown.
// If empty, defaults to SIGINT and SIGTERM.
Signals []os.Signal
}
ShutdownConfig configures graceful shutdown behavior.
func DefaultShutdownConfig ¶
func DefaultShutdownConfig() ShutdownConfig
DefaultShutdownConfig returns sensible default shutdown configuration.