service

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 27 Imported by: 0

README

service

CI CodeQL Coverage Mutation Documentation Go Reference Release Go License

service is a standard-library-first runtime foundation for independently deployed Go services. It coordinates lifecycle, HTTP serving, probes, and cross-cutting hooks without choosing an application architecture, router, logger backend, telemetry SDK, queue, database, or configuration source.

The cohesive API starts its stable release history at v1.0.0.

Design

  • Every goroutine has an owner, cancellation path, and join path.
  • Startup is ordered; rollback and shutdown are reverse ordered and bounded.
  • Lifecycle states and failure causes are explicit and observable.
  • Runtime observation identities are bounded before execution.
  • Each subpackage is independently importable and has no initialization side effects.
  • Optional integrations accept caller-owned values and never own exporters, logging handlers, or configuration loading.

See architecture and lifecycle and ownership for the complete contract. The adoption guides map each supported service shape to a runnable program under examples.

Reference documentation includes the API index, Kubernetes operations, migration, security, performance, and current hardening evidence. Operational integrations are covered by runtime observability and maintenance mode. Explicit owned policy construction, execution scope, lifecycle, and diagnostics are covered by resilience composition. The release evidence matrix maps every material promise to implementation, tests, and public contracts.

Package surface

Package Responsibility
service Typed commands, cohesive construction, lifecycle, signals, supervision, and ordered cleanup
serverhttp Secure HTTP defaults, serving, draining, and middleware
healthhttp Startup, liveness, readiness, and dependency checks
integration Dependency-neutral hooks for caller-owned facilities
servicetest Deterministic lifecycle and probe test utilities

Five-minute service

package main

import (
    "context"
    "os"

    "github.com/faustbrian/go-service"
)

func main() {
    os.Exit(service.Main(service.Definition{
        Identity: service.Identity{Name: "worker"},
        Commands: service.Commands{
            Worker: service.CommandFor(service.CommandSpec[struct{}]{
                Name: "worker",
                Kind: service.CommandKindLongRunning,
                Load: func(
                    context.Context,
                    service.Invocation,
                ) (struct{}, error) {
                    return struct{}{}, nil
                },
                Build: func(
                    context.Context,
                    service.BuildContext,
                    struct{},
                ) (service.Plan, error) {
                    return service.Plan{Tasks: []service.Task{{
                        Name: "worker",
                        Run: func(ctx context.Context) error {
                            <-ctx.Done()

                            return context.Cause(ctx)
                        },
                    }}}, nil
                },
            }),
        },
    }))
}

Save this as main.go, run go mod init example, add the module with go get github.com/faustbrian/go-service, and run it with go run .. Send SIGINT or SIGTERM to stop it. Long-running commands expose /livez, /startupz, and /readyz on 127.0.0.1:8081 by default. Startup follows registration order. Failed startup rolls back only transferred components. Shutdown withdraws readiness, joins supervised tasks, and then stops components in reverse order. The lower-level New, Run, and Wait APIs remain available for direct lifecycle composition.

Supplying Definition.Observer standardizes bounded runtime events while retaining caller ownership of metrics and tracing. Supplying Definition.Maintenance.Store adds down, up, and status, business admission control, and a readiness overlay without changing liveness.

Compatibility

Consumers should pin an exact released version. Breaking API changes require a new major release and explicit migration guidance.

License

MIT. See LICENSE.

Ecosystem

Use the Golib documentation portal to choose companion packages, supported stacks, recipes, and operations guidance.

Documentation

Overview

Package service coordinates service construction, startup, supervision, draining, and shutdown.

Applications may compose this root lifecycle directly or use the focused serverhttp and healthhttp subpackages. Importing service has no side effects.

Index

Examples

Constants

View Source
const (

	// MaxRuntimeIdentityBytes bounds caller-controlled names published as
	// runtime observation boundaries or metric identities.
	MaxRuntimeIdentityBytes = 128
)

Variables

View Source
var (
	// ErrShutdown is the cancellation cause used for an explicit shutdown.
	ErrShutdown = errors.New("service shutdown")
	// ErrInvalidConfig identifies configuration rejected before startup.
	ErrInvalidConfig = errors.New("invalid service configuration")
	// ErrInvalidState identifies an operation rejected by the state machine.
	ErrInvalidState = errors.New("invalid service state")
)
View Source
var ErrInvalidDefinition = errors.New("invalid service definition")

ErrInvalidDefinition identifies a rejected service definition.

View Source
var ErrMaintenance = errors.New("service maintenance failure")

ErrMaintenance identifies a maintenance state or store failure.

View Source
var ErrSignal = errors.New("service signal")

ErrSignal identifies cancellation initiated by a process signal.

Functions

func Execute

func Execute(ctx context.Context, definition Definition, invocation Invocation) int

Execute invokes one command without reading or mutating process globals.

func Main

func Main(definition Definition) int

Main invokes a definition with process arguments, environment, streams, and the platform default signal set. It returns an exit code and never calls os.Exit.

func Run

func Run(ctx context.Context, runtime *Service, config RunConfig) error

Run starts a service, owns an OS signal subscription until shutdown, and stops the service after parent cancellation or the first configured signal.

func RunWithSignals

func RunWithSignals(
	ctx context.Context,
	runtime *Service,
	shutdownTimeout time.Duration,
	signals <-chan os.Signal,
) error

RunWithSignals starts and stops a service using a caller-owned signal channel. It never closes or unregisters the channel.

func Wait

func Wait(ctx context.Context, runtime *Service, config RunConfig) error

Wait waits for cancellation or an owned OS signal and then stops an already started service. It is intended for runtimes that register supervised work between Start and Wait.

func WaitWithSignals

func WaitWithSignals(
	ctx context.Context,
	runtime *Service,
	shutdownTimeout time.Duration,
	signals <-chan os.Signal,
) error

WaitWithSignals waits using a caller-owned signal channel and stops an already started service. It never closes or unregisters the channel.

Types

type BuildContext

type BuildContext struct {
	// Identity identifies the service and selected process role.
	Identity ProcessIdentity
	// Logger is the optional caller-owned logger selected by the definition.
	Logger *slog.Logger
	// Correlation creates identifiers for platform-managed work boundaries.
	Correlation *correlation.Factory
}

BuildContext contains immutable platform-owned construction values.

type Command

type Command struct {
	// contains filtered or unexported fields
}

Command is an immutable command registration produced by CommandFor.

func CommandFor

func CommandFor[C any](spec CommandSpec[C]) Command

CommandFor erases only the immutable command registration while preserving concrete configuration in application callbacks.

type CommandKind

type CommandKind uint8

CommandKind controls long-running and one-shot runtime behavior.

const (
	// CommandKindLongRunning runs until cancellation or a runtime failure.
	CommandKindLongRunning CommandKind = iota + 1
	// CommandKindOneShot runs finite tasks and exits after cleanup.
	CommandKindOneShot
)

type CommandSpec

type CommandSpec[C any] struct {
	// Name is the lowercase kebab-case command token.
	Name string
	// Summary is the one-line help description.
	Summary string
	// Kind determines whether the command is long-running or one-shot.
	Kind CommandKind
	// Options declares bounded command-specific CLI input. Configuration
	// loaders retain the immutable raw invocation for application validation.
	Options []cli.OptionDefinition
	// Load decodes and validates command-specific configuration.
	Load func(context.Context, Invocation) (C, error)
	// Build constructs the owned runtime plan from typed configuration.
	Build func(context.Context, BuildContext, C) (Plan, error)
}

CommandSpec declares typed configuration loading and plan construction.

type Commands

