Splits interfaces into separate ones, removes overlap between interfaces, injects the necessary bits, and much more

This commit is contained in:
Shannon
2020-03-25 15:06:22 +11:00
parent 900505704c
commit 612a47b16b
56 changed files with 614 additions and 442 deletions

View File

@@ -18,6 +18,7 @@ namespace Umbraco.Core.Composing
{
"Umbraco.Core",
"Umbraco.Web",
"Umbraco.Web.BackOffice",
"Umbraco.Infrastructure",
"Umbraco.PublishedCache.NuCache",
"Umbraco.ModelsBuilder.Embedded",

View File

@@ -19,8 +19,5 @@ namespace Umbraco.Core.Hosting
Version IISVersion { get; }
string MapPath(string path);
string ToAbsolute(string virtualPath, string root);
void RegisterObject(IRegisteredObject registeredObject);
void UnregisterObject(IRegisteredObject registeredObject);
}
}

View File

@@ -0,0 +1,8 @@
namespace Umbraco.Core.Hosting
{
public interface IHostingEnvironmentLifetime
{
void RegisterObject(IRegisteredObject registeredObject);
void UnregisterObject(IRegisteredObject registeredObject);
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Umbraco.Core.Hosting;
// TODO: Can't change namespace due to breaking changes, change in netcore
namespace Umbraco.Core
@@ -16,10 +17,17 @@ namespace Umbraco.Core
/// Gets a value indicating whether the current domain is the main domain.
/// </summary>
/// <remarks>
/// When the first call is made to this there will generally be some logic executed to acquire a distributed lock lease.
/// Acquire must be called first else this will always return false
/// </remarks>
bool IsMainDom { get; }
/// <summary>
/// Tries to acquire the MainDom, returns true if successful else false
/// </summary>
/// <param name="hostingEnvironment"></param>
/// <returns></returns>
bool Acquire(IHostingEnvironmentLifetime hostingEnvironment);
/// <summary>
/// Registers a resource that requires the current AppDomain to be the main domain to function.
/// </summary>

View File

@@ -21,7 +21,7 @@ namespace Umbraco.Core.Runtime
#region Vars
private readonly ILogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private IHostingEnvironmentLifetime _hostingEnvironment;
private readonly IMainDomLock _mainDomLock;
// our own lock for local consistency
@@ -42,17 +42,24 @@ namespace Umbraco.Core.Runtime
#region Ctor
// initializes a new instance of MainDom
public MainDom(ILogger logger, IHostingEnvironment hostingEnvironment, IMainDomLock systemLock)
public MainDom(ILogger logger, IMainDomLock systemLock)
{
hostingEnvironment.RegisterObject(this);
_logger = logger;
_hostingEnvironment = hostingEnvironment;
_mainDomLock = systemLock;
}
#endregion
public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
return LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () =>
{
hostingEnvironment.RegisterObject(this);
return Acquire();
});
}
/// <summary>
/// Registers a resource that requires the current AppDomain to be the main domain to function.
/// </summary>
@@ -180,10 +187,9 @@ namespace Umbraco.Core.Runtime
/// Gets a value indicating whether the current domain is the main domain.
/// </summary>
/// <remarks>
/// The lazy initializer call will only call the Acquire callback when it's not been initialized, else it will just return
/// the value from _isMainDom which means when we set _isMainDom to false again after being signaled, this will return false;
/// Acquire must be called first else this will always return false
/// </remarks>
public bool IsMainDom => LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () => Acquire());
public bool IsMainDom => _isMainDom;
// IRegisteredObject
void IRegisteredObject.Stop(bool immediate)

View File

