Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[proposal] Add an extension interceptor for the Root Field (RootFieldInterceptor) #1646

Closed
CoreyWinkelmannPP opened this issue Oct 6, 2021 · 1 comment

Comments

@CoreyWinkelmannPP
Copy link
Contributor

When implementing an extension for gqlgen to wire in monitoring for New Relic I noticed there is no way to segment out the Root Field execution separate from the rest of the fields. My hope is to implement a new Intercept interface to accomplish this capability. Something like the following.

	RootFieldInterceptor interface {
		InterceptRootField(ctx context.Context, next RootResolver) Marshaler
	}

This would wrap the marshaler logic within the object.gotpl file when $object.Root. Here is the example within the $field.IsConcurrent section.

        case "{{$field.Name}}":
            {{- if $field.IsConcurrent }}
                field := field

                innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
                    defer func() {
                        if r := recover(); r != nil {
                            ec.Error(ctx, ec.Recover(ctx, r))
                        }
                    }()
                    res = ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
                    {{- if $field.TypeReference.GQL.NonNull }}
                        if res == graphql.Null {
                            {{- if $object.IsConcurrent }}
                                atomic.AddUint32(&invalids, 1)
                            {{- else }}
                                invalids++
                            {{- end }}
                        }
                    {{- end }}
                    return res
                }

                {{if $object.Root}}
                    rrm := func(ctx context.Context) graphql.Marshaler {
                        return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc)
                    }
                {{end}}

                out.Concurrently(i, func() graphql.Marshaler {
                    {{- if $object.Root -}}
                        return rrm(innerCtx)
                    {{- else -}}
                        return innerFunc(ctx)
                    {{end}}
                })

I would also like the name of the root resolver field so I am thinking about moving the WithFieldContext down into the field loop and add in the Field to the FieldContext. I have played around with adding a separate context as well but it seems like it fits within the FieldContext well.

	for i, field := range fields {
        {{- if $object.Root }}
            innerCtx = graphql.WithFieldContext(ctx, &graphql.FieldContext{
                Object: {{$object.Name|quote}},
                Field: field,
            })
        {{end}}

(Full diff of changes can be found here)

@CoreyWinkelmannPP CoreyWinkelmannPP changed the title Proposal: Add an extension intercepter for the Root Field (RootFieldInterceptor) Proposal: Add an extension interceptor for the Root Field (RootFieldInterceptor) Oct 6, 2021
@CoreyWinkelmannPP CoreyWinkelmannPP changed the title Proposal: Add an extension interceptor for the Root Field (RootFieldInterceptor) [proposal] Add an extension interceptor for the Root Field (RootFieldInterceptor) Oct 6, 2021
@CoreyWinkelmannPP
Copy link
Contributor Author

Closing because PR #1647 was merged in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant