v14: Async healthchecks (#17090)

* Make block editor base classes public

* Update BlockEditorValues.cs

Change to trigger a new build for #16774

* Make healthchecks fully async

* Updated obsolete comments to reference next but one major.

---------

Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
This commit is contained in:
Matt Brailsford
2025-01-31 15:13:49 +00:00
committed by GitHub
parent def9bd096f
commit 09b3bd14c0
17 changed files with 63 additions and 20 deletions

View File

@@ -61,7 +61,7 @@ public class ExecuteActionHealthCheckController : HealthCheckControllerBase
return BadRequest(invalidModelProblem);
}
HealthCheckStatus result = healthCheck.ExecuteAction(_umbracoMapper.Map<HealthCheckAction>(action)!);
HealthCheckStatus result = await healthCheck.ExecuteActionAsync(_umbracoMapper.Map<HealthCheckAction>(action)!);
return await Task.FromResult(Ok(_umbracoMapper.Map<HealthCheckResultResponseModel>(result)));
}

View File

@@ -39,6 +39,6 @@ public class CheckHealthCheckGroupController : HealthCheckGroupControllerBase
return HealthCheckGroupNotFound();
}
return await Task.FromResult(Ok(_healthCheckGroupPresentationFactory.CreateHealthCheckGroupWithResultViewModel(group)));
return Ok(await _healthCheckGroupPresentationFactory.CreateHealthCheckGroupWithResultViewModelAsync(group));
}
}

View File