@@ -11,18 +11,22 @@ namespace Umbraco.Web.Scheduling
{
public class KeepAlive : RecurringTaskBase
{
private readonly IRuntimeState _runtime;
private readonly IRuntimeState _runtimeState;
private readonly IMainDom _mainDom;
private readonly IKeepAliveSettings _keepAliveSettings;
private readonly IProfilingLogger _logger;
private readonly IServerRegistrar _serverRegistrar;
private static HttpClient _httpClient;
public KeepAlive(IBackgroundTaskRunner<RecurringTaskBase> runner, int delayMilliseconds, int periodMilliseconds,
IRuntimeState runtime, IKeepAliveSettings keepAliveSettings, IProfilingLogger logger)
IRuntimeState runtimeState, IMainDom mainDom, IKeepAliveSettings keepAliveSettings, IProfilingLogger logger, IServerRegistrar serverRegistrar)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_runtime = runtime;
_runtimeState = runtimeState;
_mainDom = mainDom;
_keepAliveSettings = keepAliveSettings;
_logger = logger;
_serverRegistrar = serverRegistrar;
if (_httpClient == null)
_httpClient = new HttpClient();
}
@@ -30,7 +34,7 @@ namespace Umbraco.Web.Scheduling
public override async Task<bool> PerformRunAsync(CancellationToken token)
{
// not on replicas nor unknown role servers
switch (_runtime.ServerRole)
switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug<KeepAlive>("Does not run on replica servers.");
@@ -41,7 +45,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
if (_runtime.IsMainDom == false)
if (_mainDom.IsMainDom == false)
{
_logger.Debug<KeepAlive>("Does not run if not MainDom.");
return false; // do NOT repeat, going down
@@ -54,7 +58,7 @@ namespace Umbraco.Web.Scheduling
{
if (keepAlivePingUrl.Contains("{umbracoApplicationUrl}"))
{
var umbracoAppUrl = _runtime.ApplicationUrl.ToString();
var umbracoAppUrl = _runtimeState.ApplicationUrl.ToString();
if (umbracoAppUrl.IsNullOrWhiteSpace())
{
_logger.Warn<KeepAlive>("No umbracoApplicationUrl for service (yet), skip.");

View File

@@ -14,26 +14,26 @@ namespace Umbraco.Web.Scheduling
{
private readonly DirectoryInfo[] _tempFolders;
private readonly TimeSpan _age;
private readonly IRuntimeState _runtime;
private readonly IMainDom _mainDom;
private readonly IProfilingLogger _logger;
public TempFileCleanup(IBackgroundTaskRunner<RecurringTaskBase> runner, int delayMilliseconds, int periodMilliseconds,
IEnumerable<DirectoryInfo> tempFolders, TimeSpan age,
IRuntimeState runtime, IProfilingLogger logger)
IMainDom mainDom, IProfilingLogger logger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
//SystemDirectories.TempFileUploads
_tempFolders = tempFolders.ToArray();
_age = age;
_runtime = runtime;
_mainDom = mainDom;
_logger = logger;
}
public override bool PerformRun()
{
// ensure we do not run if not main domain
if (_runtime.IsMainDom == false)
if (_mainDom.IsMainDom == false)
{
_logger.Debug<TempFileCleanup>("Does not run if not MainDom.");
return false; // do NOT repeat, going down

View File

@@ -13,13 +13,15 @@ namespace Umbraco.Core
/// </summary>
/// <param name="register">The application register.</param>
/// <returns>The application factory.</returns>
IFactory Boot(IRegister register);
IFactory Configure(IRegister register);
/// <summary>
/// Gets the runtime state.
/// </summary>
IRuntimeState State { get; }
void Start();
/// <summary>
/// Terminates the runtime.
/// </summary>

View File

@@ -25,21 +25,6 @@ namespace Umbraco.Core
/// </summary>
SemVersion SemanticVersion { get; }
/// <summary>
/// Gets a value indicating whether the application is running in debug mode.
/// </summary>
bool Debug { get; }
/// <summary>
/// Gets a value indicating whether the runtime is the current main domain.
/// </summary>
bool IsMainDom { get; }
/// <summary>
/// Get the server's current role.
/// </summary>
ServerRole ServerRole { get; }
/// <summary>
/// Gets the Umbraco application url.
/// </summary>
@@ -71,6 +56,5 @@ namespace Umbraco.Core
/// </summary>
BootFailedException BootFailedException { get; }
IMainDom MainDom { get; }
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Hosting;
namespace Umbraco.Core
{
@@ -16,6 +17,9 @@ namespace Umbraco.Core
/// <inheritdoc />
public bool IsMainDom { get; private set; } = true;
// always acquire
public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) => true;
/// <inheritdoc />
public bool Register(Action release, int weight = 100)
=> Register(null, release, weight);

View File

@@ -28,17 +28,18 @@ namespace Umbraco.Web
private readonly IRequestAccessor _requestAccessor;
public BatchedDatabaseServerMessenger(
IRuntimeState runtime,
IMainDom mainDom,
IUmbracoDatabaseFactory databaseFactory,
IScopeProvider scopeProvider,
ISqlContext sqlContext,
IProfilingLogger proflog,
IServerRegistrar serverRegistrar,
DatabaseServerMessengerOptions options,
IHostingEnvironment hostingEnvironment,
CacheRefresherCollection cacheRefreshers,
IRequestCache requestCache,
IRequestAccessor requestAccessor)
: base(runtime, scopeProvider, sqlContext, proflog, true, options, hostingEnvironment, cacheRefreshers)
: base(mainDom, scopeProvider, sqlContext, proflog, serverRegistrar, true, options, hostingEnvironment, cacheRefreshers)
{
_databaseFactory = databaseFactory;
_requestCache = requestCache;

View File

@@ -91,7 +91,6 @@ namespace Umbraco.Web.Compose
private readonly BackgroundTaskRunner<IBackgroundTask> _processTaskRunner;
private bool _started;
private IBackgroundTask[] _tasks;
private IndexRebuilder _indexRebuilder;
private readonly IRequestAccessor _requestAccessor;
public DatabaseServerRegistrarAndMessengerComponent(
@@ -100,14 +99,12 @@ namespace Umbraco.Web.Compose
IServerMessenger serverMessenger,
IServerRegistrationService registrationService,
ILogger logger,
IHostingEnvironment hostingEnvironment,
IndexRebuilder indexRebuilder,
IHostingEnvironmentLifetime hostingEnvironment,
IRequestAccessor requestAccessor)
{
_runtime = runtime;
_logger = logger;
_registrationService = registrationService;
_indexRebuilder = indexRebuilder;
_requestAccessor = requestAccessor;
// create task runner for DatabaseServerRegistrar

View File

@@ -4,13 +4,13 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Net;
using Umbraco.Core.Net;
namespace Umbraco.Core.Compose
{
public sealed class ManifestWatcherComponent : IComponent
{
private readonly IRuntimeState _runtimeState;
private readonly IHostingEnvironment _hosting;
private readonly ILogger _logger;
private readonly IIOHelper _ioHelper;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
@@ -19,9 +19,9 @@ namespace Umbraco.Core.Compose
// package.manifest chances and restarts the application on any change
private ManifestWatcher _mw;
public ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
public ManifestWatcherComponent(IHostingEnvironment hosting, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_runtimeState = runtimeState;
_hosting = hosting;
_logger = logger;
_ioHelper = ioHelper;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Compose
public void Initialize()
{
if (_runtimeState.Debug == false) return;
if (_hosting.IsDebugMode == false) return;
//if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false)
// return;

View File

@@ -44,7 +44,7 @@ namespace Umbraco.Core.Runtime
public override void Compose(Composition composition)
{
base.Compose(composition);
// composers
composition
.ComposeRepositories()
@@ -120,10 +120,11 @@ namespace Umbraco.Core.Runtime
// project
composition.RegisterUnique<IServerMessenger>(factory
=> new DatabaseServerMessenger(
factory.GetInstance<IRuntimeState>(),
factory.GetInstance<IMainDom>(),
factory.GetInstance<IScopeProvider>(),
factory.GetInstance<ISqlContext>(),
factory.GetInstance<IProfilingLogger>(),
factory.GetInstance<IServerRegistrar>(),
true, new DatabaseServerMessengerOptions(),
factory.GetInstance<IHostingEnvironment>(),
factory.GetInstance<CacheRefresherCollection>()

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
@@ -12,7 +11,6 @@ using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Sync;
namespace Umbraco.Core.Runtime
{
@@ -25,12 +23,26 @@ namespace Umbraco.Core.Runtime
{
private ComponentCollection _components;
private IFactory _factory;
private RuntimeState _state;
private readonly RuntimeState _state;
private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker;
private readonly IGlobalSettings _globalSettings;
private readonly IConnectionStrings _connectionStrings;
/// <summary>
/// Constructor
/// </summary>
/// <param name="configs"></param>
/// <param name="umbracoVersion"></param>
/// <param name="ioHelper"></param>
/// <param name="logger"></param>
/// <param name="profiler"></param>
/// <param name="umbracoBootPermissionChecker"></param>
/// <param name="hostingEnvironment"></param>
/// <param name="backOfficeInfo"></param>
/// <param name="dbProviderFactoryCreator"></param>
/// <param name="mainDom"></param>
/// <param name="typeFinder"></param>
public CoreRuntime(
Configs configs,
IUmbracoVersion umbracoVersion,
@@ -65,11 +77,7 @@ namespace Umbraco.Core.Runtime
// runtime state
// beware! must use '() => _factory.GetInstance<T>()' and NOT '_factory.GetInstance<T>'
// as the second one captures the current value (null) and therefore fails
_state = new RuntimeState(Logger,
Configs.Global(),
new Lazy<IMainDom>(() => mainDom),
new Lazy<IServerRegistrar>(() => _factory.GetInstance<IServerRegistrar>()),
UmbracoVersion, HostingEnvironment, BackOfficeInfo)
_state = new RuntimeState(Logger, Configs.Global(), UmbracoVersion, BackOfficeInfo)
{
Level = RuntimeLevel.Boot
};
@@ -81,12 +89,13 @@ namespace Umbraco.Core.Runtime
protected ILogger Logger { get; }
protected IBackOfficeInfo BackOfficeInfo { get; }
public IDbProviderFactoryCreator DbProviderFactoryCreator { get; }
/// <summary>
/// Gets the profiler.
/// </summary>
protected IProfiler Profiler { get; set; }
protected IProfiler Profiler { get; }
/// <summary>
/// Gets the profiling logger.
@@ -109,10 +118,10 @@ namespace Umbraco.Core.Runtime
/// <inheritdoc />
public IRuntimeState State => _state;
public IMainDom MainDom { get; private set; }
public IMainDom MainDom { get; }
/// <inheritdoc/>
public virtual IFactory Boot(IRegister register)
public virtual IFactory Configure(IRegister register)
{
if (register is null) throw new ArgumentNullException(nameof(register));
@@ -140,28 +149,24 @@ namespace Umbraco.Core.Runtime
// application environment
ConfigureUnhandledException();
ConfigureApplicationRootPath();
Boot(register, timer);
return _factory = Configure(register, timer);
}
return _factory;
}
/// <summary>
/// Boots the runtime within a timer.
/// Configure the runtime within a timer.
/// </summary>
protected virtual IFactory Boot(IRegister register, DisposableTimer timer)
private IFactory Configure(IRegister register, DisposableTimer timer)
{
if (register is null) throw new ArgumentNullException(nameof(register));
if (timer is null) throw new ArgumentNullException(nameof(timer));
Composition composition = null;
IFactory factory = null;
try
{
// throws if not full-trust
_umbracoBootPermissionChecker.ThrowIfNotPermissions();
// run handlers
RuntimeOptions.DoRuntimeBoot(ProfilingLogger);
@@ -179,15 +184,8 @@ namespace Umbraco.Core.Runtime
composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches);
composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo);
// run handlers
RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory);
// register runtime-level services
// there should be none, really - this is here "just in case"
Compose(composition);
// acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
AcquireMainDom(MainDom);
// register ourselves (TODO: Should we put this in RegisterEssentials?)
composition.Register<IRuntime>(_ => this, Lifetime.Singleton);
// determine our runtime level
DetermineRuntimeLevel(databaseFactory, ProfilingLogger);
@@ -205,13 +203,7 @@ namespace Umbraco.Core.Runtime
composers.Compose();
// create the factory
_factory = composition.CreateFactory();
// create & initialize the components
_components = _factory.GetInstance<ComponentCollection>();
_components.Initialize();
factory = composition.CreateFactory();
}
catch (Exception e)
{
@@ -228,11 +220,11 @@ namespace Umbraco.Core.Runtime
// if something goes wrong above, we may end up with no factory
// meaning nothing can get the runtime state, etc - so let's try
// to make sure we have a factory
if (_factory == null)
if (factory == null)
{
try
{
_factory = composition?.CreateFactory();
factory = composition?.CreateFactory();
}
catch { /* yea */ }
}
@@ -246,7 +238,29 @@ namespace Umbraco.Core.Runtime
// throw a BootFailedException for every requests.
}
return _factory;
return factory;
}
public void Start()
{
// throws if not full-trust
_umbracoBootPermissionChecker.ThrowIfNotPermissions();
ConfigureApplicationRootPath();
// run handlers
RuntimeOptions.DoRuntimeEssentials(_factory);
var hostingEnvironmentLifetime = _factory.TryGetInstance<IHostingEnvironmentLifetime>();
if (hostingEnvironmentLifetime == null)
throw new InvalidOperationException($"An instance of {typeof(IHostingEnvironmentLifetime)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}");
// acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
AcquireMainDom(MainDom, _factory.GetInstance<IHostingEnvironmentLifetime>());
// create & initialize the components
_components = _factory.GetInstance<ComponentCollection>();
_components.Initialize();
}
protected virtual void ConfigureUnhandledException()
@@ -273,13 +287,13 @@ namespace Umbraco.Core.Runtime
IOHelper.SetRootDirectory(path);
}
private bool AcquireMainDom(IMainDom mainDom)
private bool AcquireMainDom(IMainDom mainDom, IHostingEnvironmentLifetime hostingEnvironmentLifetime)
{
using (var timer = ProfilingLogger.DebugDuration<CoreRuntime>("Acquiring MainDom.", "Acquired."))
{
try
{
return mainDom.IsMainDom;
return mainDom.Acquire(hostingEnvironmentLifetime);
}
catch
{
@@ -338,12 +352,6 @@ namespace Umbraco.Core.Runtime
_components?.Terminate();
}
/// <summary>
/// Composes the runtime.
/// </summary>
public virtual void Compose(Composition composition)
{
}
#region Getters
@@ -384,5 +392,6 @@ namespace Umbraco.Core.Runtime
#endregion
}
}

View File

@@ -40,7 +40,7 @@ namespace Umbraco.Web.Runtime
}
/// <inheritdoc/>
public override IFactory Boot(IRegister register)
public override IFactory Configure(IRegister register)
{
var profilingLogger = new ProfilingLogger(Logger, Profiler);
@@ -57,7 +57,7 @@ namespace Umbraco.Web.Runtime
NetworkHelper.MachineName);
Logger.Debug<CoreRuntime>("Runtime: {Runtime}", GetType().FullName);
var factory = base.Boot(register);
var factory = base.Configure(register);
// now (and only now) is the time to switch over to perWebRequest scopes.
// up until that point we may not have a request, and scoped services would

View File

@@ -16,7 +16,7 @@ namespace Umbraco.Core
public static class RuntimeOptions
{
private static List<Action<IProfilingLogger>> _onBoot;
private static List<Action<Composition, AppCaches, TypeLoader, IUmbracoDatabaseFactory>> _onEssentials;
private static List<Action<IFactory>> _onEssentials;
/// <summary>
/// Executes the RuntimeBoot handlers.
@@ -33,13 +33,13 @@ namespace Umbraco.Core
/// <summary>
/// Executes the RuntimeEssentials handlers.
/// </summary>
internal static void DoRuntimeEssentials(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory)
internal static void DoRuntimeEssentials(IFactory factory)
{
if (_onEssentials== null)
return;
foreach (var action in _onEssentials)
action(composition, appCaches, typeLoader, databaseFactory);
action(factory);
}
/// <summary>
@@ -64,10 +64,10 @@ namespace Umbraco.Core
/// essential things (AppCaches, a TypeLoader, and a database factory) but
/// before anything else.</para>
/// </remarks>
public static void OnRuntimeEssentials(Action<Composition, AppCaches, TypeLoader, IUmbracoDatabaseFactory> action)
public static void OnRuntimeEssentials(Action<IFactory> action)
{
if (_onEssentials == null)
_onEssentials = new List<Action<Composition, AppCaches, TypeLoader, IUmbracoDatabaseFactory>>();
_onEssentials = new List<Action<IFactory>>();
_onEssentials.Add(action);
}
}

View File

@@ -22,44 +22,22 @@ namespace Umbraco.Core
private readonly ILogger _logger;
private readonly IGlobalSettings _globalSettings;
private readonly ConcurrentHashSet<string> _applicationUrls = new ConcurrentHashSet<string>();
private readonly Lazy<IMainDom> _mainDom;
private readonly Lazy<IServerRegistrar> _serverRegistrar;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IBackOfficeInfo _backOfficeInfo;
/// <summary>
/// Initializes a new instance of the <see cref="RuntimeState"/> class.
/// </summary>
public RuntimeState(ILogger logger, IGlobalSettings globalSettings,
Lazy<IMainDom> mainDom, Lazy<IServerRegistrar> serverRegistrar, IUmbracoVersion umbracoVersion,
IHostingEnvironment hostingEnvironment,
IUmbracoVersion umbracoVersion,
IBackOfficeInfo backOfficeInfo)
{
_logger = logger;
_globalSettings = globalSettings;
_mainDom = mainDom;
_serverRegistrar = serverRegistrar;
_umbracoVersion = umbracoVersion;
_hostingEnvironment = hostingEnvironment;
_backOfficeInfo = backOfficeInfo;
}
/// <summary>
/// Gets the server registrar.
/// </summary>
/// <remarks>
/// <para>This is NOT exposed in the interface.</para>
/// </remarks>
private IServerRegistrar ServerRegistrar => _serverRegistrar.Value;
/// <summary>
/// Gets the application MainDom.
/// </summary>
/// <remarks>
/// <para>This is NOT exposed in the interface as MainDom is internal.</para>
/// </remarks>
public IMainDom MainDom => _mainDom.Value;
/// <inheritdoc />
public Version Version => _umbracoVersion.Current;
@@ -70,23 +48,14 @@ namespace Umbraco.Core
/// <inheritdoc />
public SemVersion SemanticVersion => _umbracoVersion.SemanticVersion;
/// <inheritdoc />
public bool Debug => _hostingEnvironment.IsDebugMode;
/// <inheritdoc />
public bool IsMainDom => MainDom.IsMainDom;
/// <inheritdoc />
public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole();
/// <inheritdoc />
public Uri ApplicationUrl { get; private set; }
/// <inheritdoc />
public string CurrentMigrationState { get; internal set; }
public string CurrentMigrationState { get; private set; }
/// <inheritdoc />
public string FinalMigrationState { get; internal set; }
public string FinalMigrationState { get; private set; }
/// <inheritdoc />
public RuntimeLevel Level { get; internal set; } = RuntimeLevel.Unknown;
@@ -248,7 +217,7 @@ namespace Umbraco.Core
Reason = RuntimeLevelReason.UpgradeMigrations;
}
protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger)
private bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger)
{
var upgrader = new Upgrader(new UmbracoPlan(_umbracoVersion, _globalSettings));
var stateValueKey = upgrader.StateValueKey;

View File

@@ -81,7 +81,7 @@ namespace Umbraco.Web.Scheduling
private readonly string _logPrefix;
private readonly BackgroundTaskRunnerOptions _options;
private readonly ILogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHostingEnvironmentLifetime _hostingEnvironment;
private readonly object _locker = new object();
private readonly BufferBlock<T> _tasks = new BufferBlock<T>(new DataflowBlockOptions());
@@ -105,7 +105,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
@@ -116,7 +116,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
: this(name, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
@@ -127,7 +127,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, options, logger, hostingEnvironment, hook)
{ }
@@ -139,7 +139,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));

View File

@@ -11,22 +11,27 @@ namespace Umbraco.Web.Scheduling
{
public class HealthCheckNotifier : RecurringTaskBase
{
private readonly IRuntimeState _runtimeState;
private readonly IMainDom _mainDom;
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
private readonly IProfilingLogger _logger;
private readonly IHealthChecksSettings _healthChecksSettingsConfig;
private readonly IServerRegistrar _serverRegistrar;
private readonly IRuntimeState _runtimeState;
public HealthCheckNotifier(IBackgroundTaskRunner<RecurringTaskBase> runner, int delayMilliseconds, int periodMilliseconds,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IRuntimeState runtimeState, IProfilingLogger logger, IHealthChecksSettings healthChecksSettingsConfig)
IMainDom mainDom, IProfilingLogger logger, IHealthChecksSettings healthChecksSettingsConfig, IServerRegistrar serverRegistrar,
IRuntimeState runtimeState)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_healthChecks = healthChecks;
_notifications = notifications;
_runtimeState = runtimeState;
_mainDom = mainDom;
_logger = logger;
_healthChecksSettingsConfig = healthChecksSettingsConfig;
_serverRegistrar = serverRegistrar;
_runtimeState = runtimeState;
}
public override async Task<bool> PerformRunAsync(CancellationToken token)
@@ -34,7 +39,7 @@ namespace Umbraco.Web.Scheduling
if (_runtimeState.Level != RuntimeLevel.Run)
return true; // repeat...
switch (_runtimeState.ServerRole)
switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug<HealthCheckNotifier>("Does not run on replica servers.");
@@ -45,7 +50,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
if (_runtimeState.IsMainDom == false)
if (_mainDom.IsMainDom == false)
{
_logger.Debug<HealthCheckNotifier>("Does not run if not MainDom.");
return false; // do NOT repeat, going down

View File

@@ -11,17 +11,19 @@ namespace Umbraco.Web.Scheduling
public class LogScrubber : RecurringTaskBase
{
private readonly IRuntimeState _runtime;
private readonly IMainDom _mainDom;
private readonly IServerRegistrar _serverRegistrar;
private readonly IAuditService _auditService;
private readonly ILoggingSettings _settings;
private readonly IProfilingLogger _logger;
private readonly IScopeProvider _scopeProvider;
public LogScrubber(IBackgroundTaskRunner<RecurringTaskBase> runner, int delayMilliseconds, int periodMilliseconds,
IRuntimeState runtime, IAuditService auditService, ILoggingSettings settings, IScopeProvider scopeProvider, IProfilingLogger logger)
IMainDom mainDom, IServerRegistrar serverRegistrar, IAuditService auditService, ILoggingSettings settings, IScopeProvider scopeProvider, IProfilingLogger logger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_runtime = runtime;
_mainDom = mainDom;
_serverRegistrar = serverRegistrar;
_auditService = auditService;
_settings = settings;
_scopeProvider = scopeProvider;
@@ -53,7 +55,7 @@ namespace Umbraco.Web.Scheduling
public override bool PerformRun()
{
switch (_runtime.ServerRole)
switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug<LogScrubber>("Does not run on replica servers.");
@@ -64,7 +66,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
if (_runtime.IsMainDom == false)
if (_mainDom.IsMainDom == false)
{
_logger.Debug<LogScrubber>("Does not run if not MainDom.");
return false; // do NOT repeat, going down

View File

@@ -10,16 +10,20 @@ namespace Umbraco.Web.Scheduling
public class ScheduledPublishing : RecurringTaskBase
{
private readonly IRuntimeState _runtime;
private readonly IMainDom _mainDom;
private readonly IServerRegistrar _serverRegistrar;
private readonly IContentService _contentService;
private readonly IUmbracoContextFactory _umbracoContextFactory;
private readonly ILogger _logger;
private readonly IServerMessenger _serverMessenger;
public ScheduledPublishing(IBackgroundTaskRunner<RecurringTaskBase> runner, int delayMilliseconds, int periodMilliseconds,
IRuntimeState runtime, IContentService contentService, IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger)
IRuntimeState runtime, IMainDom mainDom, IServerRegistrar serverRegistrar, IContentService contentService, IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_runtime = runtime;
_mainDom = mainDom;
_serverRegistrar = serverRegistrar;
_contentService = contentService;
_umbracoContextFactory = umbracoContextFactory;
_logger = logger;
@@ -31,7 +35,7 @@ namespace Umbraco.Web.Scheduling
if (Suspendable.ScheduledPublishing.CanRun == false)
return true; // repeat, later
switch (_runtime.ServerRole)
switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug<ScheduledPublishing>("Does not run on replica servers.");
@@ -42,7 +46,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
if (_runtime.IsMainDom == false)
if (_mainDom.IsMainDom == false)
{
_logger.Debug<ScheduledPublishing>("Does not run if not MainDom.");
return false; // do NOT repeat, going down

View File

@@ -26,10 +26,12 @@ namespace Umbraco.Web.Scheduling
private const int OneHourMilliseconds = 3600000;
private readonly IRuntimeState _runtime;
private readonly IMainDom _mainDom;
private readonly IServerRegistrar _serverRegistrar;
private readonly IContentService _contentService;
private readonly IAuditService _auditService;
private readonly IProfilingLogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHostingEnvironmentLifetime _hostingEnvironment;
private readonly IScopeProvider _scopeProvider;
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
@@ -43,7 +45,6 @@ namespace Umbraco.Web.Scheduling
private BackgroundTaskRunner<IBackgroundTask> _keepAliveRunner;
private BackgroundTaskRunner<IBackgroundTask> _publishingRunner;
private BackgroundTaskRunner<IBackgroundTask> _tasksRunner;
private BackgroundTaskRunner<IBackgroundTask> _scrubberRunner;
private BackgroundTaskRunner<IBackgroundTask> _fileCleanupRunner;
private BackgroundTaskRunner<IBackgroundTask> _healthCheckRunner;
@@ -52,15 +53,17 @@ namespace Umbraco.Web.Scheduling
private object _locker = new object();
private IBackgroundTask[] _tasks;
public SchedulerComponent(IRuntimeState runtime,
public SchedulerComponent(IRuntimeState runtime, IMainDom mainDom, IServerRegistrar serverRegistrar,
IContentService contentService, IAuditService auditService,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger,
IHostingEnvironment hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig,
IHostingEnvironmentLifetime hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig,
IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor,
ILoggingSettings loggingSettings, IKeepAliveSettings keepAliveSettings)
{
_runtime = runtime;
_mainDom = mainDom;
_serverRegistrar = serverRegistrar;
_contentService = contentService;
_auditService = auditService;
_scopeProvider = scopeProvider;
@@ -83,7 +86,6 @@ namespace Umbraco.Web.Scheduling
// backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly
_keepAliveRunner = new BackgroundTaskRunner<IBackgroundTask>("KeepAlive", _logger, _hostingEnvironment);
_publishingRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledPublishing", _logger, _hostingEnvironment);
_tasksRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledTasks", _logger, _hostingEnvironment);
_scrubberRunner = new BackgroundTaskRunner<IBackgroundTask>("LogScrubber", _logger, _hostingEnvironment);
_fileCleanupRunner = new BackgroundTaskRunner<IBackgroundTask>("TempFileCleanup", _logger, _hostingEnvironment);
_healthCheckRunner = new BackgroundTaskRunner<IBackgroundTask>("HealthCheckNotifier", _logger, _hostingEnvironment);
@@ -138,7 +140,7 @@ namespace Umbraco.Web.Scheduling
{
// ping/keepalive
// on all servers
var task = new KeepAlive(_keepAliveRunner, DefaultDelayMilliseconds, FiveMinuteMilliseconds, _runtime, keepAliveSettings, _logger);
var task = new KeepAlive(_keepAliveRunner, DefaultDelayMilliseconds, FiveMinuteMilliseconds, _runtime, _mainDom, keepAliveSettings, _logger, _serverRegistrar);
_keepAliveRunner.TryAdd(task);
return task;
}
@@ -147,7 +149,7 @@ namespace Umbraco.Web.Scheduling
{
// scheduled publishing/unpublishing
// install on all, will only run on non-replica servers
var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _contentService, _umbracoContextFactory, _logger, _serverMessenger);
var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _mainDom, _serverRegistrar, _contentService, _umbracoContextFactory, _logger, _serverMessenger);
_publishingRunner.TryAdd(task);
return task;
}
@@ -173,7 +175,7 @@ namespace Umbraco.Web.Scheduling
}
var periodInMilliseconds = healthCheckSettingsConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000;
var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _runtime, logger, _healthChecksSettingsConfig);
var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _mainDom, logger, _healthChecksSettingsConfig, _serverRegistrar, _runtime);
_healthCheckRunner.TryAdd(task);
return task;
}
@@ -182,7 +184,7 @@ namespace Umbraco.Web.Scheduling
{
// log scrubbing
// install on all, will only run on non-replica servers
var task = new LogScrubber(_scrubberRunner, DefaultDelayMilliseconds, LogScrubber.GetLogScrubbingInterval(), _runtime, _auditService, settings, _scopeProvider, _logger);
var task = new LogScrubber(_scrubberRunner, DefaultDelayMilliseconds, LogScrubber.GetLogScrubbingInterval(), _mainDom, _serverRegistrar, _auditService, settings, _scopeProvider, _logger);
_scrubberRunner.TryAdd(task);
return task;
}
@@ -194,7 +196,7 @@ namespace Umbraco.Web.Scheduling
var task = new TempFileCleanup(_fileCleanupRunner, DefaultDelayMilliseconds, OneHourMilliseconds,
new[] { new DirectoryInfo(_ioHelper.MapPath(Constants.SystemDirectories.TempFileUploads)) },
TimeSpan.FromDays(1), //files that are over a day old
_runtime, _logger);
_mainDom, _logger);
_scrubberRunner.TryAdd(task);
return task;
}

View File

@@ -18,10 +18,10 @@ namespace Umbraco.Web.Search
private readonly IndexRebuilder _indexRebuilder;
private readonly IMainDom _mainDom;
private readonly IProfilingLogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHostingEnvironmentLifetime _hostingEnvironment;
private static BackgroundTaskRunner<IBackgroundTask> _rebuildOnStartupRunner;
public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironment hostingEnvironment, IndexRebuilder indexRebuilder)
public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironmentLifetime hostingEnvironment, IndexRebuilder indexRebuilder)
{
_mainDom = mainDom;
_logger = logger;
@@ -32,8 +32,6 @@ namespace Umbraco.Web.Search
/// <summary>
/// Called to rebuild empty indexes on startup
/// </summary>
/// <param name="indexRebuilder"></param>
/// <param name="logger"></param>
/// <param name="onlyEmptyIndexes"></param>
/// <param name="waitMilliseconds"></param>
public void RebuildIndexes(bool onlyEmptyIndexes, int waitMilliseconds = 0)

View File

@@ -28,10 +28,11 @@ namespace Umbraco.Core.Sync
//
public class DatabaseServerMessenger : ServerMessengerBase, IDatabaseServerMessenger
{
private readonly IRuntimeState _runtime;
private readonly IMainDom _mainDom;
private readonly ManualResetEvent _syncIdle;
private readonly object _locko = new object();
private readonly IProfilingLogger _profilingLogger;
private readonly IServerRegistrar _serverRegistrar;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly CacheRefresherCollection _cacheRefreshers;
private readonly ISqlContext _sqlContext;
@@ -46,14 +47,15 @@ namespace Umbraco.Core.Sync
public DatabaseServerMessengerOptions Options { get; }
public DatabaseServerMessenger(
IRuntimeState runtime, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog,
IMainDom mainDom, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IServerRegistrar serverRegistrar,
bool distributedEnabled, DatabaseServerMessengerOptions options, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers)
: base(distributedEnabled)
{
ScopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider));
_sqlContext = sqlContext;
_runtime = runtime;
_mainDom = mainDom;
_profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog));
_serverRegistrar = serverRegistrar;
_hostingEnvironment = hostingEnvironment;
_cacheRefreshers = cacheRefreshers;
Logger = proflog;
@@ -126,7 +128,7 @@ namespace Umbraco.Core.Sync
const int weight = 10;
var registered = _runtime.MainDom.Register(
var registered = _mainDom.Register(
() =>
{
lock (_locko)
@@ -262,7 +264,7 @@ namespace Umbraco.Core.Sync
_lastPruned = _lastSync;
switch (_runtime.ServerRole)
switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Single:
case ServerRole.Master:

View File

@@ -42,7 +42,7 @@ namespace Umbraco.ModelsBuilder.Embedded
private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" };
private readonly IModelsBuilderConfig _config;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IIOHelper _ioHelper;
private readonly ModelsGenerationError _errors;
@@ -51,12 +51,13 @@ namespace Umbraco.ModelsBuilder.Embedded
IProfilingLogger logger,
IModelsBuilderConfig config,
IHostingEnvironment hostingEnvironment,
IHostingEnvironmentLifetime hostingLifetime,
IIOHelper ioHelper)
{
_umbracoServices = umbracoServices;
_logger = logger;
_config = config;
_hostingEnvironment = hostingEnvironment;
_hostingLifetime = hostingLifetime;
_ioHelper = ioHelper;
_errors = new ModelsGenerationError(config, ioHelper);
_ver = 1; // zero is for when we had no version
@@ -64,7 +65,7 @@ namespace Umbraco.ModelsBuilder.Embedded
RazorBuildProvider.CodeGenerationStarted += RazorBuildProvider_CodeGenerationStarted;
if (!_hostingEnvironment.IsHosted) return;
if (!hostingEnvironment.IsHosted) return;
var modelsDirectory = _config.ModelsDirectoryAbsolute(_ioHelper);
if (!Directory.Exists(modelsDirectory))
@@ -73,7 +74,7 @@ namespace Umbraco.ModelsBuilder.Embedded
// BEWARE! if the watcher is not properly released then for some reason the
// BuildManager will start confusing types - using a 'registered object' here
// though we should probably plug into Umbraco's MainDom - which is internal
_hostingEnvironment.RegisterObject(this);
_hostingLifetime.RegisterObject(this);
_watcher = new FileSystemWatcher(modelsDirectory);
_watcher.Changed += WatcherOnChanged;
_watcher.EnableRaisingEvents = true;
@@ -677,7 +678,7 @@ namespace Umbraco.ModelsBuilder.Embedded
{
_watcher.EnableRaisingEvents = false;
_watcher.Dispose();
_hostingEnvironment.UnregisterObject(this);
_hostingLifetime.UnregisterObject(this);
}
#endregion

View File

@@ -12,11 +12,11 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Net;
using Umbraco.Core.Persistence;
using Umbraco.Core.Serialization;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Net;
using Umbraco.Web;
using Umbraco.Web.Routing;
@@ -31,7 +31,7 @@ namespace Umbraco.Tests.Common
private UriUtility _uriUtility;
private IIOHelper _ioHelper;
public TestHelperBase(Assembly entryAssembly)
protected TestHelperBase(Assembly entryAssembly)
{
SettingsForTests = new SettingsForTests();
MainDom = new SimpleMainDom();
@@ -52,12 +52,8 @@ namespace Umbraco.Tests.Common
return new RuntimeState(
Mock.Of<ILogger>(),
Mock.Of<IGlobalSettings>(),
new Lazy<IMainDom>(),
new Lazy<IServerRegistrar>(),
GetUmbracoVersion(),
GetHostingEnvironment(),
GetBackOfficeInfo()
);
GetBackOfficeInfo());
}
public abstract IBackOfficeInfo GetBackOfficeInfo();
@@ -132,6 +128,7 @@ namespace Umbraco.Tests.Common
}
public abstract IHostingEnvironment GetHostingEnvironment();
public abstract IHostingEnvironmentLifetime GetHostingEnvironmentLifetime();
public abstract IIpResolver GetIpResolver();

View File

@@ -1,31 +1,17 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
using Umbraco.Core.Persistence;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Umbraco.Tests.Integration.Testing;
namespace Umbraco.Tests.Integration
namespace Umbraco.Tests.Integration.Implementations
{
public static class HostBuilderExtensions
{
/// <summary>
/// Ensures the lifetime of the host ends as soon as code executes
/// </summary>
/// <param name="hostBuilder"></param>
/// <returns></returns>
public static IHostBuilder UseTestLifetime(this IHostBuilder hostBuilder)
{
hostBuilder.ConfigureServices((context, collection) => collection.AddSingleton<IHostLifetime, TestLifetime>());
return hostBuilder;
}
public static IHostBuilder UseLocalDb(this IHostBuilder hostBuilder, string dbFilePath)
{
// Need to register SqlClient manually

View File

@@ -8,10 +8,11 @@ using System.Net;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Diagnostics;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Net;
using Umbraco.Core.Persistence;
using Umbraco.Core.Runtime;
using Umbraco.Net;
using Umbraco.Tests.Common;
using Umbraco.Web.BackOffice;
using Umbraco.Web.BackOffice.AspNetCore;
@@ -19,11 +20,11 @@ using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment;
namespace Umbraco.Tests.Integration.Implementations
{
public class TestHelper : TestHelperBase
{
private IBackOfficeInfo _backOfficeInfo;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IIpResolver _ipResolver;
private readonly IWebHostEnvironment _hostEnvironment;
private readonly IHttpContextAccessor _httpContextAccessor;
@@ -40,11 +41,12 @@ namespace Umbraco.Tests.Integration.Implementations
&& x.ContentRootPath == CurrentAssemblyDirectory
&& x.WebRootPath == CurrentAssemblyDirectory); // same folder for now?
_hostingEnvironment = new AspNetCoreHostingEnvironment(
_hostingEnvironment = new TestHostingEnvironment(
SettingsForTests.GetDefaultHostingSettings(),
_hostEnvironment,
_httpContextAccessor,
Mock.Of<IHostApplicationLifetime>());
_httpContextAccessor);
_hostingLifetime = new AspNetCoreHostingEnvironmentLifetime(Mock.Of<IHostApplicationLifetime>());
Logger = new ProfilingLogger(new ConsoleLogger(new MessageTemplates()), Profiler);
}
@@ -75,7 +77,9 @@ namespace Umbraco.Tests.Integration.Implementations
}
public override IHostingEnvironment GetHostingEnvironment() => _hostingEnvironment;
public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _hostingLifetime;
public override IIpResolver GetIpResolver() => _ipResolver;
}
}

View File

@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Umbraco.Core.Configuration;
using Umbraco.Web.BackOffice.AspNetCore;
namespace Umbraco.Tests.Integration.Implementations
{
public class TestHostingEnvironment : AspNetCoreHostingEnvironment, Umbraco.Core.Hosting.IHostingEnvironment
{
public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor) : base(hostingSettings, webHostEnvironment, httpContextAccessor)
{
}
/// <summary>
/// Override for tests since we are not hosted
/// </summary>
/// <remarks>
/// This is specifically used by IOHelper and we want this to return false so that the root path is manually calcualted which is what we want for tests.
/// </remarks>
bool Umbraco.Core.Hosting.IHostingEnvironment.IsHosted { get; } = false;
}
}

View File

@@ -1,8 +1,8 @@
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
namespace Umbraco.Tests.Integration
namespace Umbraco.Tests.Integration.Implementations
{
/// <summary>
/// Ensures the host lifetime ends as soon as code execution is done

View File

@@ -10,6 +10,7 @@ using NUnit.Framework;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.LightInject;
@@ -46,27 +47,36 @@ namespace Umbraco.Tests.Integration
/// Manually configure the containers/dependencies and call Boot on Core runtime
/// </summary>
[Test]
public void BootCoreRuntime()
public void Boot_Core_Runtime()
{
// LightInject / Umbraco
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
var serviceProviderFactory = new UmbracoServiceProviderFactory(container);
var umbracoContainer = serviceProviderFactory.GetContainer();
// Create the core runtime
// Special case since we are not using the Generic Host, we need to manually add an AspNetCore service to the container
umbracoContainer.Register(x => Mock.Of<IHostApplicationLifetime>());
var testHelper = new TestHelper();
// Create the core runtime
var coreRuntime = new CoreRuntime(testHelper.GetConfigs(), testHelper.GetUmbracoVersion(),
testHelper.IOHelper, testHelper.Logger, testHelper.Profiler, testHelper.UmbracoBootPermissionChecker,
testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo(), testHelper.DbProviderFactoryCreator,
testHelper.MainDom, testHelper.GetTypeFinder());
// boot it!
var factory = coreRuntime.Boot(umbracoContainer);
// boot it!
var factory = coreRuntime.Configure(umbracoContainer);
Assert.IsTrue(coreRuntime.MainDom.IsMainDom);
Assert.IsNull(coreRuntime.State.BootFailedException);
Assert.AreEqual(RuntimeLevel.Install, coreRuntime.State.Level);
Assert.IsTrue(MyComposer.IsComposed);
Assert.IsFalse(MyComponent.IsInit);
Assert.IsFalse(MyComponent.IsTerminated);
coreRuntime.Start();
Assert.IsTrue(MyComponent.IsInit);
Assert.IsFalse(MyComponent.IsTerminated);
@@ -78,7 +88,7 @@ namespace Umbraco.Tests.Integration
}
/// <summary>
/// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host
/// Calling AddUmbracoCore to configure the container
/// </summary>
[Test]
public async Task AddUmbracoCore()
@@ -99,22 +109,106 @@ namespace Umbraco.Tests.Integration
});
var host = await hostBuilder.StartAsync();
var app = new ApplicationBuilder(host.Services);
// assert results
var runtimeState = umbracoContainer.GetInstance<IRuntimeState>();
var mainDom = umbracoContainer.GetInstance<IMainDom>();
var runtimeState = app.ApplicationServices.GetRequiredService<IRuntimeState>();
var mainDom = app.ApplicationServices.GetRequiredService<IMainDom>();
Assert.IsFalse(mainDom.IsMainDom); // We haven't "Started" the runtime yet
Assert.IsNull(runtimeState.BootFailedException);
Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
Assert.IsFalse(MyComponent.IsInit); // We haven't "Started" the runtime yet
await host.StopAsync();
Assert.IsFalse(MyComponent.IsTerminated); // we didn't "Start" the runtime so nothing was registered for shutdown
}
/// <summary>
/// Calling AddUmbracoCore to configure the container and UseUmbracoCore to start the runtime
/// </summary>
/// <returns></returns>
[Test]
public async Task UseUmbracoCore()
{
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
var testHelper = new TestHelper();
var hostBuilder = new HostBuilder()
.UseUmbraco(serviceProviderFactory)
.ConfigureServices((hostContext, services) =>
{
AddRequiredNetCoreServices(services, testHelper);
// Add it!
services.AddUmbracoConfiguration();
services.AddUmbracoCore(umbracoContainer, GetType().Assembly);
});
var host = await hostBuilder.StartAsync();
var app = new ApplicationBuilder(host.Services);
app.UseUmbracoCore();
// assert results
var runtimeState = app.ApplicationServices.GetRequiredService<IRuntimeState>();
var mainDom = app.ApplicationServices.GetRequiredService<IMainDom>();
Assert.IsTrue(mainDom.IsMainDom);
Assert.IsNull(runtimeState.BootFailedException);
Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
Assert.IsTrue(MyComponent.IsInit);
Assert.IsFalse(MyComponent.IsTerminated);
await host.StopAsync();
Assert.IsTrue(MyComponent.IsTerminated);
}
[Test]
public async Task Install_Database()
{
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
var testHelper = new TestHelper();
var hostBuilder = new HostBuilder()
//TODO: Need to have a configured umb version for the runtime state
.UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb"))
.UseUmbraco(serviceProviderFactory)
.ConfigureServices((hostContext, services) =>
{
AddRequiredNetCoreServices(services, testHelper);
// Add it!
services.AddUmbracoConfiguration();
services.AddUmbracoCore(umbracoContainer, GetType().Assembly);
});
var host = await hostBuilder.StartAsync();
var app = new ApplicationBuilder(host.Services);
app.UseUmbracoCore();
var runtimeState = (RuntimeState)app.ApplicationServices.GetRequiredService<IRuntimeState>();
Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
var dbBuilder = app.ApplicationServices.GetRequiredService<DatabaseBuilder>();
Assert.IsNotNull(dbBuilder);
var canConnect = dbBuilder.CanConnectToDatabase;
Assert.IsTrue(canConnect);
var dbResult = dbBuilder.CreateSchemaAndData();
Assert.IsTrue(dbResult.Success);
// TODO: Get this to work ... but to do that we need to mock or pass in a current umbraco version
//var dbFactory = app.ApplicationServices.GetRequiredService<IUmbracoDatabaseFactory>();
//var profilingLogger = app.ApplicationServices.GetRequiredService<IProfilingLogger>();
//runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger);
//Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
}
[Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")]
[Test]
@@ -128,6 +222,8 @@ namespace Umbraco.Tests.Integration
.UseUmbraco(serviceProviderFactory)
.ConfigureServices((hostContext, services) =>
{
// TODO: Try to re-register the service as a callback and see if it resolves to the same instance
lifetime1 = services.BuildServiceProvider().GetRequiredService<IHostApplicationLifetime>();
});
@@ -141,46 +237,6 @@ namespace Umbraco.Tests.Integration
}
[Test]
public async Task UseUmbracoCore()
{
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
var testHelper = new TestHelper();
var hostBuilder = new HostBuilder()
//TODO: Need to have a configured umb version for the runtime state
.UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb"))
//.UseTestLifetime()
.UseUmbraco(serviceProviderFactory)
.ConfigureServices((hostContext, services) =>
{
AddRequiredNetCoreServices(services, testHelper);
// Add it!
services.AddUmbracoConfiguration();
services.AddUmbracoCore(umbracoContainer, GetType().Assembly);
});
var host = await hostBuilder.StartAsync();
var runtimeState = (RuntimeState)umbracoContainer.GetInstance<IRuntimeState>();
Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
var dbBuilder = umbracoContainer.GetInstance<DatabaseBuilder>();
Assert.IsNotNull(dbBuilder);
var canConnect = dbBuilder.CanConnectToDatabase;
Assert.IsTrue(canConnect);
var dbResult = dbBuilder.CreateSchemaAndData();
Assert.IsTrue(dbResult.Success);
var dbFactory = umbracoContainer.GetInstance<IUmbracoDatabaseFactory>();
var profilingLogger = umbracoContainer.GetInstance<IProfilingLogger>();
runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger);
Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
}
private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory)
{
var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings());
@@ -189,9 +245,15 @@ namespace Umbraco.Tests.Integration
return umbracoContainer;
}
/// <summary>
/// These services need to be manually added because they do not get added by the generic host
/// </summary>
/// <param name="services"></param>
/// <param name="testHelper"></param>
private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper)
{
services.AddSingleton<IHttpContextAccessor>(x => testHelper.GetHttpContextAccessor());
// the generic host does add IHostEnvironment but not this one because we are not actually in a web context
services.AddSingleton<IWebHostEnvironment>(x => testHelper.GetWebHostEnvironment());
}

View File

@@ -41,6 +41,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
private readonly IEntityXmlSerializer _entitySerializer;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IHostingEnvironment _hostingEnvironment;
#region Constructors
@@ -57,6 +58,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
ILogger logger,
IGlobalSettings globalSettings,
IHostingEnvironment hostingEnvironment,
IHostingEnvironmentLifetime hostingLifetime,
IShortStringHelper shortStringHelper,
ISiteDomainHelper siteDomainHelper,
IEntityXmlSerializer entitySerializer,
@@ -67,7 +69,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
publishedSnapshotAccessor, variationContextAccessor, umbracoContextAccessor,
documentRepository, mediaRepository, memberRepository,
defaultCultureAccessor,
logger, globalSettings, hostingEnvironment, shortStringHelper, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents)
logger, globalSettings, hostingEnvironment, hostingLifetime, shortStringHelper, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents)
{
_umbracoContextAccessor = umbracoContextAccessor;
}
@@ -84,6 +86,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
ILogger logger,
IGlobalSettings globalSettings,
IHostingEnvironment hostingEnvironment,
IHostingEnvironmentLifetime hostingLifetime,
IShortStringHelper shortStringHelper,
ISiteDomainHelper siteDomainHelper,
IEntityXmlSerializer entitySerializer,
@@ -99,7 +102,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
_xmlStore = new XmlStore(serviceContext.ContentTypeService, serviceContext.ContentService, scopeProvider, _routesCache,
_contentTypeCache, publishedSnapshotAccessor, mainDom, testing, enableRepositoryEvents,
documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer, hostingEnvironment, shortStringHelper);
documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper);
_domainService = serviceContext.DomainService;
_memberService = serviceContext.MemberService;
@@ -113,6 +116,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
_siteDomainHelper = siteDomainHelper;
_entitySerializer = entitySerializer;
_hostingEnvironment = hostingEnvironment;
_hostingLifetime = hostingLifetime;
}
public override void Dispose()

View File

@@ -45,9 +45,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
private readonly IDocumentRepository _documentRepository;
private readonly IMediaRepository _mediaRepository;
private readonly IMemberRepository _memberRepository;
private readonly IGlobalSettings _globalSettings;
private readonly IEntityXmlSerializer _entitySerializer;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IShortStringHelper _shortStringHelper;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly PublishedContentTypeCache _contentTypeCache;
@@ -58,7 +57,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
private XmlStoreFilePersister _persisterTask;
private volatile bool _released;
private bool _withRepositoryEvents;
#region Constructors
@@ -67,8 +65,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
/// </summary>
/// <remarks>The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc.</remarks>
public XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache,
IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper)
: this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer, hostingEnvironment, shortStringHelper)
IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper)
: this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper)
{ }
// internal for unit tests
@@ -76,7 +74,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
// TODO: er, we DO have a DB?
internal XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache,
IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom,
bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper)
bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper)
{
if (testing == false)
EnsureConfigurationIsValid();
@@ -90,12 +88,11 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
_documentRepository = documentRepository;
_mediaRepository = mediaRepository;
_memberRepository = memberRepository;
_globalSettings = globalSettings;
_entitySerializer = entitySerializer;
_hostingEnvironment = hostingEnvironment;
_hostingLifetime = hostingLifetime;
_shortStringHelper = shortStringHelper;
_xmlFileName = TestHelper.IOHelper.MapPath(SystemFiles.GetContentCacheXml(_hostingEnvironment));
_xmlFileName = TestHelper.IOHelper.MapPath(SystemFiles.GetContentCacheXml(hostingEnvironment));
if (testing)
{
@@ -150,7 +147,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
LongRunning = true,
KeepAlive = true,
Hosted = false // main domain will take care of stopping the runner (see below)
}, logger, _hostingEnvironment);
}, logger, _hostingLifetime);
// create (and add to runner)
_persisterTask = new XmlStoreFilePersister(runner, this, logger);
@@ -207,7 +204,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
MediaTypeService.ScopedRefreshedEntity += OnMediaTypeRefreshedEntity;
MemberTypeService.ScopedRefreshedEntity += OnMemberTypeRefreshedEntity;
_withRepositoryEvents = true;
}
private void ClearEvents()
@@ -226,7 +222,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
MediaTypeService.ScopedRefreshedEntity -= OnMediaTypeRefreshedEntity;
MemberTypeService.ScopedRefreshedEntity -= OnMemberTypeRefreshedEntity;
_withRepositoryEvents = false;
}
private void LazyInitializeContent()

