mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-27 13:48:56 +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 (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// JSONGobot is a JSON representation of a Gobot.
|
// JSONGobot is a JSON representation of a Gobot.
|
||||||
@ -33,7 +31,6 @@ func NewJSONGobot(gobot *Gobot) *JSONGobot {
|
|||||||
// Robots, API commands and Events.
|
// Robots, API commands and Events.
|
||||||
type Gobot struct {
|
type Gobot struct {
|
||||||
robots *Robots
|
robots *Robots
|
||||||
trap func(chan os.Signal)
|
|
||||||
Commander
|
Commander
|
||||||
Eventer
|
Eventer
|
||||||
}
|
}
|
||||||
@ -41,18 +38,15 @@ type Gobot struct {
|
|||||||
// NewGobot returns a new Gobot
|
// NewGobot returns a new Gobot
|
||||||
func NewGobot() *Gobot {
|
func NewGobot() *Gobot {
|
||||||
return &Gobot{
|
return &Gobot{
|
||||||
robots: &Robots{},
|
robots: &Robots{},
|
||||||
trap: func(c chan os.Signal) {
|
|
||||||
signal.Notify(c, os.Interrupt)
|
|
||||||
},
|
|
||||||
Commander: NewCommander(),
|
Commander: NewCommander(),
|
||||||
Eventer: NewEventer(),
|
Eventer: NewEventer(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start calls the Start method on each robot in it's collection of robots, and
|
// Start calls the Start method on each robot in its collection of robots. On
|
||||||
// stops all robots on reception of a SIGINT. Start will block the execution of
|
// error, call Stop to ensure that all robots are returned to a sane, stopped
|
||||||
// your main function until it receives the SIGINT.
|
// state.
|
||||||
func (g *Gobot) Start() (errs []error) {
|
func (g *Gobot) Start() (errs []error) {
|
||||||
if rerrs := g.robots.Start(); len(rerrs) > 0 {
|
if rerrs := g.robots.Start(); len(rerrs) > 0 {
|
||||||
for _, err := range rerrs {
|
for _, err := range rerrs {
|
||||||
@ -61,31 +55,18 @@ func (g *Gobot) Start() (errs []error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
return errs
|
||||||
g.trap(c)
|
}
|
||||||
if len(errs) > 0 {
|
|
||||||
// there was an error during start, so we immediatly pass the interrupt
|
// Stop calls the Stop method on each robot in its collection of robots.
|
||||||
// in order to disconnect the initialized robots, connections and devices
|
func (g *Gobot) Stop() (errs []error) {
|
||||||
c <- os.Interrupt
|
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
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package gobot
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,9 +19,6 @@ func TestConnectionEach(t *testing.T) {
|
|||||||
func initTestGobot() *Gobot {
|
func initTestGobot() *Gobot {
|
||||||
log.SetOutput(&NullReadWriteCloser{})
|
log.SetOutput(&NullReadWriteCloser{})
|
||||||
g := NewGobot()
|
g := NewGobot()
|
||||||
g.trap = func(c chan os.Signal) {
|
|
||||||
c <- os.Interrupt
|
|
||||||
}
|
|
||||||
g.AddRobot(newTestRobot("Robot1"))
|
g.AddRobot(newTestRobot("Robot1"))
|
||||||
g.AddRobot(newTestRobot("Robot2"))
|
g.AddRobot(newTestRobot("Robot2"))
|
||||||
g.AddRobot(newTestRobot(""))
|
g.AddRobot(newTestRobot(""))
|
||||||
@ -68,6 +64,7 @@ func TestGobotToJSON(t *testing.T) {
|
|||||||
func TestGobotStart(t *testing.T) {
|
func TestGobotStart(t *testing.T) {
|
||||||
g := initTestGobot()
|
g := initTestGobot()
|
||||||
Assert(t, len(g.Start()), 0)
|
Assert(t, len(g.Start()), 0)
|
||||||
|
Assert(t, len(g.Stop()), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGobotStartErrors(t *testing.T) {
|
func TestGobotStartErrors(t *testing.T) {
|
||||||
@ -90,6 +87,7 @@ func TestGobotStartErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assert(t, len(g.Start()), 1)
|
Assert(t, len(g.Start()), 1)
|
||||||
|
Assert(t, len(g.Stop()), 0)
|
||||||
|
|
||||||
testDriverStart = func() (errs []error) { return }
|
testDriverStart = func() (errs []error) { return }
|
||||||
testAdaptorConnect = func() (errs []error) {
|
testAdaptorConnect = func() (errs []error) {
|
||||||
@ -99,14 +97,11 @@ func TestGobotStartErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assert(t, len(g.Start()), 1)
|
Assert(t, len(g.Start()), 1)
|
||||||
|
Assert(t, len(g.Stop()), 0)
|
||||||
|
|
||||||
testDriverStart = func() (errs []error) { return }
|
testDriverStart = func() (errs []error) { return }
|
||||||
testAdaptorConnect = func() (errs []error) { return }
|
testAdaptorConnect = func() (errs []error) { return }
|
||||||
|
|
||||||
g.trap = func(c chan os.Signal) {
|
|
||||||
c <- os.Interrupt
|
|
||||||
}
|
|
||||||
|
|
||||||
testDriverHalt = func() (errs []error) {
|
testDriverHalt = func() (errs []error) {
|
||||||
return []error{
|
return []error{
|
||||||
errors.New("driver halt error 1"),
|
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
|
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.
|
// Each enumerates through the Robots and calls specified callback function.
|
||||||
func (r *Robots) Each(f func(*Robot)) {
|
func (r *Robots) Each(f func(*Robot)) {
|
||||||
for _, robot := range *r {
|
for _, robot := range *r {
|
||||||
@ -136,6 +149,24 @@ func (r *Robot) Start() (errs []error) {
|
|||||||
return
|
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.
|
// Devices returns all devices associated with this Robot.
|
||||||
func (r *Robot) Devices() *Devices {
|
func (r *Robot) Devices() *Devices {
|
||||||
return r.devices
|
return r.devices
|
||||||
|
Loading…
x
Reference in New Issue
Block a user