-
Notifications
You must be signed in to change notification settings - Fork 344
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
Implement raw sources functionalities to move runtime risks to build … #1522
Conversation
…time currently fully implemented on OpenAPI handler only
|
also improved prepare-raw-sources CLI command
Hello folks, I appreciate your time availability, hence why I have been patiently waiting for a week before chasing; but I would be grateful if you could review this and give me some feedback. I am keen on implementing this in my project and I would like to have an expectation whether or not you're willing to bake this functionality into Mesh as per my proposal; otherwise, I will have to create some custom scripts to handle build-time download of data sources definitions directly within my project. cc @Urigo, @ardatan; hope you don't mind me tagging you directly 🙏 |
Sorry for late response! Wow, thank you so much for this!
|
Are you thinking about generatig a cache with the actual generated schema or just raw source as per my PR? If you're thinking to cache the generated GraphQL schema; how would that work in terms of becoming executable and being hydrated with resolvers, subscribers, etc? If you remember one of the conversations we had, I was mentioning how I was impressed with SwagQL since it does generate static JS files that can be just executed at runtime. Hence why, in this case, I went to create a proposal that does save raw sources specifications with an explicit process/command that Mesh can use at runtime without really altering existing executable schema capabilities of |
We are thinking of seperating execution and schema generation logic in Mesh that will speed up the bootstrap instead of code generation like SwagQL. @dotansimha and me discussed a lot about it before. initialCache: ./initial-cache.json Then on regular bootstrap, Mesh can check that file and restores the cache onto actual cache then generates schema without downloading and recollecting raw sources in the same way you implemented. |
This sounds great; bootstrap can definitely be improved
Yes, the idea is fine; I guess if we go towards this approach I would be concerned with how the cache would be handled. How long does it live? When does it get cached? In this regard, this is similar to the approach I was proposing.
Yes, I agree this is the bit I wasn't 100% happy about.
Yes, I realised this when implementing rawSources on the GraphQL handler; in fact, I ended up re-using the logic built within Having said all this, how do you want to move forward? Until that is done I don't see a good way of implementing something like the cache you are proposing; unless in order to build the static cache you want to run the full |
01600cb
to
5ae2997
Compare
Hi @santino , thank you so much for you contributions. First, we do want to have a better way to validate the eventual GraphQL schema produced by GraphQL-Mesh. I'll break my comment/review to 2 parts here: short-term and long-term. In the short-term, I think we need a dead-simple cache mechanism, managed by the Mesh core/runtime/cli, that allow handlers to persist data in cache and get it. That means, we can create a very simple cache object (with persistence) in the Mesh core, and share it with the handlers. This way, handlers that supports it can just use it as save their upstream schemas. In the long-term, we have a bigger plan to refactor GraphQL-Mesh and break it to 2 parts: schema creation (that occurs in build time) and schema execution (runtime). This way we'll be able to maintain a better compiled sources, have validations on it and cache it. |
Hey Dotan, The cache mechanism you're describing is not much different from what I proposed in this PR. I am happy to look into this however, I see myself fairly busy in the next couple of weeks; just to give some expectations. Feel free to jump on it sooner if you wish to handle it on your side earlier. The long-term plan sounds good to me and I am particularly happy you're considering reducing the pattern of the "wrapping schema" approach since it does have several downsides, as I highlighted a few times. As for my other PRs for introducing In the meantime, I'm going to close this PR so that CI resources are released. |
* feat: non-breaking GraphQL Engine * feat: make envelop take in engine functions * structural typings * remove grapqhl as peer dep from types pkg * make core more agnostic * chore(dependencies): updated changesets for modified dependencies * remove traced schema * remove traced orchestrator * make plugin agnostic * drop EnvelopError * remove more graphql import * Drop useTiming * make core completely free of graphql-js * add eslint rule * eslint disallow in types too * more agnostic packages * remove introspection util * chore(dependencies): updated changesets for modified dependencies * prettier * TEMP: make bot calm down * update all docs * test matrix for core * experimenting traced schema (ardatan#1501) * experimenting traced schema * Fix * remove comment * do optional chaining since we are not strongly typing * document * cleanup Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com> * feat: drop node 12 (ardatan#1505) * feat: remove `enableIf` utility (ardatan#1504) * feat: remove enableIf utility * make types happpy * make types happy * add changeset * feat: remove async schema plugin and rename lazy loaded schema plugin (ardatan#1506) * remove useAsyncSchema * rename to useSchemaByContext * add eslint rule (ardatan#1509) * feat: `@envelop/on-resolve` plugin for hooking into schema resolvers (ardatan#1500) * on resolve plugin * changeset * no more onResolverCalled * unused import * args is a record * integrate and useOnResolve * resolversHooksSymbol does not exist * plugincontext for OnPluginInit * on-resolve uses addPlugin * onresolvercalled is no more * refactor for new on-resolve * fix open-telemetry tests * fix newrelic * opentelemetry graphql as peer dep * tests * addPlugin doesnt need to be used * reorder * respects onPluginInit context * drop unused import * fixes false positive eslint warnings Co-authored-by: Dimitri POSTOLOV <dmytropostolov@gmail.com> * docs: order of plugins matter (ardatan#1513) * feat: remove handler for validation and parse errors (ardatan#1510) * feat: remove hanlder for validation and parse errors * tests * make it work * Add docs * Fix serialization issue * Go * .. * update docs * update test * make it work * feat: add originalError in dev mode (ardatan#1514) * remove Fn appendix * name graphql error * make ts happy * make toJSON required Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com> Co-authored-by: Laurin Quast <laurinquast@googlemail.com> * add changeset * Update .changeset/nervous-seas-own.md * Update .changeset/rude-cats-peel.md * no-use-before-define (ardatan#1522) * feat: trigger on context, validate and parse errors (ardatan#1511) * feat: trigger on context, validate and parse errors * trying * make it work * pass in phase * add phase details * feedback * docs: migration guide (ardatan#1520) * docs: migration guide * remove slashes * Update website/docs/guides/migrating-from-v2-to-v3.mdx Co-authored-by: Denis Badurina <badurinadenis@gmail.com> * feedback * document removing of orchestrated tracer * more feedback * update docs * update examples * async schema example Co-authored-by: Denis Badurina <badurinadenis@gmail.com> * Add redirects * remove deafult skip error from sentry plugin * export masked error plugin * sentry plugin default skip GraphQLError * sentry: og error is not graphql error then send to sentry * doc: drop introspection utils * should fix ts issues on v15 * test: stack error we should not match the error name since it can be different across impl * feat: use engine plugin (ardatan#1535) * feat: use engine plugin * remove assertion * make useEngine plugin the only way to pass engine functions (ardatan#1536) * make useEngine plugin the only way to pass engine fns * update types * update docs * Update packages/plugins/apollo-datasources/README.md Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com> * prettier: Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com> Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com> * fix * versioned docs with v3 default * fix build * fix * feat this is cool * docs reword schema tracing * docs add graphql error example * docs restructuring, fix typos * chore remove autogenerated changeset * cleanup changeset * docs sycn patch Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com> Co-authored-by: Denis Badurina <denis@domonda.com> Co-authored-by: Dimitri POSTOLOV <dmytropostolov@gmail.com> Co-authored-by: Laurin Quast <laurinquast@googlemail.com> Co-authored-by: Denis Badurina <badurinadenis@gmail.com>
In order to make Mesh more reliable and Production-ready, I'm proposing the following change.
The problem
Currently, Mesh handles data sources at runtime.
When invoking
getMesh()
this will loop through all data sources, download their original schemas (when remote, probably very likely), translates those into GraphQL, and finally apply all transforms and stitching.This means that after building the server bundle and deploying it to Production we risk the application not being able to start because potentially one of the data sources might experience downtime; even if a temporary glitch.
Effectively this means that all data sources become a dependency to start our servers.
This makes things troublesome because we would need to restart our server, which might not still be enough even if a just single data source is still unavailable.
Effectively, at this stage, our server is unable to serve traffic and we're blocked even though our builds are successful.
In this case, even a rollback won't solve the issue; since the previous build would also attempt to download the data sources at runtime.
The solution
I've prepared this PR to allow developers to set up data sources download at build time in just 2 simple steps.
meshrc.yaml
By doing this we can fail builds, in case of data sources downtime, and so avoid promoting the build to production which would cause potential unavailability.
Effectively this makes Mesh predictable and reliable; since we removed "third-party dependencies", we can trust that our builds are always going to work.
For the first point, I have introduced a new property to Mesh config file called
rawSourcesDir
which is a string that can be used as follows:As for the second point, I have introduced a
prepare-raw-sources
command to Mesh CLI that doesn't require any argument.This command will loop through all data sources, download the specifications for remote source only from their provider and store one file per remote data source in the given directory.
This command doesn't need any argument, since it only requires the destination directory which is read from the Mesh config file.
A build configuration could look like follow:
Next steps
I believe this proposal is extremely valid, but I want to open a conversation before completing this.
Right now I have implemented the new functionalities on the OpenAPI and the GraphQL handlers.
All other handlers still need to be extended with the newly introduced
getRawSource()
method.Included
I have introduced new types; updated existing types and added a new page to the Documentation website.