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

orphan

package
v0.15.1 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package orphan stops apps none of whose owners is active, and tells administrators (R-407 – R-409).

The pass runs on the leader. It is woken when who owns an app may have changed — migration 79's triggers notify state.AppOwnersChannel when an account is suspended or deleted, an Owner grant is added or removed — so an app stops when its last owner goes, and it also runs on a schedule in case a notification was lost.

Each pass, in order:

  1. Apps that have an active owner again are unmarked, so losing that owner is a new orphaning. A stop it made stays until somebody starts the app.
  2. Apps newly without an active owner are marked, and stopped in the same write when host policy says to (stop_orphaned_apps, on by default).
  3. Administrators are told of every marked app they have not been told of, in one notice.

Nothing here starts an app. Starting one clears the stop (migration 79) and leaves the mark, so an administrator who starts an orphaned app keeps it running.

Index

Constants

View Source
const DefaultEvery = 5 * time.Minute

DefaultEvery is how often the pass runs when nothing wakes it. A notification is how an app is stopped at once; this is for one lost while the leader was not listening.

Variables

This section is empty.

Functions

func Notice

func Notice(apps []state.OrphanApp) api.Notification

Notice is what administrators are told of apps with no active owner: which were stopped, which are still running, and what gives an app an owner again (R-105, R-409). Recipients are left to the caller.

Types

type Auditor

type Auditor interface {
	Write(ctx context.Context, e audit.Event) error
}

Auditor writes audit events.

type Listener

type Listener interface {
	Listen(ctx context.Context, channel string, changed func(payload string), connected func(bool))
}

Listener calls changed for each notification on a channel until ctx ends, and connected with whether it is listening. *state.DB is one.

type Notifier

type Notifier interface {
	Notify(ctx context.Context, n api.Notification) error
}

Notifier tells people things. subscription.Router is one.

type Pass

type Pass struct {
	Store  Store
	Policy PolicyLoader

	// Notifier, Auditor and Changes are optional. Production wires all
	// three: R-409 is a promise that administrators hear of every orphaned
	// app, and Changes is what makes a stop immediate.
	Notifier Notifier
	Auditor  Auditor
	Changes  Listener

	Logger *zap.Logger

	// Every is how often Run runs a pass with nothing to wake it. Zero is
	// DefaultEvery.
	Every time.Duration
}

Pass is the orphan job.

func (*Pass) Once

func (p *Pass) Once(ctx context.Context)

Once runs one pass.

func (*Pass) Run

func (p *Pass) Run(ctx context.Context)

Run passes until ctx is canceled: at once, whenever who owns an app may have changed, whenever the listener connects again (anything could have changed while it was not listening), and every Every.

type PolicyLoader

type PolicyLoader interface {
	Load(ctx context.Context) (policy.Document, error)
}

PolicyLoader reads host policy.

type Store

type Store interface {
	ClearOwned(ctx context.Context) ([]string, error)
	NewlyOrphaned(ctx context.Context) ([]state.OrphanApp, error)
	MarkOrphaned(ctx context.Context, appID string, stop bool) (marked, stopped bool, err error)
	Unannounced(ctx context.Context) ([]state.OrphanApp, error)
	MarkAnnounced(ctx context.Context, appIDs []string) error
	Administrators(ctx context.Context) ([]string, error)
}

Store is the state the pass reads and writes. *state.Orphans is one.

Jump to

Keyboard shortcuts

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