oversight

package module
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2024 License: Apache-2.0 Imports: 9 Imported by: 5

README

cirello.io/oversight

Go Reference

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

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

go get [-u -f] cirello.io/oversight

https://godoc.org/cirello.io/oversight

Quickstart

supervise := oversight.New(
	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 := supervise.Start(ctx); err != nil {
	log.Fatal(err)
}

Documentation

Overview

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

Refer to: https://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

Constants

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

Default restart intensity expectations.

View Source
const DefaultChildProcessTimeout = 5 * time.Second

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

Variables

View Source
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.

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

ErrInvalidConfiguration is returned when tree has invalid settings.

View Source
var ErrMissingContext = errors.New("missing context")

ErrMissingContext is returned when a nil value is passed as context

View Source
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.

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

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

View Source
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.

View Source
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.

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

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

Functions

func ChildProcessName added in v1.1.0

func ChildProcessName(ctx context.Context) string

ChildProcessName reports the child process name if available in the context.

Types

type ChildProcess

type ChildProcess func(ctx context.Context) error

ChildProcess is a function that can be supervised for restart.

type ChildProcessSpecification

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

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

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

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

func Permanent() Restart

Permanent goroutine is always restarted.

func Temporary

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

func Transient() Restart

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

type Shutdown

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

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

func Infinity

func Infinity() Shutdown

Infinity will wait until the process naturally dies.

func Timeout

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

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

State is a snapshot of the child process current state.

type Strategy

type Strategy func(t *Tree, childProcess *childProcess)

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

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

func OneForOne() Strategy

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

func RestForOne

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

func SimpleOneForOne() Strategy

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

type Tree

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

Tree is the supervisor tree proper.

Example (SinglePermanent)

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

package main

import (
	"context"
	"fmt"
	"time"

	"cirello.io/oversight"
)

func main() {
	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

func New(opts ...TreeOption) *Tree

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

func (*Tree) Add

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, func(context.Context) and *Tree. If the added child process is invalid, it is going to fail with ErrInvalidChildProcessType.

func (*Tree) Children

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

Children returns the current set of child processes.

func (*Tree) Delete

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) GetErr added in v1.1.0

func (t *Tree) GetErr() error

func (*Tree) GracefulShutdown added in v1.1.0

func (t *Tree) GracefulShutdown(ctx context.Context) error

GracefulShutdown stops the tree in reverse order. If the tree is not started, it returns ErrTreeNotRunning. If the given context is canceled, the shutdown is aborted.

func (*Tree) Start

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

Start ignites the supervisor tree.

func (*Tree) Terminate

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

type TreeOption func(*Tree)

TreeOption are applied to change the behavior of a Tree.

func DefaultMaximumRestartIntensity added in v1.0.4

func DefaultMaximumRestartIntensity() TreeOption

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

Refer to https://erlang.org/doc/design_principles/sup_princ.html#tuning-the-intensity-and-period

func DefaultRestartIntensity

func DefaultRestartIntensity() TreeOption

DefaultRestartIntensity is an alias for DefaultMaximumRestartIntensity.

Deprecated in favor of DefaultMaximumRestartIntensity.

func DefaultRestartStrategy

func DefaultRestartStrategy() TreeOption

DefaultRestartStrategy redefines the supervisor behavior to use OneForOne.

func NeverHalt

func NeverHalt() TreeOption

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

func Process

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

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

func WithLogger(logger Logger) TreeOption

WithLogger plugs a custom logger to the oversight tree.

func WithMaximumRestartIntensity added in v1.0.3

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

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

Refer to https://erlang.org/doc/design_principles/sup_princ.html#maximum-restart-intensity

func WithRestartIntensity

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

WithRestartIntensity is an alias for WithMaximumRestartIntensity. Deprecated in favor of WithMaximumRestartIntensity.

func WithRestartStrategy

func WithRestartStrategy(strategy Strategy) TreeOption

WithRestartStrategy defines a custom restart strategy for the supervisor tree.

func WithSpecification

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

func WithTree(subTree *Tree) TreeOption

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

Directories

Path Synopsis
Package easy is an easier interface to use cirello.io/oversight.
Package easy is an easier interface to use cirello.io/oversight.

Jump to

Keyboard shortcuts

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