startup

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 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