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-09-12 19:40:06 -06:00
|
|
|
type SignalDirection uint8
|
2023-07-09 14:30:30 -06:00
|
|
|
const (
|
|
|
|
Up SignalDirection = iota
|
|
|
|
Down
|
|
|
|
Direct
|
|
|
|
)
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type SignalHeader struct {
|
2023-09-12 19:40:06 -06:00
|
|
|
Direction SignalDirection `gv:"direction"`
|
|
|
|
ID uuid.UUID `gv:"id"`
|
|
|
|
ReqID uuid.UUID `gv:"req_id"`
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-07-26 15:08:14 -06:00
|
|
|
|
2023-09-18 21:43:39 -06:00
|
|
|
func (header SignalHeader) Header() SignalHeader {
|
|
|
|
return header
|
|
|
|
}
|
|
|
|
|
2023-09-20 11:05:47 -06:00
|
|
|
func (header SignalHeader) String() string {
|
2023-09-27 18:28:56 -06:00
|
|
|
return fmt.Sprintf("SignalHeader(%d, %s->%s)", header.Direction, 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-09-18 21:43:39 -06:00
|
|
|
Header() SignalHeader
|
2023-08-10 23:43:10 -06:00
|
|
|
Permission() Tree
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
|
2023-08-12 11:26:19 -06:00
|
|
|
func WaitForResponse(listener chan Signal, timeout time.Duration, req_id uuid.UUID) (Signal, error) {
|
|
|
|
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, fmt.Errorf("LISTENER_CLOSED")
|
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
if signal.Header().ReqID == req_id {
|
2023-08-12 11:26:19 -06:00
|
|
|
return signal, nil
|
|
|
|
}
|
|
|
|
case <-timeout_channel:
|
|
|
|
return nil, fmt.Errorf("LISTENER_TIMEOUT")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("UNREACHABLE")
|
|
|
|
}
|
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewSignalHeader(direction SignalDirection) SignalHeader {
|
2023-08-10 23:43:10 -06:00
|
|
|
id := uuid.New()
|
2023-08-31 19:50:32 -06:00
|
|
|
header := SignalHeader{
|
|
|
|
ID: id,
|
|
|
|
ReqID: id,
|
|
|
|
Direction: direction,
|
2023-08-10 23:43:10 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
return header
|
2023-08-10 23:43:10 -06:00
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewRespHeader(req_id uuid.UUID, direction SignalDirection) SignalHeader {
|
|
|
|
header := SignalHeader{
|
|
|
|
ID: uuid.New(),
|
|
|
|
ReqID: req_id,
|
|
|
|
Direction: direction,
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
return header
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type CreateSignal struct {
|
|
|
|
SignalHeader
|
2023-07-23 21:14:15 -06:00
|
|
|
}
|
|
|
|
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal CreateSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
return Tree{
|
2023-09-05 00:08:09 -06:00
|
|
|
SerializedType(CreateSignalType): nil,
|
2023-07-23 21:14:15 -06:00
|
|
|
}
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
2023-07-21 13:59:52 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewCreateSignal() *CreateSignal {
|
|
|
|
return &CreateSignal{
|
|
|
|
NewSignalHeader(Direct),
|
2023-07-27 16:21:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type StartSignal struct {
|
|
|
|
SignalHeader
|
2023-07-27 18:37:06 -06:00
|
|
|
}
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal StartSignal) Permission() Tree {
|
2023-08-10 23:43:10 -06:00
|
|
|
return Tree{
|
2023-09-05 00:08:09 -06:00
|
|
|
SerializedType(StartSignalType): nil,
|
2023-08-10 23:43:10 -06:00
|
|
|
}
|
2023-07-28 10:04:31 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewStartSignal() *StartSignal {
|
|
|
|
return &StartSignal{
|
|
|
|
NewSignalHeader(Direct),
|
2023-07-21 13:59:52 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-28 11:59:01 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type StopSignal struct {
|
|
|
|
SignalHeader
|
2023-08-10 23:43:10 -06:00
|
|
|
}
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal StopSignal) Permission() Tree {
|
2023-08-10 23:43:10 -06:00
|
|
|
return Tree{
|
2023-09-05 00:08:09 -06:00
|
|
|
SerializedType(StopSignalType): nil,
|
2023-08-10 23:43:10 -06:00
|
|
|
}
|
2023-07-31 19:22:33 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewStopSignal() *StopSignal {
|
|
|
|
return &StopSignal{
|
|
|
|
NewSignalHeader(Direct),
|
2023-07-28 11:59:01 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-28 12:46:06 -06:00
|
|
|
|
2023-09-20 19:14:28 -06:00
|
|
|
type SuccessSignal struct {
|
|
|
|
SignalHeader
|
|
|
|
}
|
|
|
|
func (signal SuccessSignal) Permission() Tree {
|
|
|
|
return Tree{
|
|
|
|
ResultType: {
|
|
|
|
SerializedType(SuccessSignalType): nil,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func NewSuccessSignal(req_id uuid.UUID) Signal {
|
|
|
|
return &SuccessSignal{
|
|
|
|
NewRespHeader(req_id, Direct),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type ErrorSignal struct {
|
|
|
|
SignalHeader
|
|
|
|
Error string
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-09-27 18:28:56 -06:00
|
|
|
func (signal ErrorSignal) String() string {
|
|
|
|
return fmt.Sprintf("ErrorSignal(%s, %s)", signal.SignalHeader, signal.Error)
|
|
|
|
}
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal ErrorSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
return Tree{
|
2023-09-20 19:14:28 -06:00
|
|
|
ResultType: {
|
|
|
|
SerializedType(ErrorSignalType): nil,
|
|
|
|
},
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewErrorSignal(req_id uuid.UUID, fmt_string string, args ...interface{}) Signal {
|
|
|
|
return &ErrorSignal{
|
|
|
|
NewRespHeader(req_id, Direct),
|
|
|
|
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 {
|
|
|
|
SignalHeader
|
|
|
|
}
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal ACLTimeoutSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
return Tree{
|
2023-09-05 00:08:09 -06:00
|
|
|
SerializedType(ACLTimeoutSignalType): nil,
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
|
|
|
func NewACLTimeoutSignal(req_id uuid.UUID) *ACLTimeoutSignal {
|
|
|
|
sig := &ACLTimeoutSignal{
|
|
|
|
NewRespHeader(req_id, Direct),
|
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"`
|
|
|
|
Status string `gv:"status"`
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal StatusSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
return Tree{
|
2023-09-27 18:28:56 -06:00
|
|
|
StatusType: nil,
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
func NewStatusSignal(source NodeID, status string) *StatusSignal {
|
|
|
|
return &StatusSignal{
|
|
|
|
NewSignalHeader(Up),
|
|
|
|
source,
|
|
|
|
status,
|
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-09-12 20:30:18 -06:00
|
|
|
func (signal LinkSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
return Tree{
|
2023-09-05 00:08:09 -06:00
|
|
|
SerializedType(LinkSignalType): Tree{
|
2023-08-31 19:50:32 -06:00
|
|
|
Hash(LinkActionBase, signal.Action): nil,
|
|
|
|
},
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-09-20 11:05:47 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewLinkSignal(action string, id NodeID) Signal {
|
|
|
|
return &LinkSignal{
|
|
|
|
NewSignalHeader(Direct),
|
|
|
|
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
|
|
|
const (
|
|
|
|
LockStateBase = "LOCK_STATE"
|
|
|
|
)
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal LockSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
return Tree{
|
2023-09-05 00:08:09 -06:00
|
|
|
SerializedType(LockSignalType): Tree{
|
2023-08-31 19:50:32 -06:00
|
|
|
Hash(LockStateBase, signal.State): nil,
|
|
|
|
},
|
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewLockSignal(state string) *LockSignal {
|
|
|
|
return &LockSignal{
|
|
|
|
NewSignalHeader(Direct),
|
|
|
|
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-09-12 20:30:18 -06:00
|
|
|
func (signal ReadSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
ret := Tree{}
|
|
|
|
for ext, fields := range(signal.Extensions) {
|
|
|
|
field_tree := Tree{}
|
|
|
|
for _, field := range(fields) {
|
|
|
|
field_tree[Hash(FieldNameBase, field)] = nil
|
|
|
|
}
|
2023-09-05 00:08:09 -06:00
|
|
|
ret[SerializedType(ext)] = field_tree
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-09-05 00:08:09 -06:00
|
|
|
return Tree{SerializedType(ReadSignalType): ret}
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
|
|
|
func NewReadSignal(exts map[ExtType][]string) *ReadSignal {
|
|
|
|
return &ReadSignal{
|
|
|
|
NewSignalHeader(Direct),
|
|
|
|
exts,
|
|
|
|
}
|
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
|
2023-08-31 19:50:32 -06:00
|
|
|
type ReadResultSignal struct {
|
|
|
|
SignalHeader
|
|
|
|
NodeID NodeID
|
|
|
|
NodeType NodeType
|
|
|
|
Extensions map[ExtType]map[string]SerializedValue
|
|
|
|
}
|
2023-09-12 20:30:18 -06:00
|
|
|
func (signal ReadResultSignal) Permission() Tree {
|
2023-08-31 19:50:32 -06:00
|
|
|
return Tree{
|
2023-09-20 19:14:28 -06:00
|
|
|
ResultType: {
|
|
|
|
SerializedType(ReadResultSignalType): nil,
|
|
|
|
},
|
2023-08-31 19:50:32 -06:00
|
|
|
}
|
2023-07-29 00:28:44 -06:00
|
|
|
}
|
2023-08-31 19:50:32 -06:00
|
|
|
func NewReadResultSignal(req_id uuid.UUID, node_id NodeID, node_type NodeType, exts map[ExtType]map[string]SerializedValue) *ReadResultSignal {
|
|
|
|
return &ReadResultSignal{
|
|
|
|
NewRespHeader(req_id, Direct),
|
|
|
|
node_id,
|
|
|
|
node_type,
|
|
|
|
exts,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|