Open jlengstorf opened 6 years ago
I would love to see this because I want to create a project using multiple microservices with micro-js. are PRs welcome ?
@Goluis Absolutely PRs are welcome!
Could you provide some pseudo-code or a use case for the external schemas? Specifically, how are you putting this together that doesn't work with the typical GrAMPS approach of putting the data sources together into a single executable schema?
(I'm asking so I can understand how other devs are structuring their code, not to try and shoot you down.)
@jlengstorf Can you explain to me how the stitching part works exactly. I assume that is for stitching multiple datasources together? But I'm wondering why the stitching part is defined on a single datasource. Maybe I'm missing something. The reason I'm asking it here is because of its relationship to merging with other schemas (like the external schemas discussed here).
@jlengstorf of course!
Currently data-sources are supposed to be merged with a gateway as shown here and they can also run their own gateway, but in production is the app gateway the one who merges the schemas and deploys.
Using remote schemas two things change:
Some benefits of this approach:
Note: some benefits from microservices came from zeit docs, which offers a very easily implementation of microservices at scale
@kbrandwijk The idea behind stitching in GrAMPS is, in a nutshell:
User
and Post
Post
as a peer dependency of User
(and vice versa)stitching
prop of the User
data source defines how the User
type will expose data from the Post
data source (and vice versa)The idea behind this is to allow complex schemas to be broken up into data sources without forcing them to become silos.
I don't believe this would interfere with merging into other schemas, but we haven't tested that scenario yet.
@Goluis I think I see what you're going for, but I do want to clarify that the data sources are not independently deployable. The CLI will stand up a simple gateway for development, but the intention is that those data sources will ultimately be consumed by a GrAMPS gateway.
That being said, you could certainly put multiple GrAMPS gateways into production as independent µ-services and merge them via remote schemas into a main gateway.
One thing that GrAMPS is set up to do, though, is allow data sources to be included in multiple places.
So let's take those zeit docs as an example:
To start, we have the UI µ-service and a GraphQL endpoint:
The GraphQL endpoint has three data sources:
Register
Post
User
As the product scales, you decide to split into two GraphQL µ-services:
Let’s assume both Post
and Register
rely on User
for normal operation. Since GrAMPS data sources can be installed on multiple gateways, there's nothing to stop you from including the User
data source on both µ-services:
Register
and User
data sourcesPost
and User
data sourcesThese wouldn't need to be stitched together at all, and you should get the same end result.
Am I understanding your use case correctly, or is there something I'm missing?
the difference is that if the data-source for User
is changed it will need to be updated in graphql.example.org
and graphql-register.example.org
, but if User
were a microservice with a remote schema (graphql-user.example.org
for example) and the other gateways are using a link to its schema then only graphql-user.example.org
will need to be updated
Ah, good point.
I don't have any solid argument for not adding support for external schemas. And @kbrandwijk is thumbs-upping, which I assume means he's onboard.
@Goluis Does the API addition laid out in https://github.com/gramps-graphql/gramps/issues/47#issue-283307728 seem like it's going to work for your use case? If so, want to submit the PR? 😄
@jlengstorf Well, onboard with the reasoning from @Goluis that you don't want to include it in both, and having to update in multiple places. I'm still not 100% sure about the external schemas. But I think it comes down to the positioning of GrAMPS. Do you see it as a completely self-sufficient tool, then you need this as well. Do you see it as part of a toolchain, than I would focus on the main responsibilities of the package.
@kbrandwijk I guess I'd make the argument that the maintainers of GrAMPS can't really make that decision for the devs using it. 😕
I can see it working in both contexts, depending on the structure of a given team. Maybe you could help us put together some architectural considerations for using external schemas (e.g. all the things that make you uneasy, so other devs can be aware of potential pitfalls)? Maybe we could work with @schickling to put this on https://www.advancedgraphql.com?
I think we should do a boilerplate for GrAMPS, to be used by graphql create
, so we can figure out how these tools fit together. That worked wonders to communicate the concept with the existing boilerplates, and offers a great starting point for devs. Maybe we can work on that together? Feel free to ping me on Slack.
Maybe we could work with @schickling to put this on https://www.advancedgraphql.com?
This would be awesome! @nikolasburk is planning to give Advanced GraphQL a full rehaul in January. Would be great if you'd like to get involved!
Also feel free to create PRs for it before then ofc!
Here's the apollo example of how to add multiple remote schemas working: https://launchpad.graphql.com/q5kq9z15p
I already tried to add one of the example endpoints in top of gramps without success (I don't know why it didn't work, just that the schemas weren't merged)
// useRemoteSchemas.js
import { mergeSchemas } from 'graphql-tools'
export default (remoteSchemas, grampsOptions) => async req => {
const options = grampsOptions(req)
const remotes = remoteSchemas.map(schema => schema())
const schema = mergeSchemas({
// The remote schemas are fine but no merge occurs
schemas: [options.schema, ...await Promise.all(remotes)]
})
return Object.assign(options, { schema })
}
// server.js
// Note: Only the relevant code is included
import { introspectSchema, makeRemoteExecutableSchema } from 'graphql-tools'
import { HttpLink } from 'apollo-link-http'
import fetch from 'node-fetch'
import XKCD from '@gramps/data-source-xkcd'
import useRemoteSchemas from './useRemoteSchemas'
const RemoteSchema = async () => {
const link = new HttpLink({
uri: 'https://v7l45qkw3.lp.gql.zone/graphql',
fetch
})
return makeRemoteExecutableSchema({
schema: await introspectSchema(link),
link
})
}
const GraphQLOptions = useRemoteSchemas(
[RemoteSchema],
gramps({
dataSources: [XKCD]
})
)
app.use('/graphql', graphqlExpress(GraphQLOptions))
Including remote schemas right now will require changes to the api and probably context, btw check out this current discussion about possible incoming changes to stitching schemas
Adding remote schemas will be a lot easier with the changes proposed in #62 and #63.
Porting the discussion on external executable schemas to its own issue so we don't lose track of it. Original discussion is copy-pasted below:
@mfix22 https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352119917
@jlengstorf https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352122456
@mfix22 https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352225241
@kbrandwijk https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352256297
@jlengstorf https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352257476
@kbrandwijk https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352258460
@jlengstorf https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352258843
@mfix22 https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352622460
@jlengstorf https://github.com/gramps-graphql/gramps/issues/26#issuecomment-352641566