Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi provider support #151

Merged
merged 9 commits into from
Dec 15, 2022

Conversation

Arkatufus
Copy link
Contributor

@Arkatufus Arkatufus commented Dec 14, 2022

Add multi provider support with backward compatibility

@Arkatufus Arkatufus marked this pull request as ready for review December 14, 2022 17:30
Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, a very well thought out design and a very clean + backwards compat experience, but we do need the transports themselves before integrating this.

@@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="Akka.TestKit.Xunit" Version="$(AkkaVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we should upgrade to the latest here and reference this from common.props / Directory.Build.props but we can do that later

Comment on lines -27 to +31
return new AkkaHealthCheck(new HealthCheckSettings(system), system);
return new AkkaHealthCheck(system);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

liveness {
# List of liveness probe providers.
# Custom end-user provider can be created by implementing the IProbeProvider interface.
providers {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, that makes a lot of sense

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So users can add their own custom healthcheck providers? How would they go about doing that?

Copy link
Contributor Author

@Arkatufus Arkatufus Dec 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the probe providers and probe actors themselves are exposed as an ImmutableDictionary inside in the HealthCheck extension, each are keyed to the property name inside akka.healthcheck.liveness.providers or akka.healthcheck.readiness.providers.

To override an implementation, an end user need to implement the IProbeProvider interface, then assign it to the name they wanted. For example, to override the default provider, the user can set akka.healthcheck.readiness.providers.default = "Custom.Package.ProbeProvider, Custom.Package", or even have their custom probe living side by side with the default one:

akka.healthcheck.readiness.providers {
  default : "Akka.HealthCheck.Readiness.DefaultReadinessProvider, Akka.HealthCheck"
  custom : "Custom.Package.ProbeProvider, Custom.Package"
}

The "custom" provider can be accessed by using

var provider = HealthCheck.Get(system).ReadinessProviders["custom"];

The "custom" probe actor can be accessed by using

var readinessActor = HealthCheck.Get(system).ReadinessProbes["custom"]

same thing can be done with the default provider.

{
_statusTransport = statusTransport;
_livenessProbe = livenessProbe;
_livenessProbes = livenessProbes.Values.ToList();
_logInfo = log;

ReceiveAsync<LivenessStatus>(async status =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So one question - if we have multiple healthchecks:

  • Cluster
  • Remote
  • Persistence

Suppose persistence fails but cluster and remoting are still sending happy thoughts back to the LivenessTransportActor - do the happy thoughts from the two live probes override the "things are bad" signal from the probe that is failing? I.e. do we create a false negative here when that happens?

If so, shouldn't it be that we need some more robust boolean logic here:

  1. If any of the probes are in a failing state, the entire liveness check is failed
  2. If none of the probes are in a failing state, we're live

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're also going to need to apply this to readiness checks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, I'll implement this.

@@ -18,16 +21,16 @@ namespace Akka.HealthCheck.Transports
/// </summary>
public sealed class ReadinessTransportActor : ReceiveActor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments I made about the LivenessTransportActor also apply here

}

[Fact(DisplayName = "HealthCheck should load settings properly (compat)")]
public void HealthCheck_Should_load_settings_test_compat()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

akka.healthcheck.readiness.providers.default = ""Akka.HealthCheck.Tests.AkkaHealthCheckSpecs+FakeName, Akka.HealthCheck.Tests""
";

using (var system = ActorSystem.Create("foo", config))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -96,7 +128,35 @@ public async Task Should_load_default_AkkaHealthCheck()
}

[Fact(DisplayName = "Should load AkkaHealthCheck plugin and settings with custom providers")]
public async Task Should_load_misconfigured_AkkaHealthCheck()
public async Task Should_load_custom_AkkaHealthCheck()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

}
";

using (var system = ActorSystem.Create("foo", config))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor Author

@Arkatufus Arkatufus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self review for changes request.

{
_statusTransport = statusTransport;
_livenessProbe = livenessProbe;
var probeReverseLookup = livenessProbes.ToImmutableDictionary(kvp => kvp.Value, kvp => kvp.Key);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverse lookup dictionary

_logInfo = log;

ReceiveAsync<LivenessStatus>(async status =>
{
var probeName = probeReverseLookup[Sender];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lookup the probe key name

}
finally
{
cts.Dispose();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a CTS dispose and timeout check

try
{
if (status.IsLive)
writeStatus = await _statusTransport.Go($"[{probeName}] {status.StatusMessage}", cts.Token);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagged the status message with the probe name. Will this be good enough formatting wise?

@Aaronontheweb
Copy link
Member

@Arkatufus mind looking at the failing spec here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants