In my Sitecore instance I have caching on the main navigation to improve performance, and a custom publishing event that clears the cache on publish so that the navigation gets updated appropriately. We have the typical CD/CM setup on production. My custom publishing event was working on CM (and my local single-instance), but not on CD.
Check the Scalability settings
The first thing I did was to check the scalability settings. These settings are necessary for a remote CD environment to recognize Sitecore events on the CM server and trigger the appropriate events; you have to tell both CM and CD which instance is the PublishingInstance, and what the InstanceName is (the InstanceName and PublishingInstance on CM must be the same value).
It’s a bit hard to find the documentation for setup in Sitecore’s docs. The documentation on setting up a CD server tells you to set up the InstanceName but doesn’t mention Publishing.PublishingInstance. Below are the basic settings you need to make remote events work on CD. For more detail, I suggest this post from Valtech.
<!-- INSTANCE NAME
Unique name for Sitecore instance.
Default value: (machine name and IIS site name)
-->
<setting name="InstanceName">
<patch:attribute name="value">MySite_CD</patch:attribute>
</setting>
<!-- PUBLISHING INSTANCE
Assigns the instance name of dedicated Sitecore installation for publishing operations.
When empty, all publishing operations are performed on the local installation of Sitecore.
Default vaue: (empty)
-->
<setting name="Publishing.PublishingInstance">
<patch:attribute name="value">MySite_CM</patch:attribute>
</setting>
My Scalability Settings were correct but I still wasn’t getting the event, so the next thing I checked at Sitecore’s recommendation was to see if the event was actually firing.
Add “timingLevel”=”high” to publish:end:remote
I wasn’t seeing evidence of the remote publish event in the logs, but that didn’t mean it wasn’t happening. Adding “timingLevel” adds robust logging to the event.
<event name="publish:end:remote">
<patch:attribute name="timingLevel">high</patch:attribute>
<!-- Cache clearing handler -->
<handler type="MySite.CustomCacheHandler, MySite" method="ClearCacheOnPublish"/>
</event>
This gave me more details in the logs, that shows that my event actually was working:
ManagedPoolThread #1 19:12:20 INFO Event started: publish:end:remote
[more handlers logged in between]
ManagedPoolThread #1 19:12:22 INFO Executed: MySite.CustomCacheHandler.ClearCacheOnPublish(). Elapsed: 0,898844700115826
ManagedPoolThread #1 19:12:22 INFO Event ended: publish:end:remote. Elapsed: 2065,31794450525
This meant that the publish event actually was happening, but was failing.
Make sure you’re using the right type of Sitecore EventArgs – they’re DIFFERENT for publish:end and publish:end:remote
Once I realized my event was working and it was an error in my code, I realized that the culprit had to be this part:
public void ClearCacheOnPublish(object sender, EventArgs args)
{
var sitecoreArgs = args as Sitecore.Events.SitecoreEventArgs;
if (sitecoreArgs == null)
{
return;
}
My event was triggering and there were no errors, so this must mean that sitecoreArgs was null so the method was returning before I even got to my logging statements.
This revelation led me to this blog post, which gave me the answer which I’ll recap here.
publish:end and publish:end:remote have two different types of EventArgs; SitecoreEventArgs, and PublishEndRemoteEventArgs. Because of this, trying to cast the EventArgs as SitecoreEventArgs on the publish:end:remote event returned null.
The way you retrieve the published item is also different between the two args, so I’ve included the full code for how to get the item on publish for each event:
publish:end
public void PublishEnd(object sender, EventArgs args)
{
Sitecore.Diagnostics.Log.Info("ClearCacheOnPublish START", this);
var sitecoreArgs = args as Sitecore.Events.SitecoreEventArgs;
if (sitecoreArgs == null)
{
return;
}
var publisher = sitecoreArgs.Parameters[0] as Publisher;
var rootItem = publisher.Options.RootItem;
ClearCacheOnPublish(rootItem);
}
publish:end:remote
public void PublishEndRemote(object sender, EventArgs args)
{
Sitecore.Diagnostics.Log.Info("ClearCacheOnPublishRemote START", this);
var sitecoreArgs = args as Sitecore.Data.Events.PublishEndRemoteEventArgs;
if (sitecoreArgs == null)
{
return;
}
var rootItem = Factory.GetDatabase("web").GetItem(new ID(sitecoreArgs.RootItemId));
ClearCacheOnPublish(rootItem);
}
Finally, you just need to make sure to use the PublishEndRemote method instead of PublishEnd in the Sitecore config:
<sitecore>
<events>
<event name="publish:end">
<handler type="MySite.CustomCacheHandler, MySite" method="PublishEnd"/>
</event>
<event name="publish:end:remote">
<handler type="MySite.CustomCacheHandler, MySite" method="PublishEndRemote"/>
</event>
</events>
</sitecore>