type Commands struct {
	// Serve registers the standard serve role.
	Serve Command
	// Worker registers the standard worker role.
	Worker Command
	// Schedule registers the standard schedule role.
	Schedule Command
	// Migrate registers the standard migrate role.
	Migrate Command
	// Custom contains explicitly named application commands.
	Custom []Command
}

Commands declares standard and application-specific process roles.

type Component

type Component struct {
	// Name is the unique diagnostic name used in typed lifecycle errors.
	Name string
	// CloseAdmission synchronously and idempotently stops new work from entering
	// the component. It runs once when service drain begins, before service-
	// initiated cancellation, and must return promptly. A parent context may
	// already be canceled. Nil is a valid no-op.
	CloseAdmission func() error
	// Start acquires the component resources and transfers ownership only when
	// it returns nil. It must honor context cancellation.
	Start func(context.Context) error
	// Stop releases resources after a successful Start and must honor context
	// cancellation. Nil is a valid no-op.
	Stop func(context.Context) error
}

Component is one named unit of ordered lifecycle work.

type ComponentError

type ComponentError struct {
	// Component is the configured component or supervised task name.
	Component string
	// Operation is the failed lifecycle operation.
	Operation string
	// Err is the original failure and remains available through errors.Is and
	// errors.As.
	Err error
}

ComponentError identifies a failed component operation.

func (*ComponentError) Error

func (err *ComponentError) Error() string

Error implements error.

func (*ComponentError) Unwrap

func (err *ComponentError) Unwrap() error

Unwrap returns the underlying component failure.

type Config

type Config struct {
	// Components start in listed order and stop in reverse successful order.
	Components []Component
	// StartupTimeout bounds context-aware component acquisition. Zero uses the
	// documented default.
	StartupTimeout time.Duration
	// RollbackTimeout bounds the caller's wait after startup failure. Zero uses
	// the documented default.
	RollbackTimeout time.Duration
	// MaxTasks caps concurrently active supervised tasks. Zero uses the
	// documented default.
	MaxTasks int
}

Config describes a Service.

type ConfigError

type ConfigError struct {
	// Field identifies the rejected configuration path.
	Field string
	// Reason describes why Field was rejected without exposing secret values.
	Reason string
}

ConfigError identifies one invalid configuration field.

func (*ConfigError) Error

func (err *ConfigError) Error() string

Error implements error.

func (*ConfigError) Unwrap

func (err *ConfigError) Unwrap() error

Unwrap makes ConfigError inspectable with errors.Is.

type ConfigurationError

type ConfigurationError struct {
	// Command identifies the selected command.
	Command string
	// Err retains the application configuration cause.
	Err error
}

ConfigurationError identifies a selected command configuration failure.

func (*ConfigurationError) Error

func (err *ConfigurationError) Error() string

Error returns a safe configuration diagnostic without formatting its cause.

func (*ConfigurationError) Unwrap

func (err *ConfigurationError) Unwrap() error

Unwrap returns the application configuration failure.

type ConstructionError

type ConstructionError struct {
	// Command identifies the selected command or runtime boundary.
	Command string
	// Err retains the application construction cause.
	Err error
}

ConstructionError identifies selected command plan construction failure.

func (*ConstructionError) Error

func (err *ConstructionError) Error() string

Error returns a safe construction diagnostic without formatting its cause.

func (*ConstructionError) Unwrap

func (err *ConstructionError) Unwrap() error

Unwrap returns the application construction failure.

type Definition

type Definition struct {
	// Identity identifies the deployable service.
	Identity Identity
	// Commands declares every supported process role.
	Commands Commands
	// Logger is caller owned. Nil keeps logging disabled.
	Logger *slog.Logger
	// Observer receives bounded lifecycle, task, probe, and maintenance events.
	Observer RuntimeObserver
	// CorrelationDisclosure controls correlation values included in platform
	// logs. The zero value redacts identifiers.
	CorrelationDisclosure correlation.DisclosurePolicy
	// Correlation is caller owned. Nil selects the correlation default.
	Correlation *correlation.Factory
	// TracePropagation optionally extracts caller-owned trace context after
	// correlation.
	TracePropagation serverhttp.Middleware
	// Management configures the platform-owned operational listener.
	Management Management
	// Maintenance optionally enables shared operational maintenance state,
	// built-in down/up/status commands, readiness withdrawal, and HTTP admission.
	Maintenance Maintenance
}

