-
Notifications
You must be signed in to change notification settings - Fork 133
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
PubSub iterator promise never resolves if return() called too soon #201
Comments
Okay, I think I have gotten to the bottom of it. I can get all my tests green again as long as I call Still, given this experience, I believe it would have been more appropriate to push this change with a major version bump rather than a minor one, because despite the API technically not changing, the semantics were certainly changed by the introduction of this lazy initialization. I'm also not entirely sure whether it's safe to close this issue now, because I find it hard to reason whether a situation like the snippet I originally described could be triggered in production usage. To be on the safe side, I'd say the PubSub implementation should still guard against it. |
I'll take a look at this. I feel like the behavior in the original snippet you posted should be that promise should resolve immediately with no values. |
Thanks! |
@grantwwu Sry for being quiet. I just wanted to point out and tag, that our issue could maybe have something to do with the issue meant here. If this is not the case in your opinion, just drop a comment. Thanks for help and Greets from Berlin! |
Update: This might be related: I'm writing a Jest test and I have to call setImmediate to invoke pubsub.publish() before I call the async iterator from subscribe, otherwise next() never returns: import { graphql, validateSchema, subscribe, parse, ExecutionResult } from 'graphql'
import { schema, client, pubsub } from './schema' // pubsub => graphql-subscription instance
test('subscriptions', async () => {
const document = parse(`
subscription {
create
}
`)
const sub = <AsyncIterator<ExecutionResult>>await subscribe(schema, document);
expect(sub.next).toBeDefined()
/** why is setImmediate needed here? **/
setImmediate(() => pubsub.publish('CREATE_ONE', { create: "FLUM!" }))
/** if setImmediate isn't used, the following promise is never resolved and test will timeout
const { value: { errors, data } } = await sub.next()
expect(errors).toBeUndefined()
expect(data).toBeDefined()
expect(data.create).toBe('FLUM!')
}) The need for setImmediate() is confusing, non-obvious and seems to rely on a side-effect. Awaiting form the publish() promise doesn't work, either. More details here. |
The following snippet will result in an iterator promise returned by
next()
that never resolves:The trick is that
return()
gets called synchronously while the first call tonext()
is still setting up its subscriptions.This appears to be a regression since 1.0 since I have a test suite that was green and started failing on this issue when I upgraded to 1.1.
I have tried various solutions, including monkey-patching
emptyQueue()
like this:But interestingly, doing so made other tests in my suite fail for reasons I'm afraid I don't understand right now...Ignore this last part, that failure seemed to be caused by me mis-using Jest's.resolves
method (forgetting toawait
it).The text was updated successfully, but these errors were encountered: