private async ValueTask <List <object?> > CreateStreamResultAsync( StreamDirective streamDirective) { IAsyncEnumerable <object?> enumerable = Selection.CreateStream(_resolverContext.Result !); IAsyncEnumerator <object?> enumerator = enumerable.GetAsyncEnumerator(); var next = true; try { var list = new List <object?>(); var initialCount = streamDirective.InitialCount; var count = 0; if (initialCount > 0) { while (next) { count++; next = await enumerator.MoveNextAsync().ConfigureAwait(false); list.Add(enumerator.Current); if (count >= initialCount) { break; } } } if (next) { // if the stream has more items than the initial requested items then we will // defer the rest of the stream. _operationContext.Scheduler.DeferredWork.Register( new DeferredStream( Selection, streamDirective.Label, _resolverContext.Path, _resolverContext.Parent <object>(), count - 1, enumerator, _resolverContext.ScopedContextData)); } return(list); } finally { if (!next) { // if there is no deferred work we will just dispose the enumerator. // in the case we have deferred work, the deferred stream handler is // responsible of handling the dispose. await enumerator.DisposeAsync().ConfigureAwait(false); } } }
private async ValueTask ExecuteResolverPipelineAsync(CancellationToken cancellationToken) { await _resolverContext.ResolverPipeline !(_resolverContext).ConfigureAwait(false); if (_resolverContext.Result is null) { return; } if (_resolverContext.Result is IError error) { _resolverContext.ReportError(error); _resolverContext.Result = null; return; } // if we are not a list we do not need any further result processing. if (!Selection.IsList) { return; } if (Selection.IsStreamable) { StreamDirective streamDirective = Selection.SyntaxNode.Directives.GetStreamDirective( _resolverContext.Variables) !; if (streamDirective.If) { _resolverContext.Result = await CreateStreamResultAsync(streamDirective) .ConfigureAwait(false); return; } } if (Selection.MaybeStream) { _resolverContext.Result = await CreateListFromStreamAsync() .ConfigureAwait(false); return; } switch (_resolverContext.Result) { case IExecutable executable: _resolverContext.Result = await executable .ToListAsync(cancellationToken) .ConfigureAwait(false); break; case IQueryable queryable: _resolverContext.Result = await Task.Run(() => { var items = new List <object?>(); foreach (var o in queryable) { items.Add(o); if (cancellationToken.IsCancellationRequested) { break; } } return(items); }, cancellationToken); break; } }