manager

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2019 License: AGPL-3.0 Imports: 9 Imported by: 1

Documentation

Overview

Package manager deals with managing services.

The aim of this package is to provide visibility and control over long-running goroutines. A goroutine is attached to a service. The manager can start and stop services. It also deals with service dependencies and pruning unused services.

A service must at least implement the Service interface. It may also implement these additional interfaces:

  • Needy if it depends on other services
  • Pluggable if it needs to access the exposed type of its dependencies
  • Friendly if it can use but does not need some other services
  • Exposer if it exposes a type to other services
  • Runner if it runs a long running function

This package is concurrently safe (TODO: formally verify that it is).

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotFound is returned when a service is not found for a given
	// service ID.
	ErrNotFound = errors.New("service is not registered")

	// ErrInvalidStatus is returned when a service or a dependency has an
	// invalid status.
	ErrInvalidStatus = errors.New("service has invalid status")

	// ErrNeeded is returned when a service cannot be stopped because it
	// is required by other running services.
	ErrNeeded = errors.New("service is needed by other services")

	// ErrCyclic is returned when a service has cyclic dependencies.
	ErrCyclic = errors.New("service has cyclic dependencies")

	// ErrMissingServiceID is returned when a method requiring a service ID
	// was called without providing one.
	ErrMissingServiceID = errors.New("a service ID is required")
)

Functions

This section is empty.

Types

type Exposer

type Exposer interface {
	// Expose exposes a type to other services. Services that depend on
	// this service will receive the returned object in their Plug method
	// if they have one. Services that are friendly with this services will
	// receive the returned object in their Befriend method.
	Expose() interface{}
}

Exposer exposes a type to other services.

type Friendly

type Friendly interface {
	// Likes returns a set of service identifiers this service can
	// befriend.
	Likes() map[string]struct{}

	// Befriend is called every time a service it likes just started
	// running or is about to stop. If it just started running, it is
	// passed the exposed object. If it is about to stop, nil is given.
	// It must check that the exposed type is valid before using it.
	Befriend(serviceID string, exposed interface{})
}

Friendly can befriend other services, but doesn't depend on them.

type GRPCManager

type GRPCManager interface {
	Proto(string) (*pb.Service, error)
	List() []string
	Start(string) error
	Stop(string) error
	Prune()
}

GRPCManager represents a manager that can be used by the gRPC server.

type Manager

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

Manager manages the lifecycle and dependencies of services.

You must call Work before any other function can return.

func New

func New() *Manager

New creates a new service manager.

func (*Manager) Deps

func (m *Manager) Deps(servID string) (deps []string, err error)

