oversight: cirello.io/oversight Index | Examples | Files

package oversight

import "cirello.io/oversight"

Package oversight makes a complete implementation of the Erlang supervision trees.

Refer to: http://erlang.org/doc/design_principles/sup_princ.html

supervisor := oversight.New(
	oversight.WithRestartStrategy(oversight.OneForOne()),
	oversight.Processes(func(ctx context.Context) error {
		select {
		case <-ctx.Done():
			return nil
		case <-time.After(time.Second):
			log.Println(1)
		}
		return nil
	}),
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if err := supervisor.Start(ctx); err != nil {
	log.Fatal(err)
}

Simple interface

If you do not need to use nested trees, you might prefer using cirello.io/oversight/easy instead. It provides a OneForAll tree with the automatic halting disabled.

package main

import oversight "cirello.io/oversight/easy"

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // use cancel() to halt the tree.
	ctx = oversight.WithContext(ctx)
	oversight.Add(ctx, func(ctx context.Context) {
		// ...
	})
}

This package is covered by this SLA: https://cirello.io/sla

Index

Examples

Package Files

child_process.go doc.go restart.go run.go strategy.go tree.go tree_options.go

Constants

const (
    DefaultMaxR = 1
    DefaultMaxT = 5 * time.Second
)

Default restart intensity expectations.

const DefaultChildProcessTimeout = 5 * time.Second

DefaultChildProcessTimeout defines how long child worker process should wait before detachment.

Variables

var ErrInvalidChildProcessType = errors.New("invalid child process type")

ErrInvalidChildProcessType is returned when caller tries to add an invalid child process to the oversight tree. The child process type must always be ChildProcessSpecification, ChildProcess, and *Tree.

var ErrInvalidConfiguration = errors.New("invalid tree configuration")

ErrInvalidConfiguration is returned when tree has invalid settings.

var ErrNoChildProcessLeft = errors.New("no child process left")

ErrNoChildProcessLeft means that all processes in the supervisor are done, and there is no one left to restart.

var ErrProcessNotRunning = errors.New("process not running")

ErrProcessNotRunning is returned when caller tries to terminated processes that are not running.

var ErrTooManyFailures = errors.New("too many failures")

ErrTooManyFailures means that the supervisor detected that one of the child processes has failed too much and that it decided to fully stop.

var ErrTreeNotRunning = errors.New("oversight tree is not running")

ErrTreeNotRunning is returned to Add, Terminate and Delete calls when the oversight tree is initialized but not started yet; or when at that point in time is not running anymore.

var ErrUnknownProcess = errors.New("unknown process")

ErrUnknownProcess is returned when runtime operations (like delete or terminate) failed because the process is not present.

type ChildProcess Uses

type ChildProcess func(ctx context.Context) error

ChildProcess is a function that can be supervised for restart.

type ChildProcessSpecification Uses

type ChildProcessSpecification struct {
    // Name is the human-friendly reference used for inspecting and
    // terminating child processes. If the same named is used twice, the
    // oversight tree will append a suffix to make it unique.
    Name string

    // Restart must be one of the Restart policies. The each oversight tree
    // implementation is free to interpret the result of this call.
    Restart Restart

    // Start initiates the child process in a panic-trapping cage. It does
    // not circumvent Go's panic-recover semantics. Avoid starting
    // goroutines inside the ChildProcess if they risk panic()'ing.
    Start ChildProcess

    // Shutdown defines the child process timeout. If the process is not
    // stopped within the specified duration, the oversight tree detached
    // the process and moves on. Null values mean wait forever.
    Shutdown Shutdown
}

ChildProcessSpecification provides the complete interface to configure how the child process should behave itself in case of failures.

type ChildProcessState Uses

type ChildProcessState string

ChildProcessState represents the current lifecycle step of the child process.

const (
    Starting ChildProcessState = ""
    Running  ChildProcessState = "running"
    Failed   ChildProcessState = "failed"
    Done     ChildProcessState = "done"
)

Child processes navigate through a sequence of states, that are atomically managed by the oversight tree to decide if child process needs to be started or not.

                         ┌─────────────────────┐
                         │                     │
                         │              ┌────────────┐
                         ▼         ┌───▶│   Failed   │
┌────────────┐    ┌────────────┐   │    └────────────┘
│  Starting  │───▶│  Running   │───┤
└────────────┘    └────────────┘   │    ┌────────────┐
                                   └───▶│    Done    │
                                        └────────────┘

type Logger Uses

type Logger interface {
    Printf(format string, args ...interface{})
    Println(args ...interface{})
}

Logger defines the interface for any logging facility to be compatible with oversight trees.

type Restart Uses

type Restart func(error) bool

Restart is a function that decides if a worker has to be restarted or not according to its returned error.

func Permanent Uses

func Permanent() Restart

Permanent goroutine is always restarted.

func Temporary Uses

func Temporary() Restart

Temporary goroutine is never restarted (not even when the supervisor restart strategy is rest_for_one or one_for_all and a sibling death causes the temporary process to be terminated).

func Transient Uses

func Transient() Restart

Transient goroutine is restarted only if it terminates abnormally, that is, with any error.

type Shutdown Uses

type Shutdown func() (context.Context, context.CancelFunc)

Shutdown defines how the oversight handles child processes hanging after they are signaled to stop.

