2023-07-09 14:30:30 -06:00
|
|
|
package graphvent
|
|
|
|
|
|
|
|
import (
|
2023-07-28 19:32:27 -06:00
|
|
|
"fmt"
|
2023-08-31 19:50:32 -06:00
|
|
|
"time"
|
|
|
|
|
2023-09-18 20:11:50 -06:00
|
|
|
"github.com/google/uuid"
|
2023-07-28 10:04:31 -06:00
|
|
|
)
|
|
|
|
|
2023-10-01 16:45:03 -06:00
|
|
|
type TimeoutSignal struct {
|
2023-10-13 00:32:24 -06:00
|
|
|
ResponseHeader
|
2023-10-01 16:45:03 -06:00
|
|
|
}
|
|
|
|
|
2023-10-13 00:32:24 -06:00
|
|
|
func NewTimeoutSignal(req_id uuid.UUID) *TimeoutSignal {
|
2023-10-01 16:45:03 -06:00
|
|
|
return &TimeoutSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewResponseHeader(req_id),
|
2023-10-01 16:45:03 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-03 00:59:48 -06:00
|
|
|
func (signal TimeoutSignal) String() string {
|
|
|
|
return fmt.Sprintf("TimeoutSignal(%s)", &signal.ResponseHeader)
|
|
|
|
}
|
|
|
|
|
2024-03-04 17:30:42 -07:00
|
|
|
type SignalDirection int
|
|
|
|
const (
|
|
|
|
Up SignalDirection = iota
|
|
|
|
Down
|
|
|
|
Direct
|
|
|
|
)
|
2023-10-01 16:45:03 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type SignalHeader struct {
|
2023-10-01 16:45:03 -06:00
|
|
|
Id uuid.UUID `gv:"id"`
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-07-26 15:08:14 -06:00
|
|
|
|
2023-10-01 16:45:03 -06:00
|
|
|
func (signal SignalHeader) ID() uuid.UUID {
|
|
|
|
return signal.Id
|
|
|
|
}
|
|
|
|
|
2023-09-20 11:05:47 -06:00
|
|
|
func (header SignalHeader) String() string {
|
2024-03-04 17:30:42 -07:00
|
|
|
return fmt.Sprintf("SignalHeader(%s)", header.Id)
|
2023-10-01 16:45:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type ResponseSignal interface {
|
|
|
|
Signal
|
|
|
|
ResponseID() uuid.UUID
|
|
|
|
}
|
|
|
|
|
|
|
|
type ResponseHeader struct {
|
|
|
|
SignalHeader
|
|
|
|
ReqID uuid.UUID `gv:"req_id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (header ResponseHeader) ResponseID() uuid.UUID {
|
|
|
|
return header.ReqID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (header ResponseHeader) String() string {
|
2024-03-04 17:30:42 -07:00
|
|
|
return fmt.Sprintf("ResponseHeader(%s, %s)", header.Id, header.ReqID)
|
2023-09-20 11:05:47 -06:00
|
|
|
}
|
|
|
|
|
2023-07-26 15:08:14 -06:00
|
|
|
type Signal interface {
|
2023-09-20 11:05:47 -06:00
|
|
|
fmt.Stringer
|
2023-10-01 16:45:03 -06:00
|
|
|
ID() uuid.UUID
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
|
2023-10-30 19:40:30 -06:00
|
|
|
func WaitForResponse(listener chan Signal, timeout time.Duration, req_id uuid.UUID) (ResponseSignal, []Signal, error) {
|
|
|
|
signals := []Signal{}
|
2023-08-12 11:26:19 -06:00
|
|
|
var timeout_channel <- chan time.Time
|
|
|
|
if timeout > 0 {
|
|
|
|
timeout_channel = time.After(timeout)
|
|
|
|
}
|
|
|
|
|
|
|
|
for true {
|
|
|
|
select {
|
|
|
|
case signal := <- listener:
|
|
|
|
if signal == nil {
|
2023-10-30 19:40:30 -06:00
|
|
|
return nil, signals, fmt.Errorf("LISTENER_CLOSED")
|
2023-08-12 11:26:19 -06:00
|
|
|
}
|
2023-10-30 19:40:30 -06:00
|
|
|
|
2023-10-01 16:45:03 -06:00
|
|
|
resp_signal, ok := signal.(ResponseSignal)
|
2023-10-30 19:40:30 -06:00
|
|
|
if ok == true && resp_signal.ResponseID() == req_id {
|
|
|
|
return resp_signal, signals, nil
|
|
|
|
} else {
|
|
|
|
signals = append(signals, signal)
|
2023-10-01 16:45:03 -06:00
|
|
|
}
|
|
|
|
|
2023-08-12 11:26:19 -06:00
|
|
|
case <-timeout_channel:
|
2023-10-30 19:40:30 -06:00
|
|
|
return nil, signals, fmt.Errorf("LISTENER_TIMEOUT")
|
2023-08-12 11:26:19 -06:00
|
|
|
}
|
|
|
|
}
|
2023-10-30 19:40:30 -06:00
|
|
|
return nil, signals, fmt.Errorf("UNREACHABLE")
|
2023-08-12 11:26:19 -06:00
|
|
|
}
|
|
|
|
|
2023-10-30 19:40:30 -06:00
|
|
|
//TODO: Add []Signal return as well for other signals
|
2023-08-31 19:50:32 -06:00
|
|
|
func WaitForSignal[S Signal](listener chan Signal, timeout time.Duration, check func(S)bool) (S, error) {
|
2023-07-28 19:32:27 -06:00
|
|
|
var zero S
|
2023-07-30 13:19:51 -06:00
|
|
|
var timeout_channel <- chan time.Time
|
|
|
|
if timeout > 0 {
|
|
|
|
timeout_channel = time.After(timeout)
|
|
|
|
}
|
2023-07-28 19:32:27 -06:00
|
|
|
for true {
|
|
|
|
select {
|
2023-08-08 14:00:17 -06:00
|
|
|
case signal := <- listener:
|
|
|
|
if signal == nil {
|
2023-08-31 19:50:32 -06:00
|
|
|
return zero, fmt.Errorf("LISTENER_CLOSED")
|
2023-07-28 19:32:27 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
sig, ok := signal.(S)
|
|
|
|
if ok == true {
|
|
|
|
if check(sig) == true {
|
|
|
|
return sig, nil
|
2023-07-28 19:32:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case <-timeout_channel:
|
2023-08-31 19:50:32 -06:00
|
|
|
return zero, fmt.Errorf("LISTENER_TIMEOUT")
|
2023-07-28 19:32:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return zero, fmt.Errorf("LOOP_ENDED")
|
|
|
|
}
|
|
|
|
|
2024-03-04 17:30:42 -07:00
|
|
|
func NewSignalHeader() SignalHeader {
|
2023-10-01 16:45:03 -06:00
|
|
|
return SignalHeader{
|
|
|
|
uuid.New(),
|
2023-08-10 23:43:10 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-04 17:30:42 -07:00
|
|
|
func NewResponseHeader(req_id uuid.UUID) ResponseHeader {
|
2023-10-01 16:45:03 -06:00
|
|
|
return ResponseHeader{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewSignalHeader(),
|
2023-10-01 16:45:03 -06:00
|
|
|
req_id,
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-20 19:14:28 -06:00
|
|
|
type SuccessSignal struct {
|
2023-10-01 16:45:03 -06:00
|
|
|
ResponseHeader
|
2023-09-20 19:14:28 -06:00
|
|
|
}
|
2023-11-02 20:58:38 -06:00
|
|
|
|
|
|
|
func (signal SuccessSignal) String() string {
|
2023-11-04 18:56:35 -06:00
|
|
|
return fmt.Sprintf("SuccessSignal(%s)", signal.ResponseHeader)
|
2023-11-02 20:58:38 -06:00
|
|
|
}
|
|
|
|
|
2023-11-14 16:40:17 -07:00
|
|
|
func NewSuccessSignal(req_id uuid.UUID) *SuccessSignal {
|
2023-09-20 19:14:28 -06:00
|
|
|
return &SuccessSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewResponseHeader(req_id),
|
2023-09-20 19:14:28 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type ErrorSignal struct {
|
2023-10-01 16:45:03 -06:00
|
|
|
ResponseHeader
|
2023-08-31 19:50:32 -06:00
|
|
|
Error string
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-09-27 18:28:56 -06:00
|
|
|
func (signal ErrorSignal) String() string {
|
2023-11-04 18:56:35 -06:00
|
|
|
return fmt.Sprintf("ErrorSignal(%s, %s)", signal.ResponseHeader, signal.Error)
|
2023-09-27 18:28:56 -06:00
|
|
|
}
|
2023-11-05 21:18:14 -07:00
|
|
|
func NewErrorSignal(req_id uuid.UUID, fmt_string string, args ...interface{}) *ErrorSignal {
|
2023-08-31 19:50:32 -06:00
|
|
|
return &ErrorSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewResponseHeader(req_id),
|
2023-08-31 19:50:32 -06:00
|
|
|
fmt.Sprintf(fmt_string, args...),
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type ACLTimeoutSignal struct {
|
2023-10-01 16:45:03 -06:00
|
|
|
ResponseHeader
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
|
|
|
func NewACLTimeoutSignal(req_id uuid.UUID) *ACLTimeoutSignal {
|
|
|
|
sig := &ACLTimeoutSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewResponseHeader(req_id),
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
return sig
|
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type StatusSignal struct {
|
|
|
|
SignalHeader
|
2023-09-12 19:40:06 -06:00
|
|
|
Source NodeID `gv:"source"`
|
2024-03-03 16:37:03 -07:00
|
|
|
Changes map[ExtType]Changes `gv:"changes"`
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-10-10 12:53:31 -06:00
|
|
|
func (signal StatusSignal) String() string {
|
|
|
|
return fmt.Sprintf("StatusSignal(%s, %+v)", signal.SignalHeader, signal.Changes)
|
|
|
|
}
|
2024-03-03 16:37:03 -07:00
|
|
|
func NewStatusSignal(source NodeID, changes map[ExtType]Changes) *StatusSignal {
|
2023-08-31 19:50:32 -06:00
|
|
|
return &StatusSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewSignalHeader(),
|
2023-08-31 19:50:32 -06:00
|
|
|
source,
|
2023-10-10 11:23:44 -06:00
|
|
|
changes,
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type LinkSignal struct {
|
|
|
|
SignalHeader
|
2023-09-20 11:05:47 -06:00
|
|
|
NodeID NodeID
|
2023-08-31 19:50:32 -06:00
|
|
|
Action string
|
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
const (
|
|
|
|
LinkActionBase = "LINK_ACTION"
|
|
|
|
LinkActionAdd = "ADD"
|
|
|
|
)
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewLinkSignal(action string, id NodeID) Signal {
|
|
|
|
return &LinkSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewSignalHeader(),
|
2023-08-31 19:50:32 -06:00
|
|
|
id,
|
|
|
|
action,
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type LockSignal struct {
|
|
|
|
SignalHeader
|
|
|
|
State string
|
|
|
|
}
|
2023-09-27 18:28:56 -06:00
|
|
|
func (signal LockSignal) String() string {
|
|
|
|
return fmt.Sprintf("LockSignal(%s, %s)", signal.SignalHeader, signal.State)
|
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewLockSignal(state string) *LockSignal {
|
|
|
|
return &LockSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewSignalHeader(),
|
2023-08-31 19:50:32 -06:00
|
|
|
state,
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type ReadSignal struct {
|
|
|
|
SignalHeader
|
|
|
|
Extensions map[ExtType][]string `json:"extensions"`
|
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-11-01 19:32:36 -06:00
|
|
|
func (signal ReadSignal) String() string {
|
|
|
|
return fmt.Sprintf("ReadSignal(%s, %+v)", signal.SignalHeader, signal.Extensions)
|
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewReadSignal(exts map[ExtType][]string) *ReadSignal {
|
|
|
|
return &ReadSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewSignalHeader(),
|
2023-08-31 19:50:32 -06:00
|
|
|
exts,
|
|
|
|
}
|
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type ReadResultSignal struct {
|
2023-10-01 16:45:03 -06:00
|
|
|
ResponseHeader
|
2023-08-31 19:50:32 -06:00
|
|
|
NodeID NodeID
|
|
|
|
NodeType NodeType
|
2024-03-04 17:30:42 -07:00
|
|
|
Extensions map[ExtType]map[string]any
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-11-01 19:32:36 -06:00
|
|
|
|
|
|
|
func (signal ReadResultSignal) String() string {
|
2023-11-04 18:56:35 -06:00
|
|
|
return fmt.Sprintf("ReadResultSignal(%s, %s, %+v, %+v)", signal.ResponseHeader, signal.NodeID, signal.NodeType, signal.Extensions)
|
2023-11-01 19:32:36 -06:00
|
|
|
}
|
|
|
|
|
2024-03-04 17:30:42 -07:00
|
|
|
func NewReadResultSignal(req_id uuid.UUID, node_id NodeID, node_type NodeType, exts map[ExtType]map[string]any) *ReadResultSignal {
|
2023-08-31 19:50:32 -06:00
|
|
|
return &ReadResultSignal{
|
2024-03-04 17:30:42 -07:00
|
|
|
NewResponseHeader(req_id),
|
2023-08-31 19:50:32 -06:00
|
|
|
node_id,
|
|
|
|
node_type,
|
|
|
|
exts,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|