-
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
Apollo Federation MVP #851
Conversation
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.
Very nice work! Here a tiny review 😊
Thanks again!
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.
Nice work, the code looks good.
I was hoping for more feedback from people who want to use this. I don't think there are any BC breaks in here though so let's get this ready to ship and iterate.
Might be nice to enumerate the current known limitations in the PR description (eg currently only supports single field simple keys)
@@ -95,6 +95,18 @@ func (b *builder) bindField(obj *Object, f *Field) error { | |||
f.GoReceiverName = "ec" | |||
f.GoFieldName = "introspectType" | |||
return nil | |||
case f.Name == "_entities": |
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.
does this generate invalid code if the plugin is missing? perhaps this should be injected by the plugin?
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.
It would be nice to have a mechanism that can be extended with plugins.
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.
@vektah maybe if the user has an _entities
query without federation...we can possibly check cfg.Federated && f.Name == _entities
... that said, it would be great if the plugin can inject this part, but it looks like there's no way right now...can you confirm? Thanks!
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.
Welcome back!
I wonder if we could add something to TypeMapField
in config that replaces all of this logic?
type TypeMapField struct {
Resolver bool `yaml:"resolver"`
FieldName string `yaml:"fieldName"`
// new
GeneratedMethod string `yaml:"-"`
}
which would be set here to reference __resolve_entities
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.
@vektah that's an interesting idea...I'll give it a shot 👍
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.
Actually, TypeMapField is in MutateConfig
not MutateSchema
where you linked above, can you expand more on how that would work? Thanks!
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.
Lets leave it like this for now and get this on master. Might do some cleanup once it lands to make this more pluggable.
plugin/federation/federation.go
Outdated
for _, ent := range f.Entities { | ||
union.Types = append(union.Types, ent.Name) | ||
s.AddPossibleType("_Entity", ent.Def) | ||
// s.AddImplements(ent.Name, union) // Do we need this? |
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.
I think this is what's causing the if ent
in model gen.
https://github.com/99designs/gqlgen/pull/851/files#diff-777f78d80bba845e7f5493310d21fce6R119
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.
@vektah does that mean I won't need to check for the key
directive if I add this line?
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.
Nevermind, I uncommented the line and it added _Entity to implementors
. This seems to only be used in fragment-related things?
|
||
// Entity represents a federated type | ||
// that was declared in the GQL schema. | ||
type Entity struct { |
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.
I think I would prefer if this referenced the underlying types where possible, rather than copying them just out, just in case another plugin is modifying them.
- We already have
Def
, soName
is redundant - FieldName and FieldTypeGQL come from
FieldDef
, so let's add that instead?
If we apply the same logic to RequireField
I think it can be replaced entirely by a codegen.Field
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.
@vektah I did it for Def
and FieldDef
. However, RequireField
would make setEntities
create a dummy codegen.Field
so I can have a Name to match against in GenerateCode
, then GenerateCode
will have to replace its codegen.Field with the dummy one which fields a bit ugly. Would you like me to switch that up as well?
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 Apollo federation completely separate plugin from gqlgen core code, It's greatful works!
so, plugin system is still developing. this work is very good as a space explorer, I think.
Please tell me anything I can do. 😉
@@ -95,6 +95,18 @@ func (b *builder) bindField(obj *Object, f *Field) error { | |||
f.GoReceiverName = "ec" | |||
f.GoFieldName = "introspectType" | |||
return nil | |||
case f.Name == "_entities": |
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.
It would be nice to have a mechanism that can be extended with plugins.
There are some other users over in #740, but for us (Khan Academy) I can say we're already using this and are very happy to see it merged! |
Interested in |
couple issues I've found while messing with this
service:
filename: "..."
package: "..."
(edit: thinking about it, would it make sense for service.go to be part of exec package? Wondering why it was decided to be a separate file, it would solve the first 3 issues I've run into) should be a way for users to define the federation spec (for external validations or the schema files) and fill in the blanks (of it is not provided) lastly, more of a nit pick, but the errors for failed type casting on __resolve_entities func in service.go should be more declarative (ie "Failed casting id to scalar.type", rather than it saying "opsies") Other than that, working pretty well for me. Still doing some testing. I'll report back if I find anything else. Keep up the good work 👍 |
This is great. I'm going to try using this now and will provide feedback if any. |
@marwan-at-work @vektah I have a PR that pulls in the latest gqlgen into @marwan-at-work 's federation branch and fixed the merge conflicts. Here it is: marwan-at-work#3 |
@sothychan that's great thank you 🙏 -- i've been incredibly busy the last couple of months (switched companies), but will get back to this ASAP. |
@marwan-at-work I'm running into a weird issue saying "_Entity not found in typemap" when I bind models. I'm going to look into why and submit a PR. |
hi, I tried to implement https://github.com/apollographql/federation-demo by gqlgen with this PR. I can make public my repository but federation-demo repository's license is unclear. |
Any new development in this area? We are starting to look for a service-oriented graphql, and the federation would be perfect for that. Any changes to get this moving? |
@nurdism We implemented the filename specifier here |
Now that I'm fully onboarded with my new job...I'm very happy to come back to this, I've cleared my Sunday for this PR 👍 Hopefully I can wrap it up within that day but I did notice there are some merge conflicts also when I generate tests a lot of them do fail...although federation itself works okay 😄 |
8fb9130
to
368d546
Compare
@vektah all of the comments are addressed except:
|
@vektah I managed to get the builds to pass but federation tests are still super preliminary. This leaves the field.go which I'd need some guidance as to how to inject into it from the plugin or I can a TODO comment for a follow up PR if that's something that requires more figuring out. Thanks |
Quick question @marwan-at-work. Won't the name _Entity in the generated model give problems for people that use packages for their models, since _Entity isn't exported? |
I've merged the gqlparser pr and tagged a new release. Lets update the this and get it 🚢'd.
Lets ship this as is and iterate on master. |
I think the mod file still needs a version bump to 1.2.1 |
@vektah done |
@marwan-at-work I'm pretty sure it would break as soon as you set the package for exec and model to two different values, since generated.go and service.go needs to use _Entity. |
@jepp2078 now that this is merged, it would be incredibly helpful to open an issue with reproduction steps of how it would break. I can dig into it afterwards, thanks! |
gqlgen - one of the most popular graphql Go lib - just recently added support for federation. PR to the lib was merged to master Jan 7 - 99designs/gqlgen#851 The lib doesn't have documentation for the feature yet, but it's fully working, as I am already using it in one of the projects.
gqlgen - one of the most popular graphql Go lib - just recently added support for federation. PR to the lib was merged to master Jan 7 - 99designs/gqlgen#851 The lib doesn't have documentation for the feature yet, but it's fully working, as I am already using it in one of the projects.
@vvakame @marwan-at-work @vektah can you point to this project where there is an working example? |
I cant make public it. I cant get response from Apollo org members yet... |
I haven't updated this repo in a while, but I also Go'fied the federation-demo repo when I was implementing the spec in gqlgen: https://github.com/marwan-at-work/federation-demo |
@vvakame license is now added. |
wow, thanks! |
Apollo Federation MVP
This PR is mostly to get some eyes on the current architecture and what can be improved/re-written.
Once that looks good, I'll move on to adding unit/e2e tests
Fixes #740