View File

@@ -32,8 +32,7 @@ namespace Umbraco.Tests.Routing
//create the module
var logger = Mock.Of<ILogger>();
var globalSettings = TestObjects.GetGlobalSettings();
var runtime = new RuntimeState(logger, globalSettings,
new Lazy<IMainDom>(), new Lazy<IServerRegistrar>(), UmbracoVersion, HostingEnvironment, BackOfficeInfo);
var runtime = new RuntimeState(logger, globalSettings, UmbracoVersion, BackOfficeInfo);
_module = new UmbracoInjectedModule
(

View File

@@ -146,31 +146,31 @@ namespace Umbraco.Tests.Runtimes
}
*/
// because we don't even have the core runtime component,
// there are a few required stuff that we need to compose
public override void Compose(Composition composition)
{
base.Compose(composition);
//// because we don't even have the core runtime component,
//// there are a few required stuff that we need to compose
//public override void Compose(Composition composition)
//{
// base.Compose(composition);
var scopeProvider = Mock.Of<IScopeProvider>();
Mock.Get(scopeProvider)
.Setup(x => x.CreateScope(
It.IsAny<IsolationLevel>(),
It.IsAny<RepositoryCacheMode>(),
It.IsAny<IEventDispatcher>(),
It.IsAny<bool?>(),
It.IsAny<bool>(),
It.IsAny<bool>()))
.Returns(Mock.Of<IScope>());
// var scopeProvider = Mock.Of<IScopeProvider>();
// Mock.Get(scopeProvider)
// .Setup(x => x.CreateScope(
// It.IsAny<IsolationLevel>(),
// It.IsAny<RepositoryCacheMode>(),
// It.IsAny<IEventDispatcher>(),
// It.IsAny<bool?>(),
// It.IsAny<bool>(),
// It.IsAny<bool>()))
// .Returns(Mock.Of<IScope>());
composition.RegisterUnique(scopeProvider);
}
// composition.RegisterUnique(scopeProvider);
//}
private IMainDom _mainDom;
public override IFactory Boot(IRegister container)
public override IFactory Configure(IRegister container)
{
var factory = base.Boot(container);
var factory = base.Configure(container);
_mainDom = factory.GetInstance<IMainDom>();
return factory;
}

