mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 06:15:33 +00:00
service: change stop interface (#7816)
This commit is contained in:
@@ -47,7 +47,7 @@ type Fireable interface {
|
||||
type EventSwitch interface {
|
||||
service.Service
|
||||
Fireable
|
||||
Stop() error
|
||||
Stop()
|
||||
|
||||
AddListenerForEvent(listenerID, eventValue string, cb EventCallback) error
|
||||
RemoveListenerForEvent(event string, listenerID string)
|
||||
|
||||
@@ -9,15 +9,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAlreadyStarted is returned when somebody tries to start an already
|
||||
// running service.
|
||||
ErrAlreadyStarted = errors.New("already started")
|
||||
// ErrAlreadyStopped is returned when somebody tries to stop an already
|
||||
// errAlreadyStopped is returned when somebody tries to stop an already
|
||||
// stopped service (without resetting it).
|
||||
ErrAlreadyStopped = errors.New("already stopped")
|
||||
// ErrNotStarted is returned when somebody tries to stop a not running
|
||||
// service.
|
||||
ErrNotStarted = errors.New("not started")
|
||||
errAlreadyStopped = errors.New("already stopped")
|
||||
)
|
||||
|
||||
// Service defines a service that can be started, stopped, and reset.
|
||||
@@ -46,13 +40,14 @@ type Implementation interface {
|
||||
|
||||
/*
|
||||
Classical-inheritance-style service declarations. Services can be started, then
|
||||
stopped, then optionally restarted.
|
||||
stopped, but cannot be restarted.
|
||||
|
||||
Users can override the OnStart/OnStop methods. In the absence of errors, these
|
||||
Users must implement OnStart/OnStop methods. In the absence of errors, these
|
||||
methods are guaranteed to be called at most once. If OnStart returns an error,
|
||||
service won't be marked as started, so the user can call Start again.
|
||||
|
||||
It is safe, but an error, to call Stop without calling Start first.
|
||||
The BaseService implementation ensures that the OnStop method is
|
||||
called after the context passed to Start is canceled.
|
||||
|
||||
Typical usage:
|
||||
|
||||
@@ -74,7 +69,7 @@ Typical usage:
|
||||
// start subroutines, etc.
|
||||
}
|
||||
|
||||
func (fs *FooService) OnStop() error {
|
||||
func (fs *FooService) OnStop() {
|
||||
// close/destroy private fields
|
||||
// stop subroutines, etc.
|
||||
}
|
||||
@@ -99,20 +94,20 @@ func NewBaseService(logger log.Logger, name string, impl Implementation) *BaseSe
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts the Service and calls its OnStart method. An error will be
|
||||
// returned if the service is already running or stopped. To restart a
|
||||
// stopped service, call Reset.
|
||||
// Start starts the Service and calls its OnStart method. An error
|
||||
// will be returned if the service is stopped, but not if it is
|
||||
// already running.
|
||||
func (bs *BaseService) Start(ctx context.Context) error {
|
||||
bs.mtx.Lock()
|
||||
defer bs.mtx.Unlock()
|
||||
|
||||
if bs.quit != nil {
|
||||
return ErrAlreadyStarted
|
||||
return nil
|
||||
}
|
||||
|
||||
select {
|
||||
case <-bs.quit:
|
||||
return ErrAlreadyStopped
|
||||
return errAlreadyStopped
|
||||
default:
|
||||
bs.logger.Info("starting service", "service", bs.name, "impl", bs.name)
|
||||
if err := bs.impl.OnStart(ctx); err != nil {
|
||||
@@ -132,7 +127,7 @@ func (bs *BaseService) Start(ctx context.Context) error {
|
||||
// this means stop was called manually
|
||||
return
|
||||
case <-ctx.Done():
|
||||
_ = bs.Stop()
|
||||
bs.Stop()
|
||||
}
|
||||
|
||||
bs.logger.Info("stopped service",
|
||||
@@ -143,25 +138,26 @@ func (bs *BaseService) Start(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Stop implements Service by calling OnStop (if defined) and closing quit
|
||||
// channel. An error will be returned if the service is already stopped.
|
||||
func (bs *BaseService) Stop() error {
|
||||
// Stop manually terminates the service by calling OnStop method from
|
||||
// the implementation and releases all resources related to the
|
||||
// service.
|
||||
func (bs *BaseService) Stop() {
|
||||
bs.mtx.Lock()
|
||||
defer bs.mtx.Unlock()
|
||||
|
||||
if bs.quit == nil {
|
||||
return ErrNotStarted
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-bs.quit:
|
||||
return ErrAlreadyStopped
|
||||
return
|
||||
default:
|
||||
bs.logger.Info("stopping service", "service", bs.name)
|
||||
bs.impl.OnStop()
|
||||
bs.cancel()
|
||||
|
||||
return nil
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ func TestBaseService(t *testing.T) {
|
||||
|
||||
require.True(t, ts.isStarted())
|
||||
|
||||
require.NoError(t, ts.Stop())
|
||||
ts.Stop()
|
||||
require.True(t, ts.isStopped())
|
||||
require.False(t, ts.IsRunning())
|
||||
})
|
||||
@@ -107,10 +107,10 @@ func TestBaseService(t *testing.T) {
|
||||
|
||||
require.NoError(t, ts.Start(ctx))
|
||||
require.True(t, ts.isStarted())
|
||||
require.NoError(t, ts.Stop())
|
||||
ts.Stop()
|
||||
require.True(t, ts.isStopped())
|
||||
require.False(t, ts.isMultiStopped())
|
||||
require.Error(t, ts.Stop())
|
||||
ts.Stop()
|
||||
require.False(t, ts.isMultiStopped())
|
||||
})
|
||||
t.Run("MultiThreaded", func(t *testing.T) {
|
||||
@@ -123,7 +123,7 @@ func TestBaseService(t *testing.T) {
|
||||
require.NoError(t, ts.Start(ctx))
|
||||
require.True(t, ts.isStarted())
|
||||
|
||||
go func() { _ = ts.Stop() }()
|
||||
go ts.Stop()
|
||||
go cancel()
|
||||
|
||||
ts.Wait()
|
||||
|
||||
Reference in New Issue
Block a user