Managing Episerver Find Exceptions when querying the index
I have been working on the Episerver Find implementation here at Redweb for a client build. I was noticing that there were some errors that would occasionally happen when performing some queries against the index. After having a look around, I came across this article that gave me a solution to the issue and thought I would share the implementation into the project.
Firstly, I put a try catch around any of the Find services when they would be making a query against the index so that any errors would be caught. I can then check to see if the error is a ClientException or a ServiceException. If they are I can log the error with the exception to make sure there isn’t an issue with what we have written.
try
{
var search = _findClient.Search<SupplierProduct>();
if (!productCategoryId.IsNullOrWhiteSpace())
{
search = search.Filter(x => x.ParentCategory.Match(categoryId));
}
if (!string.IsNullOrWhiteSpace(queryString))
{
search = search.For(queryString).InField(x => x.Name);
}
if (!facetsList.IsNullOrEmpty())
{
search = search.MatchCategories(facetsList);
}
var supplierResults = search
.ApplyBestBets()
.UsingAutoBoost()
.Skip((currentPage - 1) * resultsPerPage)
.Take(resultsPerPage)
.StaticallyCacheFor(TimeSpan.FromMinutes(1))
.GetContentResult();
return supplierResults;
}
catch (Exception ex) when(ex is ClientException || ex is ServiceException)
{
Services.Episerver.Logger.Log(Level.Error, "Shop Search encountered an Episerver Find Exception", ex);
return new EmptyContentResult<SupplierProduct>();
}
To make sure that the user has the best experience possible, a new type of content result was created. This means that if an error occurs an EmptyContentResult would be returned rather than an error. The new content result would have no results programmed set within the properties and can have the type passed into it so that it returns the correct class type for the search being performed.
public class EmptyContentResult<T> : ContentResult<T> where T : IContentData
{
public EmptyContentResult() : base(
Enumerable.Empty<T>(),
new SearchResults<ContentInLanguageReference>(
new SearchResult<ContentInLanguageReference>()
{
Facets = new FacetResults(),
Hits = new HitCollection<ContentInLanguageReference>()
{
Hits = Enumerable.Empty<SearchHit<ContentInLanguageReference>>().ToList()
},
Shards = new Shards()
}))
{ }
}
This means that if any errors occur, although an empty page would show to the user, it would not break their view of the site and handle the error in an appropriate manner. This was very quick to implement across all the search methods on the site and also catches any of the errors that could occur out of our control.
I hope this helps some people out and I have also linked to the original source if anyone wants to look at it as well.
Comments