Skip to content

Repository files navigation

Golang Application Ignition

Before the engine wakes, the omens must be read.
Before the machine sleeps, its spirit must be honored.
To kill a process without rite is to invite the wrath of the Machine God.

— Tech-Priest Dominus Ferrox, Adeptus Mechanicus

The go-app-ignition package provides a simple lifecycle for applications.


Content


Getting started

When developing an application, two related tasks come up repeatedly:

  • checking dependency readiness (readiness probes) before startup
  • shutting down cleanly (graceful shutdown) when a stop signal is received.

The go-app-ignition package provides an implementation of this lifecycle:

  1. Runs a configured set of readiness probes (ReadinessHandlers) before starting the applications.
  2. Exposes the current readiness status via the AppIgnition.Ready() method, which can be used in a health-check endpoint.
  3. Starts the applications (App) and waits for a termination signal: a readiness-probe error, an application error, an OS signal (SIGINT/SIGTERM), or an explicit request via ExitChan.
  4. Performs a graceful shutdown of all applications, joining any resulting errors via errors.Join.

A working example, verified by go test, is available in app_ignition_example_test.go.

A detailed description of the components is provided in the Architecture section.

Install

go get -u github.com/AlTheOne/go-app-ignition

Architecture

The package consists of two files at the module root:

  • readiness.go handles readiness-probe orchestration
  • app_ignition.go handles the application lifecycle.

Core components

AppIgnition

The package's central struct, managing the lifecycle. Created via NewAppIgnition and exposes two methods:

  • Run(ctx context.Context, shutdownRelease context.CancelFunc) error — runs the readiness probes, starts the given applications, blocks waiting for a termination signal, and performs a graceful shutdown; returns the combined error or nil.
  • Ready() bool — thread-safely returns the current readiness status; can be used, for example, in a health-check endpoint.

ReadinessHandlers

The []ReadinessHandler type — a set of readiness probes run concurrently before starting the applications, via errgroup. If any probe returns an error, the context of the remaining probes is cancelled, and AppIgnition.Run returns that error. A function that doesn't watch for context cancellation on its own can be adapted via ReadinessHandlerWrapper.

App

The interface every managed application must implement:

type App interface {
	Run() error      // blocking run
	Shutdown() error // graceful shutdown
}

Run() must block until the application either terminates on its own (in which case AppIgnition initiates shutdown of the other applications) or Shutdown() is called.

Control channels

Besides the readiness probes and applications, NewAppIgnition accepts two channels through which the calling code controls shutdown:

Parameter Type Purpose
errExitChan chan error Reports a fatal error (e.g. from the application itself); the error is propagated as the result of Run.
exitChan chan struct{} Requests a clean shutdown with no error, e.g. from an admin endpoint.

SIGINT/SIGTERM signals are intercepted automatically inside Run and don't require a separate channel from the calling code.

Lifecycle

sequenceDiagram
    actor Caller
    participant AI as AppIgnition
    participant RH as ReadinessHandle
    participant Apps as App(s)
    participant OS as OS (syscalls)

    Caller->>AI: Run(ctx, shutdownRelease)

    alt the apps list is empty
        AI-->>Caller: return nil
    else the apps list is not empty
        AI->>RH: ReadinessHandle(ctx, logger, handlers...)
        RH-->>AI: err

        alt err != nil
            AI-->>Caller: return err
        else readiness OK
            AI->>AI: ready.Store(true)

            loop for every App
                AI->>Apps: go App.Run()
            end

            AI->>OS: signal.Notify(SIGINT, SIGTERM)
            AI->>AI: runSignalListener(): select

            par possible wake-up sources
                OS-->>AI: SIGINT / SIGTERM
            and
                Apps-->>AI: Run() returned an error → errExitChan
            and
                Caller-->>AI: ctx.Done() (external cancellation)
            and
                Caller-->>AI: close(ExitChan)
            end

            AI->>AI: ready.Store(false)

            loop for every App
                AI->>Apps: Shutdown()
                Apps-->>AI: err
            end

            AI->>OS: signal.Stop() (unsubscribe)
            AI->>Caller: shutdownRelease()
            AI-->>Caller: return err (errors.Join)
        end
    end
Loading

Alternatives

If you need extended functionality or a different approach, consider the packages below:

  • skovtunenko/graterm - provides primitives to perform ordered GRAceful TERmination for Golang applications.
  • appleboy/graceful - graceful shutdown package when a service is turned off by software function.
  • meshapi/go-shutdown - lightweight Go package to handle process terminations and shutdowns gracefully.
  • maxbolgarin/contem - zero-dependency drop-in context.Context replacement for graceful shutdown.

About

Golang Application Ignition - package provides a simple lifecycle for applications

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages