/// <summary> /// Initiates a catalog publishing. /// </summary> /// <param name="catalogPublisher">Instance of the object which implements ICatalogPublisher.</param> /// <returns>True if changed products were found in CRT, False otherwise.</returns> /// <remarks>Retrieves the channel's catalogs from CRT and then checks whether CRT contains changed products for each of the catalogs. If changed products are found then /// ICatalogPublisher's callbacks are executed to let the caller's code process changed products.</remarks> public bool PublishCatalog(ICatalogPublisher catalogPublisher) { if (catalogPublisher == null) { throw new ArgumentNullException(nameof(catalogPublisher)); } List <long> productCatalogIds = new List <long>(1); // If catalogs were published to this channel, a given product will be published into SP for each catalog // in which it appears, so catalogless publishing would not yield different results for those products. // If, however, a product was published directly from the assortment, that product will only be detected // and published to SP if the ForceCataloglessPublishing flag is set to 'true' (1) in the job configuration file. // The semantics of forcing catalogless publishing as strict, in that catalog-less products will be published // if and only if the flag is set. That means, for instance, that if the flag is not set and there are no // catalogs published to this channel, the SP job will not detect/publish any products to SP. if (this.publishingConfig.ForceNoCatalogPublishing) { NetTracer.Information(Resources.ProductCatalogToPublish, 0, "unspecified", "(not a proper catalog)"); productCatalogIds.Add(0); } IReadOnlyCollection <ProductCatalog> productCatalogs = this.GetCatalogs(); bool deletesFound = this.DeleteProducts(productCatalogs, catalogPublisher); foreach (ProductCatalog productCatalog in productCatalogs) { productCatalogIds.Add(productCatalog.RecordId); } ChangedProductsSearchCriteria searchCriteria = new ChangedProductsSearchCriteria { DataLevel = CommerceEntityDataLevel.Complete }; searchCriteria.Context.ChannelId = this.onlineChannel.RecordId; bool isInitialSync; QueryResultSettings productsQuerySettings = this.CreateGetListingsCriteria( this.onlineChannel.ChannelProperties, searchCriteria, out isInitialSync); bool changesFound = false; try { Stopwatch readChangedProductsWatch = Stopwatch.StartNew(); searchCriteria.Session = this.productManager.BeginReadChangedProducts(searchCriteria); readChangedProductsWatch.Stop(); this.LogTimingMessage(Resources.Duration_ReadChangedProducts, readChangedProductsWatch.Elapsed, searchCriteria.Session.TotalNumberOfProducts); if (searchCriteria.Session.TotalNumberOfProducts > 0) { changesFound = true; int totalProductsCount = 0; Stopwatch timerCummulativeListingRetrieval = new Stopwatch(); // loop through the product catalogs, retrieving products. foreach (long productCatalogId in productCatalogIds) { NetTracer.Information(Resources.StartReadProductsFromCatalog, productCatalogId); // set the catalog id on the search criteria searchCriteria.Context.CatalogId = productCatalogId; searchCriteria.Session.ResetNumberOfProductsRead(); int pageNumberForCatalog = 0; int catalogProductsCount = 0; // inner loop: load changes, page by page, up to catalog max size do { timerCummulativeListingRetrieval.Start(); ChangedProductsSearchResult getProductsResults = this.LoadChangedProducts(searchCriteria, productsQuerySettings); timerCummulativeListingRetrieval.Stop(); int numberOfReadProducts = getProductsResults.Results.Count; totalProductsCount += numberOfReadProducts; catalogProductsCount += numberOfReadProducts; this.LogTimingMessage(Resources.NumberOfReadProductsInPageSummary, productCatalogId, catalogProductsCount, totalProductsCount, timerCummulativeListingRetrieval.Elapsed); catalogPublisher.OnChangedProductsFound(getProductsResults, pageNumberForCatalog, productCatalogId); pageNumberForCatalog++; }while (searchCriteria.Session.NumberOfProductsRead < searchCriteria.Session.TotalNumberOfProducts); this.LogTimingMessage(Resources.CatalogReadCompleted, productCatalogId, catalogProductsCount, totalProductsCount, timerCummulativeListingRetrieval.Elapsed); catalogPublisher.OnCatalogReadCompleted(productCatalogId, this); } // for each product catalog this.LogTimingMessage(Resources.AllCatalogsReadCompleted, totalProductsCount, timerCummulativeListingRetrieval.Elapsed); } // if changed products were found } finally { this.productManager.EndReadChangedProducts(searchCriteria.Session); } ChannelProperty channelProperty = new ChannelProperty { Name = KeySyncAnchor, Value = new string(searchCriteria.Session.NextSynchronizationToken) }; this.channelManager.UpdateChannelProperties(new ChannelProperty[] { channelProperty }); return(changesFound || deletesFound); }