renames objects/methods and adds a lock to the routing mechanism

This commit is contained in:
Shannon
2019-09-09 23:25:28 +10:00
parent 8fef824dc1
commit fdad387414
8 changed files with 61 additions and 23 deletions

View File

@@ -46,7 +46,11 @@ namespace Umbraco.Tests.Routing
logger,
null, // FIXME: PublishedRouter complexities...
Mock.Of<IVariationContextAccessor>(),
Mock.Of<IUmbracoContextFactory>()
Mock.Of<IUmbracoContextFactory>(),
new Umbraco.Web.Cache.BackgroundPublishedSnapshotServiceNotifier(
Factory.GetInstance<IPublishedModelFactory>(),
Factory.GetInstance<IPublishedSnapshotService>(),
Logger)
);
runtime.Level = RuntimeLevel.Run;

View File

@@ -8,29 +8,62 @@ using Umbraco.Web.Scheduling;
namespace Umbraco.Web.Cache
{
public sealed class BackgroundSafeLiveFactory
/// <summary>
/// Used to notify the <see cref="IPublishedSnapshotService"/> of changes using a background thread
/// </summary>
/// <remarks>
/// When in Pure Live mode, the models need to be rebuilt before the IPublishedSnapshotService is notified which can result in performance penalties so
/// this performs these actions on a background thread so the user isn't waiting for the rebuilding to occur on a UI thread.
/// </remarks>
public sealed class BackgroundPublishedSnapshotServiceNotifier
{
private readonly IPublishedModelFactory _publishedModelFactory;
private readonly IPublishedSnapshotService _publishedSnapshotService;
private BackgroundTaskRunner<IBackgroundTask> _runner;
private readonly BackgroundTaskRunner<IBackgroundTask> _runner;
public BackgroundSafeLiveFactory(IPublishedModelFactory publishedModelFactory, IPublishedSnapshotService publishedSnapshotService, ILogger logger)
/// <summary>
/// Constructor
/// </summary>
/// <param name="publishedModelFactory"></param>
/// <param name="publishedSnapshotService"></param>
/// <param name="logger"></param>
public BackgroundPublishedSnapshotServiceNotifier(IPublishedModelFactory publishedModelFactory, IPublishedSnapshotService publishedSnapshotService, ILogger logger)
{
_publishedModelFactory = publishedModelFactory;
_publishedSnapshotService = publishedSnapshotService;
// TODO: We have the option to check if we are in live mode and only run on a background thread if that is the case, else run normally?
// IMO I think we should just always run on a background thread, then no matter what state the app is in, it's always doing a consistent operation.
_runner = new BackgroundTaskRunner<IBackgroundTask>("RebuildModelsAndCache", logger);
}
public void Execute(ContentTypeCacheRefresher.JsonPayload[] payloads)
/// <summary>
/// Blocks until the background operation is completed
/// </summary>
public void Wait() => _runner.StoppedAwaitable.GetAwaiter().GetResult(); //TODO: do we need a try/catch?
/// <summary>
/// Notify the <see cref="IPublishedSnapshotService"/> of content type changes
/// </summary>
/// <param name="payloads"></param>
public void NotifyWithSafeLiveFactory(ContentTypeCacheRefresher.JsonPayload[] payloads)
{
_runner.TryAdd(new RebuildModelsAndCacheTask(payloads, _publishedModelFactory, _publishedSnapshotService));
}
public void Execute(DataTypeCacheRefresher.JsonPayload[] payloads)
/// <summary>
/// Notify the <see cref="IPublishedSnapshotService"/> of data type changes
/// </summary>
/// <param name="payloads"></param>
public void NotifyWithSafeLiveFactory(DataTypeCacheRefresher.JsonPayload[] payloads)
{
_runner.TryAdd(new RebuildModelsAndCacheTask(payloads, _publishedModelFactory, _publishedSnapshotService));
}
/// <summary>
/// A simple background task that notifies the <see cref="IPublishedSnapshotService"/> of changes
/// </summary>
private class RebuildModelsAndCacheTask : IBackgroundTask
{
private readonly DataTypeCacheRefresher.JsonPayload[] _dataTypePayloads;
@@ -71,10 +104,7 @@ namespace Umbraco.Web.Cache
});
}
public Task RunAsync(CancellationToken token)
{
throw new System.NotImplementedException();
}
public Task RunAsync(CancellationToken token) => throw new System.NotImplementedException();
public bool IsAsync => false;

View File