Definition declares the complete immutable process construction surface.

type DefinitionError

type DefinitionError struct {
	// Field identifies the rejected definition path.
	Field string
	// Reason safely describes the rejected contract.
	Reason string
}

DefinitionError identifies one invalid public definition field.

func (*DefinitionError) Error

func (err *DefinitionError) Error() string

Error returns a safe definition diagnostic.

func (*DefinitionError) Unwrap

func (err *DefinitionError) Unwrap() error

Unwrap makes DefinitionError inspectable with errors.Is.

type FileMaintenanceStore

type FileMaintenanceStore struct {
	// contains filtered or unexported fields
}

FileMaintenanceStore is an atomic file-backed single-host maintenance store. Multiple processes may share it only when the filesystem provides atomic rename and coherent reads for the configured path.

func NewFileMaintenanceStore

func NewFileMaintenanceStore(path string) (*FileMaintenanceStore, error)

NewFileMaintenanceStore constructs an inert file store without touching the filesystem.

func (*FileMaintenanceStore) ClearMaintenance

func (store *FileMaintenanceStore) ClearMaintenance(ctx context.Context) error

ClearMaintenance removes the file snapshot. An absent file is already clear.

func (*FileMaintenanceStore) LoadMaintenance

func (store *FileMaintenanceStore) LoadMaintenance(ctx context.Context) (MaintenanceState, error)

LoadMaintenance reads and validates the complete file snapshot.

func (*FileMaintenanceStore) StoreMaintenance

func (store *FileMaintenanceStore) StoreMaintenance(
	ctx context.Context,
	state MaintenanceState,
) error

StoreMaintenance atomically publishes one enabled file snapshot.

type HTTP

type HTTP struct {
	// Address is bound by the platform. Exactly one of Address and Listener is
	// required.
	Address string
	// Listener transfers ownership after successful plan validation.
	Listener net.Listener
	// Handler owns application routing and protocol behavior.
	Handler http.Handler
	// Options explicitly customize the serverhttp runtime.
	Options []serverhttp.Option
	// TrustCorrelation authenticates an immediate peer before inbound
	// correlation metadata is preserved.
	TrustCorrelation func(*http.Request) bool
	// RejectInvalidCorrelation returns HTTP 400 instead of replacing malformed
	// metadata.
	RejectInvalidCorrelation bool
}

HTTP declares one caller-owned business handler and listener boundary.

type Identity

type Identity struct {
	// Name is the stable lowercase service name.
	Name string
	// Version is the semantic build version, or empty when unavailable.
	Version string
	// Commit is the hexadecimal source revision, or empty when unavailable.
	Commit string
	// BuildTime is an RFC3339 build timestamp, or empty when unavailable.
	BuildTime string
	// GoVersion is the Go toolchain version, or empty when unavailable.
	GoVersion string
	// Environment identifies the deployment environment without becoming a
	// metric label.
	Environment string
	// Instance identifies the process instance without becoming a metric label.
	Instance string
}

Identity describes one deployable service.

type Invocation

type Invocation struct {
	// Args is the tokenized argument list without the process name.
	Args []string
	// Environment is the immutable process-environment snapshot.
	Environment []string
	// Stdout receives help, version, and successful command output.
	Stdout io.Writer
	// Stderr receives one safe terminal diagnostic.
	Stderr io.Writer
	// Signals supplies deterministic cancellation events. Nil follows only the
	// parent context.
	Signals <-chan os.Signal
	// contains filtered or unexported fields
}

Invocation is an immutable in-process command request.

type Maintenance

type Maintenance struct {
	// Store supplies runtime snapshots and the built-in command operations.
	Store MaintenanceStore
	// RefreshInterval controls how often a running process refreshes Store.
	RefreshInterval time.Duration
	// OperationTimeout bounds store operations. Zero selects one second.
	OperationTimeout time.Duration
	// Response optionally renders a caller-owned maintenance body. The platform
	// writes status 503 and maintenance headers before invoking it.
	Response http.Handler
}

Maintenance configures optional runtime maintenance behavior. When Store is set, down, up, and status commands are reserved and every long-running role polls the store, withdraws readiness, and gates business HTTP.

type MaintenanceError

type MaintenanceError struct {
	// Operation is the bounded operation name.
	Operation string
	// Err preserves the cause without formatting it.
	Err error
}

MaintenanceError identifies one safe maintenance operation failure.

func (*MaintenanceError) Error

func (err *MaintenanceError) Error() string

Error returns a secret-safe maintenance diagnostic.

func (*MaintenanceError) Unwrap

func (err *MaintenanceError) Unwrap() []error

Unwrap preserves both the stable classification and the operation cause.

type MaintenanceSource

type MaintenanceSource interface {
	// LoadMaintenance returns the latest complete snapshot.
	LoadMaintenance(context.Context) (MaintenanceState, error)
}

MaintenanceSource loads an immutable maintenance snapshot. Implementations must honor context cancellation and publish snapshots atomically.

type MaintenanceState

type MaintenanceState struct {
	// Enabled controls business admission and readiness.
	Enabled bool
	// Since records when maintenance was enabled.
	Since time.Time
	// RetryAfter becomes the Retry-After response header.
	RetryAfter time.Duration
	// Refresh becomes the Refresh response header.
	Refresh time.Duration
	// Redirect is an optional absolute-path redirect.
	Redirect string
	// Secret is an optional URL-safe bypass token. It is never rendered by
	// status output, errors, logs, or runtime events.
	Secret string
}

MaintenanceState is one immutable maintenance publication.

type MaintenanceStore

type MaintenanceStore interface {
	MaintenanceSource
	// StoreMaintenance atomically publishes an enabled snapshot.
	StoreMaintenance(context.Context, MaintenanceState) error
	// ClearMaintenance atomically disables maintenance.
	ClearMaintenance(context.Context) error
}

MaintenanceStore controls maintenance mode and also supplies runtime state. A shared database or cache adapter can implement this interface without creating a dependency from service to that backend.

func NewSharedMaintenanceStore

func NewSharedMaintenanceStore(operations MaintenanceStoreOperations) (MaintenanceStore, error)

NewSharedMaintenanceStore validates and adapts a caller-owned multi-instance storage implementation.

type MaintenanceStoreOperations

type MaintenanceStoreOperations struct {
	// Load reads the latest complete caller-owned snapshot.
	Load func(context.Context) (MaintenanceState, error)
	// Store atomically publishes an enabled caller-owned snapshot.
	Store func(context.Context, MaintenanceState) error
	// Clear atomically disables the caller-owned snapshot.
	Clear func(context.Context) error
}

MaintenanceStoreOperations adapts caller-owned shared storage operations.

type Management

type Management struct {
	// Address is bound by the platform. Empty with no Listener selects
	// 127.0.0.1:8081.
	Address string
	// Listener transfers ownership after successful plan validation.
	Listener net.Listener
	// Details enables bounded check names and binary statuses.
	Details bool
	// TrustCorrelation authenticates an immediate peer before inbound
	// correlation metadata is preserved.
	TrustCorrelation func(*http.Request) bool
	// RejectInvalidCorrelation returns HTTP 400 instead of replacing malformed
	// metadata.
	RejectInvalidCorrelation bool
}

Management configures the platform-owned operational listener.

type PanicError

type PanicError struct {
	// Component is the component or supervised task that panicked.
	Component string
	// Operation is the lifecycle operation that panicked.
	Operation string
	// Value is the recovered panic value. Error deliberately does not format it.
	Value any
}

PanicError reports a recovered component panic without formatting its value into an error string that may be logged or returned externally.

func (*PanicError) Error

func (err *PanicError) Error() string

Error implements error without disclosing the recovered value.

type Plan

type Plan struct {
	// Components start in declaration order and stop in reverse order.
	Components []Component
	// Tasks are finite one-shot work or supervised long-running work.
	Tasks []Task
	// HTTP optionally declares one business HTTP listener for a long-running
	// command.
	HTTP *HTTP
	// Readiness contains only dependencies required to accept new work.
	Readiness []ReadinessCheck
	// Management explicitly enables probes for a one-shot command. It is
	// ignored for long-running commands, which always expose probes.
	Management bool
	// ManagementConfig overrides the definition-level management listener for
	// the selected plan. The platform snapshots the pointed-to value.
	ManagementConfig *Management
}

Plan declares resources and work owned by the selected command.

type ProcessIdentity

type ProcessIdentity struct {
	Identity
	// Role is the selected command name.
	Role string
}

ProcessIdentity is the service identity for one selected process role.

type ReadinessCheck

type ReadinessCheck struct {
	// Name is the unique secret-safe dependency name.
	Name string
	// Run evaluates whether the dependency can accept new work.
	Run func(context.Context) error
}

ReadinessCheck is one named dependency required to accept new work.

type RunConfig

type RunConfig struct {
	// Signals is the set that initiates shutdown. Empty uses platform defaults.
	Signals []os.Signal
	// ShutdownTimeout bounds cleanup after cancellation. Zero uses the
	// documented default.
	ShutdownTimeout time.Duration
}

RunConfig controls process signal handling and the shutdown bound.

type RuntimeEvent

type RuntimeEvent struct {
	// Kind identifies the platform boundary.
	Kind RuntimeEventKind
	// Result is the bounded outcome classification.
	Result RuntimeEventResult
	// Identity identifies the service process and selected role.
	Identity ProcessIdentity
	// Boundary names the validated component, task, probe, or store boundary.
	Boundary string
	// Duration is the measured operation duration when applicable.
	Duration time.Duration
	// Transition reports an availability or lifecycle state transition.
	Transition bool
	// Method is a bounded HTTP method for request events only.
	Method string
	// Status is an HTTP response status for request events only.
	Status int
	// At is the event publication time.
	At time.Time
}

RuntimeEvent is a bounded, secret-safe platform observation. Boundary is a validated component, task, probe, or maintenance-store name. Identity values are suitable for logs and telemetry resources; Environment and Instance must not be used as metric labels.

type RuntimeEventKind

type RuntimeEventKind string

RuntimeEventKind identifies one bounded platform-managed runtime boundary.

const (
	// RuntimeEventStartup reports process startup boundaries.
	RuntimeEventStartup RuntimeEventKind = "startup"
	// RuntimeEventConstruction reports selected-role configuration and plan construction.
	RuntimeEventConstruction RuntimeEventKind = "construction"
	// RuntimeEventReadiness reports readiness availability transitions.
	RuntimeEventReadiness RuntimeEventKind = "readiness"
	// RuntimeEventDrain reports the beginning of graceful drain.
	RuntimeEventDrain RuntimeEventKind = "drain"
	// RuntimeEventShutdown reports bounded shutdown completion.
	RuntimeEventShutdown RuntimeEventKind = "shutdown"
	// RuntimeEventTask reports platform-supervised task execution.
	RuntimeEventTask RuntimeEventKind = "task"
	// RuntimeEventComponentStart reports owned component initialization.
	RuntimeEventComponentStart RuntimeEventKind = "component-start"
	// RuntimeEventComponentStop reports owned component cleanup.
	RuntimeEventComponentStop RuntimeEventKind = "component-stop"
	// RuntimeEventProbe reports one management probe result.
	RuntimeEventProbe RuntimeEventKind = "probe"
	// RuntimeEventMaintenance reports maintenance-state changes or refresh failures.
	RuntimeEventMaintenance RuntimeEventKind = "maintenance"
	// RuntimeEventRequest reports one platform-managed business HTTP request.
	RuntimeEventRequest RuntimeEventKind = "request"
)

