Routine manager can now be shut down
This commit is contained in:
parent
066247a08f
commit
631796a726
@ -7,9 +7,43 @@ import "log"
|
|||||||
import "time"
|
import "time"
|
||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
// Routine is a long-running function that does not return until it is finished.
|
type routine struct {
|
||||||
// An error is returned if the routine exited due to an error.
|
run, shutdown func () error
|
||||||
type Routine func () error
|
}
|
||||||
|
|
||||||
|
func (routine routine) Run () error {
|
||||||
|
if routine.run == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return routine.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (routine routine) Shutdown () error {
|
||||||
|
if routine.shutdown == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return routine.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From creates a routine from a separate run and shutdown function.
|
||||||
|
func From (run, shutdown func () error) Routine {
|
||||||
|
return routine {
|
||||||
|
run: run,
|
||||||
|
shutdown: shutdown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routine is an object that can be run and stopped.
|
||||||
|
type Routine interface {
|
||||||
|
// Run is a long-running function that does not return until it is
|
||||||
|
// finished. An error is returned if the routine exited due to an error.
|
||||||
|
Run () error
|
||||||
|
|
||||||
|
// Shutdown stops Run.
|
||||||
|
Shutdown () error
|
||||||
|
}
|
||||||
|
|
||||||
// Manager is a system capable of managing multiple routines, and restarting
|
// Manager is a system capable of managing multiple routines, and restarting
|
||||||
// them if they fail.
|
// them if they fail.
|
||||||
@ -27,6 +61,9 @@ type Manager struct {
|
|||||||
// is nil, messages will be written to the standard logger. To disable
|
// is nil, messages will be written to the standard logger. To disable
|
||||||
// logging altogether, this can be set to io.Discard.
|
// logging altogether, this can be set to io.Discard.
|
||||||
Logger io.Writer
|
Logger io.Writer
|
||||||
|
|
||||||
|
stoppingMutex sync.Mutex
|
||||||
|
stopping bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run spawns all routines in the Routines slice. If a routine exits with an
|
// Run spawns all routines in the Routines slice. If a routine exits with an
|
||||||
@ -47,6 +84,21 @@ func (manager *Manager) Run () error {
|
|||||||
return errExit
|
return errExit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown shuts down all routines in the manager.
|
||||||
|
func (manager *Manager) Shutdown () (err error) {
|
||||||
|
manager.stoppingMutex.Lock()
|
||||||
|
manager.stopping = true
|
||||||
|
manager.stoppingMutex.Unlock()
|
||||||
|
|
||||||
|
for _, routine := range manager.Routines {
|
||||||
|
routineErr := routine.Shutdown()
|
||||||
|
if routineErr != nil {
|
||||||
|
err = routineErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Append adds one or more routines to the Routines slice. This has no effect if
|
// Append adds one or more routines to the Routines slice. This has no effect if
|
||||||
// the manager is already running.
|
// the manager is already running.
|
||||||
func (manager *Manager) Append (routines ...Routine) {
|
func (manager *Manager) Append (routines ...Routine) {
|
||||||
@ -66,9 +118,15 @@ func (manager *Manager) runRoutine (routine Routine, group *sync.WaitGroup, errE
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
for {
|
for {
|
||||||
|
stopping := false
|
||||||
|
manager.stoppingMutex.Lock()
|
||||||
|
stopping = manager.stopping
|
||||||
|
manager.stoppingMutex.Unlock()
|
||||||
|
if stopping { break }
|
||||||
|
|
||||||
// TODO: recover from panics
|
// TODO: recover from panics
|
||||||
lastStart := time.Now()
|
lastStart := time.Now()
|
||||||
err = routine()
|
err = routine.Run()
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
manager.log("(i) routine exited")
|
manager.log("(i) routine exited")
|
||||||
|
Loading…
Reference in New Issue
Block a user