[resolvers][federation] Bring Federation reference selection set to ResolversParentTypes instead of each resolver #10297
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Ref CODEGEN-512
Description
Context
A Federation entity's resolvers may be triggered by one of these two paths:
__resolveReference
to resolve the relevant fieldLet's look at this example:
The following query triggers the 1st scenario for
User.name
:When the 1st scenario triggers, it behaves like a non-Federated Graph i.e.
User.name
'sParent
isUser
The following query triggers the 2nd scenario for
User.name
:In this scenario:
__resolveReference
receives{__typename: 'User', id: string}
as ref__resolveReference
is not declared,{__typename: 'User', id: string}
is automatically passed on and becomes theUser.name
'sParent
Breaking Change Proposal
Currently,
User.name
'sParent
type:{ __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>
if a field is marked as@external
(implemented in here but I don't agree with this implementation, or my understanding of@external
is wrong 🤔 ) ...User
...... but never both at the same time.
This is not correct because there are two ways to get to
User.name
so theParent
should be eitherUser
or{ __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>
.So, here's how I think this should be changed for a federated entity (
User
in this case):ResolversParentTypes['User']
should beUser | { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>
(plus any extra possibilities from added by@provides
- More on this in another PR)User.name
need to know/check the parent, because we don't know which flow it comes from.UserMapper
is used, then both paths require the previous resolver to return theUserMapper
. i.e.ResolversParentTypes['User']
simply becomesUserMapper
(existing behaviour)__resolveReference
MUST be explicitly implemented to turn ref intoUserMapper
This solution makes it simpler to write plugin code, because we "normalise" both paths'
Parent
types. However, (*) and (**) could cause friction for users to understand and use - unless we make Server Preset to auto generate resolvers, to make sure users implement resolvers to return mappers, to avoid runtime errors for Federation use cases (which can be done)Type of change
How Has This Been Tested?