Periodically Rebuild Link Databases using an Agent in Sitecore
Last week a colleague had asked me whether rebuilding the Link Database would solve an issue she was seeing. That conversation got me thinking: wouldn’t it be nice if we could automate the rebuilding of the Link Database for each Sitecore database at a scheduled time?
I am certain others have already created solutions to do this — if you know of any, please share in a comment — but I didn’t conduct a search to find any (I normally advocate not reinventing the wheel for code solutions but wanted to have some fun building a new solution).
In the spirit of my post on putting Sitecore to work for you, I built the following Sitecore agent (check out John West’s blog post on Sitecore agents to learn more):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Diagnostics;
using Sitecore.Jobs;
namespace Sitecore.Sandbox.Tasks
{
public class RebuildLinkDatabasesAgent
{
private static readonly IList<Database> Databases = new List<Database>();
private static readonly Stopwatch Stopwatch = Stopwatch.StartNew();
public void Run()
{
JobManager.Start(CreateNewJobOptions());
}
protected virtual JobOptions CreateNewJobOptions()
{
return new JobOptions("RebuildLinkDatabasesAgent", "index", Context.Site.Name, this, "RebuildLinkDatabases");
}
protected virtual void RebuildLinkDatabases()
{
Job job = Context.Job;
try
{
RebuildLinkDatabases(Databases);
}
catch (Exception ex)
{
job.Status.Failed = true;
job.Status.Messages.Add(ex.ToString());
}
job.Status.State = JobState.Finished;
}
private void RebuildLinkDatabases(IEnumerable<Database> databases)
{
Assert.ArgumentNotNull(databases, "databases");
foreach (Database database in databases)
{
Stopwatch.Start();
RebuildLinkDatabase(database);
Stopwatch.Stop();
LogEntry(database, Stopwatch.Elapsed.Milliseconds);
}
}
protected virtual void RebuildLinkDatabase(Database database)
{
Assert.ArgumentNotNull(database, "database");
Globals.LinkDatabase.Rebuild(database);
}
protected virtual void LogEntry(Database database, int elapsedMilliseconds)
{
Assert.ArgumentNotNull(database, "database");
if (string.IsNullOrWhiteSpace(LogEntryFormat))
{
return;
}
Log.Info(string.Format(LogEntryFormat, database.Name, elapsedMilliseconds), this);
}
private static void AddDatabase(XmlNode configNode)
{
if (configNode == null || string.IsNullOrWhiteSpace(configNode.InnerText))
{
return;
}
Database database = TryGetDatabase(configNode.InnerText);
if (database != null)
{
Databases.Add(database);
}
}
private static Database TryGetDatabase(string databaseName)
{
Assert.ArgumentNotNullOrEmpty(databaseName, "databaseName");
try
{
return Factory.GetDatabase(databaseName);
}
catch (Exception ex)
{
Type agentType = typeof(RebuildLinkDatabasesAgent);
Log.Error(agentType.ToString(), ex, agentType);
}
return null;
}
private string LogEntryFormat { get; set; }
}
}
Logic in the class above reads in a list of databases set in a configuration file, adds them to a list for processing — these are only added to the list if they exist — and rebuilds the Link Database in each via a Sitecore job.
I added some timing logic to see how long it takes to rebuild each database, and capture this information in the Sitecore log.
I then wired up the above class in Sitecore using the following patch include configuration file:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<scheduling>
<agent type="Sitecore.Sandbox.Tasks.RebuildLinkDatabasesAgent" method="Run" interval="00:01:00">
<databases hint="raw:AddDatabase">
<database>core</database>
<database>master</database>
<database>web</database>
</databases>
<LogEntryFormat>Rebuilt link database: {0} in {1} milliseconds.</LogEntryFormat>
</agent>
</scheduling>
</sitecore>
</configuration>
I’ve set this agent to run every minute for testing, but it would probably be wise to have this run no more than once or twice a day.
After waiting a bit, I saw the following in my Sitecore log:
I do question the rebuild times. These seem quite small, especially when it takes a while to rebuild the Link Databases via the Sitecore Control Panel. If you have any ideas/thoughts on why there is an incongruence between the times in my log and how long it takes to rebuild these via the Sitecore Control Panel, please share in a comment.
Further, if you have any recommendations on making this code better, or have other ideas on automating the rebuilding of Link Databases in Sitecore, please drop a comment.
Until next time, have a Sitecoretastic day!