@@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Mapping;
namespace Umbraco.Cms.Api.Management.Factories;
// TODO (V16): Make internal sealed.
public class HealthCheckGroupPresentationFactory : IHealthCheckGroupPresentationFactory
{
private readonly HealthChecksSettings _healthChecksSettings;
@@ -40,13 +41,21 @@ public class HealthCheckGroupPresentationFactory : IHealthCheckGroupPresentation
return groups;
}
[Obsolete("Use CreateHealthCheckGroupWithResultViewModelAsync instead. Will be removed in v17.")]
public HealthCheckGroupWithResultResponseModel CreateHealthCheckGroupWithResultViewModel(IGrouping<string?, HealthCheck> healthCheckGroup)
=> CreateHealthCheckGroupWithResultViewModelAsync(healthCheckGroup).GetAwaiter().GetResult();
[Obsolete("Use CreateHealthCheckGroupWithResultViewModelAsync instead. Will be removed in v17.")]
public HealthCheckWithResultPresentationModel CreateHealthCheckWithResultViewModel(HealthCheck healthCheck) =>
CreateHealthCheckWithResultViewModelAsync(healthCheck).GetAwaiter().GetResult();
public async Task<HealthCheckGroupWithResultResponseModel> CreateHealthCheckGroupWithResultViewModelAsync(IGrouping<string?, HealthCheck> healthCheckGroup)
{
var healthChecks = new List<HealthCheckWithResultPresentationModel>();
foreach (HealthCheck healthCheck in healthCheckGroup)
{
healthChecks.Add(CreateHealthCheckWithResultViewModel(healthCheck));
healthChecks.Add(await CreateHealthCheckWithResultViewModelAsync(healthCheck));
}
var healthCheckGroupViewModel = new HealthCheckGroupWithResultResponseModel
@@ -57,11 +66,11 @@ public class HealthCheckGroupPresentationFactory : IHealthCheckGroupPresentation
return healthCheckGroupViewModel;
}
public HealthCheckWithResultPresentationModel CreateHealthCheckWithResultViewModel(HealthCheck healthCheck)
public async Task<HealthCheckWithResultPresentationModel> CreateHealthCheckWithResultViewModelAsync(HealthCheck healthCheck)
{
_logger.LogDebug($"Running health check: {healthCheck.Name}");
IEnumerable<HealthCheckStatus> results = healthCheck.GetStatus().Result;
IEnumerable<HealthCheckStatus> results = await healthCheck.GetStatusAsync();
var healthCheckViewModel = new HealthCheckWithResultPresentationModel
{

View File

@@ -7,7 +7,19 @@ public interface IHealthCheckGroupPresentationFactory
{
IEnumerable<IGrouping<string?, HealthCheck>> CreateGroupingFromHealthCheckCollection();
[Obsolete("Use CreateHealthCheckGroupWithResultViewModelAsync instead. Will be removed in v17.")]
HealthCheckGroupWithResultResponseModel CreateHealthCheckGroupWithResultViewModel(IGrouping<string?, HealthCheck> healthCheckGroup);
[Obsolete("Use CreateHealthCheckGroupWithResultViewModelAsync instead. Will be removed in v17.")]
HealthCheckWithResultPresentationModel CreateHealthCheckWithResultViewModel(HealthCheck healthCheck);
Task<HealthCheckGroupWithResultResponseModel> CreateHealthCheckGroupWithResultViewModelAsync(IGrouping<string?, HealthCheck> healthCheckGroup)
#pragma warning disable CS0618 // Type or member is obsolete
=> Task.FromResult(CreateHealthCheckGroupWithResultViewModel(healthCheckGroup));
#pragma warning restore CS0618 // Type or member is obsolete
Task<HealthCheckWithResultPresentationModel> CreateHealthCheckWithResultViewModelAsync(HealthCheck healthCheck)
#pragma warning disable CS0618 // Type or member is obsolete
=> Task.FromResult(CreateHealthCheckWithResultViewModel(healthCheck));
#pragma warning restore CS0618 // Type or member is obsolete
}

View File

@@ -63,7 +63,7 @@ public abstract class AbstractSettingsCheck : HealthCheck
"healthcheck", "checkErrorMessageUnexpectedValue", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, ItemPath });
/// <inheritdoc />
public override Task<IEnumerable<HealthCheckStatus>> GetStatus()
public override Task<IEnumerable<HealthCheckStatus>> GetStatusAsync()
{
// update the successMessage with the CurrentValue
var successMessage = string.Format(CheckSuccessMessage, ItemPath, Values, CurrentValue);

View File

@@ -38,7 +38,7 @@ public class DatabaseIntegrityCheck : HealthCheck
/// <summary>
/// Get the status for this health check
/// </summary>
public override Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
Task.FromResult((IEnumerable<HealthCheckStatus>)new[] { CheckDocuments(false), CheckMedia(false) });
/// <inheritdoc />

View File

@@ -35,7 +35,7 @@ public class FolderAndFilePermissionsCheck : HealthCheck
/// <summary>
/// Get the status for this health check
/// </summary>
public override Task<IEnumerable<HealthCheckStatus>> GetStatus()
public override Task<IEnumerable<HealthCheckStatus>> GetStatusAsync()
{
_filePermissionHelper.RunFilePermissionTestSuite(
out Dictionary<FilePermissionTest, IEnumerable<string>> errors);

View File

@@ -62,7 +62,7 @@ public abstract class BaseHttpHeaderCheck : HealthCheck
/// <summary>
/// Get the status for this health check
/// </summary>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
await Task.WhenAll(CheckForHeader());
/// <summary>

View File

@@ -35,7 +35,7 @@ public class ExcessiveHeadersCheck : HealthCheck
/// <summary>
/// Get the status for this health check
/// </summary>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
await Task.WhenAll(CheckForHeaders());
/// <summary>

View File

@@ -43,7 +43,7 @@ public class HstsCheck : BaseHttpHeaderCheck
protected override string ReadMoreLink => Constants.HealthChecks.DocumentationLinks.Security.HstsCheck;
/// <inheritdoc />
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
new HealthCheckStatus[] { await CheckForHeader() };
/// <summary>

View File

@@ -46,7 +46,7 @@ public class HttpsCheck : HealthCheck
_hostingEnvironment = hostingEnvironment;
}
/// <inheritdoc />
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
await Task.WhenAll(
CheckIfCurrentSchemeIsHttps(),
CheckHttpsConfigurationSetting(),

View File

@@ -35,7 +35,7 @@ public class UmbracoApplicationUrlCheck : HealthCheck
/// <summary>
/// Get the status for this health check
/// </summary>
public override Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
Task.FromResult(CheckUmbracoApplicationUrl().Yield());
private HealthCheckStatus CheckUmbracoApplicationUrl()

View File

@@ -34,7 +34,7 @@ public class SmtpCheck : HealthCheck
/// <summary>
/// Get the status for this health check
/// </summary>
public override Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
Task.FromResult(CheckSmtpSettings().Yield());
/// <summary>

View File

@@ -46,12 +46,34 @@ public abstract class HealthCheck : IDiscoverable
/// If there are possible actions to take to rectify this check, this method must be overridden by a sub class
/// in order to explicitly provide those actions.
/// </remarks>
public abstract Task<IEnumerable<HealthCheckStatus>> GetStatus();
[Obsolete("Use GetStatusAsync instead. Will be removed in v17")]
public virtual Task<IEnumerable<HealthCheckStatus>> GetStatus() => Task.FromResult(Enumerable.Empty<HealthCheckStatus>());
/// <summary>
/// Get the status for this health check
/// </summary>
/// <returns></returns>
/// <remarks>
/// If there are possible actions to take to rectify this check, this method must be overridden by a sub class
/// in order to explicitly provide those actions.
/// </remarks>
#pragma warning disable CS0618 // Type or member is obsolete
public virtual Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() => GetStatus();
#pragma warning restore CS0618 // Type or member is obsolete
/// <summary>
/// Executes the action and returns it's status
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public abstract HealthCheckStatus ExecuteAction(HealthCheckAction action);
public virtual HealthCheckStatus ExecuteAction(HealthCheckAction action) =>
new HealthCheckStatus("Not implemented");
/// <summary>
/// Executes the action and returns it's status
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public virtual Task<HealthCheckStatus> ExecuteActionAsync(HealthCheckAction action) =>
Task.FromResult(ExecuteAction(action));
}

View File

@@ -26,7 +26,7 @@ public class HealthCheckResults
{
try
{
return await t.GetStatus();
return await t.GetStatusAsync();
}
catch (Exception ex)
{

View File

@@ -136,6 +136,6 @@ public class HealthCheckNotifierJobTests
{
public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => new("Check message");
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() => Enumerable.Empty<HealthCheckStatus>();
public override async Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() => Enumerable.Empty<HealthCheckStatus>();
}
}

View File

@@ -26,7 +26,7 @@ public class HealthCheckResultsTests
public override HealthCheckStatus ExecuteAction(HealthCheckAction action) =>
throw new NotImplementedException();
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
new List<HealthCheckStatus> { new(_message) { ResultType = _resultType } };
}
@@ -56,7 +56,7 @@ public class HealthCheckResultsTests
{
}
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() =>
public override async Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() =>
throw new Exception("Check threw exception");
}