diff --git a/router/core/graphql_handler.go b/router/core/graphql_handler.go index feb745390a..f64eec8c9b 100644 --- a/router/core/graphql_handler.go +++ b/router/core/graphql_handler.go @@ -243,7 +243,15 @@ func (h *GraphQLHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } - info, err := h.executor.Resolver.ArenaResolveGraphQLResponse(resolveCtx, p.Response, hpw) + var ( + info *resolve.GraphQLResolveInfo + err error + ) + if bytecodePlan := reqCtx.operation.preparedPlan.bytecodePlan; bytecodePlan.FastPathReady() { + info, err = h.executor.Resolver.ArenaResolveGraphQLResponseBytecode(resolveCtx, p.Response, bytecodePlan, hpw) + } else { + info, err = h.executor.Resolver.ArenaResolveGraphQLResponse(resolveCtx, p.Response, hpw) + } reqCtx.dataSourceNames = getSubgraphNames(p.Response.DataSources) if err != nil { trackFinalResponseError(resolveCtx.Context(), err) diff --git a/router/core/operation_planner.go b/router/core/operation_planner.go index f9da57396f..92d023a090 100644 --- a/router/core/operation_planner.go +++ b/router/core/operation_planner.go @@ -5,6 +5,7 @@ import ( "strconv" "time" + "github.com/jensneuse/abstractlogger" "golang.org/x/sync/singleflight" graphqlmetricsv1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/graphqlmetrics/v1" @@ -13,12 +14,15 @@ import ( "github.com/wundergraph/graphql-go-tools/v2/pkg/ast" "github.com/wundergraph/graphql-go-tools/v2/pkg/astparser" "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/plan" + "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/planbytecode" + "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/planbytecode/compiler" "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/postprocess" "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/resolve" ) type planWithMetaData struct { preparedPlan plan.Plan + bytecodePlan *planbytecode.Program operationDocument, schemaDocument *ast.Document typeFieldUsageInfo []*graphqlschemausage.TypeFieldUsageInfo argumentUsageInfo []*graphqlmetricsv1.ArgumentUsageInfo @@ -92,9 +96,18 @@ func (p *OperationPlanner) planOperation(content string, name string, includeQue } post := postprocess.NewProcessor(postprocess.CollectDataSourceInfo()) post.Process(preparedPlan) + var bytecodePlan *planbytecode.Program + if compiledPlan, err := compiler.Compile(preparedPlan); err != nil { + if p.executor.PlanConfig.Logger != nil { + p.executor.PlanConfig.Logger.Warn("Failed to compile bytecode execution plan; falling back to standard resolver path", abstractlogger.Error(err)) + } + } else if compiledPlan != nil { + bytecodePlan = compiledPlan + } return &planWithMetaData{ preparedPlan: preparedPlan, + bytecodePlan: bytecodePlan, operationDocument: &doc, schemaDocument: p.executor.RouterSchema, }, nil