Hello - I am testing out GraphQL Federation in Tyk Dashboard. I was able to setup a simple example, but had an issue with a more complex example. I have two subgraphs that share common types - for example PageInfo from the Relay pagination spec. When I attempt to create the supergraph I get a GraphQL schema error:
there can be only one type named ‘PageInfo’
field ‘PageInfo.endCursor’ can only be defined once
field ‘PageInfo.hasNextPage’ can only be defined once
field ‘PageInfo.hasPreviousPage’ can only be defined once
field ‘PageInfo.startCursor’ can only be defined once
Apollo has introduced a custom directive called @shareable but that does not seem to work with Tyk. It appears to cause an error
tyk-dashboard | time=“Aug 17 17:01:05” level=error msg=“Could not build federated schema” error=“parse graphql document string: external: unexpected literal - got: UNDEFINED want one of: [ON], locations: [{Line:432 Column:75}], path: []
tyk-dashboard | external: invalid directive location: on, locations: [{Line:432 Column:86}], path: []”
Thanks for the quick reply Zaid as always.
Do you have any suggestions as a work around? We were planning on using the Netflix DGS framework for our GraphQL services and it produces some shared enums that are causing issues.
Here is the error when I try to add the second subgraph to my supergraph: Invalid GraphQL schema
there can be only one query type in schema
there can be only one mutation type in schema
there can be only one type named ‘ErrorDetail’
enum value ‘ErrorDetail.DEADLINE_EXCEEDED’ can only be defined once
enum value ‘ErrorDetail.ENHANCE_YOUR_CALM’ can only be defined once
enum value ‘ErrorDetail.FIELD_NOT_FOUND’ can only be defined once
enum value ‘ErrorDetail.INVALID_ARGUMENT’ can only be defined once
enum value ‘ErrorDetail.INVALID_CURSOR’ can only be defined once
enum value ‘ErrorDetail.MISSING_RESOURCE’ can only be defined once
enum value ‘ErrorDetail.SERVICE_ERROR’ can only be defined once
enum value ‘ErrorDetail.TCP_FAILURE’ can only be defined once
enum value ‘ErrorDetail.THROTTLED_CONCURRENCY’ can only be defined once
enum value ‘ErrorDetail.THROTTLED_CPU’ can only be defined once
enum value ‘ErrorDetail.UNIMPLEMENTED’ can only be defined once
enum value ‘ErrorDetail.UNKNOWN’ can only be defined once
there can be only one type named ‘ErrorType’
enum value ‘ErrorType.BAD_REQUEST’ can only be defined once
enum value ‘ErrorType.FAILED_PRECONDITION’ can only be defined once
enum value ‘ErrorType.INTERNAL’ can only be defined once
enum value ‘ErrorType.NOT_FOUND’ can only be defined once
enum value ‘ErrorType.PERMISSION_DENIED’ can only be defined once
enum value ‘ErrorType.UNAUTHENTICATED’ can only be defined once
enum value ‘ErrorType.UNAVAILABLE’ can only be defined once
enum value ‘ErrorType.UNKNOWN’ can only be defined once
Tyk will not be able to federate these subgraphs unfortunately. You will need to use Apollo gateway to federate the schema. You can then use Tyk on top of Apollo to manage the grapqhl federated graph as a graphql endpoint. But Tyk will not be able to federate your subgraphs for you unfortunately.
we are also testing the combination of Tyk + Netflix DGS + Federation and run into the same problems.
Tyk currently only implements Federation Spec Version 1, so no @shareable can be used. So far understood…
However, according to Federation Spec Version 1, it should still be possible for the sub schemas to successfully merge into a federated graph as long as the types are defined identically.
“For enums and unions, all possible values must match across all defining subgraphs. Even if a particular subgraph doesn’t use a particular value, that value still must be defined in the schema.”
Isn’t there maybe another idea (besides moving the federation to the Apollo gateway) or a workaround? Otherwise this problem makes the use of Tyk and Netflix DGS impossible, which would be a pity…
@sefi18 not sure which Tyk version you’re using but there will be a fix coming out in the next release for exactly this. This will be 4.2.0 which is due to be out I think next week or so.
Here’s an excerpt from release notes:
Shared types
Types of the same name can be defined in more than one subgraph (a shared type). This will no longer produce an error if each definition is exactly identical.
Shared types cannot be extended outside of the current subgraph, and the resolved extension must be identical to the resolved extension of the shared type in all other subgraphs (see subgraph normalisation notes). Attempting to extend a shared type will result in an error.
The federated supergraph will include a single definition of a shared type, regardless of how many times it has been identically defined in its subgraphs.
Also there will be improvements to enum normalisation:
Subgraph normalisation before federation
Extensions of types whose base type is defined in the same subgraph will be resolved before an attempt at federation. A valid example involving a shared type:
Subgraph 1:
enum Example { A, B } extend enum Example { C }
Subgraph 2:
enum Example { A, B, C }
The enum named “Example” defined in Subgraph 1 would resolve to be identical to the same-named enum defined in Subgraph 2 before federation takes place. The resulting supergraph would include a single definition of this enum.
thanks for the hint regarding version 4.2, this is indeed exactly what we need.
We tested today again with our graphql subgraphs and the error messages regarding duplicate enum values are gone. Unfortunately there is still one error message left when we try to federate in one supergraph:
Supergraph schema validation failed: ‘there can be only one query type in schema’
We checked different variants of schema definitions but without success.
In my understanding neither query nor mutation type should have an extend or @extends declaration.
What is exactly expected by Tyk in the subgraph schema definitions here?
Is @extends supported for extended entity type definitions? (this what DGS uses instead of “extend type”)
From the error message alone it is difficult to grasp the reason for the problem…
This error occurs when the federated supergraph contains more than one Query operation.
Extending the root operations (Query, Mutation, Subscription) is necessary. The open-source tests for federation are available here, and you’ll notice “extend type Query” appears quite frequently. If you’ve seen contradicting information, please do send it over to me.
With some luck, this above might solve your problem. If not, please don’t hesitate to @ me, and we’ll take it from there.
I have a guess as to what might be causing the problem:
Our microservices are implemented with Netflix DGS and Java. There seems to be a limitation in a dependent GraphQL Java library (graphql-java) that it cannot write “extend type query” to the SDL.
Instead it writes the following:
type Query @extends {
According to Apollo Federation Spec v1 this directive is an alternative and therefore probably supported by Apollo Gateway.
Some libraries such as graphql-java don’t have native support for type extensions in their printer. Apollo Federation supports using an @extends directive in place of extend type to annotate type references
I see support for @extends in the codebase, so my advice would be to try it. There’s some chance it hasn’t been fully integrated into federation, but that’s something I can look at if you can confirm it’s not working.
I can confirm that it does not work with “type Query @extends” for our graphs, which is present in all SDLs.
So far I have tested with three of our original microservices, which have quite big schema definitions.
Maybe I have to boil it down a bit and check it with a less complex example and only two services…
Still, it would be great if you could verify that it’s even possible at the moment!
What’s interesting: It is only the query type the gateway is complaining about. The other types (mutation and federated entities) do not appear in the error message…
Are there any errors? Is federation actually successful? My expectations were one of two things:
Federation fails (with an error)
It works (which clearly it does not)
There’s a possibility that the extension happens successfully but the directive is not removed, which may be a problem. What does the supergraph look like?
Please leave this with me. I’ll do a little bit of preliminary investigation, but I think my suspicions that the @extends directive is not fully integrated into federation might be correct.
If that is the case, I unfortunately cannot promise a time frame under which it would be fixed. Nonetheless, it is certainly something we would want to fix as soon as possible.