Support returning async iterables from resolver functions#2712
Support returning async iterables from resolver functions#2712IvanGoncharov merged 2 commits intographql:asynciteratablefrom
Conversation
57ca245 to
08acc44
Compare
08acc44 to
39a4c55
Compare
| isAsyncIterable(resultOrStream) | ||
| ? mapAsyncIterator( | ||
| ((resultOrStream: any): AsyncIterable<mixed>), | ||
| resultOrStream, |
There was a problem hiding this comment.
@IvanGoncharov since adding boolean %checks(value instanceof AsyncIterable) to isAsyncIterable I was able to remove the cast here, but I was not able to remove it from the other side of the ternary.
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ src/subscription/subscribe.js:166:9
Cannot call sourcePromise.then with function bound to onFulfill because mixed [1] is incompatible
with object type [2] in type argument Yield [3] of the return value of property @@asyncIterator of
the return value. [incompatible-call]
src/subscription/subscribe.js
[2] 117│ ): Promise<AsyncIterator<ExecutionResult> | ExecutionResult> {
:
163│ mapSourceToResponse,
164│ reportGraphQLError,
165│ )
166│ : resultOrStream,
167│ );
168│ }
169│
:
[1] 206│ ): Promise<AsyncIterable<mixed> | ExecutionResult> {
/private/tmp/flow/flowlib_5bfb8b1/core.js
[3] 562│ interface $AsyncIterator<+Yield,+Return,-Next> {
src/__tests__/starWarsSchema.js
Outdated
| let i = 0; | ||
| for (const friend of friends) { | ||
| // eslint-disable-next-line no-await-in-loop | ||
| await new Promise((r) => setTimeout(r, 1)); |
There was a problem hiding this comment.
Why do you need setTimeout?
A promise is always processed on a next tick even if it already resolved.
There was a problem hiding this comment.
Leftover from when I was trying to time results for tests combining @stream and @defer. Not needed any more and removed from this PR
src/__tests__/starWarsSchema.js
Outdated
| i++; | ||
| } | ||
| // close iterator asynchronously | ||
| await new Promise((r) => setTimeout(r, 1)); |
src/__tests__/starWarsSchema.js
Outdated
| description: | ||
| 'The friends of the droid, or an empty list if they have none. Returns an AsyncIterable', | ||
| args: { | ||
| errorIndex: { type: GraphQLInt }, |
There was a problem hiding this comment.
It's better to move non-trivial tests here: https://github.com/graphql/graphql-js/blob/master/src/execution/__tests__/lists-test.js
Starwars schema is intended as just a sample schema to quickly demonstrate all basic features.
There was a problem hiding this comment.
Removed these tests and added new tests to lists-test.js
src/execution/execute.js
Outdated
| * Complete a async iterable value by completing each item in the list with | ||
| * the inner type | ||
| */ | ||
|
|
src/execution/execute.js
Outdated
| return iterator.next().then( | ||
| ({ value, done }) => { | ||
| if (done) { | ||
| return; |
There was a problem hiding this comment.
You can return completedResults here right?
And save one tick.
There was a problem hiding this comment.
Yes, updated to return completedResults here and in the error handler.
src/execution/execute.js
Outdated
|
|
||
| const itemType = returnType.ofType; | ||
|
|
||
| const handleNext = () => { |
There was a problem hiding this comment.
Usually, if we don't need this we use standard function syntax and put such functions after return of the main function.
There was a problem hiding this comment.
I refactored this a little bit so the handleNext function is no longer required. We do not need to create inline functions which rely on closures any more.
src/execution/execute.js
Outdated
| const itemType = returnType.ofType; | ||
|
|
||
| const handleNext = () => { | ||
| const fieldPath = addPath(path, index); |
There was a problem hiding this comment.
Can you please check if you need to add third argument.
There was a problem hiding this comment.
I'm not sure I understand what the third argument is for and when it should be passed. I updated it to pass undefined as that's what's done currently for list values:
graphql-js/src/execution/execute.js
Line 944 in 6012d28
bc704f9 to
56d2ba0
Compare
|
@IvanGoncharov this is ready for another review whenever you have some time. |
|
@robrichard Had a surgery so was offline for the last few weeks. |
|
@IvanGoncharov no rush, please take your time |
|
@robrichard I merged some changes to |
56d2ba0 to
1ff8a36
Compare
|
@IvanGoncharov this is up to date now |
src/execution/execute.js
Outdated
| const iteratorMethod = result[SYMBOL_ASYNC_ITERATOR]; | ||
| const iterator = iteratorMethod.call(result); |
There was a problem hiding this comment.
@robrichard Can we do?
| const iteratorMethod = result[SYMBOL_ASYNC_ITERATOR]; | |
| const iterator = iteratorMethod.call(result); | |
| const iterator = result[SYMBOL_ASYNC_ITERATOR](result); |
93bbece to
0ef8163
Compare
0ef8163 to
65450d3
Compare
|
@robrichard Thanks for your patience and sorry for such long delay. |
65450d3 to
f0c3215
Compare
|
@robrichard I rebased this PR against |
Co-authored-by: Ivan Goncharov <[email protected]>
Co-authored-by: Ivan Goncharov <[email protected]>
Co-authored-by: Ivan Goncharov <[email protected]>
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Co-authored-by: Ivan Goncharov <[email protected]> support async benchmark tests add benchmark tests for list fields add test for error from completeValue in AsyncIterable resolver change execute implementation for async iterable resolvers correctly handle promises returned by completeValue in async iterable resovlers
Returning AsyncIterables in resolver methods is useful when
@streamis supported and can be added without any breaking changes. This is split out from #2319