Temporarily disable the catalogitem change manager

When you run large imports you might run into the issue that the “Change log auto truncate job” will timeout because the tblActivityLog has become very large.

When that happens you can manually run a stored procedure on the DB as described here.

To prevent it from happening, as from EPiServer.Commerce 11.6.0, you can disable CatalogItemChangeManager completely by adding an appsetting:

<add key="episerver:DisableCatalogEventDrivenIndexing" value="true" />

But there might be scenarios where you only want to disable the CatalogItemChangeManager when running the import job.

In case you have not created the job yourself you can use the following custom CatalogItemChangeManager.

public class CustomCatalogItemChangeManager : CatalogItemChangeManager
{
	private readonly IScheduledJobRepository scheduledJobRepository;

	public CustomCatalogItemChangeManager(
		IChangeNotificationManager changeNotificationManager,
		EntryIdentityResolver entryIdentityResolver,
		IScheduledJobRepository scheduledJobRepository)
		: base(changeNotificationManager: changeNotificationManager, entryIdentityResolver: entryIdentityResolver)
	{
		this.scheduledJobRepository = scheduledJobRepository;
	}

	public override void InsertChanges(IEnumerable<int> entryIds)
	{
		ScheduledJob job = this.scheduledJobRepository.Get(new Guid("guid-of-import-job"));
		if (job != null && job.IsRunning)
		{
			return;
		}

		base.InsertChanges(entryIds: entryIds);
	}
}

In this one you can check if the job is running by getting the job information from the scheduledJobRepository through it’s Guid. If it is don’t insert the changes.

In case you have created the job yourself, you can use the following custom CatalogItemChangeManager.

public class CustomCatalogItemChangeManager : CatalogItemChangeManager
{
	public CustomCatalogItemChangeManager(
		IChangeNotificationManager changeNotificationManager,
		EntryIdentityResolver entryIdentityResolver)
		: base(changeNotificationManager: changeNotificationManager, entryIdentityResolver: entryIdentityResolver)
	{
		this.SavingChangesEnabled = true;
	}

	public bool SavingChangesEnabled { get; set; }

	public override void InsertChanges(IEnumerable<int> entryIds)
	{
		if (!this.SavingChangesEnabled)
		{
			return;
		}

		base.InsertChanges(entryIds: entryIds);
	}
}

In this version you get the instance of CustomCatalogItemChangeManager in your job and set the SavingChangesEnabled property to false when starting the import. When done, set the property to true again.

public override string Execute()
{
	CustomCatalogItemChangeManager customCatalogItemChangeManager = null;


	try
	{
		customCatalogItemChangeManager = this.catalogItemChangeHandler as CustomCatalogItemChangeManager;
		
		if (customCatalogItemChangeManager != null)
		{
			customCatalogItemChangeManager.SavingChangesEnabled = false;
		}

		// Do your magic
	}
	finally
	{
		if (customCatalogItemChangeManager != null)
		{
			customCatalogItemChangeManager.SavingChangesEnabled = true;
		}
	}

	return "Job done"
}

In a configurable module you need to configure that the custom CatalogItemChangeManager is used like this:

container.Configure(x => x.For<CatalogItemChangeHandlerBase>().Use<CustomCatalogItemChangeManager>());

// for .Net 5 also add this one
container.Configure(x => x.For<CatalogItemChangeManager>().Use<CustomCatalogItemChangeManager>());

And that’s it. The complete code sample is also in a gist

One thought on “Temporarily disable the catalogitem change manager

Leave a comment