public static IEnumerable <TResponse> SendAll <TRequest, TResponse>(
            this IServiceClient client,
            int batchSize,
            IEnumerable <TRequest> requests,
            CancellationToken?cancellationToken = null,
            IProgressReporter progressReporter  = null)
            where TRequest : IReturn <TResponse>
        {
            var responses = new List <TResponse>();

            progressReporter?.Started();

            var requestBatches = BatchesOf(requests, batchSize)
                                 .ToList();

            var totalCount = requestBatches.Sum(b => b.Length);

            foreach (var requestBatch in requestBatches)
            {
                var firstRequest = requestBatch.First();

                var requestNameResolver = EndpointRequestNameResolvers
                                          .GetOrAdd(client, serviceClient => new ServerRequestNameResolver());

                var serverRequestName = requestNameResolver.ResolveRequestName(client, firstRequest);

                responses.AddRange(SendBatch <TResponse>(client, serverRequestName, requestBatch.Cast <object>()));

                progressReporter?.Progress(responses.Count, totalCount);

                if (cancellationToken.HasValue && cancellationToken.Value.IsCancellationRequested)
                {
                    break;
                }
            }

            progressReporter?.Completed();

            return(responses);
        }
Пример #2
0
        private IEnumerable <TDomainObject> GetPaginatedResults <TDomainObject, TRequest, TResponse>(TRequest requestDto, TResponse responseDto, CancellationToken?cancellationToken, IProgressReporter progressReporter)
            where TRequest : IPaginatedRequest, IReturn <TResponse>
            where TResponse : IPaginatedResponse <TDomainObject>
        {
            var totalCount = responseDto.TotalCount;

            for (var count = 0; count < totalCount;)
            {
                if (responseDto.DomainObjects == null)
                {
                    break;
                }

                if (cancellationToken.HasValue && cancellationToken.Value.IsCancellationRequested)
                {
                    break;
                }

                foreach (var domainObject in responseDto.DomainObjects)
                {
                    yield return(domainObject);
                }

                count += responseDto.DomainObjects.Count;

                progressReporter?.Progress(count, totalCount);

                if (count >= totalCount || count >= responseDto.TotalCount || !responseDto.DomainObjects.Any() || string.IsNullOrEmpty(responseDto.Cursor))
                {
                    break;
                }

                requestDto.Cursor = responseDto.Cursor;

                responseDto = Get(requestDto);
            }

            progressReporter?.Completed();
        }
Пример #3
0
        public static IEnumerable <TResponse> SendAll <TRequest, TResponse>(
            this IServiceClient client,
            int batchSize,
            IEnumerable <TRequest> requests,
            Action <TRequest, ResponseStatus> failedRequestHandler = null,
            CancellationToken?cancellationToken = null,
            IProgressReporter progressReporter  = null)
            where TRequest : IReturn <TResponse>
        {
            var responses = new List <TResponse>();

            progressReporter?.Started();

            var requestBatches = BatchesOf(requests, batchSize)
                                 .ToList();

            var totalCount = requestBatches.Sum(b => b.Length);

            var failedRequests = 0;

            foreach (var requestBatch in requestBatches)
            {
                var firstRequest = requestBatch.First();

                var requestNameResolver = EndpointRequestNameResolvers
                                          .GetOrAdd(client, serviceClient => new ServerRequestNameResolver());

                var serverRequestName = requestNameResolver.ResolveRequestName(client, firstRequest);

                var batchRequests = requestBatch.ToList();

                while (true)
                {
                    if (cancellationToken.HasValue && cancellationToken.Value.IsCancellationRequested)
                    {
                        break;
                    }

                    try
                    {
                        var batchResponses = SendBatch <TResponse>(client, serverRequestName, batchRequests.Cast <object>());

                        responses.AddRange(batchResponses);

                        break;
                    }
                    catch (WebServiceException webServiceException)
                    {
                        if (failedRequestHandler != null &&
                            (webServiceException.ResponseStatus?.Meta?.TryGetValue("AutoBatchIndex", out var textValue) ?? false) &&
                            int.TryParse(textValue, out var batchIndex) &&
                            batchIndex >= 0 && batchIndex < requestBatch.Length)
                        {
                            failedRequestHandler(batchRequests[batchIndex], webServiceException.ResponseStatus);

                            ++failedRequests;

                            batchRequests.RemoveAt(batchIndex);

                            if (!batchRequests.Any())
                            {
                                break;
                            }

                            if (failedRequests > totalCount / 4)
                            {
                                throw new WebServiceException($"Too many failed batch requests ({failedRequests} out of {totalCount}) for {serverRequestName}.", webServiceException)
                                      {
                                          StatusCode = 500
                                      }
                            }
                            ;

                            continue;
                        }

                        throw;
                    }
                }

                progressReporter?.Progress(responses.Count, totalCount);

                if (cancellationToken.HasValue && cancellationToken.Value.IsCancellationRequested)
                {
                    break;
                }
            }

            progressReporter?.Completed();

            return(responses);
        }