Readiness Healthcheck with warmup C#

Viewed 532

I am using Readiness healthchecks for my project and want to add a warmup period to it. Dependency Injection is being used to get the warmup task from the Kernel but I am not able to get it because the Readiness Healthcheck is being initialized before the IKernel it seems. I am getting the follow error:

Unable to resolve service for type 'IKernel' while attempting to activate 'Project.Ranking.API.HealthCheck.RankingReadinessHealthCheck'.

How does one use a class to warm up the pod before it is being used. I have not been able to find a working example where someone warms up before the endpoints are available.

UPDATE:

Core.Library Startup.CS

public void CoreConfigureServices(IServiceCollection services) 
{
... other code

            services.AddHealthChecks()
                .AddIdentityServer("https://identity.example.com")
                .AddCheck<IReadinessHealthCheck>("Readiness", failureStatus: null)
                .AddCheck<ILivenessHealthCheck>("Liveness", failureStatus: null);

            services.AddSingleton<ILivenessHealthCheck, LivenessHealthCheck>();
}

public void CoreConfigure(IApplicationBuilder app, IHostEnvironment env)
{
... other code

app.UseHealthChecks("/healthcheck/live", new HealthCheckOptions()
            {
                Predicate = check => check.Name == "Liveness"
            });

            app.UseHealthChecks("/healthcheck/ready", new HealthCheckOptions()
            {
                Predicate = check => check.Name == "Readiness",
            });
}

API Startup.CS

public void ConfigureServices(IServiceCollection services)
{
   CoreConfigureServices(services);

... other code

services.AddSingleton<Core.Library.IReadinessHealthCheck, ReadinessHealthCheck>();
}

public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
CoreConfigure(app, env);

... other code

//Here used to be the warm up, but this is used in the liveness probe and i want to warm up in the readiness probe
//Kernel.Get<IWarmupTask>().Initialize();

Kernel.Bind<IReadinessHealthCheck>().To<ReadinessHealthCheck>();
}

Core.Library BaseReadinessHealthCheck.cs

public abstract class BaseReadinessHealthCheck : IReadinessHealthCheck
    {
        public BaseReadinessHealthCheck()
        {
        }

        private bool StartupTaskCompleted { get; set; } = false;

        public abstract void WarmUp();

        public void CompleteTask()
        {
            StartupTaskCompleted = true;
        }

        public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            //start tasks
            if (!StartupTaskCompleted)
            {
                Task.Run(() => WarmUp());
            }

            if (StartupTaskCompleted)
            {
                return Task.FromResult(HealthCheckResult.Healthy("The startup task is finished."));
            }

            return Task.FromResult(HealthCheckResult.Unhealthy("The startup task is still running."));
        }
    }

API ReadinessHealthCheck.CS

public class ReadinessHealthCheck : ReadinessHealthCheck
    {
        public ReadinessHealthCheck(IKernel kernel) : base(kernel)
        {
        }

        public override void WarmUp()
        {
// I want to do a warmup here, where it calls IWarmupTask 

            CompleteTask();
        }
    }
0 Answers
Related