Why silent saving with a processing server is a bad idea

This post highlights why silent saving, EventDisabler or using BulkUpdateContext can lead to inconsistent data on a multi-CM environment i.E. when using a processing server.

Silent saving

Silent saving or using BulkUpdateContext will prevent firing an item:saving and item:saved event when Items are written through code. This can for example speed up imports where many items are written to the database.

Example:

var item = Database.GetDatabase("master").GetItem("/sitecore/content/home");
item.Editing.BeginEdit();
item["Some Field"] = $"Updated: {DateTime.Now}";
item.Editing.EndEdit(true); // true enables silent saving

This will update the field and will not trigger any index update nor any other item:saved / item:saving pipeline events.

The first issue here is that the updated field will most likely not be visible on your site or in content editor. This is because your data is already cached in one of Sitecore’s several caching layers. After silent saving, the item won’t be cleared from these layers.

A hacky workaround is to manually clear the items from cache after saving. This might work on a single-CM-environment but as soon as multiple CM instances are in place, there will be trouble.

Cache clearing across multiple instances

Sitecore uses an event queue to communicate item changes with all servers connected to the database. When CM1 changes an item, it is cleared from cache of CM2 through the item:saved:remote event. This is not the case when silent saving! CM2 will never learn of any changes on CM1 and if an author changes the item on CM2, the changes from CM1 will be overwritten.

silent-saving-race-condition

This is just a simplified example. I saw these issues at a client where the layout field was being updated through a batch job on the processing instance. When authors would update these items it lead to completely corrupted layout fields.

How to get around these issues

In most cases, I would just simply not use silent saving, EventDisabler or BulkUpdateContext when more than one CM instance is present. This will make bulk updates a bit slower but data consistency is usually a higher priority.

In cases where indexing needs to be disabled during bulk updates, try

IndexCustodian.PauseIndexing();
IndexCustodian.ResumeIndexing();

but bear in mind that this will disable indexing on the entire instance.

Another workaround could be to implement a custom remote event that will clear the changed items from cache. This post documents how custom events can be implemented.

Conclusion

In a setup where a processing instance or generally where more than one CM instance are present, these issues need to be considered.
If you need to add a processing instance to an existing setup, it is important to analyze the existing code base and make alterations if silent saving, EventDisabler or BulkUpdateContext are used.


Leave a Reply

Your email address will not be published. Required fields are marked *