We are upgrading our GraphQL Federation to the latest “@apollo/gateway”: “2.14.4” and find out that it handles fragment on interface differently than the older version.
In the older version, the query plan will interpret fragment to a flat call to subgraph, including the typename field automatically. But in 2.14.4, the call to subgraph now receives the fragment directly without an interpretation and typename is no longer added. That breaks our feature as our subgraph only responds __typename when __typename is present in the input (and our existing queries didn’t include the __typename field)
So I wonder if this is a bug in the @apollo/gateway engine, or maybe our subgraph is encouraged to respond typename ourselves on Interfaces. (I tested with letting subgraph to respond typename regardless of the input, the federation server worked well with it). What is the best practice to use __interface? Is it encourage to exist on fragment in the input queries?
This part of the code in query-planner-js/src/buildPlan.ts suggests that typename should still be added. But in "@apolloapolloapolloapollo/gateway": “2.14.4”, our query didn’t have typename at all.
const reuseQueryFragments = this.config.reuseQueryFragments ?? true;
let fragments = operation.fragments;
if (fragments && !fragments.isEmpty() && reuseQueryFragments) {
// For all subgraph fetches we query `__typename` on every abstract types (see `FetchGroup.toPlanNode`) so if we want
// to have a chance to reuse fragments, we should make sure those fragments also query `__typename` for every abstract type.
fragments = addTypenameFieldForAbstractTypesInNamedFragments(fragments);
} else {
fragments = undefined;
}
Something have caused this part of the code to be skipped. I wonder if it happened to do with the flag this.config.debug.bypassPlannerForSingleSubgraph before the block. I tried a query that makes requests to 2 subgraphs, and the problem persists. (So it wasn’t bypassPlannerForSingleSubgraph)
Can you provide some additional information on what you are encountering and what problems this causes?
Query planner is responsible for generating an “efficient” plan on how to fulfill user request. This involves normalization of a query and then generation of 1+ subgraph fetches to fulfill the user request. Due to the normalization process your incoming queries may not be the same as the ones that gateway sends to the subgraph.
bypassPlannerForSingleSubgraph is an option to skip the planning entirely and pass in the original query to the target subgraph (i.e. skip normalization and query plan generation). This was specifically added for monographs (i.e. single GraphQL subgraph). In this situation, if your original query did not include __typename selection it won’t be include query either.
Referenced section of the code populates __typename defensively (in many cases it may not be needed) and its only used IF you choose a query plan option to reuseQueryFragments (this option attempts to preserve user provided fragments from the original query in the subgraph queries).
If you don’t enable any query optimizations OR use the option to generateQueryFragments (preferred mechanism) then this normalization is not applied at all and __typenames will only be included if needed.
Whether you are using reuseQueryFragments, generateQueryFragments or send uncompressed queries, query planner should generate valid queries. Your queries to the gateway/router should only include what is necessary for the clients. If additional data is necessary (e.g. through @requires or some type condition information) it will be populated by the query planner.