View File

@@ -72,7 +72,7 @@ namespace Umbraco.Tests.Runtimes
var mainDom = new SimpleMainDom();
var umbracoVersion = TestHelper.GetUmbracoVersion();
var backOfficeInfo = TestHelper.GetBackOfficeInfo();
var runtimeState = new RuntimeState(logger, null, new Lazy<IMainDom>(() => mainDom), new Lazy<IServerRegistrar>(() => factory.GetInstance<IServerRegistrar>()), umbracoVersion, hostingEnvironment, backOfficeInfo);
var runtimeState = new RuntimeState(logger, null, umbracoVersion, backOfficeInfo);
var configs = TestHelper.GetConfigs();
var variationContextAccessor = TestHelper.VariationContextAccessor;
@@ -84,7 +84,6 @@ namespace Umbraco.Tests.Runtimes
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
coreRuntime.Compose(composition);
// determine actual runtime level
runtimeState.DetermineRuntimeLevel(databaseFactory, logger);
@@ -279,7 +278,6 @@ namespace Umbraco.Tests.Runtimes
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
coreRuntime.Compose(composition);
// get the components
// all of them?

View File

@@ -19,13 +19,13 @@ namespace Umbraco.Tests.Scheduling
public class BackgroundTaskRunnerTests
{
private ILogger _logger;
private IHostingEnvironment _hostingEnvironment;
private IHostingEnvironmentLifetime _hostingEnvironment;
[OneTimeSetUp]
public void InitializeFixture()
{
_logger = new ConsoleLogger(new MessageTemplates());
_hostingEnvironment = TestHelper.GetHostingEnvironment();
_hostingEnvironment = TestHelper.GetHostingEnvironmentLifetime();
}
[Test]
@@ -934,7 +934,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public void SourceTaskTest()
{
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger, TestHelper.GetHostingEnvironment());
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger, TestHelper.GetHostingEnvironmentLifetime());
var task = new SourceTask();
runner.Add(task);

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Tests.Scheduling
public async Task ThreadResumeIssue()
{
var logger = new DebugDiagnosticsLogger(new MessageTemplates());
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment());
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironmentLifetime());
var work = new ThreadResumeIssueWorkItem();
runner.Add(work);
@@ -77,7 +77,7 @@ namespace Umbraco.Tests.Scheduling
public async Task DebuggerInterferenceIssue()
{
var logger = new DebugDiagnosticsLogger(new MessageTemplates());
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment());
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironmentLifetime());
var taskCompleted = false;
runner.TaskCompleted += (sender, args) =>
{

View File

@@ -21,12 +21,12 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Net;
using Umbraco.Core.Persistence;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Net;
using Umbraco.Tests.Common;
using Umbraco.Web;
using Umbraco.Web.Hosting;
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.TestHelpers
/// </summary>
public static class TestHelper
{
private static TestHelperInternal _testHelperInternal = new TestHelperInternal();
private static readonly TestHelperInternal _testHelperInternal = new TestHelperInternal();
private class TestHelperInternal : TestHelperBase
{
public TestHelperInternal() : base(typeof(TestHelperInternal).Assembly)
@@ -62,6 +62,9 @@ namespace Umbraco.Tests.TestHelpers
public override IHostingEnvironment GetHostingEnvironment()
=> new AspNetHostingEnvironment(SettingsForTests.GetDefaultHostingSettings());
public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime()
=> new AspNetHostingLifetime();
public override IIpResolver GetIpResolver()
=> new AspNetIpResolver();
}
@@ -320,6 +323,8 @@ namespace Umbraco.Tests.TestHelpers
public static IHostingEnvironment GetHostingEnvironment() => _testHelperInternal.GetHostingEnvironment();
public static IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime();
public static IIpResolver GetIpResolver() => _testHelperInternal.GetIpResolver();
public static IRequestCache GetRequestCache() => _testHelperInternal.GetRequestCache();

View File

@@ -265,6 +265,7 @@ namespace Umbraco.Tests.TestHelpers
Logger,
Factory.GetInstance<IGlobalSettings>(),
HostingEnvironment,
HostingLifetime,
ShortStringHelper,
new SiteDomainHelper(),
Factory.GetInstance<IEntityXmlSerializer>(),

View File

@@ -51,10 +51,10 @@ using Umbraco.Web.Templates;
using Umbraco.Web.PropertyEditors;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Models;
using Umbraco.Core.Net;
using Umbraco.Core.Request;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Net;
using Umbraco.Tests.LegacyXmlPublishedCache;
using Umbraco.Web.AspNet;
using Umbraco.Web.Install;
@@ -140,6 +140,7 @@ namespace Umbraco.Tests.Testing
protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance<IProfilingLogger>();
protected IHostingEnvironment HostingEnvironment { get; } = new AspNetHostingEnvironment(TestHelpers.SettingsForTests.GetDefaultHostingSettings());
protected IHostingEnvironmentLifetime HostingLifetime { get; } = new AspNetHostingLifetime();
protected IIpResolver IpResolver => Factory.GetInstance<IIpResolver>();
protected IBackOfficeInfo BackOfficeInfo => Factory.GetInstance<IBackOfficeInfo>();
protected AppCaches AppCaches => Factory.GetInstance<AppCaches>();

View File

@@ -423,6 +423,7 @@ namespace Umbraco.Tests.Web.Mvc
new TestDefaultCultureAccessor(),
Current.Logger, TestObjects.GetGlobalSettings(),
TestHelper.GetHostingEnvironment(),
TestHelper.GetHostingEnvironmentLifetime(),
ShortStringHelper,
new SiteDomainHelper(),
Factory.GetInstance<IEntityXmlSerializer>(),

View File

@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Hosting;
using Umbraco.Core.Net;
using Umbraco.Core.Runtime;
namespace Umbraco.Web.BackOffice.AspNetCore
{
/// <summary>
/// Adds/replaces AspNetCore specific services
/// </summary>
[ComposeBefore(typeof(ICoreComposer))]
[ComposeAfter(typeof(CoreInitialComposer))]
public class AspNetCoreComposer : IComposer
{
public void Compose(Composition composition)
{
// AspNetCore specific services
composition.RegisterUnique<IHttpContextAccessor, HttpContextAccessor>();
// Our own netcore implementations
composition.RegisterUnique<IUmbracoApplicationLifetime, AspNetCoreUmbracoApplicationLifetime>();
composition.RegisterUnique<IHostingEnvironmentLifetime, AspNetCoreHostingEnvironmentLifetime>();
}
}
}

View File

@@ -1,11 +1,8 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Umbraco.Core;
using Umbraco.Core.Configuration;
@@ -13,30 +10,29 @@ namespace Umbraco.Web.BackOffice.AspNetCore
{
public class AspNetCoreHostingEnvironment : Umbraco.Core.Hosting.IHostingEnvironment
{
private readonly ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper> _registeredObjects =
new ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper>();
private readonly IHostingSettings _hostingSettings;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private string _localTempPath;
public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor, IHostApplicationLifetime hostHostApplicationLifetime)
public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor)
{
_hostingSettings = hostingSettings ?? throw new ArgumentNullException(nameof(hostingSettings));
_webHostEnvironment = webHostEnvironment;
_httpContextAccessor = httpContextAccessor;
_hostApplicationLifetime = hostHostApplicationLifetime;
SiteName = webHostEnvironment.ApplicationName;
ApplicationId = AppDomain.CurrentDomain.Id.ToString();
ApplicationPhysicalPath = webHostEnvironment.ContentRootPath;
ApplicationVirtualPath = "/"; //TODO how to find this, This is a server thing, not application thing.
IISVersion = new Version(0, 0); // TODO not necessary IIS
IISVersion = new Version(0, 0); // TODO not necessary IIS
IsDebugMode = _hostingSettings.DebugMode;
}
public bool IsHosted { get; } = true;
public string SiteName { get; }
public string ApplicationId { get; }
@@ -56,7 +52,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore
switch (_hostingSettings.LocalTempStorageLocation)
{
case LocalTempStorage.AspNetTemp:
return _localTempPath = System.IO.Path.Combine(Path.GetTempPath(),ApplicationId, "UmbracoData");
// TODO: I don't think this is correct? but also we probably can remove AspNetTemp as an option entirely
// since this is legacy and we shouldn't use it
return _localTempPath = System.IO.Path.Combine(Path.GetTempPath(), ApplicationId, "UmbracoData");
case LocalTempStorage.EnvironmentTemp:
@@ -84,8 +83,11 @@ namespace Umbraco.Web.BackOffice.AspNetCore
}
}
// TODO: This may need to take into account ~/ paths which means the ApplicationVirtualPath and is this the content root or web root?
public string MapPath(string path) => Path.Combine(_webHostEnvironment.WebRootPath, path);
public string MapPath(string path)
{
var newPath = path.TrimStart('~', '/').Replace('/', Path.DirectorySeparatorChar);
return Path.Combine(_webHostEnvironment.WebRootPath, newPath);
}
// TODO: Need to take into account 'root' here
public string ToAbsolute(string virtualPath, string root)
@@ -101,43 +103,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
return applicationPath.Add(segment).Value;
}
public void RegisterObject(IRegisteredObject registeredObject)
{
var wrapped = new RegisteredObjectWrapper(registeredObject);
if (!_registeredObjects.TryAdd(registeredObject, wrapped))
{
throw new InvalidOperationException("Could not register object");
}
var cancellationTokenRegistration = _hostApplicationLifetime.ApplicationStopping.Register(() => wrapped.Stop(true));
wrapped.CancellationTokenRegistration = cancellationTokenRegistration;
}
public void UnregisterObject(IRegisteredObject registeredObject)
{
if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
{
wrapped.CancellationTokenRegistration.Unregister();
}
}
private class RegisteredObjectWrapper
{
private readonly IRegisteredObject _inner;
public RegisteredObjectWrapper(IRegisteredObject inner)
{
_inner = inner;
}
public CancellationTokenRegistration CancellationTokenRegistration { get; set; }
public void Stop(bool immediate)
{
_inner.Stop(immediate);
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using Microsoft.Extensions.Hosting;
using Umbraco.Core;
using Umbraco.Core.Hosting;
namespace Umbraco.Web.BackOffice.AspNetCore
{
public class AspNetCoreHostingEnvironmentLifetime : IHostingEnvironmentLifetime
{
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper> _registeredObjects =
new ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper>();
public AspNetCoreHostingEnvironmentLifetime(IHostApplicationLifetime hostApplicationLifetime)
{
_hostApplicationLifetime = hostApplicationLifetime;
}
public void RegisterObject(IRegisteredObject registeredObject)
{
var wrapped = new RegisteredObjectWrapper(registeredObject);
if (!_registeredObjects.TryAdd(registeredObject, wrapped))
{
throw new InvalidOperationException("Could not register object");
}
var cancellationTokenRegistration = _hostApplicationLifetime.ApplicationStopping.Register(() => wrapped.Stop(true));
wrapped.CancellationTokenRegistration = cancellationTokenRegistration;
}
public void UnregisterObject(IRegisteredObject registeredObject)
{
if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
{
wrapped.CancellationTokenRegistration.Unregister();
}
}
private class RegisteredObjectWrapper
{
private readonly IRegisteredObject _inner;
public RegisteredObjectWrapper(IRegisteredObject inner)
{
_inner = inner;
}
public CancellationTokenRegistration CancellationTokenRegistration { get; set; }
public void Stop(bool immediate)
{
_inner.Stop(immediate);
}
}
}
}

View File

@@ -2,6 +2,9 @@ using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Hosting;
namespace Umbraco.Web.BackOffice.AspNetCore
{
@@ -14,5 +17,52 @@ namespace Umbraco.Web.BackOffice.AspNetCore
return app;
}
/// <summary>
/// Start Umbraco
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseUmbracoCore(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
// Register a listener for application shutdown in order to terminate the runtime
var hostLifetime = app.ApplicationServices.GetRequiredService<IHostingEnvironmentLifetime>();
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
hostLifetime.RegisterObject(runtimeShutdown);
// Start the runtime!
runtime.Start();
return app;
}
/// <summary>
/// Ensures the runtime is shutdown when the application is shutting down
/// </summary>
private class CoreRuntimeShutdown : IRegisteredObject
{
public CoreRuntimeShutdown(IRuntime runtime, IHostingEnvironmentLifetime hostLifetime)
{
_runtime = runtime;
_hostLifetime = hostLifetime;
}
private bool _completed = false;
private readonly IRuntime _runtime;
private readonly IHostingEnvironmentLifetime _hostLifetime;
public void Stop(bool immediate)
{
if (!_completed)
{
_completed = true;
_runtime.Terminate();
_hostLifetime.UnregisterObject(this);
}
}
}
}
}