Deps finds and sorts in topological order the services required by the given service (meaning an order in which all the dependencies can be started.

The returned slice contains the given service ID (in last position).

It returns an error if the dependency graph is cyclic (meaning there isn't an order in which to properly start dependencies).

The order of dependencies is deterministic.

func (*Manager) Errored

func (m *Manager) Errored(servID string) (<-chan error, error)

Errored returns a channel that will be notified of the error and closed once a service errors.

If the services is already errored, the channel receives the error and closes immediately.

func (*Manager) Expose

func (m *Manager) Expose(servID string) (interface{}, error)

Expose returns the object returned by the Expose method of the service.

It returns nil if the service doesn't implement the Exposer interface or if it exposed nil.

func (*Manager) Fgraph

func (m *Manager) Fgraph(w io.Writer, servID string, prefix string) error

Fgraph prints a unicode dependency graph of a service to a writer.

func (*Manager) Find

func (m *Manager) Find(servID string) (serv Service, err error)

Find returns a service.

func (*Manager) List

func (m *Manager) List() (servIDs []string)

List returns all the registered service IDs.

func (*Manager) Proto

func (m *Manager) Proto(servID string) (*pb.Service, error)

Proto returns a Protobuf struct for a service.

func (*Manager) Prunable

func (m *Manager) Prunable(servID string) (bool, error)

Prunable returns true if a service is prunable (meaning it wasn't started explicitly).

func (*Manager) Prune

func (m *Manager) Prune()

Prune stops all active services that are prunable and don't have services that depend on it.

It:

  • finds a service that can be pruned
  • stops the service
  • waits for it to stop or exit with an error
  • repeats until no service can be pruned

func (*Manager) Register

func (m *Manager) Register(serv Service)

Register adds a service to the set of known services.

func (*Manager) RegisterService

func (m *Manager) RegisterService()

RegisterService registers the manager itself as a service.

func (*Manager) Running

func (m *Manager) Running(servID string) (<-chan struct{}, error)

Running returns a channel that will be closed once a service is running.

If the services is already running, the channel closes immediately.

func (*Manager) Start

func (m *Manager) Start(servID string) error

Start starts a registered service and all its dependencies in topological order.

It blocks until all the services have started or after the first failure.

After a successful start, the service status will be set to Running. If it failed to start a dependency, the status will remain Stopped, but an error will be returned. If all dependencies started, but the service failed to start, its status will be set to Errored, and an error will be returned.

Starting a service makes it non-prunable, but the dependencies are prunable (but not stoppable) unless they were started with Start(). Calling Start() on an already running service will make it non-prunable.

It:

  • safely obtains the dependencies of the service in topological order
  • starts the dependencies and the service in order

func (*Manager) Starting

func (m *Manager) Starting(servID string) (<-chan struct{}, error)

Starting returns a channel that will be closed once a service is starting.

If the services is already starting, the channel closes immediately.

func (*Manager) Status

func (m *Manager) Status(servID string) (StatusCode, error)

Status returns the status of a service.

func (*Manager) Stop

func (m *Manager) Stop(servID string) error

Stop stops a service. Stopping a service will fail if it is a dependency of other running services or it isn't running.

It:

  • safely obtains the state of the service
  • stops the service
  • waits for the service to stop or exit with an error

func (*Manager) StopAll

func (m *Manager) StopAll()

StopAll stops all active services in an order which respects dependencies.

It:

  • finds a service that can be stopped
  • stops the service
  • waits for it to stop or exit with an error
  • repeats until no service can be stopped

func (*Manager) Stoppable

func (m *Manager) Stoppable(servID string) (bool, error)

Stoppable returns true if a service is stoppable (meaning it isn't a dependency of a running service.

func (*Manager) Stopped

func (m *Manager) Stopped(servID string) (<-chan struct{}, error)

Stopped returns a channel that will be closed once a service stopped.

If the services is already stopped, the channel receives immediately.

func (*Manager) Stopping

func (m *Manager) Stopping(servID string) (<-chan struct{}, error)

Stopping returns a channel that will be closed once a service is stopping.

If the services is already stopping, the channel closes immediately.

func (*Manager) Work

func (m *Manager) Work(ctx context.Context) error

Work tells the manager to start and execute tasks in the queues.

It blocks until the context is canceled.

type Needy

type Needy interface {
	// Needs returns a set of service identifiers needed before this
	// service can start.
	Needs() map[string]struct{}
}

Needy depends on other services.

type Pluggable

type Pluggable interface {
	Needy

	// Plug is given a map of exposed connected objects, giving the handler
	// a chance to use them. It must check that the types are correct, or
	// return an error.
	Plug(exposed map[string]interface{}) error
}

Pluggable connects other services.

type Queue

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

Queue executes functions sequentially.

func NewQueue

func NewQueue() *Queue

NewQueue creates a new queue.

func (*Queue) Do

func (q *Queue) Do(task func())

Do puts a task at the end of the queue and blocks until executed.

func (*Queue) DoError

func (q *Queue) DoError(task func() error) error

DoError puts a task that can return an error at the end of the queue and blocks until executed.

func (*Queue) DoErrorHi

func (q *Queue) DoErrorHi(task func() error) error

DoErrorHi puts a task that can return an error at the end of the hi-priority queue and blocks until executed.

func (*Queue) DoHi

func (q *Queue) DoHi(task func())

DoHi puts a task at the end of the hi-priority queue and blocks until executed.

func (*Queue) Stop

func (q *Queue) Stop()

Stop stops the queue.

func (*Queue) Work

func (q *Queue) Work(ctx context.Context) error

Work tells the queue to start executing tasks.

It blocks until the context is canceled.

type Runner

type Runner interface {
	// Run should start the service. It should block until the service is
	// done or the context is canceled. It should call running() once it
	// has started, and stopping() when it begins stopping.
	Run(ctx context.Context, running, stopping func()) error
}

Runner runs a function.

type Service

type Service interface {
	// ID returns a unique identifier.
	ID() string

	// Name returns a user friendly name.
	Name() string

	// Desc returns a short description of what the service does.
	Desc() string
}

Service describes a Stratumn Node service.

type ServiceGroup

type ServiceGroup struct {
	// GroupID is a unique identifier that will be used as the service ID.
	GroupID string

	// GroupName is a human friendly name for the group.
	GroupName string

	// GroupDesc is a description of what the group represents.
	GroupDesc string

	// Services are the services that this group starts.
	Services map[string]struct{}
}

ServiceGroup represents a group of services.

It is implemented as a service.

func (*ServiceGroup) Desc

func (s *ServiceGroup) Desc() string

Desc returns a description of what the service does.

func (*ServiceGroup) ID

func (s *ServiceGroup) ID() string

ID returns the unique identifier of the service.

func (*ServiceGroup) Name

func (s *ServiceGroup) Name() string

Name returns the human friendly name of the service.

func (*ServiceGroup) Needs

func (s *ServiceGroup) Needs() map[string]struct{}

Needs returns the set of services this service depends on.

type StatusCode

type StatusCode int8

StatusCode represents the status of a service.

const (
	Stopped StatusCode = iota
	Starting
	Running
	Stopping
	Errored
)

Service statuses.

func (StatusCode) String

func (s StatusCode) String() string

String returns a string representation of a service status.

Directories

Path Synopsis
mockgrpc
Package mockgrpc is a generated GoMock package.
Package mockgrpc is a generated GoMock package.
Package mockmanager is a generated GoMock package.
Package mockmanager is a generated GoMock package.
Package testservice defines types to help test services.
Package testservice defines types to help test services.

Jump to

Keyboard shortcuts

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