-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Refactor federation requires to populate on entity via a function #2676
Conversation
@MiguelCastillo @dnerdy @a8m @giautm @vvakame I would appreciate your views on this PR. I'm leaning in favor, as this seems less messy than a lot of other approaches, and could potentially open up some more flexibility for other extensions (e.g. caching, data loading, Ent style eager loading). |
This PR is intended to address when extending a federated entity with a field of an array type containing object (not primitives/scalars) and then adding a field that requires the array field, gqlgen generate generates invalid code. @jesse-apollo @dariuszkuc Questions from some other Khan engineers:
See: |
Following the thread |
The goal is to offer the most versatility with the minimal amount of generated complexity. I didn't see a way to cleanly utilize the current paradigm for all use cases that
We initially took this route and built out some code to test it. However, it didn't seem like a viable approach due to the fact that the requires could have multiple fields, some layered under array(s). This would require generating code to do recursive array initialization and pointer to struct initialization to populate those leaf nodes at multiple levels.
|
@jesse-apollo thanks for this work! the federation spec is fuzzy about whether or not fieldsets are supported in repeated fields. https://www.apollographql.com/docs/federation/federated-types/federated-directives#requires. But yeah i think it makes sense it's supposed to work. At a quick glance it seems like you are generating a function that is called to populate the |
Yes, that's correct. The entity is first resolved and then passed to the generated function along with the representations |
Signed-off-by: Steve Coffman <steve@khanacademy.org>
I know it's WIP, but I regenerated and pushed it to your fork as I'm curious to see if this would be sufficient to pass the https://github.com/apollographql/apollo-federation-subgraph-compatibility suite. Feel free to continue to work on it. |
if _, ok := requiresImports[imp.ImportPath]; ok { | ||
// import exists in both places, remove | ||
delete(requiresImports, imp.ImportPath) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if _, ok := requiresImports[imp.ImportPath]; ok { | |
// import exists in both places, remove | |
delete(requiresImports, imp.ImportPath) | |
} | |
delete(requiresImports, imp.ImportPath) |
You don't need the conditional check, as delete will no-op if the key does not exist
plugin/federation/testdata/entityresolver/generated/federation.requires.go
Show resolved
Hide resolved
plugin/federation/testdata/entityresolver/generated/federation.requires.go
Show resolved
Hide resolved
For users who are happy with the current federation support (those with no need for slices/arrays), I would like for gqlgen to continue to work without configuration changes or any new coding. I think if people do not opt-in, you could still create a generated "PopulateUserRequires" but for them that it would not just be a stub but would continue to provide the current federation support. This would basically be a slight refactor. If you want to add a configuration option so people can opt-in to creating a Also, it would be important to demonstrate an example of taking a stub |
While in general I agree that breaking API changes should be avoided. Hiding this improvement behind an opt-in mechanism is IMHO a bad idea as it leads to two different ways in how data is populated and will most likely end up with user errors. Current implementation is broken for list fields and nullable external fields. I guess you could highlight this in the doc but IMHO that will still lead to user confusion, i.e. how users would know whether to opt-in or use the defaults? in most cases they would try it first with default mechanism, encounter some failure (hopefully during testing and before they deploy to prod) and then try to figure out what went wrong. Unless exception message is self explanatory (right now it is not and I don't think it can be) then finding that their underlying issue is because they didn't opt-in to this mechanism may not be as simple as it sounds. |
This PR does not currently provide an example of how to code a As a result, the current PR is not just a breaking change requiring some minor work to update. This PR change requires a substantial engineering project for every user requiring a deep and nuanced view of both GraphQL and federation. It also substantially increases the scope of work necessary for anyone new who wants to adopt gqlgen with federation support, such as those considering transitioning their backends from other languages. I am going to be on vacation for the next 9 days. I believe my colleague @MiguelCastillo will be able to spend some time mulling this over and seeing what we can do here. |
In my opinion, any real world complex use case that uses federation, will have use case where nested field @require would exist in schema. Ideally Gqlgen library should take care of it (Implicit parsing or explicit on developer). In my Opinion this PR fixes a bug, rather than implementing a corner use case. It changes underlying implementation a bit is debatable but there should not be opt-in/opt-out , this is must have functionality for federation to work for any real world use case. Even if someone does not have nested @require fields dependency initially, they may introduce it at later stage (May be after moving to production) ... even if we mention this on doc people do not read Readme file line by line :) Also we are using this library for our project and due to this bug, we are not able to move forward with it. if this PR merge sooner it would be better for our team. |
Hey, I just merged #2720 which will make the resolver implementation configurable via a new template I wonder if you could similarly facilitate more complicated federation use cases with some sort of optional template? |
Two bugs I found with the changeset:
I've forked this changeset in order to utilize this feature while waiting for this to be merged. If need by I can push my fixes for these to this PR. |
@ldebruijn can you make a small repository that demonstrates federation using your gqlgen fork? |
Following the thread here, we at Shipt would love to see this fix get merged. I will try to help if I see an area where we can contribute. |
@parkerroan can you or your colleagues make a demo federation repository that uses this PR to demonstrate how this could possibly work? |
Yes, we have a demo repo for testing federation features that is pretty lightweight. I will take a look at this PR and test it out, I have not had a chance to really look into the details of this yet to be honest as I just found this PR today. Just reading the thread and description from @jesse-apollo it looks promising. |
Can someone expidite this merge ? |
This PR will break existing federation users, without any examples for how they can fix things. |
Please open a new PR that addresses one or more of the issues without breaking existing users. |
The PR is WIP as I'd like to elicit feedback before regenerating the tests, etc.
This PR addresses several issues:
@external
directive applied on a list which is used in a@requires
field is wrong. #2559The PR creates a new rendered template with functions that pass the requires representations to a generated function with the entity. From here the user can apply the requires data as needed.
The output of the rendered templates looks like this:
We (the Apollo team) think this approach is more flexible and future proof as it handles much more complex use cases like @requires nesting in repeated fields. Our initial approach was to try and extend the existing requires functionality using recursive template rendering but this proved to be complex and difficult to test.
cc @brh55 @dariuszkuc
I have: