Skip to content
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

Schema Stitching & Client generation #5

Closed
vektah opened this issue Feb 14, 2018 · 20 comments · Fixed by #1218
Closed

Schema Stitching & Client generation #5

vektah opened this issue Feb 14, 2018 · 20 comments · Fixed by #1218
Labels
accepted enhancement New feature or request

Comments

@vektah
Copy link
Collaborator

vektah commented Feb 14, 2018

It would be neat if you could take a schema and generate a strictly typed client from it:

type Schema {
   getUser(id: Int) User
}

type User {
 ...
}
generate-client schema.graphql -package myclient

It would generate a client allowing easy querying of schemas, carrying selection set information forward in context:

func (r *Resolver) Profile_user(ctx context.Context, parent *Profile) (myclient.User, error) {
	return r.myclient.GetUser(ctx, parent.UserID)
}

Under the hood the client would generate the query based on the selection set (does it need any type information to generate the query?) and unmarshal the result, looking at __typename where appropriate to create the correct concrete types.

What about https://github.com/shurcooL/githubql?
It relies heavily on reflection to generate the query from the struct, but the shape isn't known until runtime so there is nothing to reflect.

@vektah vektah added this to the 1.0 milestone Feb 14, 2018
@vektah vektah added the enhancement New feature or request label Mar 8, 2018
@vektah vektah removed this from the 1.0 milestone Jun 29, 2018
@aaahrens
Copy link

Is this currently implemented?

@vektah
Copy link
Collaborator Author

vektah commented Sep 13, 2018

Not yet

@sdalezman
Copy link

We're currently doing this within code right now and it's proven to be a bit challenging with edge-cases to support.

We'd be happy to help out on implementing schema stitching, but before jumping in wanted to see if there was an agreed upon design for it before writing any code?

@robinbraemer
Copy link

robinbraemer commented Dec 26, 2018

Are there any updates?

@txbrown
Copy link

txbrown commented Jan 11, 2019

+1

@k-kundan
Copy link

Any updates on this?

@sdalezman
Copy link

sdalezman commented Jan 22, 2019

@vektah we've been thinking a lot about this issue bec we've kind of done this in a round about manner at the moment. We have a few graphql api's on top of our centralized grpahql api. What we noticed is that we typically query these services in isolation and rely on the centralized end point for heavy lifting for things like combining data cross-service.

Let's say we had a user and comments service, then right now we wrap a query around each service so our central query looks like this:

type Query {
    user: User,
    comments: Comments
}

type User {
    // some query operations
}

type Comments {
    // some query operations
} 

Our resolvers for users and comments use what we call our query generator. The query generator introspects the fields being requested and generates a new graphql query to the sub-service. That way if let's say we're querying for 4 objects from the user service we could batch them in one request without having 4 different resolvers each with their own http overhead. Again one big reason we did that is we typically aren't querying for comments + users together at the moment.

Our query generator at the moment, is definitely not great and I would say that's probably due to a lack of us truly understanding what's happening under the hood in the graphql.CollectedField. That means we can't use all graphql features because the limitations in our query generator. We've accepted this trade-off because of the advantages of having a centralized graphql service with the sub-routing.

All that being said, given that we've worked on the above for multiple services I think an ideal solution would allow a user to define a schema stitch at the gqlgen level.

stitch: 
  # NOTE: you can define as many stitches as necessary
  serviceName: [some-custom-defined-name]
  serviceURL: [some-url]
  # requestFn allows us to define a custom request generator function so that we can add any authorization headers to our sub service as well as add tracing etc
  requestFn: api.requestFn

gqlgen would then see that and when running the gqlgen generation, it would request that sub-service schema (using the requestFn). It would then merge that schema with the parent schema. It would also save which graphql key belongs to the stitch defined in the yaml. When gqlgen parses a query it would then group together all the queries to that sub-service and send the request to the sub-service, combines all the responses back together and send them back to the user.

In my ideal, ideal world it would also be great if we can have dataloaders between services that are coordinated by this centralized endpoint.

It would also be really cool if we could define custom encoding mechanisms for the child api's. I know graphql whole's thing is http over json, but when we're thinking about sub-service api's and scale, it would be great to be able to use thrift or proto-buffers to encode the requests + responses and save on larger queries.

One other dream I have with this setup is that as we continue to add to our child-graphql-api's it would be great if our parent graphql api was seamlessly updated. Meaning the child would be able to register with the parent that it's schema changed and the parent would automatically update itself. That might be a little difficult to achieve, but as we're speaking about dreams that's on the list. It almost takes you down the path of being able to have children register themselves with the parent graphql api almost in a service discovery mechanism (would definitely make it easier for us to continue to spin up micro-services).

We're definitely running into issues with our current setup and would really like to make progress here. We're happy to help out on a design/building of this feature, but would be great to hear your thoughts first.

@tdi
Copy link

tdi commented Apr 19, 2019

👍

@ibizaman
Copy link

Just wanted to link to https://github.com/dillonkearns/elm-graphql as this is exactly what elm-graphql is doing for Elm. cc @dillonkearns

@sdalezman
Copy link

Not sure where the comment went, but saw an email about Apollo federation, which looks like a way better implementation than my above suggestion. Is there interest in the gqlgen team in adding that support directly?

@josemarluedke
Copy link

Apollo Federation looks amazing: https://blog.apollographql.com/apollo-federation-f260cf525d21

Any plans for implementing something like that?

@csilvers
Copy link
Contributor

We at Khan Academy are looking to implement apollo federation, and will likely try to do it using gqlgen. We're not ready to start yet, but when the time comes we'd love to have some partners! (If someone else doesn't get to it first... :-) )

@StevenACoffman
Copy link
Collaborator

@csilvers I was looking at doing this same thing, so probably better to combine forces. I’m happy to help out.

@csilvers
Copy link
Contributor

Great! -- it sounds like a number of people are interested in taking a stab at this. Our timeframe is still a few months out probaly -- we need to do a bunch of (mostly non-technical) planning first -- but I think it definitely makes sense for folks to be open when they start working on something, so other interested parties can follow along! This issue is probably as good a place as any to coordinate.

@StevenACoffman
Copy link
Collaborator

Ref #740

@stale
Copy link

stale bot commented Sep 16, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Sep 16, 2019
@vektah vektah added accepted and removed stale labels Sep 22, 2019
@sateeshpnv
Copy link
Contributor

Is this in progress? How can I help?

@csilvers
Copy link
Contributor

csilvers commented Nov 6, 2019

This has been superseded by #740 .

This was referenced Feb 5, 2020
@JensRantil
Copy link

This has been superseded by #740 .

Given this, should this issue be closed (and "Stitching gql" in https://gqlgen.com/feature-comparison/ be updated)?

StevenACoffman added a commit to StevenACoffman/gqlgen that referenced this issue Jun 16, 2020
@carwyn
Copy link

carwyn commented Feb 13, 2021

I noticed that #950 was merged into this and this was superseded by #740 but I'm not sure if the client generation part was implemented as part of that?

Also see: https://github.com/Yamashou/gqlgenc and Generate GraphQL Client Code With Go

cgxxv pushed a commit to cgxxv/gqlgen that referenced this issue Mar 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.