示例#1
0
        public void PurgeQueue(IFeedSubmissionEntryService feedSubmissionService)
        {
            var entriesToDelete = feedSubmissionService.GetAll().Where(rre => rre.AmazonRegion == _region && rre.MerchantId == _merchantId);

            feedSubmissionService.DeleteRange(entriesToDelete);
            feedSubmissionService.SaveChanges();
        }
示例#2
0
        public void Setup()
        {
            _options = new EasyMwsOptions();
            var propertiesContainer = new FeedSubmissionPropertiesContainer("testFeedContent", "testFeedType", false,
                                                                            new List <string>(MwsMarketplaceGroup.AmazonEurope().Select(m => m.Id)));
            var serializedPropertiesContainer = JsonConvert.SerializeObject(propertiesContainer);

            _feedSubmissionEntries = new List <FeedSubmissionEntry>
            {
                new FeedSubmissionEntry(serializedPropertiesContainer)
                {
                    Id = 2
                },
                new FeedSubmissionEntry(serializedPropertiesContainer)
                {
                    Id                = 1,
                    AmazonRegion      = AmazonRegion.Europe,
                    TargetHandlerId   = "TargetHandlerId",
                    TargetHandlerArgs = JsonConvert.SerializeObject(new Dictionary <string, object> {
                        { "key1", "value1" }
                    }),
                    FeedType           = propertiesContainer.FeedType,
                    FeedSubmissionData = JsonConvert.SerializeObject(propertiesContainer)
                }
            };

            _loggerMock = new Mock <IEasyMwsLogger>();
            _feedSubmissionCallbackRepoMock = new Mock <IFeedSubmissionEntryRepository>();
            _feedSubmissionCallbackRepoMock.Setup(x => x.GetAll()).Returns(_feedSubmissionEntries.AsQueryable());
            _feedSubmissionEntryService = new FeedSubmissionEntryService(_feedSubmissionCallbackRepoMock.Object, _options, _loggerMock.Object);
        }
示例#3
0
        public void DownloadNextFeedSubmissionResultFromAmazon(IFeedSubmissionEntryService feedSubmissionService)
        {
            var nextFeedWithProcessingComplete = feedSubmissionService.GetNextFromQueueOfProcessingCompleteFeeds(_merchantId, _region);

            if (nextFeedWithProcessingComplete == null)
            {
                return;
            }

            _feedSubmissionProcessor.DownloadFeedSubmissionResultFromAmazon(feedSubmissionService, nextFeedWithProcessingComplete);
        }
示例#4
0
        public void SubmitNextFeedInQueueToAmazon(IFeedSubmissionEntryService feedSubmissionService)
        {
            var feedSubmission = feedSubmissionService.GetNextFromQueueOfFeedsToSubmit(_merchantId, _region);

            if (feedSubmission == null)
            {
                return;
            }

            _feedSubmissionProcessor.SubmitFeedToAmazon(feedSubmissionService, feedSubmission);
        }
示例#5
0
        public void RequestFeedSubmissionStatusesAllFromAmazon(IFeedSubmissionEntryService feedSubmissionService)
        {
            var       allFeedSubmissions = feedSubmissionService.GetAllSubmittedFeedsFromQueue(_merchantId, _region).ToList();
            const int batchSize          = 20;
            var       numberOfBatches    = (allFeedSubmissions.Count + batchSize - 1) / batchSize;

            for (int batchNumber = 0; batchNumber < numberOfBatches; batchNumber++)
            {
                var nextBatchOfEntriesToProcess = allFeedSubmissions.Skip(batchSize * batchNumber).Take(batchSize).ToList();
                RequestFeedSubmissionStatusesBatchFromAmazon(feedSubmissionService, nextBatchOfEntriesToProcess);
            }
        }
 public void UnlockFeedSubmissionEntries(IFeedSubmissionEntryService feedSubmissionService, IEnumerable <string> feedSubmissionIds)
 {
     foreach (var submissionId in feedSubmissionIds)
     {
         var feedSubmissionEntry = feedSubmissionService.FirstOrDefault(fsc => fsc.FeedSubmissionId == submissionId);
         if (feedSubmissionEntry != null)
         {
             feedSubmissionService.Unlock(feedSubmissionEntry, "Unlocking multiple feed submission entries - amazon processing status update has been completed.");
             feedSubmissionService.Update(feedSubmissionEntry);
         }
     }
     feedSubmissionService.SaveChanges();
 }
示例#7
0
        public void PollFeeds(IFeedSubmissionEntryService feedSubmissionService)
        {
            _logger.Debug("Executing polling action for feed requests.");

            _feedSubmissionProcessor.CleanUpFeedSubmissionQueue(feedSubmissionService);

            SubmitNextFeedInQueueToAmazon(feedSubmissionService);

            RequestFeedSubmissionStatusesAllFromAmazon(feedSubmissionService);

            DownloadNextFeedSubmissionResultFromAmazon(feedSubmissionService);

            PublishEventsForPreviouslySubmittedFeeds(feedSubmissionService);
        }
