Documentation
¶
Index ¶
- type Error
- type ErrorKind
- type Maestro
- func (m *Maestro) AddService(name string, req bool, s Service, deps ...string)
- func (m *Maestro) AddServiceWithBackoff(name string, req bool, maxRetries uint, initialBackoff time.Duration, ...)
- func (m *Maestro) Service(name string) Service
- func (m *Maestro) ServiceReady(ctx context.Context, name string) Service
- func (m *Maestro) StartAll(ctx context.Context) <-chan error
- func (m *Maestro) StopAll(ctx context.Context) <-chan error
- type Service
- type ServiceBase
- func (sb *ServiceBase) Dependencies() map[string]struct{}
- func (sb *ServiceBase) Name() string
- func (sb *ServiceBase) Required() bool
- func (sb *ServiceBase) RetryConf() (uint, time.Duration)
- func (sb *ServiceBase) Started() <-chan error
- func (sb *ServiceBase) Stopped() <-chan error
- func (sb *ServiceBase) String() string
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Error ¶
type Error struct {
Kind ErrorKind
Service Service
ServiceName string
ServiceErr error
Dependency string
Parent string
CircularDeps []string
}
Error is an error returned by BandMaster.
Only the `Kind` field is guaranteed to be defined at all times; the rest may or may not be set depending on the kind of the returned error.
type ErrorKind ¶
type ErrorKind int
ErrorKind enumerates the possible kind of errors returned by BandMaster.
const ( /* common */ ErrUnknown ErrorKind = iota // unknown error /* fatal */ ErrServiceAlreadyExists ErrorKind = iota // service already exists ErrServiceWithoutBase ErrorKind = iota // service must inherit form ServiceBase ErrServiceDependsOnItself ErrorKind = iota // service depends on its own self ErrServiceDuplicateDependency ErrorKind = iota // service has duplicate dependencies /* dependencies */ ErrDependencyMissing ErrorKind = iota // no such dependency ErrDependencyCircular ErrorKind = iota // circular dependencies detected /* runtime */ ErrServiceStartFailure ErrorKind = iota // service failed to start ErrServiceStopFailure ErrorKind = iota // service failed to stop )
type Maestro ¶
type Maestro struct {
// contains filtered or unexported fields
}
A Maestro registers services and their dependencies, computes depency trees and properly handles the boot & shutdown processes of these trees.
It does not care the slightest as to what happens to a service during the span of its lifetime; only boot & shutdown processes matter to it.
func GlobalMaestro ¶
func GlobalMaestro() *Maestro
GlobalMaestro returns package-level Maestro; this is what you want to use most of the time. This is thread-safe.
func NewMaestro ¶
func NewMaestro() *Maestro
NewMaestro instanciates a new local Maestro.
Unless you're facing special circumstances, you might just as well use the already instanciated, package-level Maestro.
func ReplaceGlobalMaestro ¶
ReplaceGlobalMaestro replaces the package-level Maestro with your own. This is thred-safe.
func (*Maestro) AddService ¶
AddService registers a Service with the Maestro.
The direct dependencies of this service can be specified using the names with which they were themselves registered. You do NOT need to specify its indirect dependencies. You're free to indicate the names of dependencies that haven't been registered yet: the final dependency-tree is only computed at StartAll() time.
The specified `req` boolean marks the service as required; which can be a helpful indicator as to whether you can afford to ignore some errors that might happen later on.
func (*Maestro) AddServiceWithBackoff ¶
func (m *Maestro) AddServiceWithBackoff( name string, req bool, maxRetries uint, initialBackoff time.Duration, s Service, deps ...string, )
AddServiceWithBackoff is an enhanced version of AddService that allows to configure exponential backoff in case of failures to boot.
`maxRetries` defines the maximum number of times that the service will try to boot; while `initialBackoff` specifies the initial sleep-time before each retry.
func (*Maestro) Service ¶
Service returns the service associated with the specified name, whether it is marked as ready or not. It it thread-safe.
If no such service exists, this method will return a nil value.
func (*Maestro) ServiceReady ¶
Service returns the service associated with the specified name, but blocks until it is marked as ready before returning. It it thread-safe.
If no such service exists, this method will immediately return a nil value.
Cancelling the specified context by any mean will unblock the method and return a nil value.
func (*Maestro) StartAll ¶
StartAll starts all the dependencies referenced by this Maestro in the order required by the dependency-tree. Services that don't depend on one another will be started in parallel.
StartAll is blocking: on success, the returned channel is closed and hence will return nil values indefinitely; on failure, one or more errors are returned, then the channel gets closed. In either case, once this channel is closed, except for those that returned an error, all services can be safely considered up & running.
If the specified context were to get cancelled for any reason (say a caught SIGINT for example), the entire boot process will be cleanly cancelled too. Note that some of the services may well have been successfully started before the cancellation event actually hit the pipeline though: thus you should probably call StopAll() after cancelling a boot process.
Before actually doing anything, StartAll will check for missing and/or circular dependencies; if any such thing were to be detected, an error will be pushed on the returned channel and NOTHING will get started.
func (*Maestro) StopAll ¶
StopAll stops all the services managed by the Maestro in the reversed order in which they were started. Services that don't depend on one another will be stopped in parallel.
StopAll is blocking: on success, the returned channel is closed and hence will return nil values indefinitely; on failure, one or more errors are returned, then the channel gets closed. In either case, once this channel is closed, except for those that returned an error, all services can be safely considered properly shutdown.
If the specified context were to get cancelled for any reason (say a caught SIGINT for example), the entire stop process will be cleanly cancelled too. Note that some of the services may well have been successfully stopped before the cancellation event actually hit the pipeline though.
type Service ¶
type Service interface {
Start(ctx context.Context, deps map[string]Service) error
Stop(ctx context.Context) error
Name() string
Required() bool
RetryConf() (uint, time.Duration)
String() string
Started() <-chan error
Stopped() <-chan error
}
Service is the main interface behind Bandmaster, any service that wishes to be operated by a Maestro must implement it.
To ease the integration of new services into the system, a ServiceBase class that you can pseudo-inherit from (i.e. embed) is provided and will automagically fill in most of the boilerplate required to implement the Service interface. See any service implementation in "services/" folder for examples of this.
type ServiceBase ¶
type ServiceBase struct {
// contains filtered or unexported fields
}
A ServiceBase implements most of the boilerplate required to satisfy the Service interface. You can, and should, embed it in your service structure to ease its integration in BandMaster. See any service implementation in "services/" folder for examples of this.
func NewServiceBase ¶
func NewServiceBase() *ServiceBase
NewServiceBase returns a properly initialized ServiceBase that you can embed in your service definition.
func (*ServiceBase) Dependencies ¶
func (sb *ServiceBase) Dependencies() map[string]struct{}
Dependencies returns a set of the direct dependencies of the service.
func (*ServiceBase) Name ¶
func (sb *ServiceBase) Name() string
Name returns the name of the service; it is thread-safe.
func (*ServiceBase) Required ¶
func (sb *ServiceBase) Required() bool
Required returns true if the service is marked as required; it is thread-safe.
func (*ServiceBase) RetryConf ¶
func (sb *ServiceBase) RetryConf() (uint, time.Duration)
RetryConf returns the number of retries and the initial value used by the the service for exponential backoff; it is thread-safe.
func (*ServiceBase) Started ¶
func (sb *ServiceBase) Started() <-chan error
Started returns a channel that will get closed once the boot process went successfully. This is thread-safe.
Every failed start attempt will push an error (retries due to exponential backoff are not treated as failed attempts); hence you need to make sure to keep reading continuously on the returned channel or you might block the Maestro otherwise.
func (*ServiceBase) Stopped ¶
func (sb *ServiceBase) Stopped() <-chan error
Stopped returns a channel that will get closed once the shutdown process went successfully. This is thread-safe.
Every failed shutdown attempt will push an error (retries due to exponential backoff are not treated as failed attempts); hence you need to make sure to keep reading continuously on the returned channel or you might block the Maestro otherwise.
func (*ServiceBase) String ¶
func (sb *ServiceBase) String() string