-
Notifications
You must be signed in to change notification settings - Fork 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
generateSchemaHash doesn't await execution result #1935
Comments
I can confirm that by awaiting the execution result, and doing a delayed storing of the result like this works: apollo-server-core/dist/utils/schemaHash.js line 15: async function generateSchemaHash(schema) {
const introspectionQuery = utilities_1.getIntrospectionQuery()
const documentAST = language_1.parse(introspectionQuery)
const result = await execution_1.execute(schema, documentAST) apollo-server-core/dist/ApolloServer.js: line 226 this.schemaHash = ''
schemaHash_1
.generateSchemaHash(this.schema)
.then(
hash => (this.schemaHash = hash),
err => console.error('Warning: Could not generated schema hash', err)
) |
...is the error I'm getting. |
@martijnwalraven This is not fixed in 2.2.1, right? |
The problem is still present in 2.2.1 |
Hmmm, this is surprising, because executing an introspection query is normally guaranteed to be synchronous. If |
The workaround I describe above worked fine for me |
Yep, I'm not saying that workaround doesn't work, but it's unfortunate it's required because introspection is meant to be synchronous. |
We expect introspection queries to behave in an synchronous manner since they do not have any resolvers which return Promises. This expectation seems to also be had by `graphql-js` which utilizes `graphqlSync`, rather than `graphql` for execution of introspection queries. In fact, this may be one of the entire reasons that `graphqlSync` exists: to fulfill a contract for synchronous execution of server introspection. The introspection tests within `graphql-js` seem to support this theory[[0]]. Utilities which wrap GraphQL resolvers should take care to maintain the execution dynamics of what they are wrapping, or they should avoid wrapping introspection types entirely by checking the type with the `isIntrospectionType` predicate function from `graphql/type`[[1]]. [0]: https://github.com/graphql/graphql-js/blob/787422956c9554d12d063a41fe35705335ec6290/src/type/__tests__/introspection-test.js [1]: https://github.com/graphql/graphql-js/blob/74d1e941/src/type/introspection.js#L484. Closes: #1935
Just to be clear, this problem only manifests itself if when
I'm happy to revisit this in the future but, as I've indicated in the commit message for #1955's 45bdcd9, the more correct solution here would be to maintain the synchronicity of introspection query execution by changing |
@abernix I'm encountering this too and I don't use graphql-middleware, I don't even have it in my node_modules. |
Furthermore, this behavior breaks existing code with a minor release :( The only thing this adds is the schemaHash which is not crucial for operation. |
Ok, thanks for reporting back @wmertens! Then something else is breaking that contract then! I hadn't been able to reproduce this without |
I do make my own schema using the objects, and I wrap the resolvers, but I can't think of any place where I asynchronously define the types |
@wmertens If you have the ability to try to figure out a minimum reproduction, I'd really appreciate it! |
@abernix no real time to spend on this in the coming days :( Do you happen to know how the executor decides that the result should be a promise? |
@wmertens Sure! It occurs within |
@wmertens Can you share a brief example of how you wrap the resolvers? |
confirmed this issue after update |
Still, since this is a minor release, and it breaks previously working code, can't there be a deprecation and making it throw in the next major release? |
I think that this has been implied, but not stated explicitly. It appears that this also means that the Middleware examples found in the README and documentation (Express, etc.) throw an error when a user attempts to run the given example:
|
@ascott1 I'm not finding that to be true. This reproduction of the example you linked to above doesn't seem to be affected. Are you sure you're not wrapping otherwise synchronous resolvers with @wmertens We're working on addressing the problem you're encountering, but I'm not sure what you're suggesting be deprecated. |
@abernix Running that README example was where I originally ran into the error. I am now unable to replicate it, so it may have been user error on my end. |
@wmertens Just to be clear, we haven't done anything to change a schema to return a In the case of an introspection query, it has — by design — no asynchronous behavior. This is corroborated by graphql/graphql-js#1120 in Looking at the code you've provided in #1935 (comment), I don't see anything problematic. However, the Gist you linked to at https://gist.github.com/wmertens/c291e074c74b88a482b2c61abe5b9947#file-makeschema-js-L44-L67 could definitely be problematic if you used (your) |
@abernix Hmm, I rewrote everything so that it maintains resolver async status, but the error is still present. I'm not using any other wrappers AFAIK. What I mean by deprecating is that, until 2.0.5, people could have incorrect schemas that worked, and by upgrading a minor Apollo version, their code will break. You could make the schemahash async until the next major version and in the meantime deprecate those incorrect async schemas. |
🤷♂️ very odd, I tracked it down to kadirahq/graphql-errors#18 even though I had disabled it before. Anyway, I got 2.2.0 to work now. @abernix I guess this issue is a "wontfix" now, unless you go the deprecation route? Feel free to close. |
What is the deal with this? The following basic example even has this problem:
So apollo is completely broken in the latest version? |
@BrendanBall The reproduction you've included — if it is failing — seems to be missing clarity on some other attributes which are contributing to your particular failure because it reproduces fine using the above code, as seen here: https://glitch.com/edit/#!/joyous-pressure I will close this for now because, as stated above, Apollo Server seems to be in compliance with the expectations of the GraphQL reference implementation and test-suite: that is, the introspection query execution should operate in a synchronous behavior. If you continue to experience this issue, please open a new issue with a full reproduction (though keep in mind if it's still using |
this might be useful for someone, but i was struggling this for a while and then realized that |
Maybe this will help someone. I got to this thread because I was getting the following error:
which I tracked down to apollo-server-cores's // ...
const utilities_1 = require("graphql/utilities");
const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
const crypto_1 = require("crypto");
function generateSchemaHash(schema) {
const introspectionQuery = utilities_1.getIntrospectionQuery();
// ... But the thing is const utilities_1 = require("graphql/utilities");
const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
const crypto_1 = require("crypto");
function generateSchemaHash(schema) {
const introspectionQuery = utilities_1.introspectionQuery;
// ... got me rid of the first error, but then I started to get
which I'm still unable to fix. |
Hi, just for documentation, we can repro this issue on a Meteor app. Still unsure why or what we are expected to fix or change though even after reading this thread. We do not use Edit: if you need reproduction simply install Vulcan |
Hi, I've updated my test. I can still reproduce this issue with a minimal schema (the example schema defined here in the official doc). If someone wants to take a look, the server is defined here: https://github.com/VulcanJS/Vulcan/tree/apollo2/packages/vulcan-lib/lib/server/apollo-server It only happens in test environment though, the server works fine otherwise. |
@eric-burel It's probably not this one, but you have to look for lines like https://github.com/VulcanJS/Vulcan/blob/b2e3aaaeb54a266a060c539f45fbf0f9fd208e96/packages/vulcan-lib/lib/server/intl.js#L49 where it's wrapping a resolver with an async version without checking if the resolver returns a promise… |
@eric-burel The assessment and identification of the issue by @wmertens here is correct. (Thanks, @wmertens!) The VulcanJS resolver wrapper should maintain the existing execution synchronicity dynamics of the resolver its wrapping. One way to do this could be to check if the existing resolver is I would suggest submitting a PR to the Vulcan project which adds such a guard. |
Hi, I've tried again using a really minimal schema, I can still reproduce in Meteor test mode. Here is the example test:
I don't get what happens honestly. First, why is an introspection query triggered? Is this supposed to happen when the server is first created? Then, why would it fail? The schema is really minimal, so this could only come from how Meteor works, maybe related to how it runs queries? I am running Sorry to bother or if it is not the appropriate thread, it's just a bit unsettling. It happens only during test but I am worried that this could happen with no reason (or at least no reason I can grasp) in production too. I still try my best to solve this. |
Also, @abernix you say that adding a |
Async resolvers are fine, but field types must be able to be introspected
synchronously. So any wrapper that walks the schema and wraps resolvers
must maintain synchronicity
Your configuration contains something that makes this fail.
Wout.
…On Tue, Jan 29, 2019, 6:44 PM Eric Burel ***@***.*** wrote:
Also, @abernix <https://github.com/abernix> you say that adding a
isIntrospectionType would avoid this issue, which I understand, but you
you also say that the wrapper should maintain the resolver synchronicity. I
am not sure I get this second part correctly. What if I want to write a
directive that makes sync fields async? E.g if I want to query a
translation from a distant server, and apply it to the field, I transform a
sync resolver in an async resolver.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1935 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AADWluIfpLBnC3Vzg0TqG5x22_w2zHruks5vIIiYgaJpZM4YUdg4>
.
|
@eric-burel If you can provide a minimal reproduction, I can try to take a look. I wouldn't assume it's anything related to Meteor (as a maintainer on the Meteor project, I can't think of anything that would do this. ☄️ ).
Apollo Server introspects itself when it starts up. But that's just the symptom, not the cause. (And in this case, is a great smoke test which ensures that your introspection schema is behaving synchronously, as it is intended.)
You can do that, so long as you don't make an introspection type (e.g. |
Hi guys, I finally figured out what happens. @ascott1 had a Thanks a lot for taking time to answer me though, this will definitely help me to avoid potential future issues with introspection! |
I am getting this error while using code from this link https://github.com/jaydenseric/apollo-upload-examples in different project and i am unable to correct this issue. |
@dev-reactjs can you check your |
I think It would be good to specifically mention that the |
Hit this up today after reworking on an old project. i confirm upgrading fixes the issue. |
This is what peer dependencies are for. Why is |
@joshduck I'm going to lock this issue because I feel like multiple issues are starting to get conflated. We do recommend updating to newer versions of If anyone continues to experience problems, please do open a new issue with a runnable reproduction. Thanks! |
There's a problem here:
apollo-server/packages/apollo-server-core/src/utils/schemaHash.ts
Line 11 in 6bd73b1
in graphql-js, this can return a Promise:
https://github.com/graphql/graphql-js/blob/f529809f5408fb9a343e669ea4d4851add3df004/src/execution/execute.js#L141-L144
So generateSchemaHash has to always return a Promise, too.
This probably causes all the graphql-middleware issues, like #1934
The text was updated successfully, but these errors were encountered: