2023-04-08 13:58:47 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2023-06-01 13:11:32 -06:00
|
|
|
"log"
|
2023-04-08 13:58:47 -06:00
|
|
|
"sync"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
)
|
|
|
|
|
2023-05-08 21:42:33 -06:00
|
|
|
// Generate a random graphql id
|
2023-05-31 00:37:51 -06:00
|
|
|
func randid() string{
|
2023-04-08 13:58:47 -06:00
|
|
|
uuid_str := uuid.New().String()
|
2023-05-31 00:37:51 -06:00
|
|
|
return uuid_str
|
2023-04-08 13:58:47 -06:00
|
|
|
}
|
|
|
|
|
2023-06-01 22:42:47 -06:00
|
|
|
type GraphSignal interface {
|
|
|
|
Source() GraphNode
|
|
|
|
Type() string
|
|
|
|
Description() string
|
|
|
|
}
|
|
|
|
|
|
|
|
type BaseSignal struct {
|
|
|
|
source GraphNode
|
|
|
|
signal_type string
|
|
|
|
description string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (signal BaseSignal) Source() GraphNode {
|
|
|
|
return signal.source
|
|
|
|
}
|
|
|
|
|
|
|
|
func (signal BaseSignal) Type() string {
|
|
|
|
return signal.signal_type
|
|
|
|
}
|
|
|
|
|
|
|
|
func (signal BaseSignal) Description() string {
|
|
|
|
return signal.description
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSignal(source GraphNode, signal_type string) (BaseSignal) {
|
|
|
|
signal := BaseSignal{
|
|
|
|
source: source,
|
|
|
|
signal_type: signal_type,
|
|
|
|
}
|
|
|
|
return signal
|
|
|
|
}
|
|
|
|
|
2023-05-08 21:42:33 -06:00
|
|
|
// GraphNode is the interface common to both DAG nodes and Event tree nodes
|
2023-04-08 13:58:47 -06:00
|
|
|
type GraphNode interface {
|
|
|
|
Name() string
|
|
|
|
Description() string
|
2023-05-31 00:37:51 -06:00
|
|
|
ID() string
|
2023-06-01 22:42:47 -06:00
|
|
|
Update(update GraphSignal) error
|
|
|
|
RegisterChannel(listener chan GraphSignal)
|
|
|
|
UnregisterChannel(listener chan GraphSignal)
|
|
|
|
UpdateChannel() chan GraphSignal
|
2023-04-08 13:58:47 -06:00
|
|
|
}
|
|
|
|
|
2023-05-08 21:42:33 -06:00
|
|
|
// BaseNode is the most basic implementation of the GraphNode interface
|
|
|
|
// It is used to implement functions common to Events and Resources
|
2023-04-08 13:58:47 -06:00
|
|
|
type BaseNode struct {
|
|
|
|
name string
|
|
|
|
description string
|
2023-05-31 00:37:51 -06:00
|
|
|
id string
|
2023-06-01 22:42:47 -06:00
|
|
|
signal chan GraphSignal
|
2023-04-08 13:58:47 -06:00
|
|
|
listeners_lock sync.Mutex
|
2023-06-01 22:42:47 -06:00
|
|
|
listeners map[chan GraphSignal]chan GraphSignal
|
2023-04-08 13:58:47 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (node * BaseNode) Name() string {
|
|
|
|
return node.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node * BaseNode) Description() string {
|
|
|
|
return node.description
|
|
|
|
}
|
|
|
|
|
2023-05-31 00:37:51 -06:00
|
|
|
func (node * BaseNode) ID() string {
|
2023-04-08 13:58:47 -06:00
|
|
|
return node.id
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new listener channel for the node, add it to the nodes listener list, and return the new channel
|
2023-06-01 13:11:32 -06:00
|
|
|
const listener_buffer = 10
|
2023-06-01 22:42:47 -06:00
|
|
|
func (node * BaseNode) UpdateChannel() chan GraphSignal {
|
|
|
|
new_listener := make(chan GraphSignal, listener_buffer)
|
|
|
|
node.RegisterChannel(new_listener)
|
2023-04-08 13:58:47 -06:00
|
|
|
return new_listener
|
|
|
|
}
|
|
|
|
|
2023-06-01 22:42:47 -06:00
|
|
|
func (node * BaseNode) RegisterChannel(listener chan GraphSignal) {
|
2023-04-08 13:58:47 -06:00
|
|
|
node.listeners_lock.Lock()
|
2023-06-01 22:42:47 -06:00
|
|
|
_, exists := node.listeners[listener]
|
|
|
|
if exists == false {
|
|
|
|
node.listeners[listener] = listener
|
2023-04-08 13:58:47 -06:00
|
|
|
}
|
2023-06-01 22:42:47 -06:00
|
|
|
node.listeners_lock.Unlock()
|
|
|
|
}
|
2023-04-08 13:58:47 -06:00
|
|
|
|
2023-06-01 22:42:47 -06:00
|
|
|
func (node * BaseNode) UnregisterChannel(listener chan GraphSignal) {
|
|
|
|
node.listeners_lock.Lock()
|
|
|
|
_, exists := node.listeners[listener]
|
|
|
|
if exists == false {
|
|
|
|
panic("Attempting to unregister non-registered listener")
|
|
|
|
} else {
|
|
|
|
delete(node.listeners, listener)
|
2023-04-08 13:58:47 -06:00
|
|
|
}
|
|
|
|
node.listeners_lock.Unlock()
|
2023-06-01 22:42:47 -06:00
|
|
|
}
|
2023-04-08 13:58:47 -06:00
|
|
|
|
2023-06-01 22:42:47 -06:00
|
|
|
// Send the update to listener channels
|
|
|
|
func (node * BaseNode) UpdateListeners(update GraphSignal) {
|
|
|
|
node.listeners_lock.Lock()
|
|
|
|
|
|
|
|
for _, listener := range node.listeners {
|
|
|
|
log.Printf("UPDATE_LISTENER %s: %p", node.Name(), listener)
|
|
|
|
listener <- update
|
|
|
|
}
|
|
|
|
|
|
|
|
node.listeners_lock.Unlock()
|
2023-04-08 13:58:47 -06:00
|
|
|
}
|
|
|
|
|
2023-06-01 22:42:47 -06:00
|
|
|
// Basic implementation that sends the signal to the nodes channel
|
|
|
|
func (node * BaseNode) Update(signal GraphSignal) error {
|
|
|
|
log.Printf("UPDATE: BaseNode %s: %+v", node.Name(), signal)
|
|
|
|
node.UpdateListeners(signal)
|
|
|
|
return nil
|
2023-04-08 13:58:47 -06:00
|
|
|
}
|