change service#Start to return just error (Refs #45)
``` @melekes yeah, bool is superfluous @ethanfrey If I remember correctly when I was writing test code, if I call Start() on a Service that is already running, it returns (false, nil). Only if I try to legitimately start it, but it fails in startup do I get an error. The distinction is quite important to make it safe for reentrant calls. The other approach would be to have a special error type like ErrAlreadyStarted, then check for that in your code explicitly. Kind of like if I make a db call in gorm, and get an error, I check if it is a RecordNotFound error, or whether there was a real error with the db query. @melekes Ah, I see. Thanks. I must say I like ErrAlreadyStarted approach more (not just in Golang) ```
This commit is contained in:
parent
ac0cf0b2e2
commit
4123d54bf6
|
@ -1,13 +1,19 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrAlreadyStarted = errors.New("already started")
|
||||||
|
ErrAlreadyStopped = errors.New("already stopped")
|
||||||
|
)
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
Start() (bool, error)
|
Start() error
|
||||||
OnStart() error
|
OnStart() error
|
||||||
|
|
||||||
Stop() bool
|
Stop() bool
|
||||||
|
@ -94,11 +100,11 @@ func (bs *BaseService) SetLogger(l log.Logger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements Servce
|
// Implements Servce
|
||||||
func (bs *BaseService) Start() (bool, error) {
|
func (bs *BaseService) Start() error {
|
||||||
if atomic.CompareAndSwapUint32(&bs.started, 0, 1) {
|
if atomic.CompareAndSwapUint32(&bs.started, 0, 1) {
|
||||||
if atomic.LoadUint32(&bs.stopped) == 1 {
|
if atomic.LoadUint32(&bs.stopped) == 1 {
|
||||||
bs.Logger.Error(Fmt("Not starting %v -- already stopped", bs.name), "impl", bs.impl)
|
bs.Logger.Error(Fmt("Not starting %v -- already stopped", bs.name), "impl", bs.impl)
|
||||||
return false, nil
|
return ErrAlreadyStopped
|
||||||
} else {
|
} else {
|
||||||
bs.Logger.Info(Fmt("Starting %v", bs.name), "impl", bs.impl)
|
bs.Logger.Info(Fmt("Starting %v", bs.name), "impl", bs.impl)
|
||||||
}
|
}
|
||||||
|
@ -106,12 +112,12 @@ func (bs *BaseService) Start() (bool, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// revert flag
|
// revert flag
|
||||||
atomic.StoreUint32(&bs.started, 0)
|
atomic.StoreUint32(&bs.started, 0)
|
||||||
return false, err
|
return err
|
||||||
}
|
}
|
||||||
return true, err
|
return nil
|
||||||
} else {
|
} else {
|
||||||
bs.Logger.Debug(Fmt("Not starting %v -- already started", bs.name), "impl", bs.impl)
|
bs.Logger.Debug(Fmt("Not starting %v -- already started", bs.name), "impl", bs.impl)
|
||||||
return false, nil
|
return ErrAlreadyStarted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import (
|
||||||
// listener to an event, and sends a string "data".
|
// listener to an event, and sends a string "data".
|
||||||
func TestAddListenerForEventFireOnce(t *testing.T) {
|
func TestAddListenerForEventFireOnce(t *testing.T) {
|
||||||
evsw := NewEventSwitch()
|
evsw := NewEventSwitch()
|
||||||
started, err := evsw.Start()
|
err := evsw.Start()
|
||||||
if !started || err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
||||||
}
|
}
|
||||||
messages := make(chan EventData)
|
messages := make(chan EventData)
|
||||||
|
@ -33,8 +33,8 @@ func TestAddListenerForEventFireOnce(t *testing.T) {
|
||||||
// listener to an event, and sends a thousand integers.
|
// listener to an event, and sends a thousand integers.
|
||||||
func TestAddListenerForEventFireMany(t *testing.T) {
|
func TestAddListenerForEventFireMany(t *testing.T) {
|
||||||
evsw := NewEventSwitch()
|
evsw := NewEventSwitch()
|
||||||
started, err := evsw.Start()
|
err := evsw.Start()
|
||||||
if !started || err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
||||||
}
|
}
|
||||||
doneSum := make(chan uint64)
|
doneSum := make(chan uint64)
|
||||||
|
@ -62,8 +62,8 @@ func TestAddListenerForEventFireMany(t *testing.T) {
|
||||||
// of the three events.
|
// of the three events.
|
||||||
func TestAddListenerForDifferentEvents(t *testing.T) {
|
func TestAddListenerForDifferentEvents(t *testing.T) {
|
||||||
evsw := NewEventSwitch()
|
evsw := NewEventSwitch()
|
||||||
started, err := evsw.Start()
|
err := evsw.Start()
|
||||||
if !started || err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
||||||
}
|
}
|
||||||
doneSum := make(chan uint64)
|
doneSum := make(chan uint64)
|
||||||
|
@ -107,8 +107,8 @@ func TestAddListenerForDifferentEvents(t *testing.T) {
|
||||||
// for each of the three events.
|
// for each of the three events.
|
||||||
func TestAddDifferentListenerForDifferentEvents(t *testing.T) {
|
func TestAddDifferentListenerForDifferentEvents(t *testing.T) {
|
||||||
evsw := NewEventSwitch()
|
evsw := NewEventSwitch()
|
||||||
started, err := evsw.Start()
|
err := evsw.Start()
|
||||||
if !started || err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
||||||
}
|
}
|
||||||
doneSum1 := make(chan uint64)
|
doneSum1 := make(chan uint64)
|
||||||
|
@ -167,8 +167,8 @@ func TestAddDifferentListenerForDifferentEvents(t *testing.T) {
|
||||||
// the listener and fires a thousand integers for the second event.
|
// the listener and fires a thousand integers for the second event.
|
||||||
func TestAddAndRemoveListener(t *testing.T) {
|
func TestAddAndRemoveListener(t *testing.T) {
|
||||||
evsw := NewEventSwitch()
|
evsw := NewEventSwitch()
|
||||||
started, err := evsw.Start()
|
err := evsw.Start()
|
||||||
if !started || err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
||||||
}
|
}
|
||||||
doneSum1 := make(chan uint64)
|
doneSum1 := make(chan uint64)
|
||||||
|
@ -212,8 +212,8 @@ func TestAddAndRemoveListener(t *testing.T) {
|
||||||
// TestRemoveListener does basic tests on adding and removing
|
// TestRemoveListener does basic tests on adding and removing
|
||||||
func TestRemoveListener(t *testing.T) {
|
func TestRemoveListener(t *testing.T) {
|
||||||
evsw := NewEventSwitch()
|
evsw := NewEventSwitch()
|
||||||
started, err := evsw.Start()
|
err := evsw.Start()
|
||||||
if !started || err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
||||||
}
|
}
|
||||||
count := 10
|
count := 10
|
||||||
|
@ -265,8 +265,8 @@ func TestRemoveListener(t *testing.T) {
|
||||||
// `go test -race`, to examine for possible race conditions.
|
// `go test -race`, to examine for possible race conditions.
|
||||||
func TestRemoveListenersAsync(t *testing.T) {
|
func TestRemoveListenersAsync(t *testing.T) {
|
||||||
evsw := NewEventSwitch()
|
evsw := NewEventSwitch()
|
||||||
started, err := evsw.Start()
|
err := evsw.Start()
|
||||||
if !started || err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
t.Errorf("Failed to start EventSwitch, error: %v", err)
|
||||||
}
|
}
|
||||||
doneSum1 := make(chan uint64)
|
doneSum1 := make(chan uint64)
|
||||||
|
|
Loading…
Reference in New Issue