-
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
replace raw mapAsyncIterable with Repeater based approach #3694
Conversation
✅ Deploy Preview for compassionate-pike-271cb3 ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
Hi @yaacovCR, I'm @github-actions bot happy to help you with this PR 👋 Supported commandsPlease post this commands in separate comments and only one per comment:
|
7e1c2a8
to
5e2ae2b
Compare
Some of the changes in the tests for However, some of the changes are because I have not yet gotten my Repeater-based map transducer to properly handle a "recovered" call to Note this comment: repeaterjs/repeater#72 (comment)
Unfortunately, despite the fact that no one should be doing that, perhaps they are, and the current mapAsyncIterable supports this behavior. So our Repeater-based transducer (or Repeaters themselves) apparently need some fine-tuning? Investigation continues. @brainkim @IvanGoncharov et al, all thoughts/comments are welcome. |
Note that the Repeater-based map transducer in this PR is basically from repeaterjs/repeater#48 (comment) With the additional ability to forward |
Perhaps of interest: microsoft/TypeScript#45400 |
Returns an object that conforms to the AsyncGenerator type signature, but the behavior of the properties do not conform to the AsyncGenerator specification(https://tc39.es/ecma262/#sec-properties-of-asyncgenerator-prototype). In particular, with async generators, all promises returned by next, return, and throw resolve in call order. TS does not include a type that is AsyncGeneratorLike, and AsyncIterableIterator has an optional return, while here return is present, so the best things seems to be to just let TS infer the type.
859fd66
to
da727e8
Compare
I realized that the behavior of the current implementation of I have therefore reverted my test changes in this regard. I have also completed the changes within the repeater-based map iterable to map iterables that continue to yield values even after their return method is called. This PR is now ready for review. In summary, with no significant change to the mapAsyncIterable tests, the repeater based approach shows how the current implementation gives you an object that has the same API as a generator, but is not actually a generator, in that calls to I have also updated the PR description above to add an additional motivating point with regard to incremental delivery. |
Wow -- how silly of me! In changing Repeaters to behave exactly-exactly-exactly like AsyncGenerators, I had to give up on concurrent returns. Meaning, if a for await loop is iterating through the repeater, and you call the repeater's (A) you run into the secure stop problem that maybe we should still avoid But we should really all get on the same page as to whether we:
Whew! That's a lot to think about. Does the spec have anything to say about all this? Not that I could find. Cancellation is discussed, but it doesn't seem to specify what should happen to a previously requested payload if a concurrent unsubscribe is triggered. This sounds like a good discussion topic for the next js-wg meeting! |
I'm going to close this stale PR, at least for now. I think the way forward should be to follow along with https://tc39.es/proposal-iterator-helpers/ and that iterating prematurely would add more unhelpful noise. As far as I know, we have not had add actual library users raise issue with the potentially misleading signature we are using. |
The basic idea behind this PR is that graphql-js should not export something with type signature of an async generator that sometimes does not behave like an async generator.
Repeaters — thanks to the amazing work of @brainkim — can exhibit behavior that matches exactly to that of async generators.
In particular:
next()
,return()
, andthrow()
will not interfere with each other; they will be executed sequentially.next()
,return()
, andthrow()
will all settle in call order.Additional motivation:
graphql-executor
builds on Repeaters to create a Publisher abstraction that allows the executor to push results to the generator as they are ready, without the need for any complicated promise racing.