So you have a presentation control (let’s say a sublayout) that relies on Sitecore.Search APIs to get the data to render (news articles for example). Second ingredient in this recipe is HTML cache that you have enabled for this control. The third ingredient is a dedicated Content Delivery server.

You’ve got yourself a race condition between IndexingProvider and HTML Cache!

Now here is what’s going to happen in production:

  1. Authors create new news article. (00:00)

  2. Editors publish. (00:01)

  3. All needed caches are cleared on remote CD server, including HTML cache. (00:03)

  4. A visitors requests /news on your CD server. (00:04)
    => This request tells Sitecore to cache your control now. Obviously, with stale data.

  5. IndexingProvider gets triggered on _Indexing.UpdateInterval _which is 5 minutes by default (00:08)
    => Search index is updated with the new article created on step 1.

  6. Another visitors requests /news on your CD server. (00:10)
    => Stale html output will be served from cache.

As you can see, such sequence of events is quite realistic, and would happen quite frequently if you have all the ingredients in the recipe.

Since HTML cache clear happens on the remote servers after remote publish:end is being replayed (a couple of seconds after the publishing is done on the CM server), and the index update is governed by a interval based disconnected process that would lag most of the times, what you really need is a way to connect the two processes.

Good news is that Sitecore has all proper tools for the job!

First off, you can leverage the following event, which is getting triggered on the DataProvider level after the IndexingProvider is done updating the index:

<!-- database:propertychanged(string parameterName)

Raised when database property was changed. -->  
<event name="database:propertychanged" />

Secondly, Sitecore already has the handler for html cache clearing.

So simply by registering the HtmlCacheClearer on database:propertychanged would get the job done:

<event name="database:propertychanged">

<handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache">

<sites hint="list">

<site>website</site>

</sites>

</handler>
</event>

While this approach works, unfortunately it is not efficient, as the HtmlCacheClearer would be triggered every time an entry is written to the _Properties _table, and Sitecore does that a lot (EventQueue is one example).

So, you can modify the source of the HtmlCacheClearer and read the name of the property, compare it with the IndexingManager’s LastUpdateProperty, and have a much more efficient code running:

var propertyName = Event.ExtractParameter(args, 0) as string;

if (propertyName == null) return;

if(propertyName.Equals(IndexingManager.LastUpdatePropertyKey))  
{

// do the html cache clear magic
}

Important note: in my local tests, I have the _database:propertychanged _event execute twice, thus triggering two html cache clearings on index update. I don’t see this as a major problem, and this is not a trivial problem to solve.

Hope this solution is going to save you some time.