The Hive integration does not support schema stitched projects where multiple services contribute to the final graph
dpnova opened this issue · comments
Issue workflow progress
Progress of the issue based on the
Contributor Workflow
- 1. The issue provides a reproduction available on
Github,
Stackblitz
or
CodeSandbox
Make sure to fork this template and run
yarn generate
in the terminal.Please make sure Mesh package versions under
package.json
matches yours.
- 2. A failing test has been provided
- 3. A local solution has been provided
- 4. A pull request is pending review
Describe the bug
Having multiple handlers all using the same hive schema source results in mesh thinking that all fields exist on all subgraph services:
sources:
- name: datasets
handler:
graphql:
source: ${BACKEND_GRAPH_SOURCE}
subscriptionsProtocol: SSE
schemaHeaders:
X-Hive-CDN-Key: ${BACKEND_GRAPH_HIVE_CDN_KEY}
endpoint: ${DATASETS_API}
- name: calculations
handler:
graphql:
source: ${BACKEND_GRAPH_SOURCE}
subscriptionsProtocol: SSE
schemaHeaders:
X-Hive-CDN-Key: ${BACKEND_GRAPH_HIVE_CDN_KEY}
endpoint: ${CALCULATIONS_API}
This would be avoided by having mesh be able to fetch an individual service's schema - potentially from the services
artefact type documented here
One solution of course, is to split each subgraph into a separate Hive project, but that defeats the purpose of using a stitched project in Hive.
To Reproduce Steps to reproduce the behavior:
Expected behavior
Environment:
- OS:
@graphql-mesh/...
:- NodeJS:
Additional context
Unfortunately the current version of Mesh doesn't have an integration like you described. Each source needs to be a seperate Hive project, and merged/composed by Mesh CLI's build command not by Hive.
We call this version of Mesh v0.
However you can check incoming release-candidate Mesh v1 that has a different approach similar to what you asked for;
https://the-guild.dev/graphql/mesh/v1
But that newer version of Mesh uses Federation instead of "Stitching".
Unfortunately the current version of Mesh doesn't have an integration like you described. Each source needs to be a seperate Hive project, and merged/composed by Mesh CLI's build command not by Hive. We call this version of Mesh v0. However you can check incoming release-candidate Mesh v1 that has a different approach similar to what you asked for; https://the-guild.dev/graphql/mesh/v1 But that newer version of Mesh uses Federation instead of "Stitching".
Ah - when I spoke to @Urigo about this he was all about the new stitching. Are we moving from it to prefer federation now? Is there a place where the current "best practice" thoughts from the guild are?
I always liked that stitching didn't force subgraphs to know about how they are federated. Or has federation improved on this front now?
I always liked the type merging approach 🤔
One thought I mentioned in a support ticket to hive was to have separate CDN links for each subservice in a stitched graph.
Edit: nm I saw the reply over there.
This will be a new mesh project, it seems like we should roll forward to the v1 approach.
I need to do some reading.
FYI @kamilkisiela Our workaround for now is to download the services cdn object and write schema files locally before we mesh build.
What is considered state of the art now? https://the-guild.dev/graphql/stitching/handbook/other-integrations/federation-to-stitching-sdl#adapting-federation-services
@dpnova the approach that @ardatan is talking about with v1 (which we recommend you try, if you need help, we can connect our teams together through Slack and we can answer any questions you might have)
is federation approach with stitching as the implementation itself (it fully supports federation)
You can still use the current approach
The main thing you will miss is the static analysis that makes sure all graphs are connecting in a predictable way and also a supergraph that makes sure execution is more predictable
The state of the art would be the Mesh v1 docs which we are currently working on to get it ready for the release, so any thing that you think is missing there please let us know and we'll add it!
thanks @Urigo ! Right now we depend on additionalResolvers
pretty heavily to force visiting every instance of a particular Query.foo
and Subscription.foo
that is defined on multiple backend services - if we can continue to do that with V1 we should be fine. I'll do a blog post about our sync engine and how it's powered by mesh soon 👍
Given this is a wontfix, I'll include our workaround here for anyone else in the same situation. We run this before mesh build, and have the meshrc refer to the local file paths for each handler source
.
import fs from 'fs'
import path from 'path'
const CDN_URL = process.env.BACKEND_GRAPH_SERVICE_SOURCE ?? ''
const CDN_KEY = process.env.BACKEND_GRAPH_HIVE_CDN_KEY ?? ''
async function downloadSchemas() {
const requestOptions = {
method: 'GET',
headers: {
'X-Hive-CDN-Key': CDN_KEY,
redirect: 'follow',
},
}
try {
console.debug('Downloading from CDN', CDN_URL)
const response = await fetch(CDN_URL, requestOptions)
if (!response.ok) {
throw new Error(`Failed to fetch schemas: ${response.statusText}`)
}
const services = await response.json()
for (const service of services) {
const { name, sdl, url } = service
const filePath = path.join(__dirname, `/../schemas/${name}.graphql`)
const fileContent = `${sdl}
`
fs.writeFileSync(filePath, fileContent, 'utf8')
}
} catch (error) {
console.error(`Error downloading schemas: ${error.message}`)
throw error
}
}
downloadSchemas()