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

31 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to this module will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [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.
[0.9.0]: https://code.nochebuena.dev/go/launcher/releases/tag/v0.9.0