From d8d736eddaef54219c592bc61aac90997e46bc75 Mon Sep 17 00:00:00 2001 From: Stephan Date: Sat, 13 Aug 2016 12:58:58 +0200 Subject: [PATCH] Resvolution - HealthCheckResolver --- src/Umbraco.Web/Current.cs | 4 ++ .../HealthCheck/HealthCheckCollection.cs | 12 +++++ .../HealthCheck/HealthCheckController.cs | 14 +++--- .../HealthCheck/HealthCheckResolver.cs | 48 ------------------- .../HeathCheckCollectionBuilder.cs | 36 ++++++++++++++ .../HealthCheck/IHealthCheckResolver.cs | 9 ---- src/Umbraco.Web/Umbraco.Web.csproj | 4 +- src/Umbraco.Web/WebBootManager.cs | 8 ++-- 8 files changed, 64 insertions(+), 71 deletions(-) create mode 100644 src/Umbraco.Web/HealthCheck/HealthCheckCollection.cs delete mode 100644 src/Umbraco.Web/HealthCheck/HealthCheckResolver.cs create mode 100644 src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs delete mode 100644 src/Umbraco.Web/HealthCheck/IHealthCheckResolver.cs diff --git a/src/Umbraco.Web/Current.cs b/src/Umbraco.Web/Current.cs index f483361151..b1b65cae7b 100644 --- a/src/Umbraco.Web/Current.cs +++ b/src/Umbraco.Web/Current.cs @@ -3,6 +3,7 @@ using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.Strings; +using Umbraco.Web.HealthCheck; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using CoreCurrent = Umbraco.Core.DependencyInjection.Current; @@ -114,6 +115,9 @@ namespace Umbraco.Web public static UrlProviderCollection UrlProviders => Container.GetInstance(); + public static HealthCheckCollectionBuilder HealthCheckCollectionBuilder + => Container.GetInstance(); + #endregion #region Core Getters diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckCollection.cs b/src/Umbraco.Web/HealthCheck/HealthCheckCollection.cs new file mode 100644 index 0000000000..070ee4303e --- /dev/null +++ b/src/Umbraco.Web/HealthCheck/HealthCheckCollection.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using Umbraco.Core.DependencyInjection; + +namespace Umbraco.Web.HealthCheck +{ + public class HealthCheckCollection : BuilderCollectionBase + { + public HealthCheckCollection(IEnumerable items) + : base(items) + { } + } +} diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs index 3a3230179a..886fe7f4a3 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs @@ -12,16 +12,16 @@ namespace Umbraco.Web.HealthCheck /// public class HealthCheckController : UmbracoAuthorizedJsonController { - private readonly IHealthCheckResolver _healthCheckResolver; + private readonly HealthCheckCollectionBuilder _builder; public HealthCheckController() { - _healthCheckResolver = HealthCheckResolver.Current; + _builder = Current.HealthCheckCollectionBuilder; } - public HealthCheckController(IHealthCheckResolver healthCheckResolver) + public HealthCheckController(HealthCheckCollectionBuilder builder) { - _healthCheckResolver = healthCheckResolver; + _builder = builder; } /// @@ -31,7 +31,7 @@ namespace Umbraco.Web.HealthCheck public object GetAllHealthChecks() { var context = new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current); - var groups = _healthCheckResolver.GetHealthChecks(context) + var groups = _builder.CreateCollection(context) .GroupBy(x => x.Group) .OrderBy(x => x.Key); var healthCheckGroups = new List(); @@ -53,7 +53,7 @@ namespace Umbraco.Web.HealthCheck public object GetStatus(Guid id) { var context = new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current); - var check = _healthCheckResolver.GetHealthChecks(context).FirstOrDefault(x => x.Id == id); + var check = _builder.CreateCollection(context).FirstOrDefault(x => x.Id == id); if (check == null) throw new InvalidOperationException("No health check found with ID " + id); return check.GetStatus(); @@ -63,7 +63,7 @@ namespace Umbraco.Web.HealthCheck public HealthCheckStatus ExecuteAction(HealthCheckAction action) { var context = new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current); - var check = _healthCheckResolver.GetHealthChecks(context).FirstOrDefault(x => x.Id == action.HealthCheckId); + var check = _builder.CreateCollection(context).FirstOrDefault(x => x.Id == action.HealthCheckId); if (check == null) throw new InvalidOperationException("No health check found with id " + action.HealthCheckId); return check.ExecuteAction(action); diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckResolver.cs b/src/Umbraco.Web/HealthCheck/HealthCheckResolver.cs deleted file mode 100644 index 1b7868432c..0000000000 --- a/src/Umbraco.Web/HealthCheck/HealthCheckResolver.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using LightInject; -using Umbraco.Core.Logging; -using Umbraco.Core.ObjectResolution; - -namespace Umbraco.Web.HealthCheck -{ - /// - /// Resolves all health check instances - /// - /// - /// Each instance scoped to the lifespan of the http request - /// - internal class HealthCheckResolver : ContainerLazyManyObjectsResolver, IHealthCheckResolver - { - public HealthCheckResolver(IServiceContainer container, ILogger logger, Func> types) - : base(container, logger, types, ObjectLifetimeScope.Transient) // do NOT change .Transient, see CreateValues below - { } - - protected override IEnumerable CreateValues(ObjectLifetimeScope scope) - { - // note: constructor dependencies do NOT work with lifetimes other than transient - // see https://github.com/seesharper/LightInject/issues/294 - EnsureTypesRegisterred(scope, container => - { - // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is - // the container, 'info' describes the ctor argument, and 'args' contains the args that - // were passed to GetInstance() - use first arg if it is the right type, - // - // for HealthCheckContext - container.RegisterConstructorDependency((factory, info, args) => args.Length > 0 ? args[0] as HealthCheckContext : null); - }); - - var arg = new object[] { _healthCheckContext }; - return InstanceTypes.Select(x => (HealthCheck) Container.GetInstance(x, arg)); - } - - private HealthCheckContext _healthCheckContext; - - public IEnumerable GetHealthChecks(HealthCheckContext context) - { - _healthCheckContext = context; - return Values; - } - } -} diff --git a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs new file mode 100644 index 0000000000..891231e4d0 --- /dev/null +++ b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs @@ -0,0 +1,36 @@ +using LightInject; +using Umbraco.Core.DependencyInjection; + +namespace Umbraco.Web.HealthCheck +{ + public class HealthCheckCollectionBuilder : LazyCollectionBuilderBase + { + public HealthCheckCollectionBuilder(IServiceContainer container) + : base(container) + { + // because collection builders are "per container" this ctor should run only once per container. + // + // note: constructor dependencies do NOT work with lifetimes other than transient + // see https://github.com/seesharper/LightInject/issues/294 + // + // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is + // the container, 'info' describes the ctor argument, and 'args' contains the args that + // were passed to GetInstance() - use first arg if it is the right type. + // + // for HealthCheckContext + container.RegisterConstructorDependency((factory, info, args) => args.Length > 0 ? args[0] as HealthCheckContext : null); + } + + protected override HealthCheckCollectionBuilder This => this; + + protected override void Initialize() + { + // nothing - do not register the collection + } + + public HealthCheckCollection CreateCollection(HealthCheckContext context) + { + return new HealthCheckCollection(CreateItems(context)); + } + } +} diff --git a/src/Umbraco.Web/HealthCheck/IHealthCheckResolver.cs b/src/Umbraco.Web/HealthCheck/IHealthCheckResolver.cs deleted file mode 100644 index 65afa67740..0000000000 --- a/src/Umbraco.Web/HealthCheck/IHealthCheckResolver.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Web.HealthCheck -{ - public interface IHealthCheckResolver - { - IEnumerable GetHealthChecks(HealthCheckContext context); - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 4c86e35b22..04797ecae6 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -161,6 +161,8 @@ + + @@ -201,12 +203,10 @@ - - diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index 9b2af1c05a..d07069dea6 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -545,12 +545,10 @@ namespace Umbraco.Web CultureDictionaryFactoryResolver.Current = new CultureDictionaryFactoryResolver(Container); Container.Register(); - HealthCheckResolver.Current = new HealthCheckResolver(Container, ProfilingLogger.Logger, - () => PluginManager.ResolveTypes()); - - // fixme - remove for NuCache else it fails + HealthCheckCollectionBuilder.Register(Container) + .AddProducer(() => PluginManager.ResolveTypes()) + .Exclude(); // fixme must remove else NuCache dies! // but we should also have one for NuCache AND NuCache should be a component that does all this - HealthCheckResolver.Current.RemoveType(); } ///