示例#8
0
        public void RequestFeedSubmissionStatusesFromAmazon(IFeedSubmissionEntryService feedSubmissionService)
        {
            var feedSubmissionIds = feedSubmissionService.GetIdsForSubmittedFeedsFromQueue(_merchantId, _region).ToList();

            if (!feedSubmissionIds.Any())
            {
                return;
            }

            var feedSubmissionResults = _feedSubmissionProcessor.RequestFeedSubmissionStatusesFromAmazon(feedSubmissionService, feedSubmissionIds, _merchantId);

            if (feedSubmissionResults != null)
            {
                _feedSubmissionProcessor.QueueFeedsAccordingToProcessingStatus(feedSubmissionService, feedSubmissionResults);
            }

            _feedSubmissionProcessor.UnlockFeedSubmissionEntries(feedSubmissionService, feedSubmissionIds);
        }
示例#9
0
        public void RequestFeedSubmissionStatusesBatchFromAmazon(IFeedSubmissionEntryService feedSubmissionService, List <FeedSubmissionEntry> feedSubmissionsBatch)
        {
            if (!feedSubmissionsBatch.Any())
            {
                return;
            }

            feedSubmissionService.LockMultipleEntries(feedSubmissionsBatch, "Amazon status update has started");

            var feedSubmissionIds     = feedSubmissionsBatch.Select(_ => _.FeedSubmissionId);
            var feedSubmissionResults = _feedSubmissionProcessor.RequestFeedSubmissionStatusesFromAmazon(feedSubmissionService, feedSubmissionIds, _merchantId);

            if (feedSubmissionResults != null)
            {
                _feedSubmissionProcessor.QueueFeedsAccordingToProcessingStatus(feedSubmissionService, feedSubmissionResults);
            }

            feedSubmissionService.UnlockMultipleEntries(feedSubmissionsBatch, "Amazon status update has been completed");
        }
示例#10
0
        public void QueueFeed(IFeedSubmissionEntryService feedSubmissionService, FeedSubmissionPropertiesContainer propertiesContainer, string targetEventId = null, Dictionary <string, object> targetEventArgs = null)
        {
            try
            {
                if (propertiesContainer == null)
                {
                    throw new ArgumentNullException();
                }

                var serializedPropertiesContainer = JsonConvert.SerializeObject(propertiesContainer);

                var feedSubmission = new FeedSubmissionEntry(serializedPropertiesContainer)
                {
                    AmazonRegion             = _region,
                    MerchantId               = _merchantId,
                    LastSubmitted            = DateTime.MinValue,
                    DateCreated              = DateTime.UtcNow,
                    IsProcessingComplete     = false,
                    HasErrors                = false,
                    SubmissionErrorData      = null,
                    FeedSubmissionRetryCount = 0,
                    FeedSubmissionId         = null,
                    FeedType          = propertiesContainer.FeedType,
                    TargetHandlerId   = targetEventId,
                    TargetHandlerArgs = targetEventArgs == null ? null : JsonConvert.SerializeObject(targetEventArgs),
                    InstanceId        = _options?.EventPublishingOptions?.RestrictInvocationToOriginatingInstance?.HashedInstanceId,
                    Details           = new FeedSubmissionDetails
                    {
                        FeedContent = ZipHelper.CreateArchiveFromContent(propertiesContainer.FeedContent)
                    }
                };

                feedSubmissionService.Unlock(feedSubmission, "Unlocking single feed submission entry - newly created, ready for processing.");
                feedSubmissionService.Create(feedSubmission);
                feedSubmissionService.SaveChanges();

                _logger.Debug($"The following feed was queued for submission to Amazon {feedSubmission.EntryIdentityDescription}.");
            }
            catch (Exception e)
            {
                _logger.Error(e.Message, e);
            }
        }
