graphvent/signal.go

262 lines
5.3 KiB
Go

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