Documentation
¶
Overview ¶
Package supervisor provides supervisor trees for Go applications.
This package implements supervisor trees, similar to what Erlang runtime offers. It is built on top of context package, with all of its advantages, namely the possibility trickle down context-related values and cancelation signals.
A supervisor tree can be composed either of services or other supervisors - each supervisor can have its own set of configurations. Any instance of supervisor.Service can be added to a tree.
Supervisor ├─▶ Supervisor (if one service dies, only one is restarted) │ ├─▶ Service │ └─▶ Service ├─▶ Group (if one service dies, all others are restarted too) │ └─▶ Service │ Service │ Service └─▶ Service
Example:
package main import ( "fmt" "os" "os/signal" "time" "cirello.io/supervisor" "context" ) type Simpleservice int func (s *Simpleservice) String() string { return fmt.Sprintf("simple service %d", int(*s)) } func (s *Simpleservice) Serve(ctx context.Context) { for { select { case <-ctx.Done(): return default: fmt.Println("do something...") time.Sleep(500 * time.Millisecond) } } } func main(){ var supervisor supervisor.Supervisor svc := Simpleservice(1) supervisor.Add(&svc) // Simply, if not special context is needed: // supervisor.Serve() // Or, using context.Context to propagate behavior: c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) ctx, cancel := context.WithCancel(context.Background()) go func(){ <-c fmt.Println("halting supervisor...") cancel() }() supervisor.Serve(ctx) }
TheJerf's blog post about Suture is a very good and helpful read to understand how this package has been implemented.
This is package is inspired by github.com/thejerf/suture
Index ¶
- Constants
- func Permanent(s *ServiceSpecification)
- func Temporary(s *ServiceSpecification)
- func Transient(s *ServiceSpecification)
- type Group
- type Service
- type ServiceOption
- type ServiceSpecification
- type Supervisor
- func (s *Supervisor) Add(service Service, opts ...ServiceOption)
- func (s *Supervisor) AddFunc(f func(context.Context), opts ...ServiceOption) string
- func (s *Supervisor) Cancelations() map[string]context.CancelFunc
- func (s *Supervisor) Remove(name string)
- func (s *Supervisor) Serve(ctx context.Context)
- func (s *Supervisor) Services() map[string]Service
- func (s *Supervisor) String() string
Examples ¶
Constants ¶
const AlwaysRestart = -1
AlwaysRestart adjusts the supervisor to never halt in face of failures.
Variables ¶
This section is empty.
Functions ¶
func Transient ¶
func Transient(s *ServiceSpecification)
Transient services are restarted only when panic.
Types ¶
type Group ¶
type Group struct {
*Supervisor
}
Group is a superset of Supervisor datastructure responsible for offering a supervisor tree whose all services are restarted whenever one of them fail or is restarted. It assumes that all services rely on each other. It implements Service, therefore it can be nested if necessary either with other Group or Supervisor. When passing the Group around, remind to do it as reference (&group).
Example ¶
package main import ( "context" "fmt" "sync" "time" "cirello.io/supervisor" ) type Simpleservice struct { id int sync.WaitGroup } func (s *Simpleservice) Serve(ctx context.Context) { fmt.Println(s.String()) s.Done() <-ctx.Done() } func (s *Simpleservice) String() string { return fmt.Sprintf("simple service %d", s.id) } func main() { supervisor := supervisor.Group{ Supervisor: &supervisor.Supervisor{}, } svc1 := &Simpleservice{id: 1} svc1.Add(1) supervisor.Add(svc1) svc2 := &Simpleservice{id: 2} svc2.Add(1) supervisor.Add(svc2) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) go supervisor.Serve(ctx) svc1.Wait() svc2.Wait() cancel() }
Output:
type Service ¶
type Service interface { // Serve is called by a Supervisor to start the service. It expects the // service to honor the passed context and its lifetime. Observe // <-ctx.Done() and ctx.Err(). If the service is stopped by anything // but the Supervisor, it will get started again. Be careful with shared // state among restarts. Serve(ctx context.Context) }
Service is the public interface expected by a Supervisor.
This will be internally named after the result of fmt.Stringer, if available. Otherwise it is going to use an internal representation for the service name.
type ServiceOption ¶ added in v1.0.0
type ServiceOption func(*ServiceSpecification)
ServiceOption modifies the service specifications.
type ServiceSpecification ¶ added in v1.0.0
type ServiceSpecification struct {
// contains filtered or unexported fields
}
ServiceSpecification defines how a service is executed by the supervisor.
type Supervisor ¶
type Supervisor struct { // Name for this supervisor tree, used for logging. Name string // MaxRestarts is the number of maximum restarts given MaxTime. If more // than MaxRestarts occur in the last MaxTime, then the supervisor // stops all services and halts. Set this to AlwaysRestart to prevent // supervisor halt. MaxRestarts int // MaxTime is the time period on which the internal restart count will // be reset. MaxTime time.Duration // Log is a replaceable function used for overall logging. // Default: log.Printf. Log func(interface{}) // contains filtered or unexported fields }
Supervisor is the basic datastructure responsible for offering a supervisor tree. It implements Service, therefore it can be nested if necessary. When passing the Supervisor around, remind to do it as reference (&supervisor). Once the supervisor is started, its attributes are frozen.
Example ¶
package main import ( "context" "fmt" "sync" "time" "cirello.io/supervisor" ) type Simpleservice struct { id int sync.WaitGroup } func (s *Simpleservice) Serve(ctx context.Context) { fmt.Println(s.String()) s.Done() <-ctx.Done() } func (s *Simpleservice) String() string { return fmt.Sprintf("simple service %d", s.id) } func main() { var supervisor supervisor.Supervisor svc := &Simpleservice{id: 1} svc.Add(1) supervisor.Add(svc) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) go supervisor.Serve(ctx) svc.Wait() cancel() }
Output:
func (*Supervisor) Add ¶
func (s *Supervisor) Add(service Service, opts ...ServiceOption)
Add inserts into the Supervisor tree a new permanent service. If the Supervisor is already started, it will start it automatically.
func (*Supervisor) AddFunc ¶ added in v0.4.1
func (s *Supervisor) AddFunc(f func(context.Context), opts ...ServiceOption) string
AddFunc inserts into the Supervisor tree a new permanent anonymous service. If the Supervisor is already started, it will start it automatically.
func (*Supervisor) Cancelations ¶
func (s *Supervisor) Cancelations() map[string]context.CancelFunc
Cancelations return a list of services names and their cancelation calls. These calls be used to force a service restart.
func (*Supervisor) Remove ¶
func (s *Supervisor) Remove(name string)
Remove stops the service in the Supervisor tree and remove from it.
func (*Supervisor) Serve ¶
func (s *Supervisor) Serve(ctx context.Context)
Serve starts the Supervisor tree. It can be started only once at a time. If stopped (canceled), it can be restarted. In case of concurrent calls, it will hang until the current call is completed.
func (*Supervisor) Services ¶
func (s *Supervisor) Services() map[string]Service
Services return a list of services
func (*Supervisor) String ¶
func (s *Supervisor) String() string