apollographql / apollographql/graphql-subscriptions

PubSub iterator promise never resolves if return() called too soon

Open
#201 7 comments 0 reactions 1 assignee Claimed by @grantwwu View on GitHub
Dominant language
TypeScript
Stars
1.6k
Forks
129
PR merge metrics
No merged PRs in 30d

Description

The following snippet will result in an iterator promise returned by `next()` that never resolves:

```js
const iterator = new PubSub().asyncIterator();
const promise = iterator.next();
iterator.return();
await promise; // will wait forever
```

The trick is that `return()` gets called synchronously while the first call to `next()` 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:

```js
PubSubAsyncIterator.prototype.emptyQueue = async function() {
if (this.running) {
this.running = false;
this.pullQueue.forEach(resolve => resolve({ value: undefined, done: true }));
this.pullQueue.length = 0;
this.pushQueue.length = 0;
const subscriptionIds = await this.allSubscribed;
if (subscriptionIds) {
this.unsubscribeAll(subscriptionIds);
}
// This one should make sure new next() calls while we were awaiting and resolved:
this.pullQueue.forEach(resolve => resolve({ value: undefined, done: true }));
}
};
```

~~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 to `await` it).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.