type RuntimeEventResult

type RuntimeEventResult string

RuntimeEventResult is the bounded result vocabulary used by runtime events.

const (
	// RuntimeResultStarted reports the beginning of owned work.
	RuntimeResultStarted RuntimeEventResult = "started"
	// RuntimeResultSucceeded reports successful completion.
	RuntimeResultSucceeded RuntimeEventResult = "succeeded"
	// RuntimeResultFailed reports failure without exposing its cause.
	RuntimeResultFailed RuntimeEventResult = "failed"
	// RuntimeResultAvailable reports an available readiness or probe state.
	RuntimeResultAvailable RuntimeEventResult = "available"
	// RuntimeResultUnavailable reports an unavailable readiness or probe state.
	RuntimeResultUnavailable RuntimeEventResult = "unavailable"
)

type RuntimeObserver

type RuntimeObserver interface {
	// ObserveRuntime receives one completed bounded platform observation.
	ObserveRuntime(context.Context, RuntimeEvent)
}

RuntimeObserver receives synchronous low-volume platform observations. An implementation must handle concurrent calls, return promptly, and must not panic. The platform contains panics and never transfers ownership of the observer.

type RuntimeObserverFunc

type RuntimeObserverFunc func(context.Context, RuntimeEvent)

RuntimeObserverFunc adapts a function to RuntimeObserver.

func (RuntimeObserverFunc) ObserveRuntime

func (observe RuntimeObserverFunc) ObserveRuntime(ctx context.Context, event RuntimeEvent)

ObserveRuntime invokes the adapted observer.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service coordinates the components it owns.

Example
package main

import (
	"context"
	"fmt"

	"github.com/faustbrian/go-service"
)

func main() {
	runtime, err := service.New(service.Config{
		Components: []service.Component{{
			Name:  "worker",
			Start: func(context.Context) error { return nil },
			Stop:  func(context.Context) error { return nil },
		}},
	})
	if err != nil {
		panic(err)
	}
	if err := runtime.Start(context.Background()); err != nil {
		panic(err)
	}
	fmt.Println(runtime.State())
	if err := runtime.Shutdown(context.Background()); err != nil {
		panic(err)
	}
	fmt.Println(runtime.State())
}
Output:
ready
stopped

func New

func New(config Config) (*Service, error)

New constructs a service without starting background work.

func (*Service) Context

func (service *Service) Context() context.Context

Context returns the service-owned context, or context.Background before startup.

func (*Service) Drain

func (service *Service) Drain() error

Drain marks a ready service as unavailable and closes component admission in reverse startup order. Concurrent and repeated calls share one result.

func (*Service) Go

func (service *Service) Go(
	name string,
	task func(context.Context) error,
) error

Go starts one named supervised task. The task receives the service context and must return after cancellation. An error or panic cancels the service and moves a ready service to draining. An error matching the canceled task context or its cause is a normal shutdown result. Shutdown joins every supervised task.

func (*Service) Ready

func (service *Service) Ready() bool

Ready reports whether every component is started and the service is still accepting new work.

func (*Service) Shutdown

func (service *Service) Shutdown(ctx context.Context) error

Shutdown cancels the service and stops components in reverse startup order.

func (*Service) Start

func (service *Service) Start(parent context.Context) error

Start starts components in registration order.

func (*Service) StartupComplete

func (service *Service) StartupComplete() bool

StartupComplete reports whether component startup completed successfully. It remains true while the service drains and stops.

func (*Service) State

func (service *Service) State() State

