From 6b31ddad73ddbc7f882ee305f27c271538134a1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ognjen=20Kati=C4=87?= <44910579+ognjenkatic@users.noreply.github.com> Date: Fri, 7 Oct 2022 14:23:23 +0200 Subject: [PATCH 1/7] add health checks --- .gitignore | 1 + examples/ConductorSharp.ApiEnabled/Program.cs | 4 + .../Generated/Task.cs | 2 +- .../ConductorSharp.Engine.csproj | 1 + src/ConductorSharp.Engine/ExecutionManager.cs | 9 +- .../Extensions/ConductorSharpBuilder.cs | 3 + .../Extensions/WorkflowEngineBuilder.cs | 3 + .../Health/ConductorSharpHealthService.cs | 84 +++++++++++++++++++ .../Health/DeploymentHealthCheck.cs | 33 ++++++++ .../Health/IConductorSharpHealthService.cs | 12 +++ .../Health/IConductorSharpHealthUpdater.cs | 18 ++++ .../Service/DeploymentService.cs | 9 +- .../WorkflowEngineBackgroundService.cs | 21 ++++- 13 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs create mode 100644 src/ConductorSharp.Engine/Health/DeploymentHealthCheck.cs create mode 100644 src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs create mode 100644 src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs diff --git a/.gitignore b/.gitignore index b5457435..fd2d83a8 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ dist *.user .env *.xmldocs.xml +**/CONDUCTORSHARP_HEALTH.json \ No newline at end of file diff --git a/examples/ConductorSharp.ApiEnabled/Program.cs b/examples/ConductorSharp.ApiEnabled/Program.cs index dc2ddbe9..e8f1eb7b 100644 --- a/examples/ConductorSharp.ApiEnabled/Program.cs +++ b/examples/ConductorSharp.ApiEnabled/Program.cs @@ -1,5 +1,6 @@ using Autofac.Extensions.DependencyInjection; using ConductorSharp.ApiEnabled.Extensions; +using ConductorSharp.Engine.Health; using ConductorSharp.Engine.Util; using Serilog; @@ -12,6 +13,7 @@ // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +builder.Services.AddHealthChecks().AddCheck("deployment"); //Autofac dependency injection builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureApiEnabled(configuration); @@ -26,5 +28,7 @@ } app.UseAuthorization(); + app.MapControllers(); +app.MapHealthChecks("/health"); app.Run(); diff --git a/examples/ConductorSharp.Definitions/Generated/Task.cs b/examples/ConductorSharp.Definitions/Generated/Task.cs index d1afab87..68f05da4 100644 --- a/examples/ConductorSharp.Definitions/Generated/Task.cs +++ b/examples/ConductorSharp.Definitions/Generated/Task.cs @@ -28,7 +28,7 @@ public partial class EmailPrepareV1Output /// /// EMAIL_prepare /// - [OriginalName("EMAIL_prepare")] + [OriginalName("EMAILs_prepare")] public partial class EmailPrepareV1 : SimpleTaskModel { } public partial class CustomerGetV1Input : IRequest diff --git a/src/ConductorSharp.Engine/ConductorSharp.Engine.csproj b/src/ConductorSharp.Engine/ConductorSharp.Engine.csproj index bd020c6f..f3116732 100644 --- a/src/ConductorSharp.Engine/ConductorSharp.Engine.csproj +++ b/src/ConductorSharp.Engine/ConductorSharp.Engine.csproj @@ -18,6 +18,7 @@ + diff --git a/src/ConductorSharp.Engine/ExecutionManager.cs b/src/ConductorSharp.Engine/ExecutionManager.cs index 82fd77dc..67a203ae 100644 --- a/src/ConductorSharp.Engine/ExecutionManager.cs +++ b/src/ConductorSharp.Engine/ExecutionManager.cs @@ -12,10 +12,11 @@ using System.Threading.Tasks; using Autofac; using ConductorSharp.Engine.Util; +using ConductorSharp.Engine.Health; namespace ConductorSharp.Engine { - public class ExecutionManager + internal class ExecutionManager { private readonly SemaphoreSlim _semaphore; private readonly WorkerSetConfig _configuration; @@ -23,6 +24,7 @@ public class ExecutionManager private readonly ITaskService _taskManager; private readonly IEnumerable _registeredWorkers; private readonly ILifetimeScope _lifetimeScope; + private readonly IConductorSharpHealthUpdater _healthUpdater; // TODO: Implement polling strategy so that if there // are no requests incoming we poll less, and when queues are full @@ -38,7 +40,8 @@ public ExecutionManager( ILogger logger, ITaskService taskService, IEnumerable workerMappings, - ILifetimeScope lifetimeScope + ILifetimeScope lifetimeScope, + IConductorSharpHealthUpdater healthUpdater ) { _configuration = options; @@ -47,10 +50,12 @@ ILifetimeScope lifetimeScope _taskManager = taskService; _registeredWorkers = workerMappings; _lifetimeScope = lifetimeScope; + _healthUpdater = healthUpdater; } public async Task StartAsync(CancellationToken cancellationToken) { + await _healthUpdater.SetExecutionManagerStarted(); while (!cancellationToken.IsCancellationRequested) { var scheduleQueue = await _taskManager.GetAllQueues(); diff --git a/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs b/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs index 4d55e2b6..29331de7 100644 --- a/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs +++ b/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs @@ -1,5 +1,6 @@ using Autofac; using ConductorSharp.Engine.Behaviors; +using ConductorSharp.Engine.Health; using ConductorSharp.Engine.Interface; using ConductorSharp.Engine.Service; using ConductorSharp.Engine.Util; @@ -39,6 +40,8 @@ public IExecutionManagerBuilder AddExecutionManager(int maxConcurrentWorkers, in _builder.RegisterType().InstancePerLifetimeScope(); + _builder.RegisterType().AsImplementedInterfaces(); + return this; } diff --git a/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs b/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs index 3ddcc654..31629bf0 100644 --- a/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs +++ b/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs @@ -1,5 +1,6 @@ using Autofac; using ConductorSharp.Engine.Behaviors; +using ConductorSharp.Engine.Health; using ConductorSharp.Engine.Interface; using ConductorSharp.Engine.Service; using ConductorSharp.Engine.Util; @@ -44,6 +45,8 @@ public IWorkflowEngineExecutionManager AddExecutionManager( _builder.RegisterGeneric(typeof(ValidationBehavior<,>)).As(typeof(IPipelineBehavior<,>)); + _builder.RegisterType().AsImplementedInterfaces(); + return this; } } diff --git a/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs b/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs new file mode 100644 index 00000000..e84b3b5a --- /dev/null +++ b/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs @@ -0,0 +1,84 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace ConductorSharp.Engine.Health +{ + internal interface One { } + + public interface Two { } + + public class HealthData + { + public bool IsDeploymentStarted { get; set; } + public bool IsDeploymentCompleted { get; set; } + public bool IsExecutionManagerStarted { get; set; } + } + + public class ConductorSharpHealthService : IConductorSharpHealthService, IConductorSharpHealthUpdater + { + private static readonly SemaphoreSlim _semaphore = new(1); + + private const string HealthFileName = "CONDUCTORSHARP_HEALTH.json"; + + public async Task SetDeploymentCompleted() => await UpdateData(data => data.IsDeploymentCompleted = true); + + public async Task SetDeploymentStarted() => await UpdateData(data => data.IsDeploymentStarted = true); + + public async Task SetExecutionManagerStarted() => await UpdateData(data => data.IsExecutionManagerStarted = true); + + private async Task UpdateData(Action updateHealthData) + { + await _semaphore.WaitAsync(); + + try + { + var data = await GetHealthData(); + updateHealthData(data); + await WriteHealthData(data); + } + finally + { + _semaphore.Release(); + } + } + + public async Task GetHealthData() + { + await _semaphore.WaitAsync(); + + try + { + if (!File.Exists(HealthFileName)) + { + return new HealthData(); + } + else + { + return JsonConvert.DeserializeObject(await File.ReadAllTextAsync(HealthFileName)) ?? new HealthData(); + } + } + finally + { + _semaphore.Release(); + } + } + + private async Task WriteHealthData(HealthData healthData) => + await File.WriteAllTextAsync(HealthFileName, JsonConvert.SerializeObject(healthData)); + + public async Task ResetHealthData() => await WriteHealthData(new HealthData()); + + public Task RemoveHealthData() + { + if (File.Exists(HealthFileName)) + File.Delete(HealthFileName); + + return Task.CompletedTask; + } + } +} diff --git a/src/ConductorSharp.Engine/Health/DeploymentHealthCheck.cs b/src/ConductorSharp.Engine/Health/DeploymentHealthCheck.cs new file mode 100644 index 00000000..ec550d70 --- /dev/null +++ b/src/ConductorSharp.Engine/Health/DeploymentHealthCheck.cs @@ -0,0 +1,33 @@ +using Microsoft.Extensions.Diagnostics.HealthChecks; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace ConductorSharp.Engine.Health +{ + public class DeploymentHealthCheck : IHealthCheck + { + private readonly IConductorSharpHealthService _healthService; + + public DeploymentHealthCheck(IConductorSharpHealthService healthService) + { + _healthService = healthService; + } + + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + var healthData = await _healthService.GetHealthData(); + + if (healthData.IsDeploymentCompleted) + { + return new HealthCheckResult(HealthStatus.Healthy, "Deployment completed"); + } + else + { + return new HealthCheckResult(context.Registration.FailureStatus, "Deployment not completed"); + } + } + } +} diff --git a/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs b/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs new file mode 100644 index 00000000..bd3e7533 --- /dev/null +++ b/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace ConductorSharp.Engine.Health +{ + public interface IConductorSharpHealthService + { + Task GetHealthData(); + } +} diff --git a/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs b/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs new file mode 100644 index 00000000..2de70ca5 --- /dev/null +++ b/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace ConductorSharp.Engine.Health +{ + internal interface IConductorSharpHealthUpdater + { + Task ResetHealthData(); + Task RemoveHealthData(); + Task SetDeploymentCompleted(); + + Task SetDeploymentStarted(); + + Task SetExecutionManagerStarted(); + } +} diff --git a/src/ConductorSharp.Engine/Service/DeploymentService.cs b/src/ConductorSharp.Engine/Service/DeploymentService.cs index 6825b37b..f1aa3352 100644 --- a/src/ConductorSharp.Engine/Service/DeploymentService.cs +++ b/src/ConductorSharp.Engine/Service/DeploymentService.cs @@ -1,4 +1,5 @@ using ConductorSharp.Client.Service; +using ConductorSharp.Engine.Health; using ConductorSharp.Engine.Interface; using ConductorSharp.Engine.Model; using Microsoft.Extensions.Logging; @@ -6,20 +7,23 @@ namespace ConductorSharp.Engine.Service { - public class DeploymentService : IDeploymentService + internal class DeploymentService : IDeploymentService { private readonly IMetadataService _metadataService; private readonly ILogger _logger; + private readonly IConductorSharpHealthUpdater _healthUpdater; - public DeploymentService(IMetadataService metadataService, ILogger logger) + public DeploymentService(IMetadataService metadataService, ILogger logger, IConductorSharpHealthUpdater healthUpdater) { _metadataService = metadataService; _logger = logger; + _healthUpdater = healthUpdater; } public async Task Deploy(Deployment deployment) { + await _healthUpdater.SetDeploymentStarted(); _logger.LogInformation("Deploying conductor definitions"); if (deployment.TaskDefinitions.Count > 0) @@ -35,6 +39,7 @@ public async Task Deploy(Deployment deployment) // TODO: Add registration for event handlers _logger.LogInformation("Finished deploying conductor definitions"); + await _healthUpdater.SetDeploymentCompleted(); } public async Task Remove(Deployment deployment) diff --git a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs index 89dee1dd..d0d3ce85 100644 --- a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs +++ b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs @@ -1,22 +1,30 @@ -using ConductorSharp.Engine.Interface; +using ConductorSharp.Engine.Health; +using ConductorSharp.Engine.Interface; using Microsoft.Extensions.Hosting; using System.Threading; using System.Threading.Tasks; namespace ConductorSharp.Engine.Service { - public class WorkflowEngineBackgroundService : IHostedService + internal class WorkflowEngineBackgroundService : IHostedService { private readonly IDeploymentService _deploymentService; private readonly ExecutionManager _executionManager; private readonly ModuleDeployment _deployment; + private readonly IConductorSharpHealthUpdater _healthUpdater; private Task _executingTask; - public WorkflowEngineBackgroundService(IDeploymentService deploymentService, ExecutionManager executionManager, ModuleDeployment deployment) + public WorkflowEngineBackgroundService( + IDeploymentService deploymentService, + ExecutionManager executionManager, + ModuleDeployment deployment, + IConductorSharpHealthUpdater healthUpdater + ) { _deploymentService = deploymentService; _executionManager = executionManager; _deployment = deployment; + _healthUpdater = healthUpdater; } public Task StartAsync(CancellationToken cancellationToken) @@ -27,10 +35,15 @@ public Task StartAsync(CancellationToken cancellationToken) private async Task RunAsync(CancellationToken cancellationToken) { + await _healthUpdater.ResetHealthData(); await _deploymentService.Deploy(_deployment); await _executionManager.StartAsync(cancellationToken); } - public async Task StopAsync(CancellationToken cancellationToken) => await _executingTask; + public async Task StopAsync(CancellationToken cancellationToken) + { + _healthUpdater.RemoveHealthData().Wait(); + await _executingTask; + } } } From 019fd1277cafef76d9185878365cce87862bb287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ognjen=20Kati=C4=87?= <44910579+ognjenkatic@users.noreply.github.com> Date: Fri, 7 Oct 2022 14:28:13 +0200 Subject: [PATCH 2/7] add missing comma --- src/ConductorSharp.Engine/ExecutionManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConductorSharp.Engine/ExecutionManager.cs b/src/ConductorSharp.Engine/ExecutionManager.cs index 40e5abe2..2b4d4c49 100644 --- a/src/ConductorSharp.Engine/ExecutionManager.cs +++ b/src/ConductorSharp.Engine/ExecutionManager.cs @@ -35,7 +35,7 @@ public ExecutionManager( ITaskService taskService, IEnumerable workerMappings, ILifetimeScope lifetimeScope, - IConductorSharpHealthUpdater healthUpdater + IConductorSharpHealthUpdater healthUpdater, IPollTimingStrategy pollTimingStrategy, IPollOrderStrategy pollOrderStrategy ) From 9bd6450794400d35465552d24eebe4167d1bafbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ognjen=20Kati=C4=87?= <44910579+ognjenkatic@users.noreply.github.com> Date: Fri, 7 Oct 2022 14:28:40 +0200 Subject: [PATCH 3/7] add missing comma --- .../Service/WorkflowEngineBackgroundService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs index cd6a8f07..3c2d27f1 100644 --- a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs +++ b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs @@ -20,7 +20,7 @@ internal class WorkflowEngineBackgroundService : IHostedService, IDisposable private readonly CancellationTokenSource _stoppingCts = new(); public WorkflowEngineBackgroundService( - IConductorSharpHealthUpdater healthUpdater + IConductorSharpHealthUpdater healthUpdater, ILogger logger, IHostApplicationLifetime hostApplicationLifetime, IDeploymentService deploymentService, From bafdaeb330ae08d03b723454dd586cb55d786542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ognjen=20Kati=C4=87?= <44910579+ognjenkatic@users.noreply.github.com> Date: Fri, 7 Oct 2022 15:01:25 +0200 Subject: [PATCH 4/7] update services --- examples/ConductorSharp.ApiEnabled/Program.cs | 2 +- src/ConductorSharp.Engine/ExecutionManager.cs | 4 -- ...hCheck.cs => ConductorSharpHealthCheck.cs} | 12 ++-- .../Health/ConductorSharpHealthService.cs | 62 +++++++++---------- .../Health/IConductorSharpHealthService.cs | 3 +- .../Health/IConductorSharpHealthUpdater.cs | 12 ++-- .../Service/DeploymentService.cs | 6 +- .../WorkflowEngineBackgroundService.cs | 6 +- 8 files changed, 48 insertions(+), 59 deletions(-) rename src/ConductorSharp.Engine/Health/{DeploymentHealthCheck.cs => ConductorSharpHealthCheck.cs} (69%) diff --git a/examples/ConductorSharp.ApiEnabled/Program.cs b/examples/ConductorSharp.ApiEnabled/Program.cs index e8f1eb7b..a1ee324e 100644 --- a/examples/ConductorSharp.ApiEnabled/Program.cs +++ b/examples/ConductorSharp.ApiEnabled/Program.cs @@ -13,7 +13,7 @@ // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); -builder.Services.AddHealthChecks().AddCheck("deployment"); +builder.Services.AddHealthChecks().AddCheck("running"); //Autofac dependency injection builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureApiEnabled(configuration); diff --git a/src/ConductorSharp.Engine/ExecutionManager.cs b/src/ConductorSharp.Engine/ExecutionManager.cs index 2b4d4c49..e8cefe68 100644 --- a/src/ConductorSharp.Engine/ExecutionManager.cs +++ b/src/ConductorSharp.Engine/ExecutionManager.cs @@ -25,7 +25,6 @@ internal class ExecutionManager private readonly ITaskService _taskManager; private readonly IEnumerable _registeredWorkers; private readonly ILifetimeScope _lifetimeScope; - private readonly IConductorSharpHealthUpdater _healthUpdater; private readonly IPollTimingStrategy _pollTimingStrategy; private readonly IPollOrderStrategy _pollOrderStrategy; @@ -35,7 +34,6 @@ public ExecutionManager( ITaskService taskService, IEnumerable workerMappings, ILifetimeScope lifetimeScope, - IConductorSharpHealthUpdater healthUpdater, IPollTimingStrategy pollTimingStrategy, IPollOrderStrategy pollOrderStrategy ) @@ -46,14 +44,12 @@ IPollOrderStrategy pollOrderStrategy _taskManager = taskService; _registeredWorkers = workerMappings; _lifetimeScope = lifetimeScope; - _healthUpdater = healthUpdater; _pollTimingStrategy = pollTimingStrategy; _pollOrderStrategy = pollOrderStrategy; } public async Task StartAsync(CancellationToken cancellationToken) { - await _healthUpdater.SetExecutionManagerStarted(); var currentSleepInterval = _configuration.SleepInterval; while (!cancellationToken.IsCancellationRequested) diff --git a/src/ConductorSharp.Engine/Health/DeploymentHealthCheck.cs b/src/ConductorSharp.Engine/Health/ConductorSharpHealthCheck.cs similarity index 69% rename from src/ConductorSharp.Engine/Health/DeploymentHealthCheck.cs rename to src/ConductorSharp.Engine/Health/ConductorSharpHealthCheck.cs index ec550d70..462c0b3b 100644 --- a/src/ConductorSharp.Engine/Health/DeploymentHealthCheck.cs +++ b/src/ConductorSharp.Engine/Health/ConductorSharpHealthCheck.cs @@ -7,26 +7,26 @@ namespace ConductorSharp.Engine.Health { - public class DeploymentHealthCheck : IHealthCheck + public class ConductorSharpHealthCheck : IHealthCheck { private readonly IConductorSharpHealthService _healthService; - public DeploymentHealthCheck(IConductorSharpHealthService healthService) + public ConductorSharpHealthCheck(IConductorSharpHealthService healthService) { _healthService = healthService; } public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { - var healthData = await _healthService.GetHealthData(); + var healthData = await _healthService.GetHealthData(cancellationToken); - if (healthData.IsDeploymentCompleted) + if (healthData.IsExecutionManagerRunning) { - return new HealthCheckResult(HealthStatus.Healthy, "Deployment completed"); + return new HealthCheckResult(HealthStatus.Healthy, "Deployment has been completed and Execution Manager is running"); } else { - return new HealthCheckResult(context.Registration.FailureStatus, "Deployment not completed"); + return new HealthCheckResult(context.Registration.FailureStatus, "Execution Manager is not running"); } } } diff --git a/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs b/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs index e84b3b5a..20a7fcd5 100644 --- a/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs +++ b/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs @@ -8,15 +8,9 @@ namespace ConductorSharp.Engine.Health { - internal interface One { } - - public interface Two { } - public class HealthData { - public bool IsDeploymentStarted { get; set; } - public bool IsDeploymentCompleted { get; set; } - public bool IsExecutionManagerStarted { get; set; } + public bool IsExecutionManagerRunning { get; set; } } public class ConductorSharpHealthService : IConductorSharpHealthService, IConductorSharpHealthUpdater @@ -25,41 +19,32 @@ public class ConductorSharpHealthService : IConductorSharpHealthService, IConduc private const string HealthFileName = "CONDUCTORSHARP_HEALTH.json"; - public async Task SetDeploymentCompleted() => await UpdateData(data => data.IsDeploymentCompleted = true); - - public async Task SetDeploymentStarted() => await UpdateData(data => data.IsDeploymentStarted = true); + public async Task UnsetExecutionManagerRunning(CancellationToken cancellationToken = default) => + await UpdateData(data => data.IsExecutionManagerRunning = false, cancellationToken); - public async Task SetExecutionManagerStarted() => await UpdateData(data => data.IsExecutionManagerStarted = true); + public async Task SetExecutionManagerRunning(CancellationToken cancellationToken = default) => + await UpdateData(data => data.IsExecutionManagerRunning = true, cancellationToken); - private async Task UpdateData(Action updateHealthData) + private async Task UpdateData(Action updateHealthData, CancellationToken cancellationToken = default) { - await _semaphore.WaitAsync(); - - try - { - var data = await GetHealthData(); - updateHealthData(data); - await WriteHealthData(data); - } - finally - { - _semaphore.Release(); - } + var data = await GetHealthData(cancellationToken); + updateHealthData(data); + await WriteHealthData(data, cancellationToken); } - public async Task GetHealthData() + public async Task GetHealthData(CancellationToken cancellationToken = default) { - await _semaphore.WaitAsync(); - try { + await _semaphore.WaitAsync(cancellationToken); if (!File.Exists(HealthFileName)) { return new HealthData(); } else { - return JsonConvert.DeserializeObject(await File.ReadAllTextAsync(HealthFileName)) ?? new HealthData(); + return JsonConvert.DeserializeObject(await File.ReadAllTextAsync(HealthFileName, cancellationToken)) + ?? new HealthData(); } } finally @@ -68,17 +53,28 @@ public async Task GetHealthData() } } - private async Task WriteHealthData(HealthData healthData) => - await File.WriteAllTextAsync(HealthFileName, JsonConvert.SerializeObject(healthData)); + private async Task WriteHealthData(HealthData healthData, CancellationToken cancellationToken = default) + { + try + { + await _semaphore.WaitAsync(cancellationToken); + await File.WriteAllTextAsync(HealthFileName, JsonConvert.SerializeObject(healthData), cancellationToken); + } + finally + { + _semaphore.Release(); + } + } - public async Task ResetHealthData() => await WriteHealthData(new HealthData()); + public async Task ResetHealthData(CancellationToken cancellationToken = default) => + await WriteHealthData(new HealthData(), cancellationToken); - public Task RemoveHealthData() + public void RemoveHealthData() { if (File.Exists(HealthFileName)) File.Delete(HealthFileName); - return Task.CompletedTask; + return; } } } diff --git a/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs b/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs index bd3e7533..6a4ec694 100644 --- a/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs +++ b/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace ConductorSharp.Engine.Health { public interface IConductorSharpHealthService { - Task GetHealthData(); + Task GetHealthData(CancellationToken cancellationToken = default); } } diff --git a/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs b/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs index 2de70ca5..ee1078ca 100644 --- a/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs +++ b/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs @@ -1,18 +1,16 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace ConductorSharp.Engine.Health { internal interface IConductorSharpHealthUpdater { - Task ResetHealthData(); - Task RemoveHealthData(); - Task SetDeploymentCompleted(); - - Task SetDeploymentStarted(); - - Task SetExecutionManagerStarted(); + Task ResetHealthData(CancellationToken cancellationToken = default); + void RemoveHealthData(); + Task SetExecutionManagerRunning(CancellationToken cancellationToken = default); + Task UnsetExecutionManagerRunning(CancellationToken cancellationToken = default); } } diff --git a/src/ConductorSharp.Engine/Service/DeploymentService.cs b/src/ConductorSharp.Engine/Service/DeploymentService.cs index f1aa3352..59d4f814 100644 --- a/src/ConductorSharp.Engine/Service/DeploymentService.cs +++ b/src/ConductorSharp.Engine/Service/DeploymentService.cs @@ -12,18 +12,15 @@ internal class DeploymentService : IDeploymentService private readonly IMetadataService _metadataService; private readonly ILogger _logger; - private readonly IConductorSharpHealthUpdater _healthUpdater; - public DeploymentService(IMetadataService metadataService, ILogger logger, IConductorSharpHealthUpdater healthUpdater) + public DeploymentService(IMetadataService metadataService, ILogger logger) { _metadataService = metadataService; _logger = logger; - _healthUpdater = healthUpdater; } public async Task Deploy(Deployment deployment) { - await _healthUpdater.SetDeploymentStarted(); _logger.LogInformation("Deploying conductor definitions"); if (deployment.TaskDefinitions.Count > 0) @@ -39,7 +36,6 @@ public async Task Deploy(Deployment deployment) // TODO: Add registration for event handlers _logger.LogInformation("Finished deploying conductor definitions"); - await _healthUpdater.SetDeploymentCompleted(); } public async Task Remove(Deployment deployment) diff --git a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs index 3c2d27f1..a998f4f6 100644 --- a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs +++ b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs @@ -52,12 +52,14 @@ private async Task RunAsync(CancellationToken cancellationToken) { try { - await _healthUpdater.ResetHealthData(); + await _healthUpdater.ResetHealthData(cancellationToken); await _deploymentService.Deploy(_deployment); + await _healthUpdater.SetExecutionManagerRunning(cancellationToken); await _executionManager.StartAsync(cancellationToken); } catch (Exception exception) { + await _healthUpdater.UnsetExecutionManagerRunning(); _logger.LogCritical(exception, "Workflow Engine Background Service encountered an error"); throw; } @@ -69,7 +71,7 @@ private async Task RunAsync(CancellationToken cancellationToken) public async Task StopAsync(CancellationToken cancellationToken) { - _healthUpdater.RemoveHealthData().Wait(); + _healthUpdater.RemoveHealthData(); if (_executingTask == null) { return; From c913048eb52c485174eba6dade791a9abff996d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ognjen=20Kati=C4=87?= <44910579+ognjenkatic@users.noreply.github.com> Date: Fri, 7 Oct 2022 15:06:08 +0200 Subject: [PATCH 5/7] update settings --- examples/ConductorSharp.Definitions/Generated/Task.cs | 2 +- examples/ConductorSharp.Definitions/appsettings.json | 2 +- examples/ConductorSharp.NoApi/appsettings.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ConductorSharp.Definitions/Generated/Task.cs b/examples/ConductorSharp.Definitions/Generated/Task.cs index 68f05da4..d1afab87 100644 --- a/examples/ConductorSharp.Definitions/Generated/Task.cs +++ b/examples/ConductorSharp.Definitions/Generated/Task.cs @@ -28,7 +28,7 @@ public partial class EmailPrepareV1Output /// /// EMAIL_prepare /// - [OriginalName("EMAILs_prepare")] + [OriginalName("EMAIL_prepare")] public partial class EmailPrepareV1 : SimpleTaskModel { } public partial class CustomerGetV1Input : IRequest diff --git a/examples/ConductorSharp.Definitions/appsettings.json b/examples/ConductorSharp.Definitions/appsettings.json index fa169067..c3c5ffd3 100644 --- a/examples/ConductorSharp.Definitions/appsettings.json +++ b/examples/ConductorSharp.Definitions/appsettings.json @@ -5,6 +5,6 @@ "LongPollInterval": 100, "MaxConcurrentWorkers": 10, "SleepInterval": 500, - "PreventErrorOnBadRequest": false + "PreventErrorOnBadRequest": true } } diff --git a/examples/ConductorSharp.NoApi/appsettings.json b/examples/ConductorSharp.NoApi/appsettings.json index c3c5ffd3..fa169067 100644 --- a/examples/ConductorSharp.NoApi/appsettings.json +++ b/examples/ConductorSharp.NoApi/appsettings.json @@ -5,6 +5,6 @@ "LongPollInterval": 100, "MaxConcurrentWorkers": 10, "SleepInterval": 500, - "PreventErrorOnBadRequest": true + "PreventErrorOnBadRequest": false } } From 05b9dcac474e6712258d42ed4f3ff5c0a0521395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ognjen=20Kati=C4=87?= <44910579+ognjenkatic@users.noreply.github.com> Date: Fri, 7 Oct 2022 19:55:29 +0200 Subject: [PATCH 6/7] add services --- .../ConductorSharp.Definitions/Program.cs | 2 + examples/ConductorSharp.NoApi/Program.cs | 2 + .../Extensions/ConductorSharpBuilder.cs | 9 ++++- .../Extensions/IExecutionManagerBuilder.cs | 4 +- .../Extensions/WorkflowEngineBuilder.cs | 1 - ....cs => ConductorSharpFileHealthService.cs} | 2 +- .../Health/IConductorSharpHealthService.cs | 4 ++ .../Health/IConductorSharpHealthUpdater.cs | 16 -------- .../Health/InMemoryHealthService.cs | 38 +++++++++++++++++++ .../WorkflowEngineBackgroundService.cs | 14 +++---- 10 files changed, 65 insertions(+), 27 deletions(-) rename src/ConductorSharp.Engine/Health/{ConductorSharpHealthService.cs => ConductorSharpFileHealthService.cs} (96%) delete mode 100644 src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs create mode 100644 src/ConductorSharp.Engine/Health/InMemoryHealthService.cs diff --git a/examples/ConductorSharp.Definitions/Program.cs b/examples/ConductorSharp.Definitions/Program.cs index 206b32bd..46959966 100644 --- a/examples/ConductorSharp.Definitions/Program.cs +++ b/examples/ConductorSharp.Definitions/Program.cs @@ -2,6 +2,7 @@ using Autofac.Extensions.DependencyInjection; using ConductorSharp.Definitions; using ConductorSharp.Engine.Extensions; +using ConductorSharp.Engine.Health; using MediatR.Extensions.Autofac.DependencyInjection; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -39,6 +40,7 @@ longPollInterval: configuration.GetValue("Conductor:LongPollInterval"), domain: configuration.GetValue("Conductor:WorkerDomain") ) + .SetHealthCheckService() .AddPipelines(pipelines => { pipelines.AddRequestResponseLogging(); diff --git a/examples/ConductorSharp.NoApi/Program.cs b/examples/ConductorSharp.NoApi/Program.cs index 1f712530..3072a646 100644 --- a/examples/ConductorSharp.NoApi/Program.cs +++ b/examples/ConductorSharp.NoApi/Program.cs @@ -1,6 +1,7 @@ using Autofac; using Autofac.Extensions.DependencyInjection; using ConductorSharp.Engine.Extensions; +using ConductorSharp.Engine.Health; using ConductorSharp.NoApi; using MediatR.Extensions.Autofac.DependencyInjection; using Microsoft.Extensions.Configuration; @@ -39,6 +40,7 @@ longPollInterval: configuration.GetValue("Conductor:LongPollInterval"), domain: configuration.GetValue("Conductor:WorkerDomain") ) + .SetHealthCheckService() .AddPipelines(pipelines => { pipelines.AddContextLogging(); diff --git a/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs b/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs index b6e3a19e..6fec8141 100644 --- a/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs +++ b/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs @@ -41,7 +41,8 @@ public IExecutionManagerBuilder AddExecutionManager(int maxConcurrentWorkers, in _builder.RegisterType().InstancePerLifetimeScope(); - _builder.RegisterType().AsImplementedInterfaces(); + _builder.RegisterType().As(); + _builder.RegisterType().As(); _builder.RegisterType().As(); @@ -61,5 +62,11 @@ public void AddRequestResponseLogging() => public void AddValidation() => _builder.RegisterGeneric(typeof(ValidationBehavior<,>)).As(typeof(IPipelineBehavior<,>)); public void AddContextLogging() => _builder.RegisterGeneric(typeof(ContextLoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>)); + + public IExecutionManagerBuilder SetHealthCheckService() where T : IConductorSharpHealthService + { + _builder.RegisterType().As(); + return this; + } } } diff --git a/src/ConductorSharp.Engine/Extensions/IExecutionManagerBuilder.cs b/src/ConductorSharp.Engine/Extensions/IExecutionManagerBuilder.cs index 0ce51831..f758aff4 100644 --- a/src/ConductorSharp.Engine/Extensions/IExecutionManagerBuilder.cs +++ b/src/ConductorSharp.Engine/Extensions/IExecutionManagerBuilder.cs @@ -1,4 +1,5 @@ -using System; +using ConductorSharp.Engine.Health; +using System; using System.Collections.Generic; using System.Text; @@ -7,5 +8,6 @@ namespace ConductorSharp.Engine.Extensions public interface IExecutionManagerBuilder { IExecutionManagerBuilder AddPipelines(Action pipelines); + IExecutionManagerBuilder SetHealthCheckService() where T : IConductorSharpHealthService; } } diff --git a/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs b/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs index 739ac486..82b6dd16 100644 --- a/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs +++ b/src/ConductorSharp.Engine/Extensions/WorkflowEngineBuilder.cs @@ -46,7 +46,6 @@ public IWorkflowEngineExecutionManager AddExecutionManager( _builder.RegisterGeneric(typeof(ValidationBehavior<,>)).As(typeof(IPipelineBehavior<,>)); - _builder.RegisterType().AsImplementedInterfaces(); _builder.RegisterType().As(); _builder.RegisterType().As(); diff --git a/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs b/src/ConductorSharp.Engine/Health/ConductorSharpFileHealthService.cs similarity index 96% rename from src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs rename to src/ConductorSharp.Engine/Health/ConductorSharpFileHealthService.cs index 20a7fcd5..eb4195e4 100644 --- a/src/ConductorSharp.Engine/Health/ConductorSharpHealthService.cs +++ b/src/ConductorSharp.Engine/Health/ConductorSharpFileHealthService.cs @@ -13,7 +13,7 @@ public class HealthData public bool IsExecutionManagerRunning { get; set; } } - public class ConductorSharpHealthService : IConductorSharpHealthService, IConductorSharpHealthUpdater + public class ConductorSharpFileHealthService : IConductorSharpHealthService { private static readonly SemaphoreSlim _semaphore = new(1); diff --git a/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs b/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs index 6a4ec694..bfe22d5e 100644 --- a/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs +++ b/src/ConductorSharp.Engine/Health/IConductorSharpHealthService.cs @@ -9,5 +9,9 @@ namespace ConductorSharp.Engine.Health public interface IConductorSharpHealthService { Task GetHealthData(CancellationToken cancellationToken = default); + Task ResetHealthData(CancellationToken cancellationToken = default); + void RemoveHealthData(); + Task SetExecutionManagerRunning(CancellationToken cancellationToken = default); + Task UnsetExecutionManagerRunning(CancellationToken cancellationToken = default); } } diff --git a/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs b/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs deleted file mode 100644 index ee1078ca..00000000 --- a/src/ConductorSharp.Engine/Health/IConductorSharpHealthUpdater.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ConductorSharp.Engine.Health -{ - internal interface IConductorSharpHealthUpdater - { - Task ResetHealthData(CancellationToken cancellationToken = default); - void RemoveHealthData(); - Task SetExecutionManagerRunning(CancellationToken cancellationToken = default); - Task UnsetExecutionManagerRunning(CancellationToken cancellationToken = default); - } -} diff --git a/src/ConductorSharp.Engine/Health/InMemoryHealthService.cs b/src/ConductorSharp.Engine/Health/InMemoryHealthService.cs new file mode 100644 index 00000000..fd485d36 --- /dev/null +++ b/src/ConductorSharp.Engine/Health/InMemoryHealthService.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace ConductorSharp.Engine.Health +{ + public class InMemoryHealthService : IConductorSharpHealthService + { + private static bool _isExecutionManagerRunning; + + public Task GetHealthData(CancellationToken cancellationToken = default) + { + return Task.FromResult(new HealthData { IsExecutionManagerRunning = _isExecutionManagerRunning }); + } + + public void RemoveHealthData() { } + + public Task ResetHealthData(CancellationToken cancellationToken = default) + { + _isExecutionManagerRunning = false; + return Task.CompletedTask; + } + + public Task SetExecutionManagerRunning(CancellationToken cancellationToken = default) + { + _isExecutionManagerRunning = true; + return Task.CompletedTask; + } + + public Task UnsetExecutionManagerRunning(CancellationToken cancellationToken = default) + { + _isExecutionManagerRunning = false; + return Task.CompletedTask; + } + } +} diff --git a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs index a998f4f6..a5d2c30b 100644 --- a/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs +++ b/src/ConductorSharp.Engine/Service/WorkflowEngineBackgroundService.cs @@ -15,12 +15,12 @@ internal class WorkflowEngineBackgroundService : IHostedService, IDisposable private readonly IDeploymentService _deploymentService; private readonly ExecutionManager _executionManager; private readonly ModuleDeployment _deployment; - private readonly IConductorSharpHealthUpdater _healthUpdater; + private readonly IConductorSharpHealthService _healthService; private Task _executingTask; private readonly CancellationTokenSource _stoppingCts = new(); public WorkflowEngineBackgroundService( - IConductorSharpHealthUpdater healthUpdater, + IConductorSharpHealthService healthService, ILogger logger, IHostApplicationLifetime hostApplicationLifetime, IDeploymentService deploymentService, @@ -33,7 +33,7 @@ ModuleDeployment deployment _deploymentService = deploymentService; _executionManager = executionManager; _deployment = deployment; - _healthUpdater = healthUpdater; + _healthService = healthService; } public Task StartAsync(CancellationToken cancellationToken) @@ -52,14 +52,14 @@ private async Task RunAsync(CancellationToken cancellationToken) { try { - await _healthUpdater.ResetHealthData(cancellationToken); + _healthService.RemoveHealthData(); await _deploymentService.Deploy(_deployment); - await _healthUpdater.SetExecutionManagerRunning(cancellationToken); + await _healthService.SetExecutionManagerRunning(cancellationToken); await _executionManager.StartAsync(cancellationToken); } catch (Exception exception) { - await _healthUpdater.UnsetExecutionManagerRunning(); + await _healthService.UnsetExecutionManagerRunning(); _logger.LogCritical(exception, "Workflow Engine Background Service encountered an error"); throw; } @@ -71,7 +71,7 @@ private async Task RunAsync(CancellationToken cancellationToken) public async Task StopAsync(CancellationToken cancellationToken) { - _healthUpdater.RemoveHealthData(); + _healthService.RemoveHealthData(); if (_executingTask == null) { return; From 46e17ef2cafa1b7cf90e19b821fba564d6db803e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ognjen=20Kati=C4=87?= <44910579+ognjenkatic@users.noreply.github.com> Date: Fri, 7 Oct 2022 21:19:27 +0200 Subject: [PATCH 7/7] make healthcheck services singleton --- docker-compose.override.yml | 23 +++++++++++++++++++ .../Extensions/HostConfiguration.cs | 2 ++ .../ConductorSharp.Definitions/Program.cs | 2 +- examples/ConductorSharp.NoApi/Program.cs | 2 +- .../Extensions/ConductorSharpBuilder.cs | 4 ++-- ...eHealthService.cs => FileHealthService.cs} | 4 ++-- 6 files changed, 31 insertions(+), 6 deletions(-) rename src/ConductorSharp.Engine/Health/{ConductorSharpFileHealthService.cs => FileHealthService.cs} (94%) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 17cc4b44..f505adaa 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,7 +1,30 @@ version: '3.4' services: + + conductorsharp.noapi: + healthcheck: + test: bash -c "[ -f /app/CONDUCTORSHARP_HEALTH.json ]" + interval: 60s + retries: 5 + start_period: 20s + timeout: 10s + + conductorsharp.definitions: + healthcheck: + test: bash -c "[ -f /app/CONDUCTORSHARP_HEALTH.json ]" + interval: 60s + retries: 5 + start_period: 20s + timeout: 10s + conductorsharp.apienabled: + healthcheck: + test: bash -c "[ -f /app/CONDUCTORSHARP_HEALTH.json ]" + interval: 60s + retries: 5 + start_period: 20s + timeout: 10s environment: - ASPNETCORE_ENVIRONMENT=Development ports: diff --git a/examples/ConductorSharp.ApiEnabled/Extensions/HostConfiguration.cs b/examples/ConductorSharp.ApiEnabled/Extensions/HostConfiguration.cs index 5ea3188d..d31a44bf 100644 --- a/examples/ConductorSharp.ApiEnabled/Extensions/HostConfiguration.cs +++ b/examples/ConductorSharp.ApiEnabled/Extensions/HostConfiguration.cs @@ -1,5 +1,6 @@ using Autofac; using ConductorSharp.Engine.Extensions; +using ConductorSharp.Engine.Health; using MediatR.Extensions.Autofac.DependencyInjection; namespace ConductorSharp.ApiEnabled.Extensions; @@ -22,6 +23,7 @@ public static IHostBuilder ConfigureApiEnabled(this IHostBuilder hostBuilder, Co longPollInterval: configuration.GetValue("Conductor:LongPollInterval"), domain: configuration.GetValue("Conductor:WorkerDomain") ) + .SetHealthCheckService() .AddPipelines(pipelines => { pipelines.AddContextLogging(); diff --git a/examples/ConductorSharp.Definitions/Program.cs b/examples/ConductorSharp.Definitions/Program.cs index 46959966..02c88e92 100644 --- a/examples/ConductorSharp.Definitions/Program.cs +++ b/examples/ConductorSharp.Definitions/Program.cs @@ -40,7 +40,7 @@ longPollInterval: configuration.GetValue("Conductor:LongPollInterval"), domain: configuration.GetValue("Conductor:WorkerDomain") ) - .SetHealthCheckService() + .SetHealthCheckService() .AddPipelines(pipelines => { pipelines.AddRequestResponseLogging(); diff --git a/examples/ConductorSharp.NoApi/Program.cs b/examples/ConductorSharp.NoApi/Program.cs index 3072a646..07209c68 100644 --- a/examples/ConductorSharp.NoApi/Program.cs +++ b/examples/ConductorSharp.NoApi/Program.cs @@ -40,7 +40,7 @@ longPollInterval: configuration.GetValue("Conductor:LongPollInterval"), domain: configuration.GetValue("Conductor:WorkerDomain") ) - .SetHealthCheckService() + .SetHealthCheckService() .AddPipelines(pipelines => { pipelines.AddContextLogging(); diff --git a/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs b/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs index 6fec8141..2bca4b78 100644 --- a/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs +++ b/src/ConductorSharp.Engine/Extensions/ConductorSharpBuilder.cs @@ -41,7 +41,7 @@ public IExecutionManagerBuilder AddExecutionManager(int maxConcurrentWorkers, in _builder.RegisterType().InstancePerLifetimeScope(); - _builder.RegisterType().As(); + _builder.RegisterType().As().SingleInstance(); _builder.RegisterType().As(); @@ -65,7 +65,7 @@ public void AddRequestResponseLogging() => public IExecutionManagerBuilder SetHealthCheckService() where T : IConductorSharpHealthService { - _builder.RegisterType().As(); + _builder.RegisterType().As().SingleInstance(); return this; } } diff --git a/src/ConductorSharp.Engine/Health/ConductorSharpFileHealthService.cs b/src/ConductorSharp.Engine/Health/FileHealthService.cs similarity index 94% rename from src/ConductorSharp.Engine/Health/ConductorSharpFileHealthService.cs rename to src/ConductorSharp.Engine/Health/FileHealthService.cs index eb4195e4..02e6962c 100644 --- a/src/ConductorSharp.Engine/Health/ConductorSharpFileHealthService.cs +++ b/src/ConductorSharp.Engine/Health/FileHealthService.cs @@ -13,9 +13,9 @@ public class HealthData public bool IsExecutionManagerRunning { get; set; } } - public class ConductorSharpFileHealthService : IConductorSharpHealthService + public class FileHealthService : IConductorSharpHealthService { - private static readonly SemaphoreSlim _semaphore = new(1); + private readonly SemaphoreSlim _semaphore = new(1); private const string HealthFileName = "CONDUCTORSHARP_HEALTH.json";