Adds checks to see if the app is shutting down while processing instruction batches, if so it will exit instruction processing. Also set a timeout on the wait lock so that if the app is shutting down it will after 5 seconds.

This commit is contained in:
Shannon
2016-10-26 11:37:59 +02:00
parent f153332ad5
commit 8b411c3d46

View File

@@ -116,10 +116,13 @@ namespace Umbraco.Core.Sync
_released = true; // no more syncs
}
// Wait for pending sync this is waiting for _syncIdle.Set()
// to be called. Until that is called, the appdomain cannot shut down!
// so whatever is locking this currently should hurry up!
_syncIdle.WaitOne();
//only wait 5 seconds
var result =_syncIdle.WaitOne(5000);
if (result == false)
{
//a timeout occurred :/
_logger.Warn<DatabaseServerMessenger>("The wait lock timed out, application is shutting down. The current instruction batch will be re-processed.");
}
},
weight);
@@ -222,7 +225,7 @@ namespace Umbraco.Core.Sync
ProcessDatabaseInstructions();
//Check for pruning throttling
if ((DateTime.UtcNow - _lastPruned).TotalSeconds <= Options.PruneThrottleSeconds)
if ((_released || (DateTime.UtcNow - _lastPruned).TotalSeconds <= Options.PruneThrottleSeconds))
return;
_lastPruned = _lastSync;
@@ -238,8 +241,12 @@ namespace Umbraco.Core.Sync
}
finally
{
//We must reset our flag and signal any waiting locks
_syncing = false;
lock (_locko)
{
//We must reset our flag and signal any waiting locks
_syncing = false;
}
_syncIdle.Set();
}
}
@@ -279,10 +286,10 @@ namespace Umbraco.Core.Sync
var lastId = 0;
//IMPORTANT! We are doing a Query here instead of a Fetch, this means that it will open a data reader
// which we are iterating over instead of loading everything into memory and iterating over that.
// When doing this we always must use a for loop so that the Enumerator is disposed and the reader is closed.
foreach (var dto in _appContext.DatabaseContext.Database.Query<CacheInstructionDto>(topSql))
//It would have been nice to do this in a Query instead of Fetch using a data reader to save
// some memory however we cannot do thta because inside of this loop the cache refreshers are also
// performing some lookups which cannot be done with an active reader open
foreach (var dto in _appContext.DatabaseContext.Database.Fetch<CacheInstructionDto>(topSql))
{
//If this flag gets set it means we're shutting down! In this case, we need to exit asap and cannot
// continue processing anything otherwise we'll hold up the app domain shutdown
@@ -318,7 +325,11 @@ namespace Umbraco.Core.Sync
//if they couldn't be all processed (i.e. we're shutting down) then exit
if (success == false)
{
_logger.Info<DatabaseServerMessenger>("The current batch of instructions was not processed, app is shutting down");
break;
}
}
if (lastId > 0)
@@ -550,6 +561,8 @@ namespace Umbraco.Core.Sync
/// </returns>
private bool NotifyRefreshers(IEnumerable<RefreshInstruction> instructions)
{
var processed = new HashSet<RefreshInstruction>();
foreach (var instruction in instructions)
{
//Check if the app is shutting down, we need to exit if this happens.
@@ -558,6 +571,10 @@ namespace Umbraco.Core.Sync
return false;
}
//this has already been processed
if (processed.Contains(instruction))
continue;
switch (instruction.RefreshType)
{
case RefreshMethodType.RefreshAll:
@@ -579,6 +596,8 @@ namespace Umbraco.Core.Sync
RemoveById(instruction.RefresherId, instruction.IntId);
break;
}
processed.Add(instruction);
}
return true;
}