Beispiel #1
0
        public async Task QueryAsync(IClientProxy caller, string rawQuery)
        {
            CancelOngoingQuery(out var currentCt);

            var query = new Query(rawQuery);

            using (_logger.BeginScope(LogProperties.QueryId, query.Id))
            {
                currentCt.ThrowIfCancellationRequested();
                _logger.Verbose("Notifying frontend that query is received.");
                await caller.InvokeAsync(new QueryReceived(query), currentCt);

                var providers = GetProviders(query);
                _logger.Verbose("Notifying frontend that query will be handled by {providerCount} providers.", providers.Count);
                await caller.InvokeAsync(QueryExecuting.By(providers), currentCt);

                // Execute query
                var allTasks = providers.Select(p => Task.Run(async() =>
                {
                    var providerName = p.GetType().Name;
                    using (var operation = _logger.Timed("Query from {queryProvider}", providerName))
                    {
                        try
                        {
                            var results = (await p.QueryAsync(query, currentCt)).ToList();
                            currentCt.ThrowIfCancellationRequested();
                            _logger.Debug("Provider {queryProvider} executed query successfully. {resultCount} results available.", providerName, results.Count);
                            await caller.InvokeAsync(new ResultsAvailable(query.Id, results), currentCt);
                            return(results);
                        }
                        catch (Exception)
                        {
                            operation.Cancel();
                            throw;
                        }
                    }
                }, currentCt))
                               .ToList();

                // Wait for provider tasks
                await Task.WhenAll(allTasks).ContinueWith(async _ =>
                {
                    Task.WaitAll(allTasks.ToArray <Task>());
                    var allResults = allTasks.Where(t => t.IsCompleted).SelectMany(t => t.Result).ToList();

                    if (allTasks.Any(t => !t.IsCompletedSuccessfully))
                    {
                        _logger.Debug("One or more sub queries have failed.");
                        await caller.InvokeAsync(new QueryCancelled(query.Id), currentCt);
                    }
                    else
                    {
                        _logger.Verbose("Query completed. Total result count is {resultCount}", allResults.Count);
                        await caller.InvokeAsync(new QueryCompleted(query.Id, allResults), currentCt);
                    }
                });
            }
        }
Beispiel #2
0
        public async Task QueryAsync(string rawQuery, IObserver <BackendEvent> observer)
        {
            if (string.IsNullOrWhiteSpace(rawQuery))
            {
                return;
            }

            IQuery query = new Query(rawQuery);

            using (_logger.BeginScope(LogProperties.QueryId, query.Id))
                using (_logger.Timed("Query {rawQuery}", rawQuery))
                {
                    CancelOngoingQuery(out var currentCt);

                    _logger.Verbose("Notifying observers that query is received.");
                    observer.OnNext(new QueryReceived(query));
                    var providers = GetProviders(query);
                    if (!providers.Any())
                    {
                        providers = _queryProviders.ToList();
                        query     = new DefaultQuery(query);
                    }
                    _logger.Verbose("Notifying observers that query will be handled by {providerCount} providers.", providers.Count);
                    observer.OnNext(QueryExecuting.By(providers));

                    var providerTasks = providers
                                        .Select(provider =>
                                                Task.Run(async() =>
                    {
                        var operation        = _logger.Timed("{queryProvider} provider", provider.GetType().Name);
                        var providerObserver = Observer.Create <BackendEvent>(observer.OnNext, operation.Cancel, operation.Complete);
                        try
                        {
                            await provider.QueryAsync(query, providerObserver, currentCt);
                        }
                        catch (OperationCanceledException)
                        {
                            _logger.Information("Query {rawQuery} has been cancelled for {queryProvider}", rawQuery, providerObserver.GetType().Name);
                            /* Cancellation is OK */
                        }
                        catch (Exception e)
                        {
                            _logger.Information(e, "An unhandle exception was thrown.");
                        }
                        finally
                        {
                            providerObserver.OnCompleted();
                        }
                    }, currentCt))
                                        .ToArray();
                    await Task.WhenAll(providerTasks);

                    observer.OnNext(new QueryCompleted(query.Id, null));
                }
        }