Help us shape the future of Go! Take the 2026 Go Developer Survey

startup

package
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: GPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package startup tells the owner what a starting server is doing. Ether binds its port before it opens the database, and until the server is ready a Gate answers on it: the console shell and a public, read-only status (/ether/api/startup-status) render a status page, and every other route, the Plex API included, answers 503 with Retry-After. Plex clients, GDM discovery and plex.tv publication only ever see a ready server.

Index

Constants

View Source
const (
	FailDatabaseUnreachable = "database_unreachable" // PostgreSQL refused or timed out
	FailDatabaseRejected    = "database_rejected"    // bad password, missing database, invalid URL
	FailDatabaseCorrupt     = "database_corrupt"     // SQLite file damaged
	FailMigration           = "migration_failed"
	FailCredentialKey       = "credential_key"
	FailRestore             = "restore_failed" // originals could not be put back
	FailConfig              = "config"
	FailUnknown             = "unknown"
)

Failure codes: what went wrong, so the console can say what to do.

View Source
const RecoveryPrefix = "/ether/api/startup/recovery/"

RecoveryPrefix is where a failed start's recovery API is mounted.

View Source
const StatusPath = "/ether/api/startup-status"

StatusPath is the public, read-only startup status endpoint.

Variables

This section is empty.

Functions

This section is empty.

Types

type Database

type Database struct {
	// Kind is "sqlite" or "postgres".
	Kind string `json:"kind"`
	// Host is host:port (PostgreSQL only).
	Host string `json:"host,omitempty"`
}

Database names the database a server is opening, without credentials.

type Failure

type Failure struct {
	Code string `json:"code"`
	// Detail is the error, with credentials scrubbed.
	Detail string `json:"detail,omitempty"`
	// Recoverable is set when the start page may restore a backup (a
	// standalone server, whose database is a file it can replace).
	Recoverable bool `json:"recoverable,omitempty"`
}

Failure is why a start failed.

type Gate

type Gate struct {
	// Tracker supplies the status.
	Tracker *Tracker
	// Shell serves the console's static files (GET /ether/...).
	Shell http.Handler
	// Recovery, when set, serves RecoveryPrefix while the start has failed.
	Recovery http.Handler
	// Console wraps every /ether/ handler the gate serves itself (the
	// owner console's network policy). Nil leaves them as they are.
	Console func(http.Handler) http.Handler
	// contains filtered or unexported fields
}

Gate is the server's root handler for its whole life. Until Open it serves only the startup status, the console shell and (while a start has failed) the recovery API; everything else gets 503. After Open it passes requests to the server, and Close stops doing so and waits for requests in flight, so a restart drains before the server shuts down.

func (*Gate) Close

func (g *Gate) Close(ctx context.Context)

Close stops routing requests to the server (new ones get 503 and the stopping status) and waits until the requests in flight have finished or ctx ends.

func (*Gate) IsOpen

func (g *Gate) IsOpen() bool

IsOpen reports whether the server is handling requests.

func (*Gate) Open

func (g *Gate) Open(h http.Handler)

Open routes every request to h: the server is ready.

func (*Gate) ServeHTTP

func (g *Gate) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Phase

type Phase string

Phase is what a starting (or stopping) server is doing.

const (
	PhaseStarting          Phase = "starting"           // reading settings
	PhaseRestoring         Phase = "restoring"          // swapping in a restored backup
	PhaseWaitingDatabase   Phase = "waiting_database"   // PostgreSQL unreachable; retrying
	PhaseWaitingCluster    Phase = "waiting_cluster"    // older nodes must update before migrating
	PhaseBackingUp         Phase = "backing_up"         // safety copy before migrating
	PhaseMigrating         Phase = "migrating"          // applying database updates
	PhaseImporting         Phase = "importing"          // importing a restored dump
	PhaseCheckingIntegrity Phase = "checking_integrity" // checking a restored database
	PhaseStartingServices  Phase = "starting_services"
	PhaseReady             Phase = "ready"
	PhaseStopping          Phase = "stopping" // shutting down for a restart
	PhaseFailed            Phase = "failed"
)

type Status

type Status struct {
	Phase Phase `json:"phase"`
	Ready bool  `json:"ready"`
	// Message is a one-line English summary (for logs and API clients;
	// the console words its own from Phase and the fields below).
	Message string `json:"message"`
	// Step of Steps, while a phase has countable work (migrations).
	Step  int `json:"step,omitempty"`
	Steps int `json:"steps,omitempty"`
	// Started is when this start began; Since when the phase did.
	Started time.Time `json:"started"`
	Since   time.Time `json:"since"`
	Elapsed float64   `json:"elapsedSeconds"`
	// Attempt and RetryAt while waiting for the database or after a
	// failure (the server retries by itself).
	Attempt  int        `json:"attempt,omitempty"`
	RetryAt  *time.Time `json:"retryAt,omitempty"`
	Database *Database  `json:"database,omitempty"`
	Failure  *Failure   `json:"failure,omitempty"`
	// Restoring names the backup being restored.
	Restoring string `json:"restoring,omitempty"`
	Version   string `json:"version,omitempty"`
}

Status is the startup status endpoint's document. It carries no settings and no credentials.

type Tracker

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

Tracker holds a start's status. It is safe for concurrent use.

func NewTracker

func NewTracker(version string, now func() time.Time) *Tracker

NewTracker starts tracking a start of version.

func (*Tracker) Begin

func (t *Tracker) Begin()

Begin starts a new start: a restart within the process (a cluster transition or a retry after a failure) is timed from here.

func (*Tracker) Fail

func (t *Tracker) Fail(f Failure, attempt int, retry time.Duration)

Fail records a failed start the server will retry after retry.

func (*Tracker) Phase

func (t *Tracker) Phase() Phase

Phase is the current phase.

func (*Tracker) Postpone

func (t *Tracker) Postpone(retry time.Duration)

Postpone moves a failed start's next retry to retry from now (the owner is using the recovery page).

func (*Tracker) Progress

func (t *Tracker) Progress(step, steps int)

Progress records step of steps within the current phase.

func (*Tracker) Restoring

func (t *Tracker) Restoring(source string)

Restoring records the backup being restored.

func (*Tracker) Set

func (t *Tracker) Set(phase Phase)

Set moves to phase, clearing the previous phase's details.

func (*Tracker) SetDatabase

func (t *Tracker) SetDatabase(db Database)

SetDatabase records which database is being opened.

func (*Tracker) Snapshot

func (t *Tracker) Snapshot() Status

Snapshot returns the current status.

func (*Tracker) Waiting

func (t *Tracker) Waiting(phase Phase, attempt int, retry time.Duration, err error)

Waiting records a wait (for the database, or for other nodes) with the attempt that failed and when the next one is due.

Jump to

Keyboard shortcuts

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