@@ -10,11 +10,11 @@ namespace Umbraco.Web.Cache
{
public sealed class ContentTypeCacheRefresher : PayloadCacheRefresherBase<ContentTypeCacheRefresher, ContentTypeCacheRefresher.JsonPayload>
{
private readonly BackgroundSafeLiveFactory _backgroundModelFactory;
private readonly BackgroundPublishedSnapshotServiceNotifier _backgroundModelFactory;
private readonly IContentTypeCommonRepository _contentTypeCommonRepository;
private readonly IdkMap _idkMap;
public ContentTypeCacheRefresher(AppCaches appCaches, BackgroundSafeLiveFactory backgroundModelFactory, IdkMap idkMap, IContentTypeCommonRepository contentTypeCommonRepository)
public ContentTypeCacheRefresher(AppCaches appCaches, BackgroundPublishedSnapshotServiceNotifier backgroundModelFactory, IdkMap idkMap, IContentTypeCommonRepository contentTypeCommonRepository)
: base(appCaches)
{
_backgroundModelFactory = backgroundModelFactory;
@@ -80,7 +80,7 @@ namespace Umbraco.Web.Cache
MemberCacheRefresher.RefreshMemberTypes(AppCaches);
// refresh the models and cache
_backgroundModelFactory.Execute(payloads);
_backgroundModelFactory.NotifyWithSafeLiveFactory(payloads);
// now we can trigger the event
base.Refresh(payloads);

View File

@@ -9,10 +9,10 @@ namespace Umbraco.Web.Cache
public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase<DataTypeCacheRefresher, DataTypeCacheRefresher.JsonPayload>
{
private readonly BackgroundSafeLiveFactory _backgroundModelFactory;
private readonly BackgroundPublishedSnapshotServiceNotifier _backgroundModelFactory;
private readonly IdkMap _idkMap;
public DataTypeCacheRefresher(AppCaches appCaches, BackgroundSafeLiveFactory backgroundModelFactory, IdkMap idkMap)
public DataTypeCacheRefresher(AppCaches appCaches, BackgroundPublishedSnapshotServiceNotifier backgroundModelFactory, IdkMap idkMap)
: base(appCaches)
{
_backgroundModelFactory = backgroundModelFactory;
@@ -58,7 +58,7 @@ namespace Umbraco.Web.Cache
SliderValueConverter.ClearCaches();
// refresh the models and cache
_backgroundModelFactory.Execute(payloads);
_backgroundModelFactory.NotifyWithSafeLiveFactory(payloads);
base.Refresh(payloads);
}

View File

@@ -1,12 +1,8 @@
using System;
using System.Threading;
using Umbraco.Core;
using Umbraco.Core.Compose;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
using Umbraco.Core.Sync;

View File

@@ -125,7 +125,7 @@ namespace Umbraco.Web.Runtime
// register distributed cache
composition.RegisterUnique(f => new DistributedCache());
composition.RegisterUnique<BackgroundSafeLiveFactory>();
composition.RegisterUnique<BackgroundPublishedSnapshotServiceNotifier>();
// replace some services
composition.RegisterUnique<IEventMessagesFactory, DefaultEventMessagesFactory>();

View File

@@ -115,7 +115,7 @@
<Compile Include="AppBuilderExtensions.cs" />
<Compile Include="AreaRegistrationContextExtensions.cs" />
<Compile Include="AspNetHttpContextAccessor.cs" />
<Compile Include="Cache\BackgroundSafeLiveFactory.cs" />
<Compile Include="Cache\BackgroundPublishedSnapshotServiceNotifier.cs" />
<Compile Include="Cache\DistributedCacheBinder.cs" />
<Compile Include="Cache\DistributedCacheBinderComposer.cs" />
<Compile Include="Cache\DistributedCacheBinder_Handlers.cs" />

View File

@@ -18,6 +18,7 @@ using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Cache;
namespace Umbraco.Web
{
@@ -48,6 +49,7 @@ namespace Umbraco.Web
private readonly IPublishedRouter _publishedRouter;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IUmbracoContextFactory _umbracoContextFactory;
private readonly BackgroundPublishedSnapshotServiceNotifier _backgroundNotifier;
public UmbracoInjectedModule(
IGlobalSettings globalSettings,
@@ -59,7 +61,8 @@ namespace Umbraco.Web
ILogger logger,
IPublishedRouter publishedRouter,
IVariationContextAccessor variationContextAccessor,
IUmbracoContextFactory umbracoContextFactory)
IUmbracoContextFactory umbracoContextFactory,
BackgroundPublishedSnapshotServiceNotifier backgroundNotifier)
{
_combinedRouteCollection = new Lazy<RouteCollection>(CreateRouteCollection);
@@ -73,6 +76,7 @@ namespace Umbraco.Web
_publishedRouter = publishedRouter;
_variationContextAccessor = variationContextAccessor;
_umbracoContextFactory = umbracoContextFactory;
_backgroundNotifier = backgroundNotifier;
}
#region HttpModule event handlers
@@ -136,6 +140,10 @@ namespace Umbraco.Web
// do not process if this request is not a front-end routable page
var isRoutableAttempt = EnsureUmbracoRoutablePage(umbracoContext, httpContext);
// If this page is probably front-end routable, block here until the backround notifier isn't busy
if (isRoutableAttempt)
_backgroundNotifier.Wait();
// raise event here
UmbracoModule.OnRouteAttempt(this, new RoutableAttemptEventArgs(isRoutableAttempt.Result, umbracoContext, httpContext));
if (isRoutableAttempt.Success == false) return;