mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-14 17:24:04 +00:00
88 lines
3.2 KiB
Go
88 lines
3.2 KiB
Go
package suture
|
|
|
|
/*
|
|
Service is the interface that describes a service to a Supervisor.
|
|
|
|
Serve Method
|
|
|
|
The Serve method is called by a Supervisor to start the service.
|
|
The service should execute within the goroutine that this is
|
|
called in. If this function either returns or panics, the Supervisor
|
|
will call it again.
|
|
|
|
A Serve method SHOULD do as much cleanup of the state as possible,
|
|
to prevent any corruption in the previous state from crashing the
|
|
service again.
|
|
|
|
Stop Method
|
|
|
|
This method is used by the supervisor to stop the service. Calling this
|
|
directly on a Service given to a Supervisor will simply result in the
|
|
Service being restarted; use the Supervisor's .Remove(ServiceToken) method
|
|
to stop a service. A supervisor will call .Stop() only once. Thus, it may
|
|
be as destructive as it likes to get the service to stop.
|
|
|
|
Once Stop has been called on a Service, the Service SHOULD NOT be
|
|
reused in any other supervisor! Because of the impossibility of
|
|
guaranteeing that the service has actually stopped in Go, you can't
|
|
prove that you won't be starting two goroutines using the exact
|
|
same memory to store state, causing completely unpredictable behavior.
|
|
|
|
Stop should not return until the service has actually stopped.
|
|
"Stopped" here is defined as "the service will stop servicing any
|
|
further requests in the future". For instance, a common implementation
|
|
is to receive a message on a dedicated "stop" channel and immediately
|
|
returning. Once the stop command has been processed, the service is
|
|
stopped.
|
|
|
|
Another common Stop implementation is to forcibly close an open socket
|
|
or other resource, which will cause detectable errors to manifest in the
|
|
service code. Bear in mind that to perfectly correctly use this
|
|
approach requires a bit more work to handle the chance of a Stop
|
|
command coming in before the resource has been created.
|
|
|
|
If a service does not Stop within the supervisor's timeout duration, a log
|
|
entry will be made with a descriptive string to that effect. This does
|
|
not guarantee that the service is hung; it may still get around to being
|
|
properly stopped in the future. Until the service is fully stopped,
|
|
both the service and the spawned goroutine trying to stop it will be
|
|
"leaked".
|
|
|
|
Stringer Interface
|
|
|
|
When a Service is added to a Supervisor, the Supervisor will create a
|
|
string representation of that service used for logging.
|
|
|
|
If you implement the fmt.Stringer interface, that will be used.
|
|
|
|
If you do not implement the fmt.Stringer interface, a default
|
|
fmt.Sprintf("%#v") will be used.
|
|
|
|
Optional Interface
|
|
|
|
Services may optionally implement IsCompletable, which allows a service
|
|
to indicate to a supervisor that it does not need to be restarted if
|
|
it has terminated.
|
|
|
|
*/
|
|
type Service interface {
|
|
Serve()
|
|
Stop()
|
|
}
|
|
|
|
/*
|
|
|
|
IsCompletable is an optionally-implementable interface that allows a service
|
|
to report to a supervisor that it does not need to be restarted because it
|
|
has terminated normally. When a Service is going to be restarted, the
|
|
supervisor will check for this method, and if Complete returns true, the
|
|
service is removed from the supervisor instead of restarted.
|
|
|
|
This is only executed when the service is not running because it has
|
|
terminated, and has not yet been restarted.
|
|
|
|
*/
|
|
type IsCompletable interface {
|
|
Complete() bool
|
|
}
|