/// <inheritdoc /> public async Task <Response> DistributeQueryAsync(Request request) { if (!request.Validate(out var validationResult)) { return(Response.Fail(validationResult.ErrorMessage)); } var servers = _statisticsStorage.Get(request.Type); var maxSessions = _configuration.GetMaxSessionsParameter(request.Type); var availableServer = _serverDecider.FindAvailableServer(servers, maxSessions); if (availableServer is null) { return(HandleNoAvailableServerScenario(request)); } var serializedData = string.Empty; try { if (request.IsSelect) { serializedData = await _queryExecutor.QueryAsync(availableServer, request.Query); } else { await _queryExecutor.ExecuteAsync(availableServer, request.Query); } if (request.IsRetried) { _responseStorage.Add(Response.Completed(serializedData, request.RequestId)); } return(Response.Completed(serializedData, request.RequestId)); } catch (PostgresException postgresException) { var message = $"Query is not correct: {postgresException.Message}"; // postgres errors are client-side problems if (!request.AcceptRetries) { return(Response.Fail(message)); } request.RequestId = Guid.NewGuid(); _responseStorage.Add(Response.Fail(message, request.RequestId)); return(Response.Queued(request.RequestId)); } catch (Exception) { // if not postgres error, must be system error // failing if request does not support queue if (!request.AcceptRetries) { return(Response.Fail("No server available right now.")); } var maxRetryCount = _configuration.MaxRetryCount; if (request.IsRetried && request.CurrentRetryAttempt >= maxRetryCount) { _responseStorage.Add(Response.Fail("Number of allowed attempts exceeded", request.RequestId)); return(Response.Fail()); } request.IsRetried = true; request.RequestId = Guid.NewGuid(); _queue.Add(request); return(Response.Completed(request.RequestId.ToString())); } }