Moves the event handling logic to individual components, no more public "Install" methods.
This commit is contained in:
@@ -92,6 +92,8 @@ namespace Umbraco.ModelsBuilder.Embedded.DependencyInjection
|
||||
// would automatically just register for all implemented INotificationHandler{T}?
|
||||
builder.AddNotificationHandler<UmbracoApplicationStarting, ModelsBuilderNotificationHandler>();
|
||||
builder.AddNotificationHandler<ServerVariablesParsing, ModelsBuilderNotificationHandler>();
|
||||
builder.AddNotificationHandler<UmbracoApplicationStarting, LiveModelsProvider>();
|
||||
builder.AddNotificationHandler<UmbracoApplicationStarting, OutOfDateModelsStatus>();
|
||||
builder.Services.AddUnique<ModelsGenerator>();
|
||||
builder.Services.AddUnique<LiveModelsProvider>();
|
||||
builder.Services.AddUnique<OutOfDateModelsStatus>();
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Configuration;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.ModelsBuilder.Embedded.Building;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Web.Common.Lifetime;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Embedded
|
||||
{
|
||||
// supports LiveAppData - but not PureLive
|
||||
public sealed class LiveModelsProvider
|
||||
public sealed class LiveModelsProvider : INotificationHandler<UmbracoApplicationStarting>
|
||||
{
|
||||
private static Mutex s_mutex;
|
||||
private static int s_req;
|
||||
@@ -22,30 +25,49 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
private readonly ModelsGenerator _modelGenerator;
|
||||
private readonly ModelsGenerationError _mbErrors;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IUmbracoRequestLifetime _umbracoRequestLifetime;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LiveModelsProvider"/> class.
|
||||
/// </summary>
|
||||
public LiveModelsProvider(ILogger<LiveModelsProvider> logger, IOptions<ModelsBuilderSettings> config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment)
|
||||
public LiveModelsProvider(
|
||||
ILogger<LiveModelsProvider> logger,
|
||||
IOptions<ModelsBuilderSettings> config,
|
||||
ModelsGenerator modelGenerator,
|
||||
ModelsGenerationError mbErrors,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IUmbracoRequestLifetime umbracoRequestLifetime)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config.Value ?? throw new ArgumentNullException(nameof(config));
|
||||
_modelGenerator = modelGenerator;
|
||||
_mbErrors = mbErrors;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_umbracoRequestLifetime = umbracoRequestLifetime;
|
||||
}
|
||||
|
||||
// we do not manage pure live here
|
||||
internal bool IsEnabled => _config.ModelsMode.IsLiveNotPure();
|
||||
|
||||
internal void Install()
|
||||
/// <summary>
|
||||
/// Handles the <see cref="UmbracoApplicationStarting"/> notification
|
||||
/// </summary>
|
||||
public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
|
||||
{
|
||||
// just be sure
|
||||
Install();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Install()
|
||||
{
|
||||
// don't run if not enabled
|
||||
if (!IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_umbracoRequestLifetime.RequestEnd += (sender, context) => AppEndRequest(context);
|
||||
|
||||
// initialize mutex
|
||||
// ApplicationId will look like "/LM/W3SVC/1/Root/AppName"
|
||||
// name is system-wide and must be less than 260 chars
|
||||
@@ -56,34 +78,27 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
// anything changes, and we want to re-generate models.
|
||||
ContentTypeCacheRefresher.CacheUpdated += RequestModelsGeneration;
|
||||
DataTypeCacheRefresher.CacheUpdated += RequestModelsGeneration;
|
||||
|
||||
// at the end of a request since we're restarting the pool
|
||||
// NOTE - this does NOT trigger - see module below
|
||||
//umbracoApplication.EndRequest += GenerateModelsIfRequested;
|
||||
}
|
||||
|
||||
// NOTE
|
||||
// Using HttpContext Items fails because CacheUpdated triggers within
|
||||
// some asynchronous backend task where we seem to have no HttpContext.
|
||||
|
||||
// So we use a static (non request-bound) var to register that models
|
||||
// CacheUpdated triggers within some asynchronous backend task where
|
||||
// we have no HttpContext. So we use a static (non request-bound)
|
||||
// var to register that models
|
||||
// need to be generated. Could be by another request. Anyway. We could
|
||||
// have collisions but... you know the risk.
|
||||
|
||||
private void RequestModelsGeneration(object sender, EventArgs args)
|
||||
{
|
||||
//HttpContext.Current.Items[this] = true;
|
||||
_logger.LogDebug("Requested to generate models.");
|
||||
Interlocked.Exchange(ref s_req, 1);
|
||||
}
|
||||
|
||||
public void GenerateModelsIfRequested()
|
||||
private void GenerateModelsIfRequested()
|
||||
{
|
||||
//if (HttpContext.Current.Items[this] == null) return;
|
||||
if (Interlocked.Exchange(ref s_req, 0) == 0) return;
|
||||
|
||||
// cannot use a simple lock here because we don't want another AppDomain
|
||||
// to generate while we do... and there could be 2 AppDomains if the app restarts.
|
||||
if (Interlocked.Exchange(ref s_req, 0) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -91,7 +106,7 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
const int timeout = 2 * 60 * 1000; // 2 mins
|
||||
s_mutex.WaitOne(timeout); // wait until it is safe, and acquire
|
||||
_logger.LogInformation("Generate models now.");
|
||||
GenerateModels();
|
||||
_modelGenerator.GenerateModels();
|
||||
_mbErrors.Clear();
|
||||
_logger.LogInformation("Generated.");
|
||||
}
|
||||
@@ -110,13 +125,7 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateModels()
|
||||
{
|
||||
// EnableDllModels will recycle the app domain - but this request will end properly
|
||||
_modelGenerator.GenerateModels();
|
||||
}
|
||||
|
||||
public void AppEndRequest(HttpContext context)
|
||||
private void AppEndRequest(HttpContext context)
|
||||
{
|
||||
if (context.Request.IsClientSideRequest())
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Events;
|
||||
@@ -16,7 +15,6 @@ using Umbraco.Core.Services.Implement;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.ModelsBuilder.Embedded.BackOffice;
|
||||
using Umbraco.Web.Common.Lifetime;
|
||||
using Umbraco.Web.Common.ModelBinders;
|
||||
using Umbraco.Web.WebAssets;
|
||||
|
||||
@@ -30,28 +28,19 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
{
|
||||
private readonly ModelsBuilderSettings _config;
|
||||
private readonly IShortStringHelper _shortStringHelper;
|
||||
private readonly LiveModelsProvider _liveModelsProvider;
|
||||
private readonly OutOfDateModelsStatus _outOfDateModels;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly IUmbracoRequestLifetime _umbracoRequestLifetime;
|
||||
private readonly ContentModelBinder _modelBinder;
|
||||
|
||||
public ModelsBuilderNotificationHandler(
|
||||
IOptions<ModelsBuilderSettings> config,
|
||||
IShortStringHelper shortStringHelper,
|
||||
LiveModelsProvider liveModelsProvider,
|
||||
OutOfDateModelsStatus outOfDateModels,
|
||||
LinkGenerator linkGenerator,
|
||||
IUmbracoRequestLifetime umbracoRequestLifetime,
|
||||
ContentModelBinder modelBinder)
|
||||
{
|
||||
_config = config.Value;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_liveModelsProvider = liveModelsProvider;
|
||||
_outOfDateModels = outOfDateModels;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_linkGenerator = linkGenerator;
|
||||
_umbracoRequestLifetime = umbracoRequestLifetime;
|
||||
_modelBinder = modelBinder;
|
||||
}
|
||||
|
||||
@@ -62,8 +51,6 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
{
|
||||
// always setup the dashboard
|
||||
// note: UmbracoApiController instances are automatically registered
|
||||
_umbracoRequestLifetime.RequestEnd += (sender, context) => _liveModelsProvider.AppEndRequest(context);
|
||||
|
||||
_modelBinder.ModelBindingException += ContentModelBinder_ModelBindingException;
|
||||
|
||||
if (_config.ModelsMode != ModelsMode.Nothing)
|
||||
@@ -71,16 +58,6 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
FileService.SavingTemplate += FileService_SavingTemplate;
|
||||
}
|
||||
|
||||
if (_config.ModelsMode.IsLiveNotPure())
|
||||
{
|
||||
_liveModelsProvider.Install();
|
||||
}
|
||||
|
||||
if (_config.FlagOutOfDateModels)
|
||||
{
|
||||
_outOfDateModels.Install();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -89,7 +66,7 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
/// </summary>
|
||||
public Task HandleAsync(ServerVariablesParsing notification, CancellationToken cancellationToken)
|
||||
{
|
||||
var serverVars = notification.ServerVariables;
|
||||
IDictionary<string, object> serverVars = notification.ServerVariables;
|
||||
|
||||
if (!serverVars.ContainsKey("umbracoUrls"))
|
||||
{
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Core.Events;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Embedded
|
||||
{
|
||||
public sealed class OutOfDateModelsStatus
|
||||
public sealed class OutOfDateModelsStatus : INotificationHandler<UmbracoApplicationStarting>
|
||||
{
|
||||
private readonly ModelsBuilderSettings _config;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
@@ -18,11 +21,38 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
}
|
||||
|
||||
internal void Install()
|
||||
public bool IsEnabled => _config.FlagOutOfDateModels;
|
||||
|
||||
public bool IsOutOfDate
|
||||
{
|
||||
// just be sure
|
||||
if (_config.FlagOutOfDateModels == false)
|
||||
get
|
||||
{
|
||||
if (_config.FlagOutOfDateModels == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var path = GetFlagPath();
|
||||
return path != null && File.Exists(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="UmbracoApplicationStarting"/> notification
|
||||
/// </summary>
|
||||
public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
|
||||
{
|
||||
Install();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Install()
|
||||
{
|
||||
// don't run if not configured
|
||||
if (!IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ContentTypeCacheRefresher.CacheUpdated += (sender, args) => Write();
|
||||
DataTypeCacheRefresher.CacheUpdated += (sender, args) => Write();
|
||||
@@ -32,35 +62,38 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
{
|
||||
var modelsDirectory = _config.ModelsDirectoryAbsolute(_hostingEnvironment);
|
||||
if (!Directory.Exists(modelsDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(modelsDirectory);
|
||||
}
|
||||
|
||||
return Path.Combine(modelsDirectory, "ood.flag");
|
||||
}
|
||||
|
||||
private void Write()
|
||||
{
|
||||
var path = GetFlagPath();
|
||||
if (path == null || File.Exists(path)) return;
|
||||
if (path == null || File.Exists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
File.WriteAllText(path, "THIS FILE INDICATES THAT MODELS ARE OUT-OF-DATE\n\n");
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (_config.FlagOutOfDateModels == false) return;
|
||||
var path = GetFlagPath();
|
||||
if (path == null || !File.Exists(path)) return;
|
||||
File.Delete(path);
|
||||
}
|
||||
|
||||
public bool IsEnabled => _config.FlagOutOfDateModels;
|
||||
|
||||
public bool IsOutOfDate
|
||||
{
|
||||
get
|
||||
if (_config.FlagOutOfDateModels == false)
|
||||
{
|
||||
if (_config.FlagOutOfDateModels == false) return false;
|
||||
var path = GetFlagPath();
|
||||
return path != null && File.Exists(path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var path = GetFlagPath();
|
||||
if (path == null || !File.Exists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user