bootstrap

package
v0.3.0-alpha.1 Latest Latest
Warning

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

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

README

bootstrap

Application bootstrap framework with lifecycle hooks, component registration, and startup summary.

Install

go get github.com/kbukum/gokit

Quick Start — Server

Use Run() for long-running services that block until a shutdown signal:

import (
    "context"
    gkconfig "github.com/kbukum/gokit/config"
    "github.com/kbukum/gokit/bootstrap"
)

func main() {
    var cfg MyConfig
    gkconfig.LoadConfig("my-service", &cfg)

    app, _ := bootstrap.NewApp(&cfg)
    app.OnConfigure(func(ctx context.Context, a *bootstrap.App[*MyConfig]) error {
        // Wire services, register routes, etc.
        return nil
    })

    app.Run(context.Background()) // blocks until SIGINT/SIGTERM
}

Quick Start — Task / CLI

Use RunTask() for CLI tools, batch jobs, and one-shot processes:

func main() {
    var cfg MyConfig
    gkconfig.LoadConfig("my-tool", &cfg)

    app, _ := bootstrap.NewApp(&cfg)
    app.OnConfigure(func(ctx context.Context, a *bootstrap.App[*MyConfig]) error {
        // Wire dependencies
        return nil
    })

    app.RunTask(context.Background(), func(ctx context.Context) error {
        return processData(ctx) // runs to completion, then shuts down
    })
}

Both modes share the same lifecycle: Initialize → OnStart → Configure → ReadyCheck → OnReady → (execute) → OnStop → Shutdown.

Key Types & Functions

Name Description
App[C] Generic application container with lifecycle management
NewApp[C]() Create app from typed config (must satisfy Config interface)
Run() Start long-running service with signal handling
RunTask() Execute a finite task with signal-based cancellation
OnConfigure() / OnStart() / OnReady() / OnStop() Lifecycle hooks
RegisterComponent() Add a managed component
WithLogger() / WithGracefulTimeout() / WithContainer() App options
Summary Tracks and displays startup summary

⬅ Back to main README

Documentation

Overview

Package bootstrap orchestrates application lifecycle for gokit services.

It provides typed configuration loading, component registration, dependency injection, and startup/shutdown hooks for rapid service initialization.

Two execution modes are supported:

  • Run: for long-running services that block until a shutdown signal
  • RunTask: for CLI tools and batch jobs that execute a finite task

Server Example

app, _ := bootstrap.NewApp(&cfg)
app.OnConfigure(func(ctx context.Context, a *bootstrap.App[*MyConfig]) error {
    // wire up services, routes, etc.
    return nil
})
app.Run(ctx) // blocks until SIGINT/SIGTERM

Task Example

app, _ := bootstrap.NewApp(&cfg)
app.RunTask(ctx, func(ctx context.Context) error {
    return processData(ctx) // runs to completion, then shuts down
})

Index

Constants

This section is empty.

Variables

View Source
var (
	EventStart = hook.EventType("bootstrap:start")
	EventReady = hook.EventType("bootstrap:ready")
	EventStop  = hook.EventType("bootstrap:stop")
)

Lifecycle event types used with the hook registry.

Functions

This section is empty.

Types

type App

type App[C Config] struct {
	Name       string
	Version    string
	Cfg        C
	Container  *di.Container
	Components *component.Registry
	Logger     *logging.Logger
	Summary    *Summary
	// contains filtered or unexported fields
}

App represents a generic application with uniform lifecycle management. The type parameter C is the config type, which must satisfy the Config interface. Any struct embedding config.ServiceConfig automatically satisfies Config.

Example:

app, err := bootstrap.NewApp(&myConfig)
app.OnConfigure(func(ctx context.Context, a *bootstrap.App[*MyConfig]) error {
    // a.Cfg is *MyConfig — fully typed
    return nil
})
app.Run(context.Background())

func NewApp

func NewApp[C Config](cfg C, opts ...Option) (*App[C], error)

NewApp creates a new application instance from a typed config. It applies defaults, validates the config, and initializes the logging.

func (*App[C]) DisplaySummary

func (a *App[C]) DisplaySummary()

DisplaySummary prints the startup summary. It auto-collects infrastructure, routes, and health from the component registry and DI container.

func (*App[C]) OnConfigure

func (a *App[C]) OnConfigure(fn func(ctx context.Context, app *App[C]) error)

OnConfigure registers a callback to run during the configure phase. Use this to set up business-layer dependencies after infrastructure is started.

func (*App[C]) OnReady

func (a *App[C]) OnReady(hooks ...Hook)

OnReady registers a hook that runs after the application passes its ready check and is about to begin accepting traffic.

func (*App[C]) OnStart

func (a *App[C]) OnStart(hooks ...Hook)

OnStart registers a hook that runs after all components are started but before the application is marked as ready.

func (*App[C]) OnStop

func (a *App[C]) OnStop(hooks ...Hook)

OnStop registers a hook that runs during graceful shutdown before components are stopped. Use this for cleanup tasks like draining connections or deregistering from service discovery.

func (*App[C]) ReadyCheck

func (a *App[C]) ReadyCheck(ctx context.Context) error

ReadyCheck verifies that all registered components are healthy.

func (*App[C]) RegisterComponent

func (a *App[C]) RegisterComponent(c component.Component) error

RegisterComponent adds a component to the application's registry.

func (*App[C]) Run

func (a *App[C]) Run(ctx context.Context) error

Run executes the full application lifecycle for long-running services: Initialize → OnStart hooks → Configure → ReadyCheck → OnReady hooks → Block on signal → OnStop hooks → Graceful Shutdown.

func (*App[C]) RunTask

func (a *App[C]) RunTask(ctx context.Context, task func(ctx context.Context) error) error

RunTask executes a finite task with the full bootstrap lifecycle. Unlike Run(), it does not block on shutdown signals — it runs the task function and gracefully shuts down when the task completes or the context is canceled (e.g., via SIGINT/SIGTERM).

Use RunTask for CLI tools, batch jobs, and one-shot processes that need the same bootstrap infrastructure (config, logger, components, hooks) but have a finite workflow instead of running forever.

Example:

app, _ := bootstrap.NewApp(&cfg)
app.RunTask(ctx, func(ctx context.Context) error {
    return processData(ctx)
})

func (*App[C]) Shutdown

func (a *App[C]) Shutdown(ctx context.Context) error

Shutdown performs graceful shutdown using the supplied ctx. If ctx has no deadline, the configured gracefulTimeout is applied. If ctx has a deadline shorter than gracefulTimeout, ctx wins.

Use when managing your own lifecycle (e.g. when not relying on signal handling via Run).

func (*App[C]) Startup

func (a *App[C]) Startup(ctx context.Context) error

Startup performs the full bootstrap lifecycle (initialize, start hooks, configure, start components, ready check, ready hooks) without blocking on shutdown signals. Pair with Shutdown for test and CLI scenarios.

func (*App[C]) WaitForSignal

func (a *App[C]) WaitForSignal(ctx context.Context) os.Signal

WaitForSignal blocks until an OS interrupt/term signal or context cancellation.

type BusinessComponentInfo

type BusinessComponentInfo struct {
	Name         string
	Type         string // "service", "repository", "handler"
	Status       string
	Dependencies []string
}

BusinessComponentInfo represents a business-layer component (service, repository, handler).

type ClientInfo

type ClientInfo struct {
	Name   string
	Target string
	Status string
	Type   string // "grpc", "http", etc.
}

ClientInfo represents an external client connection.

type ComponentStatus

type ComponentStatus struct {
	Name    string
	Status  string
	Healthy bool
}

ComponentStatus holds the tracked status of a component during bootstrap.

type Config

type Config interface {
	GetServiceConfig() *config.ServiceConfig
	ApplyDefaults()
	Validate() error
}

Config is the interface constraint for application configuration types. Any struct that embeds config.ServiceConfig (value embedding) automatically satisfies this interface via promoted methods.

Example:

type MyConfig struct {
    config.ServiceConfig `yaml:",inline" mapstructure:",squash"`
    Database database.Config `yaml:"database" mapstructure:"database"`
}

// MyConfig automatically satisfies Config via promoted methods.
app, err := bootstrap.NewApp[*MyConfig](&cfg)

type ConsumerInfo

type ConsumerInfo struct {
	Name   string
	Group  string
	Topic  string
	Status string
}

ConsumerInfo represents a message consumer (e.g. Kafka).

type Hook

type Hook func(ctx context.Context) error

Hook is a lifecycle callback that runs during application startup or shutdown. Services register hooks to perform setup/teardown without bootstrap knowing about specific infrastructure.

type InfrastructureInfo

type InfrastructureInfo struct {
	Name          string
	ComponentName string // Internal component name (for deduplication with ComponentStatus)
	Type          string // e.g. "database", "server", "kafka", "redis"
	Status        string
	Details       string
	Port          int
	Healthy       bool
}

InfrastructureInfo holds detailed infrastructure component information.

type Option

type Option func(*appOptions)

Option configures the App during creation. Options are non-generic so they can be used with any config type.

func WithContainer

func WithContainer(c *di.Container) Option

WithContainer sets a custom DI container for the application.

func WithGracefulTimeout

func WithGracefulTimeout(d time.Duration) Option

WithGracefulTimeout sets the maximum duration for graceful shutdown.

func WithLogger

func WithLogger(l *logging.Logger) Option

WithLogger sets a custom logger for the application. If not set, the logger is auto-initialized from the config's Logging field.

type RouteInfo

type RouteInfo struct {
	Method  string
	Path    string
	Handler string
}

RouteInfo represents a registered HTTP route.

type Summary

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

Summary tracks and displays the application bootstrap process.

Output is written to the configured io.Writer (default: os.Stdout). Use SetWriter (or the WithWriter option on NewSummaryWithOptions) to redirect output — for example to a structured log line, an in-memory buffer for tests, or a file. Library code MUST NOT write directly to stdout; the configurable writer is the supported integration point.

func NewSummary

func NewSummary(serviceName, version string) *Summary

NewSummary creates a new bootstrap summary tracker that writes to os.Stdout. Use NewSummaryWithOptions to inject a custom writer.

func NewSummaryWithOptions

func NewSummaryWithOptions(serviceName, version string, opts ...SummaryOption) *Summary

NewSummaryWithOptions creates a new bootstrap summary with the given options.

func (*Summary) DisplaySummary

func (s *Summary) DisplaySummary(registry *component.Registry, container *di.Container, log *logging.Logger)

DisplaySummary prints the bootstrap summary. It auto-collects infrastructure, routes, and health from the component registry and DI registrations from the container. Manual Track* calls are only needed for non-component items (e.g., auth config).

func (*Summary) SetStartupDuration

func (s *Summary) SetStartupDuration(d time.Duration)

SetStartupDuration records the total startup time.

func (*Summary) SetWriter

func (s *Summary) SetWriter(w io.Writer)

SetWriter overrides the output writer used by Summary.DisplaySummary. A nil writer is ignored.

func (*Summary) TrackBusinessComponent

func (s *Summary) TrackBusinessComponent(name, componentType, status string, dependencies []string)

TrackBusinessComponent records a business-layer component.

func (*Summary) TrackClient

func (s *Summary) TrackClient(name, target, status, clientType string)

TrackClient records an external client connection.

func (*Summary) TrackComponent

func (s *Summary) TrackComponent(name, status string, healthy bool)

TrackComponent adds a component's bootstrap status to the summary.

func (*Summary) TrackConsumer

func (s *Summary) TrackConsumer(name, group, topic, status string)

TrackConsumer records a message consumer.

func (*Summary) TrackInfrastructure

func (s *Summary) TrackInfrastructure(info InfrastructureInfo)

TrackInfrastructure adds an infrastructure component with detailed metadata. For non-component infrastructure (e.g., auth config), InfrastructureInfo.ComponentName can be empty.

func (*Summary) TrackRoute

func (s *Summary) TrackRoute(method, path, handler string)

TrackRoute records an HTTP route.

type SummaryOption

type SummaryOption func(*Summary)

SummaryOption configures a Summary at construction time.

func WithWriter

func WithWriter(w io.Writer) SummaryOption

WithWriter sets the output writer for the summary. The default is os.Stdout. Pass io.Discard to silence the summary entirely.

Jump to

Keyboard shortcuts

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