diff --git a/execution/engine/execution_engine.go b/execution/engine/execution_engine.go index 5c03e926a1..27c7a46df1 100644 --- a/execution/engine/execution_engine.go +++ b/execution/engine/execution_engine.go @@ -53,10 +53,6 @@ func (e *internalExecutionContext) setVariables(variables []byte) { } } -func (e *internalExecutionContext) reset() { - e.resolveContext.Free() -} - type ExecutionEngine struct { logger abstractlogger.Logger config Configuration @@ -238,7 +234,7 @@ func (e *ExecutionEngine) Execute(ctx context.Context, operation *graphql.Reques return err } if resp != nil { - operation.ComputeActualCost(costCalculator, e.config.plannerConfig, resp.ActualListSizes) + operation.ComputeActualCost(costCalculator, e.config.plannerConfig, execContext.resolveContext.ActualListSizes) } return nil case *plan.SubscriptionResponsePlan: diff --git a/v2/pkg/engine/resolve/context.go b/v2/pkg/engine/resolve/context.go index dfa481b281..0b3e626f1b 100644 --- a/v2/pkg/engine/resolve/context.go +++ b/v2/pkg/engine/resolve/context.go @@ -45,6 +45,11 @@ type Context struct { SubgraphHeadersBuilder SubgraphHeadersBuilder + // ActualListSizes is populated by the resolver after resolution completes, + // before the response body is written. Maps JSON path to actual list size. + // Used to compute the actual cost. + ActualListSizes map[string]int + // GetDeduplicationData is called after the leader of an inbound singleflight request // finishes resolving. It extracts data from the leader's context (e.g. accumulated // response headers) that should be shared with all follower requests. @@ -315,6 +320,7 @@ func (c *Context) Free() { c.LoaderHooks = nil c.GetDeduplicationData = nil c.SetDeduplicationData = nil + c.ActualListSizes = nil } type traceStartKey struct{} diff --git a/v2/pkg/engine/resolve/resolve.go b/v2/pkg/engine/resolve/resolve.go index 6ce431b50a..f735752ef9 100644 --- a/v2/pkg/engine/resolve/resolve.go +++ b/v2/pkg/engine/resolve/resolve.go @@ -319,10 +319,6 @@ type GraphQLResolveInfo struct { // ResolveDeduplicated indicates whether the resolution of the entire operation was deduplicated via single flight ResolveDeduplicated bool - - // ActualListSizes maps the JSON path to the actual list size in the response. - // Used to compute the actual cost. - ActualListSizes map[string]int } func (r *Resolver) ResolveGraphQLResponse(ctx *Context, response *GraphQLResponse, data []byte, writer io.Writer) (*GraphQLResolveInfo, error) { @@ -354,7 +350,7 @@ func (r *Resolver) ResolveGraphQLResponse(ctx *Context, response *GraphQLRespons return nil, err } - resp.ActualListSizes = t.resolvable.actualListSizes + ctx.ActualListSizes = t.resolvable.actualListSizes return resp, err } @@ -415,6 +411,7 @@ func (r *Resolver) ArenaResolveGraphQLResponse(ctx *Context, response *GraphQLRe r.responseBufferPool.Release(responseArena) return nil, err } + ctx.ActualListSizes = t.resolvable.actualListSizes // first release resolverArena // all data is resolved and written into the response arena @@ -436,9 +433,6 @@ func (r *Resolver) ArenaResolveGraphQLResponse(ctx *Context, response *GraphQLRe // all data is written to the client // we're safe to release our buffer r.responseBufferPool.Release(responseArena) - - resp.ActualListSizes = t.resolvable.actualListSizes - return resp, err }