|
|
|
@ -2,6 +2,7 @@ package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"time"
|
|
|
|
|
"log"
|
|
|
|
|
"errors"
|
|
|
|
|
"reflect"
|
|
|
|
@ -66,6 +67,10 @@ type Event interface {
|
|
|
|
|
Handler(signal_type string) (func(GraphSignal) (string, error), bool)
|
|
|
|
|
RequiredResources() []Resource
|
|
|
|
|
DoneResource() Resource
|
|
|
|
|
SetTimeout(end_time time.Time, action string)
|
|
|
|
|
Timeout() <-chan time.Time
|
|
|
|
|
TimeoutAction() string
|
|
|
|
|
Signal() chan GraphSignal
|
|
|
|
|
|
|
|
|
|
finish() error
|
|
|
|
|
|
|
|
|
@ -73,6 +78,23 @@ type Event interface {
|
|
|
|
|
setParent(parent Event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (event * BaseEvent) Signal() chan GraphSignal {
|
|
|
|
|
return event.signal
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (event * BaseEvent) TimeoutAction() string {
|
|
|
|
|
return event.timeout_action
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (event * BaseEvent) Timeout() <-chan time.Time {
|
|
|
|
|
return event.timeout
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (event * BaseEvent) SetTimeout(end_time time.Time, action string) {
|
|
|
|
|
event.timeout_action = action
|
|
|
|
|
event.timeout = time.After(time.Until(end_time))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (event * BaseEvent) Handler(signal_type string) (func(GraphSignal)(string, error), bool) {
|
|
|
|
|
handler, exists := event.handlers[signal_type]
|
|
|
|
|
return handler, exists
|
|
|
|
@ -245,6 +267,8 @@ type BaseEvent struct {
|
|
|
|
|
parent Event
|
|
|
|
|
parent_lock sync.Mutex
|
|
|
|
|
abort chan string
|
|
|
|
|
timeout <-chan time.Time
|
|
|
|
|
timeout_action string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (event * BaseEvent) Action(action string) (func() (string, error), bool) {
|
|
|
|
@ -252,6 +276,33 @@ func (event * BaseEvent) Action(action string) (func() (string, error), bool) {
|
|
|
|
|
return action_fn, exists
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func EventWait(event Event) (func() (string, error)) {
|
|
|
|
|
return func() (string, error) {
|
|
|
|
|
log.Printf("EVENT_WAIT: %s TIMEOUT: %+v", event.Name(), event.Timeout())
|
|
|
|
|
select {
|
|
|
|
|
case signal := <- event.Signal():
|
|
|
|
|
if signal.Source() != nil {
|
|
|
|
|
log.Printf("EVENT_SIGNAL: %s %s %s -> %+v", event.Name(), signal.Last(), signal.Source().Name(), signal)
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("EVENT_SIGNAL: %s %s nil -> %+v", event.Name(), signal.Last(), signal)
|
|
|
|
|
}
|
|
|
|
|
if signal.Type() == "abort" {
|
|
|
|
|
return "", errors.New("State machine aborted by signal")
|
|
|
|
|
} else {
|
|
|
|
|
signal_fn, exists := event.Handler(signal.Type())
|
|
|
|
|
if exists == true {
|
|
|
|
|
log.Printf("EVENT_HANDLER: %s - %s", event.Name(), signal.Type())
|
|
|
|
|
return signal_fn(signal)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "wait", nil
|
|
|
|
|
case <- event.Timeout():
|
|
|
|
|
log.Printf("EVENT_TIMEOUT %s - NEXT_STATE: %s", event.Name(), event.TimeoutAction())
|
|
|
|
|
return event.TimeoutAction(), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewBaseEvent(name string, description string, required_resources []Resource) (BaseEvent) {
|
|
|
|
|
done_resource := NewResource("event_done", "signal that event is done", []Resource{})
|
|
|
|
|
event := BaseEvent{
|
|
|
|
@ -264,31 +315,12 @@ func NewBaseEvent(name string, description string, required_resources []Resource
|
|
|
|
|
actions: map[string]func()(string, error){},
|
|
|
|
|
handlers: map[string]func(GraphSignal)(string, error){},
|
|
|
|
|
abort: make(chan string, 1),
|
|
|
|
|
timeout: nil,
|
|
|
|
|
timeout_action: "",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LockResource(event.done_resource, &event)
|
|
|
|
|
|
|
|
|
|
event.actions["wait"] = func() (string, error) {
|
|
|
|
|
signal := <- event.signal
|
|
|
|
|
if signal.Type() == "abort" {
|
|
|
|
|
return "", errors.New("State machine aborted by signal")
|
|
|
|
|
} else if signal.Type() == "do_action" {
|
|
|
|
|
return signal.Description(), nil
|
|
|
|
|
} else {
|
|
|
|
|
signal_fn, exists := event.Handler(signal.Type())
|
|
|
|
|
if exists == true {
|
|
|
|
|
log.Printf("EVENT_HANDLER: %s - %s", event.name, signal.Type())
|
|
|
|
|
if signal.Source() != nil {
|
|
|
|
|
log.Printf("SIGNAL: %s %s -> %+v", signal.Last(), signal.Source().Name(), signal)
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("SIGNAL: %s nil -> %+v", signal.Last(), signal)
|
|
|
|
|
}
|
|
|
|
|
return signal_fn(signal)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "wait", nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return event
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -296,6 +328,8 @@ func NewEvent(name string, description string, required_resources []Resource) (*
|
|
|
|
|
event := NewBaseEvent(name, description, required_resources)
|
|
|
|
|
event_ptr := &event
|
|
|
|
|
|
|
|
|
|
event_ptr.actions["wait"] = EventWait(event_ptr)
|
|
|
|
|
|
|
|
|
|
event_ptr.actions["start"] = func() (string, error) {
|
|
|
|
|
return "", nil
|
|
|
|
|
}
|
|
|
|
@ -336,6 +370,8 @@ func NewEventQueue(name string, description string, required_resources []Resourc
|
|
|
|
|
listened_resources: map[string]Resource{},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queue.actions["wait"] = EventWait(queue)
|
|
|
|
|
|
|
|
|
|
queue.actions["start"] = func() (string, error) {
|
|
|
|
|
return "queue_event", nil
|
|
|
|
|
}
|
|
|
|
|