Documentation ¶
Index ¶
- func DescribeService(service Service) string
- func StartAndAwaitRunning(ctx context.Context, service Service) error
- func StopAndAwaitTerminated(ctx context.Context, service Service) error
- type BasicService
- func (b *BasicService) AddListener(listener Listener)
- func (b *BasicService) AwaitRunning(ctx context.Context) error
- func (b *BasicService) AwaitTerminated(ctx context.Context) error
- func (b *BasicService) FailureCase() error
- func (b *BasicService) ServiceContext() context.Context
- func (b *BasicService) ServiceName() string
- func (b *BasicService) StartAsync(parentContext context.Context) error
- func (b *BasicService) State() State
- func (b *BasicService) StopAsync()
- func (b *BasicService) WithName(name string) *BasicService
- type Listener
- type NamedService
- type OneIteration
- type RunningFn
- type Service
- type StartingFn
- type State
- type StoppingFn
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DescribeService ¶
DescribeService returns name of the service, if it has one, or returns string representation of the service.
func StartAndAwaitRunning ¶
StartAndAwaitRunning starts the service, and then waits until it reaches Running state. If service fails to start, its failure case is returned. Service must be in New state when this function is called.
Notice that context passed to the service for starting is the same as context used for waiting! If you need these contexts to be different, please use StartAsync and AwaitRunning directly.
func StopAndAwaitTerminated ¶
StopAndAwaitTerminated asks service to stop, and then waits until service reaches Terminated or Failed state. If service ends in Terminated state, this function returns error. On Failed state, it returns the failure case. Other errors are possible too (eg. if context stops before service does).
Types ¶
type BasicService ¶
type BasicService struct {
// contains filtered or unexported fields
}
BasicService implements contract of Service interface, using three supplied functions: StartingFn, RunningFn and StoppingFn. When service is started, these three functions are called as service transitions to Starting, Running and Stopping state.
Since they are called sequentially, they don't need to synchronize access on the state. (In other words: StartingFn happens-before RunningFn, RunningFn happens-before StoppingFn).
All three functions are called at most once. If they are nil, they are not called and service transitions to the next state.
Context passed to StartingFn and RunningFn function is canceled when StopAsync() is called, or service enters Stopping state. This context can be used to start additional tasks from inside StartingFn or RunningFn. Same context is available via ServiceContext() method (not part of Service interface).
Possible orders of how functions are called:
* 1. StartingFn -- if StartingFn returns error, no other functions are called.
* 1. StartingFn, 2. StoppingFn -- StartingFn doesn't return error, but StopAsync is called while running StartingFn, or context is canceled from outside while StartingFn still runs.
* 1. StartingFn, 2. RunningFn, 3. StoppingFn -- this is most common, when StartingFn doesn't return error, service is not stopped and context isn't stopped externally while running StartingFn.
func NewBasicService ¶
func NewBasicService(start StartingFn, run RunningFn, stop StoppingFn) *BasicService
NewBasicService returns service built from three functions (using BasicService).
func NewIdleService ¶
func NewIdleService(up StartingFn, down StoppingFn) *BasicService
NewIdleService initializes basic service as an "idle" service -- it doesn't do anything in its Running state, but still supports all state transitions.
func NewTimerService ¶
func NewTimerService(interval time.Duration, start StartingFn, iter OneIteration, stop StoppingFn) *BasicService
NewTimerService runs iteration function on every interval tick. When iteration returns error, service fails.
func (*BasicService) AddListener ¶
func (b *BasicService) AddListener(listener Listener)
AddListener is part of Service interface.
func (*BasicService) AwaitRunning ¶
func (b *BasicService) AwaitRunning(ctx context.Context) error
AwaitRunning is part of Service interface.
func (*BasicService) AwaitTerminated ¶
func (b *BasicService) AwaitTerminated(ctx context.Context) error
AwaitTerminated is part of Service interface.
func (*BasicService) FailureCase ¶
func (b *BasicService) FailureCase() error
FailureCase is part of Service interface.
func (*BasicService) ServiceContext ¶
func (b *BasicService) ServiceContext() context.Context
ServiceContext returns context that this service uses internally for controlling its lifecycle. It is the same context that is passed to Starting and Running functions, and is based on context passed to the service via StartAsync.
Before service enters Starting state, there is no context. This context is stopped when service enters Stopping state.
This can be useful in code, that embeds BasicService and wants to provide additional methods to its clients.
Example:
func (s *exampleService) Send(msg string) bool { ctx := s.ServiceContext() if ctx == nil { // Service is not yet started return false } select { case s.ch <- msg: return true case <-ctx.Done(): // Service is not running anymore. return false } }
This is not part of Service interface, and clients of the Service should not use it.
func (*BasicService) ServiceName ¶
func (b *BasicService) ServiceName() string
func (*BasicService) StartAsync ¶
func (b *BasicService) StartAsync(parentContext context.Context) error
StartAsync is part of Service interface.
func (*BasicService) State ¶
func (b *BasicService) State() State
State is part of Service interface.
func (*BasicService) StopAsync ¶
func (b *BasicService) StopAsync()
StopAsync is part of Service interface.
func (*BasicService) WithName ¶
func (b *BasicService) WithName(name string) *BasicService
WithName sets service name, if service is still in New state, and returns service to allow usage like NewBasicService(...).WithName("service name").
type Listener ¶
type Listener interface { // Starting is called when the service transitions from NEW to STARTING. Starting() // Running is called when the service transitions from STARTING to RUNNING. Running() // Stopping is called when the service transitions to the STOPPING state. Stopping(from State) // Terminated is called when the service transitions to the TERMINATED state. Terminated(from State) // Failed is called when the service transitions to the FAILED state. Failed(from State, failure error) }
Listener receives notifications about Service state changes.
type NamedService ¶
type NamedService interface { Service // ServiceName returns name of the service, if it has one. ServiceName() string }
NamedService extends Service with a name.
type OneIteration ¶
OneIteration is one iteration of the timer service. Called repeatedly until service is stopped, or this function returns error in which case, service will fail.
type RunningFn ¶
RunningFn function is called when service enters Running state. When it returns, service will move to Stopping state. If RunningFn or Stopping return error, Service will end in Failed state, otherwise if both functions return without error, service will end in Terminated state.
type Service ¶
type Service interface { // StartAsync starts Service asynchronously. Service must be in New State, otherwise error is returned. // Context is used as a parent context for service own context. StartAsync(ctx context.Context) error // AwaitRunning waits until service gets into Running state. // If service is in New or Starting state, this method is blocking. // If service is already in Running state, returns immediately with no error. // If service is in a state, from which it cannot get into Running state, error is returned immediately. AwaitRunning(ctx context.Context) error // StopAsync tell the service to stop. This method doesn't block and can be called multiple times. // If Service is New, it is Terminated without having been started nor stopped. // If Service is in Starting or Running state, this initiates shutdown and returns immediately. // If Service has already been stopped, this method returns immediately, without taking action. StopAsync() // AwaitTerminated waits for the service to reach Terminated or Failed state. If service is already in one of these states, // when method is called, method returns immediately. // If service enters Terminated state, this method returns nil. // If service enters Failed state, or context is finished before reaching Terminated or Failed, error is returned. AwaitTerminated(ctx context.Context) error // FailureCase returns error if Service is in Failed state. // If Service is not in Failed state, this method returns nil. FailureCase() error // State returns current state of the service. State() State // AddListener adds listener to this service. Listener will be notified on subsequent state transitions // of the service. Previous state transitions are not replayed, so it is suggested to add listeners before // service is started. // // AddListener guarantees execution ordering across calls to a given listener but not across calls to // multiple listeners. Specifically, a given listener will have its callbacks invoked in the same order // as the service enters those states. Additionally, at most one of the listener's callbacks will execute // at once. However, multiple listeners' callbacks may execute concurrently, and listeners may execute // in an order different from the one in which they were registered. AddListener(listener Listener) }
Service defines interface for controlling a service.
State diagram for the service:
┌────────────────────────────────────────────────────────────────────┐ │ │ │ ▼ ┌─────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐ ┌────────────┐ │ New │─────▶│ Starting │─────▶│ Running │────▶│ Stopping │───┬─▶│ Terminated │ └─────┘ └──────────┘ └─────────┘ └──────────┘ │ └────────────┘ │ │ │ │ │ │ ┌────────┐ └──────────────────────────────────────────┴──▶│ Failed │ └────────┘
type StartingFn ¶
StartingFn is called when service enters Starting state. If StartingFn returns error, service goes into Failed state. If StartingFn returns without error, service transitions into Running state (unless context has been canceled).
serviceContext is a context that is finished at latest when service enters Stopping state, but can also be finished earlier when StopAsync is called on the service. This context is derived from context passed to StartAsync method.
type State ¶
type State int
State of the service. See Service interface for full state diagram.
const ( New State = iota // New: Service is new, not running yet. Initial State. Starting // Starting: Service is starting. If starting succeeds, service enters Running state. Running // Running: Service is fully running now. When service stops running, it enters Stopping state. Stopping // Stopping: Service is shutting down Terminated // Terminated: Service has stopped successfully. Terminal state. Failed // Failed: Service has failed in Starting, Running or Stopping state. Terminal state. )
Possible states to represent the service State.
type StoppingFn ¶
StoppingFn function is called when service enters Stopping state. When it returns, service moves to Terminated or Failed state, depending on whether there was any error returned from previous RunningFn (if it was called) and this StoppingFn function. If both return error, RunningFn's error will be saved as failure case for Failed state. Parameter is error from Running function, or nil if there was no error.