NodeFuncWithDynamicInputs is like NodeFunc but lets a resolver customize request/cache behavior for each call (for example argument rewrites, TTL, do-not-cache, or concurrency key).
( name string, fn NodeFuncHandler[T, A, R], cacheFn DynamicInputFunc[T, A], )
| 767 | // request/cache behavior for each call (for example argument rewrites, TTL, |
| 768 | // do-not-cache, or concurrency key). |
| 769 | func NodeFuncWithDynamicInputs[T Typed, A any, R any]( |
| 770 | name string, |
| 771 | fn NodeFuncHandler[T, A, R], |
| 772 | cacheFn DynamicInputFunc[T, A], |
| 773 | ) Field[T] { |
| 774 | var zeroArgs A |
| 775 | inputs, argsErr := InputSpecsForType(zeroArgs, true) |
| 776 | if argsErr != nil { |
| 777 | var zeroSelf T |
| 778 | slog.Error("failed to parse args", "type", zeroSelf.Type(), "field", name, "error", argsErr) |
| 779 | } |
| 780 | |
| 781 | spec := &FieldSpec{ |
| 782 | Name: name, |
| 783 | Args: inputs, |
| 784 | } |
| 785 | |
| 786 | var zeroRet R |
| 787 | var returnTypeError error |
| 788 | if res, ok := any(zeroRet).(AnyResult); ok { |
| 789 | spec.Type = res.Unwrap() |
| 790 | } else { |
| 791 | spec.Type, returnTypeError = builtinOrTyped(zeroRet) |
| 792 | } |
| 793 | |
| 794 | field := Field[T]{ |
| 795 | Spec: spec, |
| 796 | Func: func(ctx context.Context, self ObjectResult[T], argVals map[string]Input, view call.View) (AnyResult, error) { |
| 797 | // these errors are deferred until runtime, since it's better (at least |
| 798 | // more testable) than panicking |
| 799 | if argsErr != nil { |
| 800 | return nil, argsErr |
| 801 | } |
| 802 | if returnTypeError != nil { |
| 803 | return nil, returnTypeError |
| 804 | } |
| 805 | |
| 806 | var args A |
| 807 | if err := spec.Args.Decode(argVals, &args, view); err != nil { |
| 808 | return nil, err |
| 809 | } |
| 810 | ret, err := fn(ctx, self, args) |
| 811 | if err != nil { |
| 812 | return nil, err |
| 813 | } |
| 814 | |
| 815 | if res, ok := any(ret).(AnyResult); ok { |
| 816 | return res, nil |
| 817 | } |
| 818 | res, err := builtinOrTyped(ret) |
| 819 | if err != nil { |
| 820 | return nil, fmt.Errorf("expected %T to be a Typed value, got %T: %w", ret, ret, err) |
| 821 | } |
| 822 | |
| 823 | return NewResultForCurrentCall(ctx, res) |
| 824 | }, |
| 825 | } |
| 826 |