diff --git a/src/Umbraco.Core/Sync/DefaultServerMessenger.cs b/src/Umbraco.Core/Sync/DefaultServerMessenger.cs index f6704dd413..d6839bc848 100644 --- a/src/Umbraco.Core/Sync/DefaultServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DefaultServerMessenger.cs @@ -20,18 +20,19 @@ namespace Umbraco.Core.Sync { private readonly Func> _getUserNamePasswordDelegate; private volatile bool _hasResolvedDelegate = false; - private readonly object _locker = new object(); - private bool _useDistributedCalls; + private readonly object _locker = new object(); protected string Login { get; private set; } protected string Password{ get; private set; } + protected bool UseDistributedCalls { get; private set; } + /// /// Without a username/password all distribuion will be disabled /// internal DefaultServerMessenger() { - _useDistributedCalls = false; + UseDistributedCalls = false; } /// @@ -55,7 +56,7 @@ namespace Umbraco.Core.Sync if (login == null) throw new ArgumentNullException("login"); if (password == null) throw new ArgumentNullException("password"); - _useDistributedCalls = useDistributedCalls; + UseDistributedCalls = useDistributedCalls; Login = login; Password = password; } @@ -221,13 +222,13 @@ namespace Umbraco.Core.Sync { Login = null; Password = null; - _useDistributedCalls = false; + UseDistributedCalls = false; } else { Login = result.Item1; Password = result.Item2; - _useDistributedCalls = UmbracoSettings.UseDistributedCalls; + UseDistributedCalls = UmbracoSettings.UseDistributedCalls; } } catch (Exception ex) @@ -235,7 +236,7 @@ namespace Umbraco.Core.Sync LogHelper.Error("Could not resolve username/password delegate, server distribution will be disabled", ex); Login = null; Password = null; - _useDistributedCalls = false; + UseDistributedCalls = false; } } } @@ -314,7 +315,7 @@ namespace Umbraco.Core.Sync //Now, check if we are using Distrubuted calls. If there are no servers in the list then we // can definitely not distribute. - if (!_useDistributedCalls || !servers.Any()) + if (!UseDistributedCalls || !servers.Any()) { //if we are not, then just invoke the call on the cache refresher InvokeMethodOnRefresherInstance(refresher, dispatchType, getId, instances); @@ -325,7 +326,7 @@ namespace Umbraco.Core.Sync MessageSeversForIdsOrJson(servers, refresher, dispatchType, instances.Select(getId)); } - private void MessageSeversForIdsOrJson( + protected virtual void MessageSeversForIdsOrJson( IEnumerable servers, ICacheRefresher refresher, MessageType dispatchType, @@ -345,7 +346,7 @@ namespace Umbraco.Core.Sync //Now, check if we are using Distrubuted calls. If there are no servers in the list then we // can definitely not distribute. - if (!_useDistributedCalls || !servers.Any()) + if (!UseDistributedCalls || !servers.Any()) { //if we are not, then just invoke the call on the cache refresher InvokeMethodOnRefresherInstance(refresher, dispatchType, ids, jsonPayload); @@ -456,16 +457,16 @@ namespace Umbraco.Core.Sync } } - List waitHandlesList; - var asyncResults = GetAsyncResults(asyncResultsList, out waitHandlesList); - + var waitHandlesList = asyncResultsList.Select(x => x.AsyncWaitHandle).ToArray(); + var errorCount = 0; - // Once for each WaitHandle that we have, wait for a response and log it - // We're previously submitted all these requests effectively in parallel and will now retrieve responses on a FIFO basis - foreach (var t in asyncResults) + //Wait for all requests to complete + WaitHandle.WaitAll(waitHandlesList.ToArray()); + + foreach (var t in asyncResultsList) { - var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15)); + //var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15)); try { @@ -520,18 +521,7 @@ namespace Umbraco.Core.Sync LogDispatchBatchError(ee); } } - - internal IEnumerable GetAsyncResults(List asyncResultsList, out List waitHandlesList) - { - var asyncResults = asyncResultsList.ToArray(); - waitHandlesList = new List(); - foreach (var asyncResult in asyncResults) - { - waitHandlesList.Add(asyncResult.AsyncWaitHandle); - } - return asyncResults; - } - + private void LogDispatchBatchError(Exception ee) { LogHelper.Error("Error refreshing distributed list", ee); diff --git a/src/Umbraco.Core/Sync/IServerAddress.cs b/src/Umbraco.Core/Sync/IServerAddress.cs index 8463c66c61..08333846a7 100644 --- a/src/Umbraco.Core/Sync/IServerAddress.cs +++ b/src/Umbraco.Core/Sync/IServerAddress.cs @@ -8,5 +8,7 @@ namespace Umbraco.Core.Sync internal interface IServerAddress { string ServerAddress { get; } + + //TODO : Should probably add things like port, protocol, server name, app id } } \ No newline at end of file diff --git a/src/Umbraco.Web/BatchedServerMessenger.cs b/src/Umbraco.Web/BatchedServerMessenger.cs index 669c1de817..8163bed4a1 100644 --- a/src/Umbraco.Web/BatchedServerMessenger.cs +++ b/src/Umbraco.Web/BatchedServerMessenger.cs @@ -67,6 +67,43 @@ namespace Umbraco.Web public string JsonPayload { get; set; } } + /// + /// We need to check if distributed calls are enabled, if they are we also want to make sure + /// that the current server's cache is updated internally in real time instead of at the end of + /// the call. This is because things like the URL cache, etc... might need to be updated during + /// the request that is making these calls. + /// + /// + /// + /// + /// + /// + /// + /// See: http://issues.umbraco.org/issue/U4-2633#comment=67-15604 + /// + protected override void MessageSeversForIdsOrJson(IEnumerable servers, ICacheRefresher refresher, MessageType dispatchType, IEnumerable ids = null, string jsonPayload = null) + { + //do all the normal stuff + base.MessageSeversForIdsOrJson(servers, refresher, dispatchType, ids, jsonPayload); + + //Now, check if we are using Distrubuted calls + if (UseDistributedCalls && servers.Any()) + { + //invoke on the current server - we will basically be double cache refreshing for the calling + // server but that just needs to be done currently, see the link above for details. + InvokeMethodOnRefresherInstance(refresher, dispatchType, ids, jsonPayload); + } + } + + /// + /// This adds the call to batched list + /// + /// + /// + /// + /// + /// + /// protected override void PerformDistributedCall( IEnumerable servers, ICacheRefresher refresher, @@ -75,6 +112,7 @@ namespace Umbraco.Web Type idArrayType = null, string jsonPayload = null) { + //NOTE: we use UmbracoContext instead of HttpContext.Current because when some web methods run async, the // HttpContext.Current is null but the UmbracoContext.Current won't be since we manually assign it. if (UmbracoContext.Current == null || UmbracoContext.Current.HttpContext == null) @@ -208,16 +246,17 @@ namespace Umbraco.Web instructions, Login, Password, null, null)); } - List waitHandlesList; - var asyncResults = GetAsyncResults(asyncResultsList, out waitHandlesList); - + var waitHandlesList = asyncResultsList.Select(x => x.AsyncWaitHandle).ToArray(); + var errorCount = 0; - // Once for each WaitHandle that we have, wait for a response and log it - // We're previously submitted all these requests effectively in parallel and will now retrieve responses on a FIFO basis - foreach (var t in asyncResults) + //Wait for all requests to complete + WaitHandle.WaitAll(waitHandlesList.ToArray()); + + foreach (var t in asyncResultsList) { - var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15)); + //var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15)); + try { cacheRefresher.EndBulkRefresh(t);