View File

@@ -19,8 +19,7 @@ using Umbraco.Core.Runtime;
namespace Umbraco.Web.BackOffice.AspNetCore
{
// TODO: Move to Umbraco.Web.Common
public static class UmbracoCoreServiceCollectionExtensions
{
/// <summary>
@@ -73,11 +72,12 @@ namespace Umbraco.Web.BackOffice.AspNetCore
if (umbContainer is null) throw new ArgumentNullException(nameof(umbContainer));
if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly));
// Special case! The generic host adds a few default services but we need to manually add this one here NOW because
// we resolve it before the host finishes configuring in the call to CreateCompositionRoot
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler);
// TODO: Get rid of this 'Current' requirement
var globalSettings = configs.Global();
var umbracoVersion = new UmbracoVersion(globalSettings);
@@ -95,9 +95,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
backOfficeInfo,
typeFinder);
hostingEnvironment.RegisterObject(new CoreRuntimeShutdown(coreRuntime));
var factory = coreRuntime.Boot(umbContainer);
var factory = coreRuntime.Configure(umbContainer);
return services;
}
@@ -119,7 +117,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connStrings, dbProviderFactoryCreator)
: new MainDomSemaphoreLock(logger, hostingEnvironment);
var mainDom = new MainDom(logger, hostingEnvironment, mainDomLock);
var mainDom = new MainDom(logger, mainDomLock);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetCoreBootPermissionsChecker(),
hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, typeFinder);
@@ -137,10 +135,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
var webHostEnvironment = serviceProvider.GetRequiredService<IWebHostEnvironment>();
// TODO: I'm unsure about this, by doing this it means we are resolving a "Different" instance to the one
// that controls the whole app because the instances comes from a different service provider. This
// could cause some issues with shutdowns, etc... we need to investigate.
var hostApplicationLifetime = serviceProvider.GetRequiredService<IHostApplicationLifetime>();
configs = serviceProvider.GetService<Configs>();
if (configs == null)
@@ -150,7 +144,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
var coreDebug = configs.CoreDebug();
var globalSettings = configs.Global();
hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime);
hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor);
ioHelper = new IOHelper(hostingEnvironment, globalSettings);
logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment,
new AspNetCoreSessionIdResolver(httpContextAccessor),
@@ -170,28 +164,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore
}
}
/// <summary>
/// Ensures the runtime is shutdown when the application is shutting down
/// </summary>
private class CoreRuntimeShutdown : IRegisteredObject
{
public CoreRuntimeShutdown(IRuntime runtime)
{
_runtime = runtime;
}
private bool _completed = false;
private readonly IRuntime _runtime;
public void Stop(bool immediate)
{
if (!_completed)
{
_completed = true;
_runtime.Terminate();
}
}
}
}
}

