mercurius: Using fastify-gql in place of Apollo Gateway does not work
Hi,
As a proof of concept, I tried taking this demo repository and replace Apollo Gateway with fastify-gql. The federated services start fine (as expected). Then, when I try to start the Gateway server, I get this error:
Error: The directive "@key" can only be used once at this location.
at assertValidSDLExtension (/Users/julienheller/projects/federation-demo/node_modules/graphql/validation/validate.js:124:11)
at extendSchema (/Users/julienheller/projects/federation-demo/node_modules/graphql/utilities/extendSchema.js:78:45)
at buildFederationSchema (/Users/julienheller/projects/federation-demo/node_modules/fastify-gql/lib/federation.js:253:22)
at buildGateway (/Users/julienheller/projects/federation-demo/node_modules/fastify-gql/lib/gateway.js:151:18)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async fp.name (/Users/julienheller/projects/federation-demo/node_modules/fastify-gql/index.js:119:15)
My guess is that both the original definition for Product
and its extended clause have a @key
directive, which are trying to be merged together. I wonder how Apollo handles this situation?
Here’s my fork to try it for yourself.
npm i
npm run start-services
npm run start-fastify-gateway
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (4 by maintainers)
I’ve spent more time debugging this, and I have come to the conclusion that my understanding of the issue as expressed in the previous message was incomplete.
Here’s my new understanding:
gets added to the schema as is, still retaining the
@key
part 2. Apollo-server overcomes the error we are getting by callingextendSchema
with the optionassumeValidSDL
as @flux627 suggested at one point. See it here: https://github.com/apollographql/apollo-server/blob/00887a1e57a26075483ba397098f6d088a706499/packages/apollo-federation/src/composition/compose.ts#L373 3. Apollo-server however add its own validations before extending the schema: https://github.com/apollographql/apollo-server/blob/00887a1e57a26075483ba397098f6d088a706499/packages/apollo-federation/src/composition/compose.ts#L371. It uses a private function fromgraphql-js
:validateSDL
. It’s the same function function used internally by validateSchema, but apollo-server replaces the rules it usesI’m working on a PR to replicate the behaviour by calling
extendSchema
withassumeValidSDL
set to true but also adding the validations.Let me rephrase that. The Apollo docs clearly state that when extending entities, the
extend
must include the same@key
directive as the original type definition. This is the case for stubs and actual extensions.As far as I can see, this is not the case - or at least it’s not enforced at the
graphql-js
level. Fastify-gql builds the schema inbuildFederationSchema
(https://github.com/mcollina/fastify-gql/blob/master/lib/federation.js#L230). In there the concatenation of the schemas from the federated services is parsed and then split in type stubs, extensions and definitions. It then proceed to make a call to extendSchema with each of those three groups.The error we get in the demo repository (and also in fastify-gql own example in https://github.com/mcollina/fastify-gql/blob/master/examples/gateway-subscription.js) is thrown by the call to
extendSchema
that tries to add all extensions at the same time. This happens regardless of how many type extensions with the same@key
directive have been added beforehand: the problem is just with callingextendSchema
with the extend for the same type with the same directive.To prove that I made this small change https://github.com/mcollina/fastify-gql/pull/221/files#diff-d9185daf57698ed90d572d1966e61b16R253-R258 where extensions are added one at the time and that fixed the issue: a sign that
extendSchema
is accepting multiple extend with the same key directive if each one happens in their own call toextendSchema
I agree with this. Regardless of what is actually causing the exception we are seeing, the correct implementation would be to replicate the behaviour of Apollo, which is to strip the directives in the federated schema.
I took a look at Apollo’s code and that appears to be happening in https://github.com/apollographql/apollo-server/blob/5bab3aedeeb1e70c636f3aa3ac7a147679f450f7/packages/apollo-federation/src/composition/normalize.ts#L20 (more specifically in https://github.com/apollographql/apollo-server/blob/5bab3aedeeb1e70c636f3aa3ac7a147679f450f7/packages/apollo-federation/src/composition/normalize.ts#L270).
So, to sum up my point:
parse
andextendSchema
fromgraphql-js
weird: a schema parsed without errors byparse
throws and error inextendSchema
, and that also depends on the fact that you make only one call or multiple calls to it. May be worth further investigating into this and report tographql-js
fastify-gql
should replicate Apollo’s behaviour and strip the directives