func Infinity Uses

func Infinity() Shutdown

Infinity will wait until the process naturally dies.

func Timeout Uses

func Timeout(d time.Duration) Shutdown

Timeout defines a duration of time that the oversight will wait before detaching from the winding process.

type State Uses

type State struct {
    Name  string
    State ChildProcessState
    Stop  func()
}

State is a snapshot of the child process current state.

type Strategy Uses

type Strategy func(t *Tree, failedChildID int)

Strategy defines how the supervisor handles individual failures and tree shutdowns (best effort). The shutdown is initiated in the reverse order of the start of the child processes. The Go scheduler implementation makes it impossible to guarantee any order regarding shutdown completion.

func OneForAll Uses

func OneForAll() Strategy

OneForAll ensures that if a child process terminates, all other child processes are terminated, and then all child processes, including the terminated one, are restarted.

func OneForOne Uses

func OneForOne() Strategy

OneForOne ensures that if a child process terminates, only that process is restarted.

func RestForOne Uses

func RestForOne() Strategy

RestForOne ensures that if a child process terminates, the rest of the child processes (that is, the child processes after the terminated process in start order) are terminated. Then the terminated child process and the rest of the child processes are restarted.

func SimpleOneForOne Uses

func SimpleOneForOne() Strategy

SimpleOneForOne behaves similarly to OneForOne but it runs the stop calls asynchronously.

type Tree Uses

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

Tree is the supervisor tree proper.

ExampleTree_singlePermanent shows how to create a static tree of permanent child processes.

Code:

supervise := oversight.New(
    oversight.Processes(func(ctx context.Context) error {
        select {
        case <-ctx.Done():
            return nil
        case <-time.After(time.Second):
            fmt.Println(1)
        }
        return nil
    }),
)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
err := supervise.Start(ctx)
if err != nil {
    fmt.Println(err)
}

Output:

1
1
too many failures

func New Uses

func New(opts ...TreeOption) *Tree

New creates a new oversight (supervisor) tree with the applied options.

func (*Tree) Add Uses

func (t *Tree) Add(spec interface{}) error

Add attaches a new child process to a running oversight tree. This call must be used on running oversight trees. If the tree is halted, it is going to fail with ErrTreeNotRunning. The valid types are ChildProcessSpecification, ChildProcess, and *Tree. If the added child process is invalid, it is going to fail with ErrInvalidChildProcessType.

func (*Tree) Children Uses

func (t *Tree) Children() []State

Children returns the current set of child processes.

func (*Tree) Delete Uses

func (t *Tree) Delete(name string) error

Delete stops the service in the oversight tree and remove from it. If the oversight tree runs out of processes to supervise, it will terminate itself with ErrNoChildProcessLeft. This call must be used on running oversight trees, if the tree is not started yet, it is going to block. If the tree is halted, it is going to fail with ErrTreeNotRunning.

func (*Tree) Start Uses

func (t *Tree) Start(rootCtx context.Context) error

Start ignites the supervisor tree.

func (*Tree) Terminate Uses

func (t *Tree) Terminate(name string) error

Terminate stop the named process. Terminated child processes do not count as failures in the oversight tree restart policy. If the oversight tree runs out of processes to supervise, it will terminate itself with ErrNoChildProcessLeft. This call must be used on running oversight trees, if the tree is not started yet, it is going to block. If the tree is halted, it is going to fail with ErrTreeNotRunning.

type TreeOption Uses

type TreeOption func(*Tree)

TreeOption are applied to change the behavior of a Tree.

func DefaultRestartIntensity Uses

func DefaultRestartIntensity() TreeOption

DefaultRestartIntensity redefines the tolerance for failures in the supervisor tree. It defaults to 1 restart (maxR) in the preceding 5 seconds (maxT).

func DefaultRestartStrategy Uses

func DefaultRestartStrategy() TreeOption

DefaultRestartStrategy redefines the supervisor behavior to use OneForOne.

func NeverHalt Uses

func NeverHalt() TreeOption

NeverHalt will configure the oversight tree to never stop in face of failure.

func Process Uses

func Process(specs ...ChildProcessSpecification) TreeOption

Process plugs one or more child processes to the supervisor tree. Process never reset the child process list.

func Processes Uses

func Processes(processes ...ChildProcess) TreeOption

Processes plugs one or more Permanent child processes to the supervisor tree. Processes never reset the child process list.

func WithLogger Uses

func WithLogger(logger Logger) TreeOption

WithLogger plugs a custom logger to the oversight tree.

func WithRestartIntensity Uses

func WithRestartIntensity(maxR int, maxT time.Duration) TreeOption

WithRestartIntensity defines a custom tolerance for failures in the supervisor tree.

func WithRestartStrategy Uses

func WithRestartStrategy(strategy Strategy) TreeOption

WithRestartStrategy defines a custom restart strategy for the supervisor tree.

func WithSpecification Uses

func WithSpecification(maxR int, maxT time.Duration, strategy Strategy) TreeOption

WithSpecification defines a custom setup to tweak restart tolerance and strategy for the instance of oversight.

func WithTree Uses

func WithTree(subTree *Tree) TreeOption

WithTree is a shortcut to add a tree as a child process.

Package oversight imports 7 packages (graph) and is imported by 1 packages. Updated 2019-03-20. Refresh now. Tools for package owners.