Files
launcher/CHANGELOG.md
Rene Nochebuena f2e3faa1d6 feat(launcher): initial stable release v0.9.0
Application lifecycle manager enforcing a three-phase init/wire/start sequence with reverse-order graceful shutdown and per-component stop timeouts.

What's included:
- `Component` interface (OnInit / OnStart / OnStop) and `Hook` type for BeforeStart wiring functions
- `Launcher` interface with Append, BeforeStart, Run (blocks on SIGINT/SIGTERM), and idempotent Shutdown(ctx)
- `New(logger, opts...)` constructor with configurable ComponentStopTimeout (default 15 s); no global state

Tested-via: todo-api POC integration
Reviewed-against: docs/adr/
2026-03-18 23:49:12 +00:00

2.8 KiB
Raw Permalink Blame History

Changelog

All notable changes to this module will be documented in this file.

The format is based on Keep a Changelog, and this module adheres to Semantic Versioning.

0.9.0 - 2026-03-18

Added

  • Component interface — OnInit() error (open connections, allocate resources), OnStart() error (start background goroutines and listeners), OnStop() error (graceful shutdown and resource release)
  • Hook type — func() error used to register dependency-injection wiring functions that run between OnInit and OnStart
  • Options struct — ComponentStopTimeout time.Duration (maximum time allowed for each component's OnStop; default 15 seconds); zero value is valid
  • Launcher interface — Append(components ...Component), BeforeStart(hooks ...Hook), Run() error, Shutdown(ctx context.Context) error
  • New(logger logz.Logger, opts ...Options) Launcher — constructs a Launcher; no package-level singletons or global state; variadic opts apply the first element if provided
  • Launcher.Append — registers one or more components in order; startup proceeds in registration order, shutdown in reverse
  • Launcher.BeforeStart — registers hooks that run after all OnInit calls complete and before any OnStart call; correct place for dependency injection wiring
  • Launcher.Run() error — executes the full lifecycle (OnInit → BeforeStart hooks → OnStart → wait → reverse-order OnStop); blocks until SIGINT, SIGTERM, or Shutdown is called
  • Launcher.Shutdown(ctx context.Context) error — triggers a graceful shutdown programmatically and waits for Run to return; idempotent via sync.Once, safe to call from multiple goroutines; ctx controls the caller-side wait timeout only
  • OS signal handling for SIGINT and SIGTERM built into Run with automatic signal.Stop cleanup on return
  • Per-component independent stop timeout: each component's OnStop runs in its own goroutine and is abandoned (with an error log) if it exceeds ComponentStopTimeout

Design Notes

  • The three-phase lifecycle (OnInit / BeforeStart / OnStart) cleanly separates resource allocation from dependency wiring from service activation, ensuring no component begins serving traffic before all its dependencies are fully initialized.
  • Shutdown runs in strict reverse registration order with a per-component independent timeout, so a stalled component cannot block others from stopping; worst-case shutdown time is n × ComponentStopTimeout.
  • Shutdown closes a channel via sync.Once rather than using a mutex or flag, making it genuinely safe to call concurrently from an OS signal handler and a test teardown racing against each other.