mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-24 13:48:49 +08:00
Isolates shutdown-logic to Robot/Robots/Gobot.Stop
Gobot no longer hijacks the os.Interrupt signal handler, leaving any shutdown logic to the user.
This commit is contained in:
parent
f25ef58c0a
commit
4b46228f67
47
gobot.go
47
gobot.go
@ -2,8 +2,6 @@ package gobot
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
)
|
||||
|
||||
// JSONGobot is a JSON representation of a Gobot.
|
||||
@ -33,7 +31,6 @@ func NewJSONGobot(gobot *Gobot) *JSONGobot {
|
||||
// Robots, API commands and Events.
|
||||
type Gobot struct {
|
||||
robots *Robots
|
||||
trap func(chan os.Signal)
|
||||
Commander
|
||||
Eventer
|
||||
}
|
||||
@ -41,18 +38,15 @@ type Gobot struct {
|
||||
// NewGobot returns a new Gobot
|
||||
func NewGobot() *Gobot {
|
||||
return &Gobot{
|
||||
robots: &Robots{},
|
||||
trap: func(c chan os.Signal) {
|
||||
signal.Notify(c, os.Interrupt)
|
||||
},
|
||||
robots: &Robots{},
|
||||
Commander: NewCommander(),
|
||||
Eventer: NewEventer(),
|
||||
}
|
||||
}
|
||||
|
||||
// Start calls the Start method on each robot in it's collection of robots, and
|
||||
// stops all robots on reception of a SIGINT. Start will block the execution of
|
||||
// your main function until it receives the SIGINT.
|
||||
// Start calls the Start method on each robot in its collection of robots. On
|
||||
// error, call Stop to ensure that all robots are returned to a sane, stopped
|
||||
// state.
|
||||
func (g *Gobot) Start() (errs []error) {
|
||||
if rerrs := g.robots.Start(); len(rerrs) > 0 {
|
||||
for _, err := range rerrs {
|
||||
@ -61,31 +55,18 @@ func (g *Gobot) Start() (errs []error) {
|
||||
}
|
||||
}
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
g.trap(c)
|
||||
if len(errs) > 0 {
|
||||
// there was an error during start, so we immediatly pass the interrupt
|
||||
// in order to disconnect the initialized robots, connections and devices
|
||||
c <- os.Interrupt
|
||||
return errs
|
||||
}
|
||||
|
||||
// Stop calls the Stop method on each robot in its collection of robots.
|
||||
func (g *Gobot) Stop() (errs []error) {
|
||||
if rerrs := g.robots.Stop(); len(rerrs) > 0 {
|
||||
for _, err := range rerrs {
|
||||
log.Println("Error:", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
// waiting for interrupt coming on the channel
|
||||
_ = <-c
|
||||
g.robots.Each(func(r *Robot) {
|
||||
log.Println("Stopping Robot", r.Name, "...")
|
||||
if herrs := r.Devices().Halt(); len(herrs) > 0 {
|
||||
for _, err := range herrs {
|
||||
log.Println("Error:", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if cerrs := r.Connections().Finalize(); len(cerrs) > 0 {
|
||||
for _, err := range cerrs {
|
||||
log.Println("Error:", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
return errs
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package gobot
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -20,9 +19,6 @@ func TestConnectionEach(t *testing.T) {
|
||||
func initTestGobot() *Gobot {
|
||||
log.SetOutput(&NullReadWriteCloser{})
|
||||
g := NewGobot()
|
||||
g.trap = func(c chan os.Signal) {
|
||||
c <- os.Interrupt
|
||||
}
|
||||
g.AddRobot(newTestRobot("Robot1"))
|
||||
g.AddRobot(newTestRobot("Robot2"))
|
||||
g.AddRobot(newTestRobot(""))
|
||||
@ -68,6 +64,7 @@ func TestGobotToJSON(t *testing.T) {
|
||||
func TestGobotStart(t *testing.T) {
|
||||
g := initTestGobot()
|
||||
Assert(t, len(g.Start()), 0)
|
||||
Assert(t, len(g.Stop()), 0)
|
||||
}
|
||||
|
||||
func TestGobotStartErrors(t *testing.T) {
|
||||
@ -90,6 +87,7 @@ func TestGobotStartErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
Assert(t, len(g.Start()), 1)
|
||||
Assert(t, len(g.Stop()), 0)
|
||||
|
||||
testDriverStart = func() (errs []error) { return }
|
||||
testAdaptorConnect = func() (errs []error) {
|
||||
@ -99,14 +97,11 @@ func TestGobotStartErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
Assert(t, len(g.Start()), 1)
|
||||
Assert(t, len(g.Stop()), 0)
|
||||
|
||||
testDriverStart = func() (errs []error) { return }
|
||||
testAdaptorConnect = func() (errs []error) { return }
|
||||
|
||||
g.trap = func(c chan os.Signal) {
|
||||
c <- os.Interrupt
|
||||
}
|
||||
|
||||
testDriverHalt = func() (errs []error) {
|
||||
return []error{
|
||||
errors.New("driver halt error 1"),
|
||||
@ -119,5 +114,6 @@ func TestGobotStartErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
Assert(t, len(g.Start()), 2)
|
||||
Assert(t, len(g.Start()), 0)
|
||||
Assert(t, len(g.Stop()), 2)
|
||||
}
|
||||
|
31
robot.go
31
robot.go
@ -67,6 +67,19 @@ func (r *Robots) Start() (errs []error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Stop calls the Stop method of each Robot in the collection
|
||||
func (r *Robots) Stop() (errs []error) {
|
||||
for _, robot := range *r {
|
||||
if errs = robot.Stop(); len(errs) > 0 {
|
||||
for i, err := range errs {
|
||||
errs[i] = fmt.Errorf("Robot %q: %v", robot.Name, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Each enumerates through the Robots and calls specified callback function.
|
||||
func (r *Robots) Each(f func(*Robot)) {
|
||||
for _, robot := range *r {
|
||||
@ -136,6 +149,24 @@ func (r *Robot) Start() (errs []error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Stop stops a Robot's connections and Devices
|
||||
func (r *Robot) Stop() (errs []error) {
|
||||
log.Println("Stopping Robot", r.Name, "...")
|
||||
if heers := r.Devices().Halt(); len(heers) > 0 {
|
||||
for _, err := range heers {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if ceers := r.Connections().Finalize(); len(ceers) > 0 {
|
||||
for _, err := range ceers {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Devices returns all devices associated with this Robot.
|
||||
func (r *Robot) Devices() *Devices {
|
||||
return r.devices
|
||||
|
Loading…
x
Reference in New Issue
Block a user