예제 #1
0
        private async void ApiQuery(ApiQuery query)
        {
            try
            {
                if (!_apiQueryUpdates.ContainsKey(query.ApiKey))
                {
                    _apiQueryUpdates.TryAdd(query.ApiKey, query);
                }

                if (!_apiQueryBusy)
                {
                    _apiQueryBusy = true;

                    while (_apiQueryUpdates.Count > 0)
                    {
                        var apiQueries = _apiQueryUpdates.Values.ToList();
                        _apiQueryUpdates.Clear();

                        var postQuery = new PostApiQuery()
                        {
                            SecurityToken = _sharedSettings.SecurityToken,
                            ApiQueries    = apiQueries
                        };

                        var start = new Stopwatch();
                        start.Start();
                        var result = await _sharedSettings.PostAsync <PostApiQuery, ReturnValue>("Remote/ApiQuery", postQuery, CancellationToken.None);

                        start.Stop();
                        _logger.LogTrace("Send api query completed in {0}ms.", start.ElapsedMilliseconds);

                        if (result.Success == false)
                        {
                            _logger.LogError(250, result.Exception,
                                             "Query api results failed.  Return message was: {0}." + result.Message);
                        }

                        // wait a little while for more tasks results to arrive.
                        await Task.Delay(500);
                    }

                    _apiQueryBusy = false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(250, ex,
                                 "Update api query failed with error.  Error was: {0}." + ex.Message);
                _apiQueryBusy = false;
            }
        }
예제 #2
0
        public async Task <string> Query(string securityKey, string action, string queryString, string ipAddress, CancellationToken cancellationToken = default)
        {
            if (_liveApis.TryGetValue(securityKey, out var apiData))
            {
                var timer = Stopwatch.StartNew();
                await apiData.WaitForTask(cancellationToken);

                JsonDocument inputColumns    = null;
                JsonDocument query           = null;
                JsonDocument inputParameters = null;

                try
                {
                    var parameters = HttpUtility.ParseQueryString(queryString);


                    if (action?.ToLower() == "info")
                    {
                        var columns       = apiData.Transform.CacheTable.Columns;
                        var inputColumns2 = apiData.Transform.GetSourceReader().CacheTable.Columns.Where(c => c.IsInput);

                        var infoQuery = new
                        {
                            Success      = true,
                            QueryColumns = columns,
                            InputColumns = inputColumns2
                        };

                        return(JsonExtensions.Serialize(infoQuery));
                    }

                    // check for a query
                    var q = parameters["q"];
                    query = q == null ? null : JsonDocument.Parse(q);

                    var i = parameters["i"];
                    inputColumns = i == null ? null : JsonDocument.Parse(i);

                    var p = parameters["p"];
                    inputParameters = p == null ? null : JsonDocument.Parse(p);

                    var cts = new CancellationTokenSource();
                    var t   = parameters["t"];
                    if (t != null)
                    {
                        if (long.TryParse(t, out var timeout))
                        {
                            cts.CancelAfter(TimeSpan.FromSeconds(timeout));
                        }
                        else
                        {
                            throw new Exception($"The timeout (t) was set to an invalid value {t}.  This needs to be the number seconds before timing out.");
                        }
                    }

                    var rows = -1;
                    var r    = parameters["r"];
                    if (r != null)
                    {
                        if (!int.TryParse(r, out rows))
                        {
                            throw new Exception($"The rows (r) was set to an invalid value {t}.  This needs to be the maximum number of rows.");
                        }
                    }

                    // TODO add EDownloadFormat to api options.
                    var selectQuery = apiData.SelectQuery == null ? new SelectQuery() : apiData.SelectQuery.CloneProperties();
                    selectQuery.LoadJsonFilters(apiData.Transform.CacheTable, query);
                    selectQuery.LoadJsonInputColumns(inputColumns);
                    selectQuery.LoadJsonParameters(inputParameters);
                    selectQuery.Rows = rows;

                    var combinedCancel = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token).Token;
                    var result         = await apiData.Transform.LookupJson(selectQuery, EDuplicateStrategy.All, combinedCancel);

                    apiData.IncrementSuccess();
                    timer.Stop();

                    var queryApi = new ApiQuery()
                    {
                        HubKey          = apiData.HubKey,
                        ApiKey          = apiData.ApiKey,
                        Success         = true, IpAddress = ipAddress,
                        Date            = DateTime.Now,
                        InputColumns    = inputColumns?.ToString(),
                        InputParameters = inputParameters?.ToString(),
                        Filters         = query?.ToString(),
                        TimeTaken       = timer.ElapsedMilliseconds
                    };

                    ApiQuery(queryApi);
                    ApiUpdate(apiData);

                    return(result);
                }
                catch (Exception ex)
                {
                    apiData.IncrementError();
                    timer.Stop();

                    var queryApi = new ApiQuery()
                    {
                        Success = false, Message = ex.Message, Exception = ex, IpAddress = ipAddress,
                        Date    = DateTime.Now, InputColumns = inputColumns?.ToString(),
                        Filters = query?.ToString(), TimeTaken = timer.ElapsedMilliseconds
                    };

                    ApiQuery(queryApi);

                    return(JsonExtensions.Serialize(new ReturnValue(false, ex.Message, ex)));
                }
                finally
                {
                    apiData.TaskComplete();
                }
            }

            throw new LiveDataException("The requested API is not available.");
        }