示例#11
0
        private void PublishEventsForPreviouslySubmittedFeeds(IFeedSubmissionEntryService feedSubmissionService)
        {
            var previouslySubmittedFeeds = feedSubmissionService.GetAllFromQueueOfFeedsReadyForCallback(_merchantId, _region);

            foreach (var feedSubmissionEntry in previouslySubmittedFeeds)
            {
                try
                {
                    var processingReportContent = ZipHelper.ExtractArchivedSingleFileToStream(feedSubmissionEntry.Details.FeedSubmissionReport);
                    var feedType    = feedSubmissionEntry.FeedType;
                    var handlerId   = feedSubmissionEntry.TargetHandlerId;
                    var handledArgs = feedSubmissionEntry.TargetHandlerArgs == null ? null : new ReadOnlyDictionary <string, object>(JsonConvert.DeserializeObject <Dictionary <string, object> >(feedSubmissionEntry.TargetHandlerArgs));
                    var eventArgs   = new FeedUploadedEventArgs(processingReportContent, feedType, handlerId, handledArgs);

                    _logger.Debug($"Attempting publish FeedUploaded for the next submitted feed in queue : {feedSubmissionEntry.EntryIdentityDescription}");
                    OnFeedUploaded(eventArgs);
                    feedSubmissionService.Delete(feedSubmissionEntry);
                    _logger.Info($"Event publishing has succeeded for {feedSubmissionEntry.EntryIdentityDescription}.");
                }
                catch (SqlException e)
                {
                    _logger.Error($"Event publishing failed for {feedSubmissionEntry.EntryIdentityDescription} due to an internal error '{e.Message}'. The event publishing will be retried at the next poll request", e);
                    feedSubmissionService.Unlock(feedSubmissionEntry, "Unlocking single feed submission entry - an SQL exception occurred while trying to invoke callback.");
                    feedSubmissionService.Update(feedSubmissionEntry);
                }
                catch (Exception e)
                {
                    _logger.Error($"Event publishing failed for {feedSubmissionEntry.EntryIdentityDescription}. Current retry count is :{feedSubmissionEntry.FeedSubmissionRetryCount}. {e.Message}", e);
                    feedSubmissionEntry.InvokeCallbackRetryCount++;
                    feedSubmissionService.Unlock(feedSubmissionEntry, "Unlocking single feed submission entry - an exception occurred while trying to invoke callback.");
                    feedSubmissionService.Update(feedSubmissionEntry);
                }
            }

            feedSubmissionService.SaveChanges();
        }
示例#12
0
        public void SubmitFeedToAmazon(IFeedSubmissionEntryService feedSubmissionService, FeedSubmissionEntry feedSubmission)
        {
            void HandleSubmitFeedSuccess(SubmitFeedResponse response)
            {
                var requestId = response?.ResponseHeaderMetadata?.RequestId ?? "unknown";
                var timestamp = response?.ResponseHeaderMetadata?.Timestamp ?? "unknown";

                feedSubmission.FeedSubmissionId         = response?.SubmitFeedResult?.FeedSubmissionInfo?.FeedSubmissionId;
                feedSubmission.FeedSubmissionRetryCount = 0;
                _logger.Info($"AmazonMWS feed submission has succeeded for {feedSubmission.EntryIdentityDescription}. FeedSubmissionId:'{feedSubmission.FeedSubmissionId}'.",
                             new RequestInfo(timestamp, requestId));
            }

            void HandleMissingFeedSubmissionId()
            {
                feedSubmission.FeedSubmissionRetryCount++;
                _logger.Warn($"SubmitFeed did not generate a FeedSubmissionId for {feedSubmission.EntryIdentityDescription}. Feed submission will be retried. FeedSubmissionRetryCount is now : {feedSubmission.FeedSubmissionRetryCount}.");
            }

            void HandleNonFatalOrGenericException(Exception e)
            {
                feedSubmission.FeedSubmissionRetryCount++;
                feedSubmission.LastSubmitted = DateTime.UtcNow;

                _logger.Warn($"AmazonMWS SubmitFeed failed for {feedSubmission.EntryIdentityDescription}. Feed submission will be retried. FeedSubmissionRetryCount is now : {feedSubmission.FeedSubmissionRetryCount}.", e);
            }

            void HandleFatalException(Exception e)
            {
                feedSubmissionService.Delete(feedSubmission);
                _logger.Error($"AmazonMWS SubmitFeed failed for {feedSubmission.EntryIdentityDescription}. The entry will now be removed from queue", e);
            }

            var missingInformationExceptionMessage = "Cannot submit queued feed to amazon due to missing feed submission information";

            if (feedSubmission == null)
            {
                throw new ArgumentNullException($"{missingInformationExceptionMessage}: Feed submission entry is null");
            }
            if (feedSubmission.FeedSubmissionData == null)
            {
                throw new ArgumentNullException($"{missingInformationExceptionMessage}: Feed submission data is null");
            }

            var feedContentZip = feedSubmission.Details?.FeedContent;

            if (feedContentZip == null)
            {
                throw new ArgumentNullException($"{missingInformationExceptionMessage}: Feed content is missing");
            }

            if (string.IsNullOrEmpty(feedSubmission?.FeedType))
            {
                throw new ArgumentException($"{missingInformationExceptionMessage}: Feed type is missing");
            }

            _logger.Debug($"Attempting to submit the next feed in queue to Amazon: {feedSubmission.EntryIdentityDescription}.");

            var feedSubmissionData = feedSubmission.GetPropertiesContainer();

            using (var stream = ZipHelper.ExtractArchivedSingleFileToStream(feedContentZip))
            {
                var submitFeedRequest = new SubmitFeedRequest
                {
                    Merchant          = feedSubmission.MerchantId,
                    FeedType          = feedSubmission.FeedType,
                    FeedContent       = stream,
                    MarketplaceIdList = feedSubmissionData.MarketplaceIdList == null ? null : new IdList {
                        Id = feedSubmissionData.MarketplaceIdList
                    },
                    PurgeAndReplace = feedSubmissionData.PurgeAndReplace ?? false,
                    ContentMD5      = MD5ChecksumHelper.ComputeHashForAmazon(stream),
                };

                if (!string.IsNullOrEmpty(_mWSAuthToken))
                {
                    submitFeedRequest.MWSAuthToken = _mWSAuthToken;
                }

                try
                {
                    feedSubmissionService.Unlock(feedSubmission, "Unlocking single feed submission entry - finished attempt to submit feed to amazon.");
                    feedSubmissionService.Update(feedSubmission);

                    var response = _marketplaceWebServiceClient.SubmitFeed(submitFeedRequest);
                    feedSubmission.LastSubmitted = DateTime.UtcNow;

                    if (string.IsNullOrEmpty(response?.SubmitFeedResult?.FeedSubmissionInfo?.FeedSubmissionId))
                    {
                        HandleMissingFeedSubmissionId();
                    }
                    else
                    {
                        HandleSubmitFeedSuccess(response);
                    }
                }
                catch (MarketplaceWebServiceException e) when(e.StatusCode == HttpStatusCode.BadRequest && IsAmazonErrorCodeFatal(e.ErrorCode))
                {
                    HandleFatalException(e);
                }
                catch (MarketplaceWebServiceException e) when(IsAmazonErrorCodeNonFatal(e.ErrorCode))
                {
                    HandleNonFatalOrGenericException(e);
                }
                catch (Exception e)
                {
                    HandleNonFatalOrGenericException(e);
                }
                finally
                {
                    stream.Dispose();
                    feedSubmissionService.SaveChanges();
                }
            }
        }
