|  |  |  | @ -186,15 +186,44 @@ func RunEvent(event Event) error { | 
		
	
		
			
				|  |  |  |  |   return nil | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func AbortEvent(event Event) error { | 
		
	
		
			
				|  |  |  |  |   signal := NewSignal(event, "abort") | 
		
	
		
			
				|  |  |  |  |   SendUpdate(event, signal) | 
		
	
		
			
				|  |  |  |  | func EventAbort(event Event) func(signal GraphSignal) (string, error) { | 
		
	
		
			
				|  |  |  |  |   return func(signal GraphSignal) (string, error) { | 
		
	
		
			
				|  |  |  |  |     if signal.Description() == event.ID() { | 
		
	
		
			
				|  |  |  |  |       AbortChildren(event) | 
		
	
		
			
				|  |  |  |  |       return "", errors.New(fmt.Sprintf("%s aborted by signal", event.ID())) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return "wait", nil | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func EventCancel(event Event) func(signal GraphSignal) (string, error) { | 
		
	
		
			
				|  |  |  |  |   return func(signal GraphSignal) (string, error) { | 
		
	
		
			
				|  |  |  |  |     if signal.Description() == event.ID() { | 
		
	
		
			
				|  |  |  |  |       CancelChildren(event) | 
		
	
		
			
				|  |  |  |  |       return "", nil | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return "wait", nil | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func CancelChildren(event Event) { | 
		
	
		
			
				|  |  |  |  |   event.LockChildren() | 
		
	
		
			
				|  |  |  |  |   for _, child := range(event.Children()) { | 
		
	
		
			
				|  |  |  |  |     AbortEvent(child) | 
		
	
		
			
				|  |  |  |  |     signal := NewSignal(event, "cancel") | 
		
	
		
			
				|  |  |  |  |     signal.description = child.ID() | 
		
	
		
			
				|  |  |  |  |     SendUpdate(child, signal) | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   event.UnlockChildren() | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func AbortChildren(event Event) { | 
		
	
		
			
				|  |  |  |  |   event.LockChildren() | 
		
	
		
			
				|  |  |  |  |   for _, child := range(event.Children()) { | 
		
	
		
			
				|  |  |  |  |     signal := NewSignal(event, "abort") | 
		
	
		
			
				|  |  |  |  |     signal.description = child.ID() | 
		
	
		
			
				|  |  |  |  |     SendUpdate(child, signal) | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   event.UnlockChildren() | 
		
	
		
			
				|  |  |  |  |   return nil | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func LockResources(event Event) error { | 
		
	
	
		
			
				
					|  |  |  | @ -287,14 +316,10 @@ func EventWait(event Event) (func() (string, error)) { | 
		
	
		
			
				|  |  |  |  |       } else { | 
		
	
		
			
				|  |  |  |  |         log.Logf("event", "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.Logf("event", "EVENT_HANDLER: %s - %s", event.Name(), signal.Type()) | 
		
	
		
			
				|  |  |  |  |           return signal_fn(signal) | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |       signal_fn, exists := event.Handler(signal.Type()) | 
		
	
		
			
				|  |  |  |  |       if exists == true { | 
		
	
		
			
				|  |  |  |  |         log.Logf("event", "EVENT_HANDLER: %s - %s", event.Name(), signal.Type()) | 
		
	
		
			
				|  |  |  |  |         return signal_fn(signal) | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |       return "wait", nil | 
		
	
		
			
				|  |  |  |  |     case <- event.Timeout(): | 
		
	
	
		
			
				
					|  |  |  | @ -330,6 +355,8 @@ func NewEvent(name string, description string, required_resources []Resource) (* | 
		
	
		
			
				|  |  |  |  |   event_ptr := &event | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   event_ptr.actions["wait"] = EventWait(event_ptr) | 
		
	
		
			
				|  |  |  |  |   event_ptr.handlers["abort"] = EventAbort(event_ptr) | 
		
	
		
			
				|  |  |  |  |   event_ptr.handlers["cancel"] = EventCancel(event_ptr) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   event_ptr.actions["start"] = func() (string, error) { | 
		
	
		
			
				|  |  |  |  |     return "", nil | 
		
	
	
		
			
				
					|  |  |  | @ -372,6 +399,8 @@ func NewEventQueue(name string, description string, required_resources []Resourc | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   queue.actions["wait"] = EventWait(queue) | 
		
	
		
			
				|  |  |  |  |   queue.handlers["abort"] = EventAbort(queue) | 
		
	
		
			
				|  |  |  |  |   queue.handlers["cancel"] = EventCancel(queue) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   queue.actions["start"] = func() (string, error) { | 
		
	
		
			
				|  |  |  |  |     return "queue_event", nil | 
		
	
	
		
			
				
					|  |  |  | @ -389,7 +418,6 @@ func NewEventQueue(name string, description string, required_resources []Resourc | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     sort.SliceStable(copied_events, less) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     wait := false | 
		
	
		
			
				|  |  |  |  |     needed_resources := map[string]Resource{} | 
		
	
		
			
				|  |  |  |  |     for _, event := range(copied_events) { | 
		
	
		
			
				|  |  |  |  |       // make sure all the required resources are registered to update the event
 | 
		
	
	
		
			
				
					|  |  |  | @ -399,7 +427,6 @@ func NewEventQueue(name string, description string, required_resources []Resourc | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       info := queue.ChildInfo(event).(*EventQueueInfo) | 
		
	
		
			
				|  |  |  |  |       if info.state == "queued" { | 
		
	
		
			
				|  |  |  |  |         wait = true | 
		
	
		
			
				|  |  |  |  |         // Try to lock it
 | 
		
	
		
			
				|  |  |  |  |         err := LockResources(event) | 
		
	
		
			
				|  |  |  |  |         // start in new goroutine
 | 
		
	
	
		
			
				
					|  |  |  | @ -418,8 +445,6 @@ func NewEventQueue(name string, description string, required_resources []Resourc | 
		
	
		
			
				|  |  |  |  |             FinishEvent(event) | 
		
	
		
			
				|  |  |  |  |           }(event, info, queue) | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |       } else if info.state == "running" { | 
		
	
		
			
				|  |  |  |  |         wait = true | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -435,11 +460,7 @@ func NewEventQueue(name string, description string, required_resources []Resourc | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     queue.UnlockChildren() | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     if wait == true { | 
		
	
		
			
				|  |  |  |  |       return "wait", nil | 
		
	
		
			
				|  |  |  |  |     } else { | 
		
	
		
			
				|  |  |  |  |       return "", nil | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return "wait", nil | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   queue.handlers["resource_connected"] = func(signal GraphSignal) (string, error) { | 
		
	
	
		
			
				
					|  |  |  | @ -509,3 +530,52 @@ func (event * BaseEvent) addChild(child Event, info EventInfo) { | 
		
	
		
			
				|  |  |  |  |   event.children = append(event.children, child) | 
		
	
		
			
				|  |  |  |  |   event.child_info[child.ID()] = info | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type GQLEvent struct { | 
		
	
		
			
				|  |  |  |  |   BaseEvent | 
		
	
		
			
				|  |  |  |  |   abort chan error | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func NewGQLEvent(listen string, child Event) * GQLEvent { | 
		
	
		
			
				|  |  |  |  |   event := &GQLEvent{ | 
		
	
		
			
				|  |  |  |  |     BaseEvent: NewBaseEvent("GQL Handler", "", []Resource{}), | 
		
	
		
			
				|  |  |  |  |     abort: make(chan error, 1), | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   event.actions["wait"] = EventWait(event) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   event.handlers["abort"] = func (signal GraphSignal) (string, error) { | 
		
	
		
			
				|  |  |  |  |     if signal.Description() == event.ID() { | 
		
	
		
			
				|  |  |  |  |       event.abort <- nil | 
		
	
		
			
				|  |  |  |  |       AbortChildren(event) | 
		
	
		
			
				|  |  |  |  |       return "", errors.New(fmt.Sprintf("%s aborted by signal", event.ID())) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return "wait", nil | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   event.handlers["cancel"] = func (signal GraphSignal) (string, error) { | 
		
	
		
			
				|  |  |  |  |     if signal.Description() == event.ID() { | 
		
	
		
			
				|  |  |  |  |       event.abort <- nil | 
		
	
		
			
				|  |  |  |  |       CancelChildren(event) | 
		
	
		
			
				|  |  |  |  |       return "", nil | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return "wait", nil | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   event.actions["start"] = func() (string, error) { | 
		
	
		
			
				|  |  |  |  |     // start the gql handler goroutine
 | 
		
	
		
			
				|  |  |  |  |     log.Logf("gql", "Starting GQL thread for %s", event.ID()) | 
		
	
		
			
				|  |  |  |  |     go func(event * GQLEvent) { | 
		
	
		
			
				|  |  |  |  |       for true { | 
		
	
		
			
				|  |  |  |  |         select { | 
		
	
		
			
				|  |  |  |  |         case <- event.abort: | 
		
	
		
			
				|  |  |  |  |           log.Logf("gql", "Stopping GQL thread for %s", event.ID()) | 
		
	
		
			
				|  |  |  |  |           break | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |     }(event) | 
		
	
		
			
				|  |  |  |  |     return "wait", nil | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return event | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | 
 |