Sitecore item deserialization is slow / triggering cache-clear

Problem: when using the Sitecore.Data.Serialization.Managerto de-serialize serialized items into Sitecore 8, my caches get cleared. This shouldn't be so, since I call it with option DisableEvents = true like this:

var options = new Sitecore.Data.Serialization.LoadOptions(masterDb);
options.ForceUpdate = true;
options.DisableEvents = true;

using (new Sitecore.SecurityModel.SecurityDisabler())
{
    Sitecore.Data.Serialization.Manager.LoadItem(itemPath, options);
}

Still, though, cache is being cleared - with debugging enabled, I get this:

36956 19:32:31 INFO Loading item from path /master/sitecore/templates/SomeFolder/SomeItem.item.

36956 19:32:34 WARN All caches have been cleared. This can decrease performance considerably.

36956 19:32:34 DEBUG All caches have been cleared. Stack trace: at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace() at Sitecore.Caching.CacheManager.ClearAllCaches() at Sitecore.Data.Serialization.Manager.<.cctor>b__1(SerializationFinishedEvent event) at Sitecore.Eventing.EventProvider.RaiseEvent(Object event, Type eventType, EventContext context) at Sitecore.Data.Serialization.Manager.DeserializationFinished(String databaseName)

Upvotes: 1

Views: 832

Answers (2)

EDIT/UPDATE

Marek's answer made me realize, I was saying something wrong. I will leave my original proposed answer intact to not cause confusion. But to sum up, calling the LoadItemmethod with option DisableEventsworks as expected. Only does it - to make up for the lack of appropriate events getting fired - trigger Manager.DeserializationFinished(...) which in turn (at least per my default Sitecore 8 setup) calls CacheManager.ClearAllCaches().

My wrong conclusion was triggered by the fact, that the CacheManager.ClearAllCaches()method is called using Sitecore's own * EventProvider* - so, as Marek points out - this is an unfortunate coincidence / clash of naming.

Actually, triggering CacheManager.ClearAllCaches() is what I wanted to avoid. So I guess somehow this "workaround" makes my deserialization faster (because it doesn't clear all the caches for each execution).


ORIGINAL POST

Ok, so I went to town and eventually discovered this, disassembling Sitecore.Data.Serialization.Manager.LoadItem(...)method (note: this is Sitecore core stuff (with my comments)):

public static Item LoadItem(string path, LoadOptions options)
    {
      Assert.ArgumentNotNullOrEmpty(path, "path");
      Assert.ArgumentNotNull((object) options, "options");
      if (!options.DisableEvents) <-------------------------- HERE IS THE BUG
        return Manager.DoLoadItem(path, options);
      Item obj;
      using (new EventDisabler())
        obj = Manager.DoLoadItem(path, options);
      //This next line fires the events - but to get here, DisableEvents must be true.
      Manager.DeserializationFinished(Manager.GetTargetDatabase(path, options));
      return obj;
    }

This looks like a bug. "If not options.DisableEvents return". There's one too many "not"?

The workaround is simply to set

options.DisableEvents = false;

Setting it to falsedisables the events listening at SerializationFinishedEvent, in this case a handler, that triggers Sitecore.Caching.CacheManager.ClearAllCaches() as hinted by the stack-trace. Even though it seems like it should be the other way around.

Upvotes: 0

Marek Musielak
Marek Musielak

Reputation: 27142

Frederik, in your answer you pasted disassembled code of the LoadItem method and you added comments in the lines, where you thought there was a bug:

// QUOTE FROM THE AUTHOR OF THE QUESTION, Frederik Struck-Schøning
public static Item LoadItem(string path, LoadOptions options)
{
    Assert.ArgumentNotNullOrEmpty(path, "path");
    Assert.ArgumentNotNull((object) options, "options");
    if (!options.DisableEvents) <-------------------------- HERE IS THE BUG
      return Manager.DoLoadItem(path, options);
    Item obj;
    using (new EventDisabler())
        obj = Manager.DoLoadItem(path, options);
    //This next line fires the events - but to get here, DisableEvents must be true.
    Manager.DeserializationFinished(Manager.GetTargetDatabase(path, options));
    return obj;
}

And then you explained why you think this code is incorrect.

Actually, it's exactly the opposite way to what you wrote.

When you deserialize items without DisableEvents set to false, all the caches are updated automatically by item:saved and other events.

If you tell Sitecore to disable all the events, caches would never be refreshed. That's the reason why Sitecore executes ClearAllCaches after the items are deserialized. It's unfortunate that in the stack trace you see name "event". All Sitecore events, like item:added, item:created, item:saved etc are not executed. There is only 1 event which is executed to notify your current instance and remote Sitecore instances and this event is SerializationFinishedEvent (in its local and remote version).

So this is not a Sitecore bug, it's naming issue rather. It might be misleading, but it all works as expected. Instead of executing series of events every time item is saved, updated, renamed and so on, there is only one notification after the DoLoadItem method is finished.

Upvotes: 2

Related Questions