private async Task <HttpResponse> ExecuteHttpRequestInternal(
            HttpRequestPriority priority,
            HttpRequest request,
            bool isBinaryContent = false,
            int timeout          = 0)
        {
            var message = new HttpRequestMessage(new HttpMethod(request.Method), request.Uri);

            foreach (var header in request.Headers)
            {
                ApplyHeader(message, header);
            }

            foreach (var header in request.CustomHeaders)
            {
                message.Headers.Add(header.Key, header.Value.ToString());
            }

            if (!string.IsNullOrEmpty(request.Data) && !string.IsNullOrEmpty(request.ContentType))
            {
                message.Content = new StringContent(request.Data ?? string.Empty);
                message.Content.Headers.ContentType = new MediaTypeHeaderValue(request.ContentType);
            }

            return(await _httpRequestsScheduler.ExecuteAsync(
                       priority,
                       message,
                       timeout,
                       isBinaryContent).ConfigureAwait(false));
        }
 public Guid Schedule(
     HttpRequestPriority priority,
     HttpRequestMessage request,
     int timeout          = 0,
     bool isBinaryContent = false)
 {
     return(ScheduleInternal(priority, request, timeout, isBinaryContent).Id);
 }
        public void ChangePriority(Guid taskId, HttpRequestPriority newPriority)
        {
            _taskIdToTaskMap.TryGetValue(taskId, out var task);

            if (task == null || task.Priority == newPriority)
            {
                return;
            }

            _tasksQueue.TryUpdatePriority(task, GetPriorityForNewItem(newPriority));
        }
        public async Task <HttpResponse> ExecuteAsync(
            HttpRequestPriority priority,
            HttpRequestMessage request,
            int timeout          = 0,
            bool isBinaryContent = false)
        {
            var task = ScheduleInternal(priority, request, timeout, isBinaryContent);

            await WaitForTaskCompletionAsync(task).ConfigureAwait(false);

            return(task.Response);
        }
        public HttpRequestsScheduler(HttpServiceGateConfig config)
        {
            _config = config;

            _supportedStatusCodes = Enum.GetValues(typeof(HttpStatusCode)).Cast <int>().ToImmutableHashSet();
            _tasksQueue           = new SimplePriorityQueue <HttpRequestScheduledTaskBase>();
            _highestPriority      = EnumExtensions.GetValues <HttpRequestPriority>().First();

            _queueSyncLock = new Object();

            InitializeMaps();

            StartTasksExecution();
        }
        public async Task <string> ExecuteRedirectOnlyAsync(HttpRequestPriority priority, string urlWithRedirect)
        {
            var task = new RedirectHttpRequestScheduledTask(_config.DeadRequestTimeoutInMilliseconds)
            {
                RequestUrl = urlWithRedirect,
                Priority   = priority
            };

            AddNewTask(priority, task);

            await WaitForTaskCompletionAsync(task).ConfigureAwait(false);

            return(task.ResponseRedirectUrl);
        }
        public async Task <HttpResponse> ExecuteApiCallAsync(HttpRequestPriority priority, HttpRequest request, int timeout = 0, params HttpStatusCode[] ignoreErrorCodes)
        {
            var response = await _client.ExecuteAsStringResponseAsync(priority, request, timeout).ConfigureAwait(false);

            if (response.IsSuccessful || ignoreErrorCodes.Contains(response.StatusCode))
            {
                return(response);
            }

            if (HttpStatusCodes.IsErrorStatus(response.StatusCode))
            {
                throw new HttpException("Error status code received", response);
            }

            return(response);
        }
        private void RemoveOldestTask(HttpRequestPriority priority)
        {
            lock (_queueSyncLock)
            {
                _perPriorityQueue[priority].TryDequeue(out var oldestTask);

                _tasksQueue.TryRemove(oldestTask);

                if (oldestTask == null)
                {
                    return;
                }

                _taskIdToTaskMap.TryRemove(oldestTask.Id, out var _);

                _priorityToTasksCountMap.AddOrUpdate(oldestTask.Priority, 0, (key, value) => value - 1);
            }
        }
        private CompleteHttpRequestScheduledTask ScheduleInternal(
            HttpRequestPriority priority,
            HttpRequestMessage request,
            int timeout          = 0,
            bool isBinaryContent = false)
        {
            var taskTimeout = timeout != 0 ? timeout : _config.DeadRequestTimeoutInMilliseconds;

            var task = new CompleteHttpRequestScheduledTask(taskTimeout)
            {
                Request         = request,
                Priority        = priority,
                IsBinaryContent = isBinaryContent,
            };

            AddNewTask(priority, task);

            return(task);
        }
        public async Task <HttpResponse> ExecuteApiCallAsync(HttpRequestPriority priority, HttpRequest request, int timeout = 0, params HttpStatusCode[] ignoreErrorCodes)
        {
            var response = await _client.ExecuteAsStringResponseAsync(priority, request, timeout).ConfigureAwait(false);

            if (ValidateResponse(response, true, ignoreErrorCodes))
            {
                return(response);
            }

            //try to retrive session again if token is not valid
            if (!IsSessionValid(response))
            {
                //if session request is already in progress, then await it
                var shouldRetrieveSession = await EnsureNoSessionRetrievalIsRunningAsync().ConfigureAwait(false);

                if (shouldRetrieveSession)
                {
                    var executionStatus = await RetrieveSessionAsync().ConfigureAwait(false);

                    if (executionStatus == ExecutionStatus.Completed)
                    {
                        request.WithCredentials(_membershipService);
                        response = await _client.ExecuteAsStringResponseAsync(priority, request).ConfigureAwait(false);
                    }
                }
                else
                {
                    request.WithCredentials(_membershipService);

                    response = await _client.ExecuteAsStringResponseAsync(priority, request).ConfigureAwait(false);
                }

                //if session issue is still not resolved, redirect to first install login screen, because we can't perform activities without session
                if (!IsSessionValid(response))
                {
                    return(response);
                }
            }

            ValidateResponse(response, ignoreErrorCodes: ignoreErrorCodes);

            return(response);
        }
        private void AddNewTask(HttpRequestPriority priority, HttpRequestScheduledTaskBase task)
        {
            _priorityToTasksCountMap.TryGetValue(priority, out var itemsCount);

            if (itemsCount > _config.MaxHttpLoadThreads)
            {
                RemoveOldestTask(priority);
            }

            _priorityToTasksCountMap.AddOrUpdate(priority, 1, (key, value) => value + 1);
            _taskIdToTaskMap.AddOrUpdate(task.Id, task, (key, value) => task);

            lock (_queueSyncLock)
            {
                var priorityForNewItem = GetPriorityForNewItem(priority);

                _tasksQueue.Enqueue(task, priorityForNewItem);
                _perPriorityQueue[priority].Enqueue(task, priorityForNewItem);
            }
        }
        public async Task <T> ExecuteApiCallAndParseAsync <T>(HttpRequestPriority priority, HttpRequest request)
        {
            var response = await ExecuteApiCallAsync(priority, request).ConfigureAwait(false);

            return(response.ParseContentAsJson <T>());
        }
 public async Task <string> GetRedirectedUrlAsync(HttpRequestPriority priority, string urlWithRedirect)
 {
     return(await _httpRequestsScheduler.ExecuteRedirectOnlyAsync(priority, urlWithRedirect).ConfigureAwait(false));
 }
 public async Task <HttpResponse> ExecuteAsBinaryResponseAsync(HttpRequestPriority priority, HttpRequest request, int timeout = 0)
 {
     return(await ExecuteHttpRequestInternal(priority, request, true, timeout).ConfigureAwait(false));
 }
        private float GetPriorityForNewItem(HttpRequestPriority priority)
        {
            _priorityToTasksCountMap.TryGetValue(priority, out var tasksCountWithTargetPriority);

            return((int)priority * PriorityRange + tasksCountWithTargetPriority);
        }