View File

@@ -1,21 +1,15 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Web;
using System.Web.Hosting;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using IRegisteredObject = Umbraco.Core.IRegisteredObject;
namespace Umbraco.Web.Hosting
{
public class AspNetHostingEnvironment : IHostingEnvironment
{
private readonly ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper> _registeredObjects =
new ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper>();
private readonly IHostingSettings _hostingSettings;
private string _localTempPath;
@@ -46,23 +40,7 @@ namespace Umbraco.Web.Hosting
}
public string ToAbsolute(string virtualPath, string root) => VirtualPathUtility.ToAbsolute(virtualPath, root);
public void RegisterObject(IRegisteredObject registeredObject)
{
var wrapped = new RegisteredObjectWrapper(registeredObject);
if (!_registeredObjects.TryAdd(registeredObject, wrapped))
{
throw new InvalidOperationException("Could not register object");
}
HostingEnvironment.RegisterObject(wrapped);
}
public void UnregisterObject(IRegisteredObject registeredObject)
{
if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
{
HostingEnvironment.UnregisterObject(wrapped);
}
}
public string LocalTempPath
{
@@ -101,20 +79,7 @@ namespace Umbraco.Web.Hosting
}
}
}
private class RegisteredObjectWrapper : System.Web.Hosting.IRegisteredObject
{
private readonly IRegisteredObject _inner;
public RegisteredObjectWrapper(IRegisteredObject inner)
{
_inner = inner;
}
public void Stop(bool immediate)
{
_inner.Stop(immediate);
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Concurrent;
using System.Web.Hosting;
using Umbraco.Core.Hosting;
using IRegisteredObject = Umbraco.Core.IRegisteredObject;
namespace Umbraco.Web.Hosting
{
public class AspNetHostingLifetime : IHostingEnvironmentLifetime
{
private readonly ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper> _registeredObjects =
new ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper>();
public void RegisterObject(IRegisteredObject registeredObject)
{
var wrapped = new RegisteredObjectWrapper(registeredObject);
if (!_registeredObjects.TryAdd(registeredObject, wrapped))
{
throw new InvalidOperationException("Could not register object");
}
HostingEnvironment.RegisterObject(wrapped);
}
public void UnregisterObject(IRegisteredObject registeredObject)
{
if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
{
HostingEnvironment.UnregisterObject(wrapped);
}
}
private class RegisteredObjectWrapper : System.Web.Hosting.IRegisteredObject
{
private readonly IRegisteredObject _inner;
public RegisteredObjectWrapper(IRegisteredObject inner)
{
_inner = inner;
}
public void Stop(bool immediate)
{
_inner.Stop(immediate);
}
}
}
}

View File

@@ -1,6 +1,7 @@
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Persistence;
@@ -18,7 +19,7 @@ namespace Umbraco.Web.Profiling
[UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)]
public class WebProfilingController : UmbracoAuthorizedJsonController
{
private readonly IRuntimeState _runtimeState;
private readonly IHostingEnvironment _hosting;
public WebProfilingController(
IGlobalSettings globalSettings,
@@ -30,17 +31,18 @@ namespace Umbraco.Web.Profiling
IRuntimeState runtimeState,
IShortStringHelper shortStringHelper,
UmbracoMapper umbracoMapper,
IPublishedUrlProvider publishedUrlProvider)
IPublishedUrlProvider publishedUrlProvider,
IHostingEnvironment hosting)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, shortStringHelper, umbracoMapper, publishedUrlProvider)
{
_runtimeState = runtimeState;
_hosting = hosting;
}
public object GetStatus()
{
return new
{
Enabled = _runtimeState.Debug
Enabled = _hosting.IsDebugMode
};
}
}}

View File

@@ -134,6 +134,7 @@
<Compile Include="AppBuilderExtensions.cs" />
<Compile Include="AreaRegistrationContextExtensions.cs" />
<Compile Include="AspNet\AspNetHostingEnvironment.cs" />
<Compile Include="AspNet\AspNetHostingLifetime.cs" />
<Compile Include="AspNet\AspNetRequestAccessor.cs" />
<Compile Include="AspNet\AspNetSessionManager.cs" />
<Compile Include="AspNet\AspNetUserAgentProvider.cs" />

View File

@@ -32,7 +32,7 @@ namespace Umbraco.Web
? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connectionStrings, dbProviderFactoryCreator)
: new MainDomSemaphoreLock(logger, hostingEnvironment);
var mainDom = new MainDom(logger, hostingEnvironment, mainDomLock);
var mainDom = new MainDom(logger, mainDomLock);
var requestCache = new HttpRequestAppCache(() => HttpContext.Current?.Items);
var umbracoBootPermissionChecker = new AspNetUmbracoBootPermissionChecker();

View File

@@ -152,7 +152,9 @@ namespace Umbraco.Web
Umbraco.Composing.Current.Profiler,
Umbraco.Composing.Current.HostingEnvironment,
Umbraco.Composing.Current.BackOfficeInfo);
_factory = Current.Factory = _runtime.Boot(register);
_factory = Current.Factory = _runtime.Configure(register);
_runtime.Start();
}
// called by ASP.NET (auto event wireup) once per app domain

View File

@@ -150,7 +150,7 @@ namespace Umbraco.Web
{
var request = GetRequestFromContext();
//NOTE: the request can be null during app startup!
return Current.RuntimeState.Debug
return Current.HostingEnvironment.IsDebugMode
&& request != null
&& (string.IsNullOrEmpty(request["umbdebugshowtrace"]) == false
|| string.IsNullOrEmpty(request["umbdebug"]) == false

View File

@@ -143,12 +143,12 @@ namespace Umbraco.Web
//in case the user bypasses the installer and just bumps the web.config or client dependency config
//if in debug mode, always burst the cache
if (Current.RuntimeState.Debug)
if (Current.HostingEnvironment.IsDebugMode)
{
return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash();
}
var version = Current.RuntimeState.SemanticVersion.ToSemanticString();
var version = Current.UmbracoVersion.SemanticVersion.ToSemanticString();
return $"{version}.{ClientDependencySettings.Instance.Version}".GenerateHash();
}
}