bootstrap

package
v0.1.15 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package bootstrap orchestrates the sequential initialization and LIFO cleanup of application components at startup.

Env is always initialized first; Log is always initialized second and closed absolutely last so that all cleanup log messages are captured before the process exits. All other components are registered via App.Add or App.AddParallel and participate in LIFO cleanup.

Basic usage:

bootstrap.New(
    env.Component("config/app.toml", &configFS),
    log.Component(),
).
    AddParallel(dbComp.Component()).
    PreReady(migrate).
    PreReady(initServices).
    Add(ginComp.Component(mount)).
    Add(httpComp.Component(func() http.Handler { return router })).
    PostReady(func() { slog.Info("server ready") }).
    Run()

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type App

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

App is the startup orchestrator. It manages the ordered initialization and LIFO cleanup of application components.

Close order guarantee:

  1. Add/AddParallel components in LIFO order
  2. envComp.Close() (usually no-op)
  3. logComp.Close() (absolutely last — flushes the async log buffer)

func New

func New(envComp IComponent, logComp IComponent) *App

New creates a new App with mandatory foundation components.

envComp is initialized first (all other components depend on configuration). logComp is initialized second and closed absolutely last so that all cleanup log messages are captured before the process exits.

Both are passed as constructor parameters rather than Add() calls to enforce the ordering constraint at compile time.

func (*App) Add

func (a *App) Add(cs ...IComponent) *App

Add appends one or more components to the sequential startup chain. Components are initialized in registration order and closed in LIFO order.

func (*App) AddParallel

func (a *App) AddParallel(cs ...IComponent) *App

AddParallel appends a group of components that initialize concurrently. All components in the group must succeed before the next phase begins. On shutdown, the group's components are closed concurrently as a unit.

func (*App) PostReady added in v0.1.15

func (a *App) PostReady(fn func()) *App

PostReady registers a callback that is invoked after all steps succeed and before the process blocks waiting for an OS signal. Multiple calls accumulate; callbacks run in registration order. Use it to log a "server ready" message or register with a service-discovery system.

Example

ExampleApp_PostReady shows how to register multiple post-startup callbacks. Each PostReady call appends a callback; all run in registration order after every step succeeds and before the process blocks waiting for an OS signal.

Multiple PostReady calls are useful when separate concerns each need a post-startup hook independently:

bootstrap.New(envComp.Component(...), logComp.Component()).
    AddParallel(dbComp.Component()).
    Add(ginComp.Component(mount)).
    Add(httpComp.Component(handler)).
    PostReady(func() { slog.Info("server ready", "addr", ":8080") }).
    PostReady(func() { discovery.Register(serviceID) }).
    Run()
package main

import (
	"fmt"

	"github.com/phcp-tech/common-library-golang/bootstrap"
)

func main() {
	app := bootstrap.New(
		bootstrap.Func("env", nil, nil),
		bootstrap.Func("log", nil, nil),
	).
		PostReady(func() { fmt.Println("first") }).
		PostReady(func() { fmt.Println("second") }).
		PostReady(func() { fmt.Println("third") })
	fmt.Println(app != nil)
}
Output:
true

func (*App) PreReady added in v0.1.15

func (a *App) PreReady(fn func() error) *App

PreReady registers a setup function that runs inline in the startup sequence, in registration order relative to Add/AddParallel calls. A non-nil error aborts startup identically to a failed Init(). Multiple calls accumulate; functions run in registration order. PreReady steps have no Close and do not participate in LIFO shutdown.

Example

ExampleApp_PreReady shows how to register inline setup functions that run in the startup sequence before the HTTP server starts. Each PreReady call appends a step; steps run in registration order relative to Add/AddParallel calls. A non-nil error aborts startup identically to a failed component Init().

bootstrap.New(envComp.Component(...), logComp.Component()).
    AddParallel(dbComp.Component()).
    PreReady(migrate).        // runs after DB is ready
    PreReady(initServices).   // runs after migrate
    Add(ginComp.Component(mount)).
    Add(httpComp.Component(handler)).
    Run()
package main

import (
	"fmt"

	"github.com/phcp-tech/common-library-golang/bootstrap"
)

func main() {
	app := bootstrap.New(
		bootstrap.Func("env", nil, nil),
		bootstrap.Func("log", nil, nil),
	).
		PreReady(func() error { return nil }).
		PreReady(func() error { return nil })
	fmt.Println(app != nil)
}
Output:
true

func (*App) Run

func (a *App) Run()

Run initializes all components, waits for a shutdown signal, then closes all components in reverse order.

On Init failure: rolls back already-initialized components in LIFO order, flushes the log buffer, then calls os.Exit(1). Panics in the main goroutine are recovered, written to stderr, and exit with code 2.

type IComponent

type IComponent interface {
	// Name returns the component name used in log messages.
	Name() string

	// Init performs initialization. A non-nil error aborts startup,
	// triggers rollback of already-started components, and exits the process.
	Init() error

	// Close releases resources. Called during shutdown in LIFO order.
	// Must never panic or block indefinitely.
	Close()
}

Component is the lifecycle unit managed by App. Init is called during startup in registration order. Close is called during shutdown in LIFO order and must never fail.

func Func

func Func(name string, init func() error, close func()) IComponent

Func creates an IComponent from an init/close function pair. close may be nil when no cleanup is needed.

Example

ExampleFunc shows how to create a simple IComponent from a pair of functions. close may be nil when no cleanup is needed.

package main

import (
	"fmt"

	"github.com/phcp-tech/common-library-golang/bootstrap"
)

func main() {
	c := bootstrap.Func("my-service",
		func() error {
			// initialise service
			return nil
		},
		func() {
			// release resources
		},
	)
	fmt.Println(c.Name())
	fmt.Println(c.Init())
}
Output:
my-service
<nil>

Jump to

Keyboard shortcuts

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