Resvolution - HealthCheckResolver

This commit is contained in:
Stephan
2016-08-13 12:58:58 +02:00
parent ebaeb98a4a
commit d8d736edda
8 changed files with 64 additions and 71 deletions

View File

@@ -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<UrlProviderCollection>();
public static HealthCheckCollectionBuilder HealthCheckCollectionBuilder
=> Container.GetInstance<HealthCheckCollectionBuilder>();
#endregion
#region Core Getters

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
using Umbraco.Core.DependencyInjection;
namespace Umbraco.Web.HealthCheck
{
public class HealthCheckCollection : BuilderCollectionBase<HealthCheck>
{
public HealthCheckCollection(IEnumerable<HealthCheck> items)
: base(items)
{ }
}
}

View File

@@ -12,16 +12,16 @@ namespace Umbraco.Web.HealthCheck
/// </summary>
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;
}
/// <summary>
@@ -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<HealthCheckGroup>();
@@ -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);

View File

@@ -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
{
/// <summary>
/// Resolves all health check instances
/// </summary>
/// <remarks>
/// Each instance scoped to the lifespan of the http request
/// </remarks>
internal class HealthCheckResolver : ContainerLazyManyObjectsResolver<HealthCheckResolver, HealthCheck>, IHealthCheckResolver
{
public HealthCheckResolver(IServiceContainer container, ILogger logger, Func<IEnumerable<Type>> types)
: base(container, logger, types, ObjectLifetimeScope.Transient) // do NOT change .Transient, see CreateValues below
{ }
protected override IEnumerable<HealthCheck> 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<HealthCheck> GetHealthChecks(HealthCheckContext context)
{
_healthCheckContext = context;
return Values;
}
}
}

View File

@@ -0,0 +1,36 @@
using LightInject;
using Umbraco.Core.DependencyInjection;
namespace Umbraco.Web.HealthCheck
{
public class HealthCheckCollectionBuilder : LazyCollectionBuilderBase<HealthCheckCollectionBuilder, HealthCheckCollection, HealthCheck>
{
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));
}
}
}

View File

@@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Web.HealthCheck
{
public interface IHealthCheckResolver
{
IEnumerable<HealthCheck> GetHealthChecks(HealthCheckContext context);
}
}

View File

@@ -161,6 +161,8 @@
<Compile Include="AspNetHttpContextAccessor.cs" />
<Compile Include="Cache\ContentCacheRefresher.cs" />
<Compile Include="Current.cs" />
<Compile Include="HealthCheck\HealthCheckCollection.cs" />
<Compile Include="HealthCheck\HeathCheckCollectionBuilder.cs" />
<Compile Include="HybridAccessorBase.cs" />
<Compile Include="HybridUmbracoContextAccessor.cs" />
<Compile Include="HttpContextUmbracoContextAccessor.cs" />
@@ -201,12 +203,10 @@
<Compile Include="Macros\MacroRenderer.cs" />
<Compile Include="Macros\UserControlMacroEngine.cs" />
<Compile Include="HealthCheck\HealthCheckGroup.cs" />
<Compile Include="HealthCheck\HealthCheckResolver.cs" />
<Compile Include="HealthCheck\HealthCheck.cs" />
<Compile Include="HealthCheck\HealthCheckStatus.cs" />
<Compile Include="HealthCheck\Checks\Security\HttpsCheck.cs" />
<Compile Include="Macros\XsltMacroEngine.cs" />
<Compile Include="HealthCheck\IHealthCheckResolver.cs" />
<Compile Include="HealthCheck\StatusResultType.cs" />
<Compile Include="HealthCheck\Checks\DataIntegrity\XmlDataIntegrityHealthCheck.cs" />
<Compile Include="Models\ContentEditing\GetAvailableCompositionsFilter.cs" />

View File

@@ -545,12 +545,10 @@ namespace Umbraco.Web
CultureDictionaryFactoryResolver.Current = new CultureDictionaryFactoryResolver(Container);
Container.Register<ICultureDictionaryFactory, DefaultCultureDictionaryFactory>();
HealthCheckResolver.Current = new HealthCheckResolver(Container, ProfilingLogger.Logger,
() => PluginManager.ResolveTypes<HealthCheck.HealthCheck>());
// fixme - remove for NuCache else it fails
HealthCheckCollectionBuilder.Register(Container)
.AddProducer(() => PluginManager.ResolveTypes<HealthCheck.HealthCheck>())
.Exclude<XmlDataIntegrityHealthCheck>(); // 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<XmlDataIntegrityHealthCheck>();
}
/// <summary>