mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-01-04 07:39:43 -06:00
* feat: dag-style execution * docs: update to reflect new context * ensure no cycles * remove example cycle * linting * lint and small fixes * update deferred rollback * last rollback handling * unset max issues * fix requeue edge case
114 lines
3.0 KiB
Go
114 lines
3.0 KiB
Go
package worker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
func decodeArgsToInterface(fnType reflect.Type) (results interface{}, err error) {
|
|
numIn := fnType.NumIn()
|
|
if numIn != 1 && numIn != 2 {
|
|
return nil, fmt.Errorf("fn must have exactly one or two arguments")
|
|
}
|
|
|
|
firstArg := fnType.In(0)
|
|
|
|
if firstArg.Kind() != reflect.Interface || !firstArg.Implements(reflect.TypeOf((*context.Context)(nil)).Elem()) {
|
|
return nil, fmt.Errorf("first argument must implement context.Context")
|
|
}
|
|
|
|
// second argument should be a pointer to a struct
|
|
if numIn == 2 {
|
|
secondArg := fnType.In(1)
|
|
|
|
if secondArg.Kind() != reflect.Ptr {
|
|
return nil, fmt.Errorf("second argument must be a pointer to a struct")
|
|
}
|
|
|
|
secondArgElem := secondArg.Elem()
|
|
|
|
if secondArgElem.Kind() != reflect.Struct {
|
|
return nil, fmt.Errorf("second argument must be a pointer to a struct")
|
|
}
|
|
|
|
return reflect.New(secondArgElem).Interface(), nil
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func decodeFnArgTypes(fnType reflect.Type) (result []reflect.Type, err error) {
|
|
if fnType.Kind() != reflect.Func {
|
|
return nil, fmt.Errorf("method must be a function")
|
|
}
|
|
|
|
numIn := fnType.NumIn()
|
|
|
|
// if not a function with one or two arguments, return an error
|
|
if numIn != 1 && numIn != 2 {
|
|
return nil, fmt.Errorf("method must have one or two arguments")
|
|
}
|
|
|
|
// if first argument is not a context, return error
|
|
firstArg := fnType.In(0)
|
|
|
|
if firstArg.Kind() != reflect.Interface || !firstArg.Implements(reflect.TypeOf((*context.Context)(nil)).Elem()) {
|
|
return nil, fmt.Errorf("first argument must be context.Context")
|
|
}
|
|
|
|
res := []reflect.Type{firstArg}
|
|
|
|
if numIn == 2 {
|
|
// if second argument is not a pointer to a struct, return error
|
|
secondArg := fnType.In(1)
|
|
|
|
if secondArg.Kind() != reflect.Ptr {
|
|
return nil, fmt.Errorf("second argument must be a pointer to a struct")
|
|
}
|
|
|
|
secondArgElem := secondArg.Elem()
|
|
|
|
if secondArgElem.Kind() != reflect.Struct {
|
|
return nil, fmt.Errorf("second argument must be a pointer to a struct")
|
|
}
|
|
|
|
res = append(res, secondArg)
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func decodeFnReturnTypes(fnType reflect.Type) (result []reflect.Type, err error) {
|
|
if fnType.NumOut() > 2 {
|
|
return nil, fmt.Errorf("fn cannot have more than 2 return values")
|
|
}
|
|
|
|
firstOut := fnType.Out(0)
|
|
|
|
// if there are two args, the first one should be a pointer to a struct
|
|
if fnType.NumOut() == 2 {
|
|
if firstOut.Kind() != reflect.Ptr {
|
|
return nil, fmt.Errorf("first argument must be a pointer to a struct when there are two return values")
|
|
}
|
|
|
|
firstOutElem := firstOut.Elem()
|
|
|
|
if firstOutElem.Kind() != reflect.Struct {
|
|
return nil, fmt.Errorf("first argument must be a pointer to a struct when there are two return values")
|
|
}
|
|
}
|
|
|
|
lastOut := fnType.Out(fnType.NumOut() - 1)
|
|
|
|
if lastOut.Kind() != reflect.Interface || !lastOut.Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
|
return nil, fmt.Errorf("last return value must be error")
|
|
}
|
|
|
|
if fnType.NumOut() == 1 {
|
|
return []reflect.Type{firstOut}, nil
|
|
}
|
|
|
|
return []reflect.Type{firstOut, lastOut}, nil
|
|
}
|