2023-10-10 18:25:30 -06:00
|
|
|
package graphvent
|
|
|
|
|
|
|
|
import (
|
|
|
|
graphql "github.com/graphql-go/graphql"
|
2023-10-10 19:35:42 -06:00
|
|
|
"github.com/google/uuid"
|
2023-10-10 18:25:30 -06:00
|
|
|
"reflect"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type StructFieldInfo struct {
|
|
|
|
Name string
|
2024-03-03 15:45:45 -07:00
|
|
|
Type *TypeInfo
|
2023-10-10 18:25:30 -06:00
|
|
|
Index []int
|
|
|
|
}
|
|
|
|
|
2024-03-03 15:45:45 -07:00
|
|
|
func ArgumentInfo(ctx *Context, field reflect.StructField, gv_tag string) (StructFieldInfo, error) {
|
|
|
|
type_info, mapped := ctx.TypeReflects[field.Type]
|
|
|
|
if mapped == false {
|
|
|
|
return StructFieldInfo{}, fmt.Errorf("field %+v is of unregistered type %+v ", field.Name, field.Type)
|
|
|
|
}
|
|
|
|
|
|
|
|
return StructFieldInfo{
|
|
|
|
Name: gv_tag,
|
|
|
|
Type: type_info,
|
|
|
|
Index: field.Index,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func SignalFromArgs(ctx *Context, signal_type reflect.Type, fields []StructFieldInfo, args map[string]interface{}, id_index, direction_index []int) (Signal, error) {
|
2023-11-13 13:23:58 -07:00
|
|
|
fmt.Printf("FIELD: %+v\n", fields)
|
2023-10-10 18:25:30 -06:00
|
|
|
signal_value := reflect.New(signal_type)
|
2023-10-10 19:35:42 -06:00
|
|
|
|
|
|
|
id_field := signal_value.Elem().FieldByIndex(id_index)
|
|
|
|
id_field.Set(reflect.ValueOf(uuid.New()))
|
|
|
|
|
|
|
|
direction_field := signal_value.Elem().FieldByIndex(direction_index)
|
|
|
|
direction_field.Set(reflect.ValueOf(Direct))
|
|
|
|
|
2023-10-10 18:25:30 -06:00
|
|
|
for _, field := range(fields) {
|
|
|
|
arg, arg_exists := args[field.Name]
|
|
|
|
if arg_exists == false {
|
|
|
|
return nil, fmt.Errorf("No arg provided named %s", field.Name)
|
|
|
|
}
|
|
|
|
field_value := signal_value.Elem().FieldByIndex(field.Index)
|
2024-03-03 15:45:45 -07:00
|
|
|
if field_value.CanConvert(field.Type.Reflect) == false {
|
|
|
|
return nil, fmt.Errorf("Arg %s wrong type %s/%s", field.Name, field_value.Type(), field.Type.Reflect)
|
2023-10-10 18:25:30 -06:00
|
|
|
}
|
2024-03-03 15:45:45 -07:00
|
|
|
value, err := field.Type.GQLValue(ctx, arg)
|
2023-10-10 18:25:30 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-11-13 13:23:58 -07:00
|
|
|
fmt.Printf("Setting %s to %+v of type %+v\n", field.Name, value, value.Type())
|
2023-10-10 18:25:30 -06:00
|
|
|
field_value.Set(value)
|
|
|
|
}
|
|
|
|
return signal_value.Interface().(Signal), nil
|
|
|
|
}
|
|
|
|
|
2024-03-03 15:45:45 -07:00
|
|
|
func NewSignalMutation(ctx *Context, name string, send_id_key string, signal_type reflect.Type) (*graphql.Field, error) {
|
2023-10-10 18:25:30 -06:00
|
|
|
args := graphql.FieldConfigArgument{}
|
|
|
|
arg_info := []StructFieldInfo{}
|
2023-10-10 19:35:42 -06:00
|
|
|
var id_index []int = nil
|
|
|
|
var direction_index []int = nil
|
2023-10-10 18:25:30 -06:00
|
|
|
|
|
|
|
for _, field := range(reflect.VisibleFields(signal_type)) {
|
|
|
|
gv_tag, tagged_gv := field.Tag.Lookup("gv")
|
|
|
|
if tagged_gv {
|
|
|
|
if gv_tag == "id" {
|
2023-10-10 19:35:42 -06:00
|
|
|
id_index = field.Index
|
|
|
|
} else if gv_tag == "direction" {
|
|
|
|
direction_index = field.Index
|
|
|
|
} else {
|
|
|
|
_, exists := args[gv_tag]
|
|
|
|
if exists == true {
|
2024-03-03 15:45:45 -07:00
|
|
|
return nil, fmt.Errorf("Signal has repeated tag %s", gv_tag)
|
2023-10-16 00:54:10 -06:00
|
|
|
} else {
|
2024-03-03 15:45:45 -07:00
|
|
|
info, err := ArgumentInfo(ctx, field, gv_tag)
|
2023-10-16 00:54:10 -06:00
|
|
|
if err != nil {
|
2024-03-03 15:45:45 -07:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
args[gv_tag] = &graphql.ArgumentConfig{
|
2023-10-10 19:35:42 -06:00
|
|
|
}
|
2023-10-16 00:54:10 -06:00
|
|
|
arg_info = append(arg_info, info)
|
2023-10-10 18:25:30 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_, send_exists := args[send_id_key]
|
|
|
|
if send_exists == false {
|
|
|
|
args[send_id_key] = &graphql.ArgumentConfig{
|
|
|
|
Type: graphql.String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resolve_signal := func(p graphql.ResolveParams) (interface{}, error) {
|
|
|
|
ctx, err := PrepResolve(p)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
send_id, err := ExtractID(p, send_id_key)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2024-03-03 15:45:45 -07:00
|
|
|
signal, err := SignalFromArgs(ctx.Context, signal_type, arg_info, p.Args, id_index, direction_index)
|
2023-10-10 18:25:30 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
msgs := Messages{}
|
2023-10-14 15:05:23 -06:00
|
|
|
msgs = msgs.Add(ctx.Context, send_id, ctx.Server, ctx.Authorization, signal)
|
2023-10-10 18:25:30 -06:00
|
|
|
|
|
|
|
response_chan := ctx.Ext.GetResponseChannel(signal.ID())
|
|
|
|
err = ctx.Context.Send(msgs)
|
|
|
|
if err != nil {
|
|
|
|
ctx.Ext.FreeResponseChannel(signal.ID())
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-10-30 19:40:30 -06:00
|
|
|
response, _, err := WaitForResponse(response_chan, 100*time.Millisecond, signal.ID())
|
2023-10-10 18:25:30 -06:00
|
|
|
if err != nil {
|
|
|
|
ctx.Ext.FreeResponseChannel(signal.ID())
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, is_success := response.(*SuccessSignal)
|
|
|
|
if is_success == true {
|
|
|
|
return "success", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
error_response, is_error := response.(*ErrorSignal)
|
|
|
|
if is_error == true {
|
|
|
|
return "error", fmt.Errorf(error_response.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("response of unhandled type %s", reflect.TypeOf(response))
|
|
|
|
}
|
|
|
|
|
2024-03-03 15:45:45 -07:00
|
|
|
return &graphql.Field{
|
2023-10-10 18:25:30 -06:00
|
|
|
Type: graphql.String,
|
|
|
|
Args: args,
|
|
|
|
Resolve: resolve_signal,
|
2024-03-03 15:45:45 -07:00
|
|
|
}, nil
|
2023-10-10 18:25:30 -06:00
|
|
|
}
|