Skip to content

Instantly share code, notes, and snippets.

@jstemerdink
Created December 11, 2018 11:04
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jstemerdink/84318b454f83ad3621fa7a45f99f3917 to your computer and use it in GitHub Desktop.

Speed up your product imports

You can use these examples to speed up your product imports in Episerver Commerce.

Read my blog here

Powered by ReSharper image

using System.Collections.Generic;
using System.Linq;
using EPiServer.Commerce.Catalog.ContentTypes;
using EPiServer.Core;
using EPiServer.Find;
using EPiServer.Find.Cms;
using EPiServer.PlugIn;
using EPiServer.Scheduler;
using EPiServer.ServiceLocation;
[ScheduledPlugIn(DisplayName = "Import products ScheduledJob", GUID = "617b1b46-c1d8-4a94-82fe-d7c689b9f7c0")]
public class ImportScheduledJob : ScheduledJobBase
{
private readonly IContentIndexer contentIndexer;
private readonly IClient searchClient;
private bool stopSignaled;
/// <summary>
/// Initializes a new instance of the <see cref="ImportScheduledJob" /> class.
/// </summary>
/// <exception cref="ActivationException">if there is are errors resolving the service instance.</exception>
public ImportScheduledJob()
{
this.IsStoppable = true;
this.searchClient = ServiceLocator.Current.GetInstance<IClient>();
this.contentIndexer = ServiceLocator.Current.GetInstance<IContentIndexer>();
}
/// <summary>
/// Called when a scheduled job executes
/// </summary>
/// <returns>A status message to be stored in the database log and visible from admin mode</returns>
public override string Execute()
{
// Call OnStatusChanged to periodically notify progress of job for manually started jobs
this.OnStatusChanged(string.Format("Starting execution of {0}", this.GetType()));
// Turn off indexing events
EventedIndexingSettings.Instance.EventedIndexingEnabled = false;
EventedIndexingSettings.Instance.ScheduledPageQueueEnabled = false;
// Do your import
// Add new or changed products to this list.
IEnumerable<ProductContent> products = new List<ProductContent>();
// Add the references of products that are removed to this list
IEnumerable<ContentReference> itemsToRemove = new List<ContentReference>();
// You can use the content indexer or the search client to add/update your content in the index. See remarks on the methods for the differences.
AddToIndex(itemsToAdd: products, contentIndexer: this.contentIndexer);
// The content indexer does not provide a batch job, so better use the search client.
RemoveFromIndex(itemsToRemove: itemsToRemove, searchClient: this.searchClient);
// Turn on indexing events again.
EventedIndexingSettings.Instance.EventedIndexingEnabled = true;
EventedIndexingSettings.Instance.ScheduledPageQueueEnabled = true;
// For long running jobs periodically check if stop is signaled and if so stop execution
if (this.stopSignaled)
{
return "Stop of job was called";
}
return "Change to message that describes outcome of execution";
}
/// <summary>
/// Determines whether this instance is stopped.
/// </summary>
/// <returns><c>true</c> if this instance is stopped; otherwise, <c>false</c>.</returns>
public bool IsStopped()
{
return this.stopSignaled;
}
/// <summary>
/// Called when a user clicks on Stop for a manually started job, or when ASP.NET shuts down.
/// </summary>
public override void Stop()
{
this.stopSignaled = true;
}
/// <summary>
/// Adds the selected items to the Find index.
/// </summary>
/// <param name="itemsToAdd">The items to add.</param>
/// <param name="contentIndexer">The content indexer.</param>
/// <remarks>Will add all language versions.</remarks>
private static void AddToIndex(IEnumerable<IContent> itemsToAdd, IContentIndexer contentIndexer)
{
contentIndexer.Index(
contentItems: itemsToAdd,
options: new IndexOptions { IndexAllLanguageVersions = true });
}
/// <summary>
/// Adds the selected items to the Find index.
/// </summary>
/// <param name="itemsToAdd">The items to add.</param>
/// <param name="searchClient">The search client.</param>
/// <remarks>
/// Will NOT add all language versions, you will need to add all content versions you want to index to the
/// <paramref name="itemsToAdd" />
/// </remarks>
private static void AddToIndex(IEnumerable<object> itemsToAdd, IClient searchClient)
{
searchClient.Index(objectsToIndex: itemsToAdd);
}
/// <summary>
/// Removes the selected items from the Find index.
/// </summary>
/// <param name="itemsToRemove">The items to remove.</param>
/// <param name="searchClient">The search client.</param>
private static void RemoveFromIndex(IEnumerable<IContent> itemsToRemove, IClient searchClient)
{
RemoveFromIndex(itemsToRemove.Select(p => p.ContentLink), searchClient: searchClient);
}
/// <summary>
/// Removes the selected items from the Find index.
/// </summary>
/// <param name="itemsToRemove">The items to remove.</param>
/// <param name="searchClient">The search client.</param>
private static void RemoveFromIndex(IEnumerable<ContentReference> itemsToRemove, IClient searchClient)
{
FilterBuilder<CatalogContentBase> deleteFilterBuilder =
new FilterBuilder<CatalogContentBase>(client: searchClient);
deleteFilterBuilder = itemsToRemove.Aggregate(
seed: deleteFilterBuilder,
func: (current, contentLink) => current.Or(x => x.ContentLink.Match(contentLink)));
searchClient.Delete<CatalogContentBase>(filter: deleteFilterBuilder);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment