diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs index 93a560ff7d..fbf099bcf1 100644 --- a/src/Umbraco.Core/Runtime/IMainDom.cs +++ b/src/Umbraco.Core/Runtime/IMainDom.cs @@ -1,7 +1,7 @@ -using System; +using System; using Umbraco.Core.Hosting; -// TODO: Can't change namespace due to breaking changes, change in netcore + namespace Umbraco.Core { /// @@ -24,18 +24,8 @@ namespace Umbraco.Core /// /// Tries to acquire the MainDom, returns true if successful else false /// - /// - /// bool Acquire(IApplicationShutdownRegistry hostingEnvironment); - /// - /// Registers a resource that requires the current AppDomain to be the main domain to function. - /// - /// An action to execute before the AppDomain releases the main domain status. - /// An optional weight (lower goes first). - /// A value indicating whether it was possible to register. - bool Register(Action release, int weight = 100); - /// /// Registers a resource that requires the current AppDomain to be the main domain to function. /// @@ -45,6 +35,6 @@ namespace Umbraco.Core /// A value indicating whether it was possible to register. /// If registering is successful, then the action /// is guaranteed to execute before the AppDomain releases the main domain status. - bool Register(Action install, Action release, int weight = 100); + bool Register(Action install = null, Action release = null, int weight = 100); } } diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs index c378f4a58b..ced7ab0655 100644 --- a/src/Umbraco.Core/Runtime/MainDom.cs +++ b/src/Umbraco.Core/Runtime/MainDom.cs @@ -66,15 +66,6 @@ namespace Umbraco.Core.Runtime }); } - /// - /// Registers a resource that requires the current AppDomain to be the main domain to function. - /// - /// An action to execute before the AppDomain releases the main domain status. - /// An optional weight (lower goes first). - /// A value indicating whether it was possible to register. - public bool Register(Action release, int weight = 100) - => Register(null, release, weight); - /// /// Registers a resource that requires the current AppDomain to be the main domain to function. /// @@ -84,7 +75,7 @@ namespace Umbraco.Core.Runtime /// A value indicating whether it was possible to register. /// If registering is successful, then the action /// is guaranteed to execute before the AppDomain releases the main domain status. - public bool Register(Action install, Action release, int weight = 100) + public bool Register(Action install = null, Action release = null, int weight = 100) { lock (_locko) { diff --git a/src/Umbraco.Core/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs index a2ef0b8d78..76e6d9a919 100644 --- a/src/Umbraco.Core/SimpleMainDom.cs +++ b/src/Umbraco.Core/SimpleMainDom.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Hosting; @@ -21,10 +21,6 @@ namespace Umbraco.Core // always acquire public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) => true; - /// - public bool Register(Action release, int weight = 100) - => Register(null, release, weight); - /// public bool Register(Action install, Action release, int weight = 100) { diff --git a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs index 0356bdefc6..826ad12c0d 100644 --- a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; @@ -51,7 +51,9 @@ namespace Umbraco.Web.Scheduling internal bool Register() { if (MainDom != null) + { return MainDom.Register(Install, Release); + } // tests Install?.Invoke(); diff --git a/src/Umbraco.Infrastructure/Search/ExamineComponent.cs b/src/Umbraco.Infrastructure/Search/ExamineComponent.cs index e866fac560..6c6e566acb 100644 --- a/src/Umbraco.Infrastructure/Search/ExamineComponent.cs +++ b/src/Umbraco.Infrastructure/Search/ExamineComponent.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -72,7 +72,7 @@ namespace Umbraco.Web.Search public void Initialize() { //let's deal with shutting down Examine with MainDom - var examineShutdownRegistered = _mainDom.Register(() => + var examineShutdownRegistered = _mainDom.Register(release: () => { using (_profilingLogger.TraceDuration("Examine shutting down")) { diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs index 09c90461ac..0b1a8340a2 100644 --- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs @@ -151,7 +151,7 @@ namespace Umbraco.Core.Sync const int weight = 10; var registered = _mainDom.Register( - () => + release: () => { lock (_locko) { @@ -169,7 +169,7 @@ namespace Umbraco.Core.Sync Logger.LogWarning("The wait lock timed out, application is shutting down. The current instruction batch will be re-processed."); } }, - weight); + weight: weight); if (registered == false) { diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs index bc97118ee4..1c5160df18 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Text; using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; @@ -27,16 +27,20 @@ namespace Umbraco.ModelsBuilder.Embedded.Building { var modelsDirectory = _config.ModelsDirectoryAbsolute(_hostingEnvironment); if (!Directory.Exists(modelsDirectory)) + { Directory.CreateDirectory(modelsDirectory); + } foreach (var file in Directory.GetFiles(modelsDirectory, "*.generated.cs")) + { File.Delete(file); + } - var typeModels = _umbracoService.GetAllTypes(); + System.Collections.Generic.IList typeModels = _umbracoService.GetAllTypes(); var builder = new TextBuilder(_config, typeModels); - foreach (var typeModel in builder.GetModelsToGenerate()) + foreach (TypeModel typeModel in builder.GetModelsToGenerate()) { var sb = new StringBuilder(); builder.Generate(sb, typeModel); diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs index 1e0008dd43..11c5d8b605 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Configuration; +using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Hosting; @@ -18,14 +19,13 @@ namespace Umbraco.ModelsBuilder.Embedded // supports LiveAppData - but not PureLive public sealed class LiveModelsProvider : INotificationHandler { - private static Mutex s_mutex; private static int s_req; private readonly ILogger _logger; private readonly ModelsBuilderSettings _config; private readonly ModelsGenerator _modelGenerator; private readonly ModelsGenerationError _mbErrors; - private readonly IHostingEnvironment _hostingEnvironment; private readonly IUmbracoRequestLifetime _umbracoRequestLifetime; + private readonly IMainDom _mainDom; /// /// Initializes a new instance of the class. @@ -35,15 +35,15 @@ namespace Umbraco.ModelsBuilder.Embedded IOptions config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, - IHostingEnvironment hostingEnvironment, - IUmbracoRequestLifetime umbracoRequestLifetime) + IUmbracoRequestLifetime umbracoRequestLifetime, + IMainDom mainDom) { _logger = logger; _config = config.Value ?? throw new ArgumentNullException(nameof(config)); _modelGenerator = modelGenerator; _mbErrors = mbErrors; - _hostingEnvironment = hostingEnvironment; _umbracoRequestLifetime = umbracoRequestLifetime; + _mainDom = mainDom; } // we do not manage pure live here @@ -66,18 +66,17 @@ namespace Umbraco.ModelsBuilder.Embedded return; } - _umbracoRequestLifetime.RequestEnd += (sender, context) => AppEndRequest(context); + // Must register with maindom in order to function. + // If registration is not successful then events are not bound + // and we also don't generate models. + _mainDom.Register(() => + { + _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 - var name = _hostingEnvironment.ApplicationId + "/UmbracoLiveModelsProvider"; - - s_mutex = new Mutex(false, name); //TODO: Replace this with MainDom? Seems we now have 2x implementations of almost the same thing - - // anything changes, and we want to re-generate models. - ContentTypeCacheRefresher.CacheUpdated += RequestModelsGeneration; - DataTypeCacheRefresher.CacheUpdated += RequestModelsGeneration; + // anything changes, and we want to re-generate models. + ContentTypeCacheRefresher.CacheUpdated += RequestModelsGeneration; + DataTypeCacheRefresher.CacheUpdated += RequestModelsGeneration; + }); } // NOTE @@ -100,28 +99,32 @@ namespace Umbraco.ModelsBuilder.Embedded return; } - try + // cannot proceed unless we are MainDom + if (_mainDom.IsMainDom) { - _logger.LogDebug("Generate models..."); - const int timeout = 2 * 60 * 1000; // 2 mins - s_mutex.WaitOne(timeout); // wait until it is safe, and acquire - _logger.LogInformation("Generate models now."); - _modelGenerator.GenerateModels(); - _mbErrors.Clear(); - _logger.LogInformation("Generated."); + try + { + _logger.LogDebug("Generate models..."); + _logger.LogInformation("Generate models now."); + _modelGenerator.GenerateModels(); + _mbErrors.Clear(); + _logger.LogInformation("Generated."); + } + catch (TimeoutException) + { + _logger.LogWarning("Timeout, models were NOT generated."); + } + catch (Exception e) + { + _mbErrors.Report("Failed to build Live models.", e); + _logger.LogError("Failed to generate models.", e); + } } - catch (TimeoutException) + else { - _logger.LogWarning("Timeout, models were NOT generated."); - } - catch (Exception e) - { - _mbErrors.Report("Failed to build Live models.", e); - _logger.LogError("Failed to generate models.", e); - } - finally - { - s_mutex.ReleaseMutex(); // release + // this will only occur if this appdomain was MainDom and it has + // been released while trying to regenerate models. + _logger.LogWarning("Cannot generate models while app is shutting down"); } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs index 33c90d13bd..0a8283b507 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs @@ -1,12 +1,12 @@ using System.IO; +using System.Threading; +using System.Threading.Tasks; 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; +using Umbraco.Core.Hosting; +using Umbraco.Web.Cache; namespace Umbraco.ModelsBuilder.Embedded { @@ -94,6 +94,6 @@ namespace Umbraco.ModelsBuilder.Embedded } File.Delete(path); - } + } } }