示例#13
0
 public void QueueFeedsAccordingToProcessingStatus(IFeedSubmissionEntryService feedSubmissionService, List <(string FeedSubmissionId, string FeedProcessingStatus)> feedProcessingStatuses)
示例#14
0
        public List <(string FeedSubmissionId, string FeedProcessingStatus)> RequestFeedSubmissionStatusesFromAmazon(IFeedSubmissionEntryService feedSubmissionService, IEnumerable <string> feedSubmissionIdList, string merchant)
        {
            List <(string FeedSubmissionId, string IsProcessingComplete)> GetProcessingStatusesPerSubmissionIdFromResponse(GetFeedSubmissionListResponse response)
            {
                var responseInfo = new List <(string FeedSubmissionId, string IsProcessingComplete)>();

                foreach (var feedSubmissionInfo in response.GetFeedSubmissionListResult.FeedSubmissionInfo)
                {
                    responseInfo.Add((feedSubmissionInfo.FeedSubmissionId, feedSubmissionInfo.FeedProcessingStatus));
                }
                return(responseInfo);
            }

            _logger.Debug($"Attempting to request feed submission statuses for all feeds in queue.");

            var request = new GetFeedSubmissionListRequest()
            {
                FeedSubmissionIdList = new IdList(), Merchant = merchant
            };

            request.FeedSubmissionIdList.Id.AddRange(feedSubmissionIdList);

            if (!string.IsNullOrEmpty(_mWSAuthToken))
            {
                request.MWSAuthToken = _mWSAuthToken;
            }

            try
            {
                var response = _marketplaceWebServiceClient.GetFeedSubmissionList(request);

                var requestId = response?.ResponseHeaderMetadata?.RequestId ?? "unknown";
                var timestamp = response?.ResponseHeaderMetadata?.Timestamp ?? "unknown";
                _logger.Debug($"AmazonMWS request for feed submission statuses succeeded.", new RequestInfo(timestamp, requestId));

                if (response?.GetFeedSubmissionListResult?.FeedSubmissionInfo != null)
                {
                    return(GetProcessingStatusesPerSubmissionIdFromResponse(response));
                }
                else
                {
                    _logger.Warn("AmazonMWS GetFeedSubmissionList response does not contain any results. The operation will be executed again at the next poll request.");
                    return(null);
                }
            }
            catch (MarketplaceWebServiceException e)
            {
                _logger.Warn($"AmazonMWS GetFeedSubmissionList failed! The operation will be executed again at the next poll request.", e);
                return(null);
            }
            catch (Exception e)
            {
                _logger.Warn($"AmazonMWS GetFeedSubmissionList failed! The operation will be executed again at the next poll request.", e);
                return(null);
            }
        }