State returns the current lifecycle state.

type ShutdownError

type ShutdownError struct {
	// Failures contains component and supervised-task failures in observation
	// order.
	Failures []error
}

ShutdownError aggregates every component and supervised-task failure observed while stopping a service.

func (*ShutdownError) Error

func (err *ShutdownError) Error() string

Error implements error without flattening failure details into one string.

func (*ShutdownError) Unwrap

func (err *ShutdownError) Unwrap() []error

Unwrap exposes every shutdown failure to errors.Is and errors.As.

type ShutdownTimeoutError

type ShutdownTimeoutError struct {
	// Err retains the deadline cause.
	Err error
}

ShutdownTimeoutError identifies cleanup that exceeded its finite budget.

func (*ShutdownTimeoutError) Error

func (err *ShutdownTimeoutError) Error() string

Error returns a stable shutdown-timeout diagnostic.

func (*ShutdownTimeoutError) Unwrap

func (err *ShutdownTimeoutError) Unwrap() error

Unwrap returns the deadline cause.

type SignalError

type SignalError struct {
	// Signal is the process signal that initiated cancellation.
	Signal os.Signal
}

SignalError records the signal that initiated shutdown.

func (*SignalError) Error

func (err *SignalError) Error() string

Error implements error.

func (*SignalError) Unwrap

func (err *SignalError) Unwrap() error

Unwrap makes SignalError inspectable with errors.Is.

type StartupError

type StartupError struct {
	// Component identifies the component whose startup failed.
	Component string
	// Err is the startup failure.
	Err error
	// Rollback contains every retained reverse-cleanup failure.
	Rollback []error
}

StartupError reports a component start failure and every rollback failure.

func (*StartupError) Error

func (err *StartupError) Error() string

Error implements error.

func (*StartupError) Unwrap

func (err *StartupError) Unwrap() []error

Unwrap exposes the startup and rollback failures to errors.Is and errors.As.

type State

type State uint8

State is a service lifecycle state.

const (
	// StateNew is the initial state before startup begins.
	StateNew State = iota
	// StateStarting means components are starting.
	StateStarting
	// StateReady means every component started successfully.
	StateReady
	// StateDraining means new work should no longer be accepted.
	StateDraining
	// StateStopping means owned components are stopping.
	StateStopping
	// StateStopped is the terminal lifecycle state.
	StateStopped
)

func (State) String

func (state State) String() string

String returns the stable machine-readable state name.

type StateError

type StateError struct {
	// Operation is the rejected lifecycle operation.
	Operation string
	// State is the lifecycle state in which Operation was rejected.
	State State
}

StateError reports an operation that is invalid in the current state.

func (*StateError) Error

func (err *StateError) Error() string

Error implements error.

func (*StateError) Unwrap

func (err *StateError) Unwrap() error

Unwrap makes StateError inspectable with errors.Is.

type Task

type Task struct {
	// Name is the unique secret-safe diagnostic name.
	Name string
	// Run executes owned work and must honor context cancellation.
	Run func(context.Context) error
}

Task is one named owned unit of application work.

Directories

Path Synopsis
examples
http-api command
ingester command
migration command
mixed-role command
rpc command
worker command
Package healthhttp provides stable HTTP liveness, startup, and readiness probes with bounded dependency checks.
Package healthhttp provides stable HTTP liveness, startup, and readiness probes with bounded dependency checks.
Package integration adapts caller-owned startup and shutdown hooks into the service lifecycle without owning their implementations or providers.
Package integration adapts caller-owned startup and shutdown hooks into the service lifecycle without owning their implementations or providers.
Package serverhttp provides an owned standard-library HTTP server runtime.
Package serverhttp provides an owned standard-library HTTP server runtime.
Package servicetest provides deterministic lifecycle and HTTP probe test utilities without timing sleeps.
Package servicetest provides deterministic lifecycle and HTTP probe test utilities without timing sleeps.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL