Created
August 31, 2017 08:04
-
-
Save drpeck/fbaf6f8f3acb58b834dc8947aae1083e to your computer and use it in GitHub Desktop.
Hack/ workaround to Umbraco Courier not being updated on slave servers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CourierUmbracoEvents : ApplicationEventHandler | |
{ | |
//Wait 5 seconds after an examine index before trying to republish what has been indexed | |
private const int DelayAfterIndex = 5 * 1000; | |
//Give a republishe 2 minutes to complete | |
private const int IndexTimeout = 120 * 1000; | |
private Guid _lastIndexId; | |
private List<int> _indexedContentIds = new List<int>(); | |
private Dictionary<int, DateTime> _republishRegister = new Dictionary<int, DateTime>(); | |
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) | |
{ | |
LogHelper.Info<CourierUmbracoEvents>("CourierUmbracoEvents init"); | |
var serverRegistrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2; | |
if (serverRegistrar == null || serverRegistrar.GetCurrentServerRole() != ServerRole.Master) | |
{ | |
LogHelper.Info<CourierUmbracoEvents>("CourierUmbracoEvents exiting because not master"); | |
return; | |
} | |
//Listening to all NodeIndexed on ExternalIndexer (Courier extracting events aren't firing) | |
foreach (var indexProvider in ExamineManager.Instance.IndexProviderCollection | |
.OfType<BaseIndexProvider>() | |
.Where(x => Constants.Examine.ExternalIndexer == x.Name)) | |
{ | |
LogHelper.Debug<CourierUmbracoEvents>("Listening to NodeIndexed for ExternalIndexer"); | |
indexProvider.NodeIndexed += (sender, e) => NodeIndexed(e.NodeId); | |
} | |
} | |
private void NodeIndexed(int nodeId) | |
{ | |
LogHelper.Debug<CourierUmbracoEvents>("IndexProvider_NodeIndexed called for nodeId: " + nodeId); | |
ClearTimeoutsOnRepublishRegister(); | |
if (_republishRegister.ContainsKey(nodeId) == true) | |
{ | |
LogHelper.Debug<CourierUmbracoEvents>("Not scheduling a republish for {0} as we have an active timeout for it", () => nodeId); | |
return; | |
} | |
_indexedContentIds.Add(nodeId); | |
//Make a reference to the most recent index | |
var indexId = Guid.NewGuid(); | |
_lastIndexId = indexId; | |
//After a second, check if the session has ended | |
Task.Run(() => { PauseAfterExamineIndex(indexId); }); | |
} | |
private async void PauseAfterExamineIndex(Guid indexId) | |
{ | |
//Pause to wait for courier to complete, and avoid clashes | |
await Task.Delay(DelayAfterIndex); | |
LogHelper.Debug<CourierUmbracoEvents>("AfterExamineIndex running after a {0} delay", () => DelayAfterIndex); | |
//Don't republish if there has been another index while we've been sleeping | |
if (_lastIndexId != indexId) | |
return; | |
int[] ids; | |
lock (this) | |
{ | |
//Get a distinct list of ides requested for republish | |
ids = _indexedContentIds.Distinct().ToArray(); | |
//and wipe the list for next time | |
_indexedContentIds.Clear(); | |
} | |
LogHelper.Debug<CourierUmbracoEvents>("Scheduling a republish to avoid Courier issue with ids '{0}'", () => string.Join(",", ids)); | |
Republish(ids); | |
} | |
private void Republish(int[] nodeIds) | |
{ | |
if (nodeIds.Any() == false) | |
return; | |
//Set the time for valid node | |
foreach (var nodeId in nodeIds) | |
{ | |
_republishRegister[nodeId] = DateTime.Now; | |
} | |
var serverRegistrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2; | |
if (serverRegistrar == null) | |
{ | |
LogHelper.Debug<CourierUmbracoEvents>("serverRegistrar is null"); | |
return; | |
} | |
LogHelper.Debug<CourierUmbracoEvents>("Performing distributed refresh for: {0}", () => string.Join(", ", nodeIds)); | |
ServerMessengerResolver.Current.Messenger.PerformRefresh(serverRegistrar.Registrations, new PageCacheRefresher(), nodeIds); | |
} | |
private void ClearTimeoutsOnRepublishRegister() | |
{ | |
var threshold = DateTime.Now.AddMilliseconds(IndexTimeout * -1); | |
_republishRegister.RemoveAll(o => o.Value < threshold); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment