From c291a6a065bfe70ae334209cb1c90be5f80a8856 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Fri, 13 Dec 2024 22:05:54 +0330 Subject: [PATCH] Use recommended NATS.Net client for Nats package (#2336) * Use recommnded NATS.Net client for nats package * Try resolve NatsConnection before INatsConnection * Update readme --- Directory.Packages.props | 2 +- .../NatsHealthCheckBuilderExtensions.cs | 79 +++------ .../HealthChecks.Nats.csproj | 2 +- src/HealthChecks.Nats/NatsHealthCheck.cs | 103 +---------- src/HealthChecks.Nats/NatsOptions.cs | 30 ---- src/HealthChecks.Nats/README.md | 32 +--- .../DependencyInjection/RegistrationTests.cs | 92 ++++++---- .../Functional/NatsHealthCheckTests.cs | 162 ++++++++---------- .../HealthChecks.Nats.approved.txt | 16 +- 9 files changed, 171 insertions(+), 347 deletions(-) delete mode 100644 src/HealthChecks.Nats/NatsOptions.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index f41297994f..5af2c85ee4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -72,7 +72,7 @@ - + diff --git a/src/HealthChecks.Nats/DependencyInjection/NatsHealthCheckBuilderExtensions.cs b/src/HealthChecks.Nats/DependencyInjection/NatsHealthCheckBuilderExtensions.cs index e0cfeb7e03..fb0a1b5e67 100644 --- a/src/HealthChecks.Nats/DependencyInjection/NatsHealthCheckBuilderExtensions.cs +++ b/src/HealthChecks.Nats/DependencyInjection/NatsHealthCheckBuilderExtensions.cs @@ -1,5 +1,6 @@ using HealthChecks.Nats; using Microsoft.Extensions.Diagnostics.HealthChecks; +using NATS.Client.Core; namespace Microsoft.Extensions.DependencyInjection; @@ -11,81 +12,41 @@ public static class NatsHealthCheckBuilderExtensions internal const string NAME = "nats"; /// - /// Add a health check for Nats. + /// Add a health check for Nats services. /// /// The . - /// The action to configure the Nats setup. - /// - /// The health check name. - /// Optional. - /// If the type name 'nats' will be used for the name. - /// + /// + /// An optional factory to obtain instance. + /// When not provided, is simply resolved from . + /// The health check name. Optional. If null the type name 'nats' will be used for the name. /// - /// The that should be reported when the health check fails. - /// Optional. - /// If then the default status of will be reported. - /// - /// A list of tags that can be used to filter sets of health checks. Optional. - /// An optional System.TimeSpan representing the timeout of the check. - /// The . - public static IHealthChecksBuilder AddNats( - this IHealthChecksBuilder builder, - Action? setup, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - var options = new NatsOptions(); - setup?.Invoke(options); - - builder.Services.AddSingleton(_ => new NatsHealthCheck(options)); - - return builder.Add(new HealthCheckRegistration( - name ?? NAME, - sp => sp.GetRequiredService(), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Nats. - /// - /// The . - /// The factory to configure the Nats setup. - /// - /// The health check name. - /// Optional. - /// If the type name 'nats' will be used for the name. - /// - /// - /// The that should be reported when the health check fails. - /// Optional. - /// If then the default status of will be reported. + /// The that should be reported when the health check fails. Optional. If null then + /// the default status of will be reported. /// /// A list of tags that can be used to filter sets of health checks. Optional. /// An optional representing the timeout of the check. - /// The . + /// The specified . public static IHealthChecksBuilder AddNats( this IHealthChecksBuilder builder, - Action? setup, - string? name = default, + Func? clientFactory = default, + string? name = NAME, HealthStatus? failureStatus = default, IEnumerable? tags = default, TimeSpan? timeout = default) { return builder.Add(new HealthCheckRegistration( name ?? NAME, - sp => - { - var options = new NatsOptions(); - setup?.Invoke(sp, options); - - return new NatsHealthCheck(options); - }, + sp => Factory(clientFactory, sp), failureStatus, tags, timeout)); + + static NatsHealthCheck Factory(Func? clientFactory, IServiceProvider sp) + { + // The user might have registered a factory for NatsConnection type, but not for the abstraction (INatsConnection). + // That is why we try to resolve NatsConnection first. + INatsConnection client = clientFactory?.Invoke(sp) ?? sp.GetService() ?? sp.GetRequiredService(); + return new(client); + } } } diff --git a/src/HealthChecks.Nats/HealthChecks.Nats.csproj b/src/HealthChecks.Nats/HealthChecks.Nats.csproj index 0726bbe5e0..6450c7780b 100644 --- a/src/HealthChecks.Nats/HealthChecks.Nats.csproj +++ b/src/HealthChecks.Nats/HealthChecks.Nats.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/HealthChecks.Nats/NatsHealthCheck.cs b/src/HealthChecks.Nats/NatsHealthCheck.cs index cf5fa2ab6c..9e444c2cb8 100644 --- a/src/HealthChecks.Nats/NatsHealthCheck.cs +++ b/src/HealthChecks.Nats/NatsHealthCheck.cs @@ -1,111 +1,26 @@ -using System.Text; using Microsoft.Extensions.Diagnostics.HealthChecks; -using NATS.Client; +using NATS.Client.Core; namespace HealthChecks.Nats; /// /// Health check for Nats Server. /// -/// -/// Relies on a static which provides factory methods to create -/// connections to NATS Servers, and a object connected to the NATS server. -/// -public sealed class NatsHealthCheck : IHealthCheck, IDisposable +public sealed class NatsHealthCheck(INatsConnection connection) : IHealthCheck { - private static readonly ConnectionFactory _connectionFactory = new(); + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) => + await TryConnectAsync(connection).ConfigureAwait(false); - private readonly NatsOptions _options; - - private IConnection? _connection; - - public NatsHealthCheck(NatsOptions natsOptions) - { - _options = Guard.ThrowIfNull(natsOptions); - } - - /// - public Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + private static async Task TryConnectAsync(INatsConnection natsConnection) { try { - // Create new connection if there is no existing one - IConnection? connection = _connection; - if (connection == null) - { -#pragma warning disable IDISP001 // Dispose created [false positive, https://github.com/DotNetAnalyzers/IDisposableAnalyzers/issues/515] - connection = CreateConnection(_options); -#pragma warning restore IDISP001 // Dispose created - var exchanged = Interlocked.CompareExchange(ref _connection, connection, null); - if (exchanged != null) // was set by other thread - { - connection.Dispose(); - connection = exchanged; - } - } - - // reset connection in case of stuck so the next HC call will establish it again - // https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/1544 - if (connection.State == ConnState.DISCONNECTED || connection.State == ConnState.CLOSED) - _connection = null; - - var healthCheckResult = GetHealthCheckResultFromState(connection); - return Task.FromResult(healthCheckResult); + await natsConnection.ConnectAsync().ConfigureAwait(false); + return HealthCheckResult.Healthy(); } - catch (Exception ex) - { - var unhealthy = new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - return Task.FromResult(unhealthy); - } - - IConnection CreateConnection(NatsOptions options) + catch (Exception) { - if (!string.IsNullOrWhiteSpace(options.CredentialsPath)) - return _connectionFactory.CreateConnection(options.Url, options.CredentialsPath); - if (!string.IsNullOrWhiteSpace(options.Jwt) && !string.IsNullOrWhiteSpace(options.PrivateNKey)) - return _connectionFactory.CreateConnection(options.Url, options.Jwt, options.PrivateNKey); - return _connectionFactory.CreateConnection(options.Url); + return HealthCheckResult.Unhealthy(); } - - HealthCheckResult GetHealthCheckResultFromState(IConnection connection) - { - string description = GetDescription(connection); - - return connection.State switch - { - ConnState.CONNECTED => HealthCheckResult.Healthy(description, GetStatsData(connection)), - ConnState.CONNECTING - or ConnState.RECONNECTING - or ConnState.DRAINING_SUBS - or ConnState.DRAINING_PUBS => HealthCheckResult.Degraded(description), - ConnState.CLOSED - or ConnState.DISCONNECTED => HealthCheckResult.Unhealthy(description), - _ => new HealthCheckResult(context.Registration.FailureStatus, description), - }; - } - - static string GetDescription(IConnection connection) - { - var sb = new StringBuilder(); - sb.AppendFormat("{0}: {1}; ", nameof(connection.ClientIP), connection.ClientIP); - if (!string.IsNullOrWhiteSpace(connection.ConnectedUrl)) - sb.AppendFormat("{0}: {1}; ", nameof(connection.ConnectedUrl), connection.ConnectedUrl); - sb.AppendFormat("{0}: {1}; ", nameof(connection.State), connection.State); - if (connection.SubscriptionCount != default) - sb.AppendFormat("{0}: {1}", nameof(connection.SubscriptionCount), connection.SubscriptionCount); - return sb.ToString(); - } - - static IReadOnlyDictionary GetStatsData(IConnection connection) => - new Dictionary - { - [nameof(connection.Stats.InMsgs)] = connection.Stats.InMsgs, - [nameof(connection.Stats.OutMsgs)] = connection.Stats.OutMsgs, - [nameof(connection.Stats.InBytes)] = connection.Stats.InBytes, - [nameof(connection.Stats.OutBytes)] = connection.Stats.OutBytes, - [nameof(connection.Stats.Reconnects)] = connection.Stats.Reconnects - }; } - - public void Dispose() => _connection?.Dispose(); } diff --git a/src/HealthChecks.Nats/NatsOptions.cs b/src/HealthChecks.Nats/NatsOptions.cs deleted file mode 100644 index b23e378dd5..0000000000 --- a/src/HealthChecks.Nats/NatsOptions.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace HealthChecks.Nats; - -/// -/// Options for . -/// -public class NatsOptions -{ - /// - /// A string containing the URL (or URLs) to the NATS Server. - /// - public string Url { get; set; } = "nats://demo.nats.io:4222"; - - /// - /// The full path to a chained credentials file. - /// - public string? CredentialsPath { get; set; } - - /// - /// The path to a user's public JWT credentials. - /// - public string? Jwt { get; set; } - - /// - /// The path to a file for user's private Nkey seed. - /// - /// - /// - /// - public string? PrivateNKey { get; set; } -} diff --git a/src/HealthChecks.Nats/README.md b/src/HealthChecks.Nats/README.md index f4351ba3cb..87e85467e7 100644 --- a/src/HealthChecks.Nats/README.md +++ b/src/HealthChecks.Nats/README.md @@ -1,7 +1,7 @@ # NATS Health Check This health check verifies the ability to communicate with a [NATS server](https://nats.io/about/). \ -It relies on `NATS.Client` package. \ +It relies on `NATS.Net` package. \ Latest tag for the [official dockerhub image](https://hub.docker.com/_/nats/) is `2.6.6`. ## Builder Extension @@ -9,21 +9,21 @@ Latest tag for the [official dockerhub image](https://hub.docker.com/_/nats/) is ```csharp public void ConfigureServices(IServiceCollection services) { + var options = NatsOpts.Default with + { + Url = "nats://demo.nats.io:4222" + }; + services + .AddSingleton(new NatsConnection(options)) .AddHealthChecks() - .AddNats(options => - { - options.Url = "nats://demo.nats.io:4222"; - options.CredentialsPath = "The full path to a chained credentials file."; - options.Jwt = "The path to a user's public JWT credentials."; - options.PrivateNKey = "The path to a file for user user's private Nkey seed."; - }); + .AddNats(); } ``` `Url` property is NATS server url and is **mandatory**. \ There is a demo instance `nats://demo.nats.io:4222` managed by nats.io and this is the default value for the url property. \ -The rest of the properties in `NatsOptions` are optional. \ +The rest of the properties in `NatsOpts` are optional. \ Docker image produces `nats://localhost:4222`. \ Url might also be a string containing multiple URLs to the NATS Server, e.g. `nats://localhost:4222, nats://localhost:8222`. @@ -31,20 +31,6 @@ See [NKeys](https://docs.nats.io/running-a-nats-service/configuration/securing_n See [Authenticating with a Credentials File](https://docs.nats.io/using-nats/developer/connecting/creds) for details related to the `CredentialsPath` property. -The setup action used by the extension method caters for all three overloads supplied by the Nats client to create a connection off of a connection factory. - -```csharp -namespace NATS.Client -{ - public sealed class ConnectionFactory - { - public IConnection CreateConnection(string url); - public IConnection CreateConnection(string url, string credentialsPath); - public IConnection CreateConnection(string url, string jwt, string privateNkey); - } -} -``` - Like all `IHealthChecksBuilder` extensions, all the following parameters have type `default` values and may be overridden: - `name`: The health check name. Default if not specified is `nats`. diff --git a/test/HealthChecks.Nats.Tests/DependencyInjection/RegistrationTests.cs b/test/HealthChecks.Nats.Tests/DependencyInjection/RegistrationTests.cs index c0fbacc962..da2be2a245 100644 --- a/test/HealthChecks.Nats.Tests/DependencyInjection/RegistrationTests.cs +++ b/test/HealthChecks.Nats.Tests/DependencyInjection/RegistrationTests.cs @@ -1,3 +1,4 @@ +using NATS.Client.Core; using static HealthChecks.Nats.Tests.Defines; namespace HealthChecks.Nats.Tests.DependencyInjection; @@ -5,67 +6,88 @@ namespace HealthChecks.Nats.Tests.DependencyInjection; public class nats_registration_should { [Fact] - public void add_health_check_when_properly_configured_locally() => - RegistrationFact( - _ => _.Url = DefaultLocalConnectionString, - check => check.ShouldBeOfType()); + public void add_health_check_when_properly_configured() + { + var services = new ServiceCollection(); + services.AddHealthChecks() + .AddNats(ClientFactory); - [Fact] - public void add_named_health_check_when_properly_configured_multiple_local_instances() => - RegistrationFact( - _ => _.Url = MixedLocalUrl, - check => check.ShouldBeOfType(), - name: CustomRegistrationName); + using var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetRequiredService>(); - [Fact] - public void add_health_check_when_demo_instance_properly_configured() => - RegistrationFact( - setup => setup.Url = DemoConnectionString, - check => check.ShouldBeOfType()); + var registration = options.Value.Registrations.First(); + var check = registration.Factory(serviceProvider); + + registration.Name.ShouldBe("nats"); + check.ShouldBeOfType(); + } [Fact] - public void add_health_check_with_service_provider() + public void add_named_health_check_when_properly_configured() { var services = new ServiceCollection(); - - services - .AddSingleton() - .AddHealthChecks() - .AddNats((sp, setup) => setup.Url = sp.GetRequiredService().ConnectionString); + services.AddHealthChecks() + .AddNats(clientFactory: ClientFactory, name: "custom-nats"); using var serviceProvider = services.BuildServiceProvider(); var options = serviceProvider.GetRequiredService>(); var registration = options.Value.Registrations.First(); - registration.Name.ShouldBe(NatsName); - var check = registration.Factory(serviceProvider); + registration.Name.ShouldBe("custom-nats"); check.ShouldBeOfType(); } - private void RegistrationFact(Action setup, Action assert, string? name = null) + [Theory] + [InlineData(false)] + [InlineData(true)] + public void add_health_check_when_properly_configured_by_using_singlton_regestration(bool registerAsAbstraction) { var services = new ServiceCollection(); - services.AddHealthChecks().AddNats(setup, name); + var natsOpts = NatsOpts.Default with + { + Url = DefaultLocalConnectionString, + }; + var connection = new NatsConnection(natsOpts); + + if (registerAsAbstraction) + { + services.AddSingleton(connection); + } + else + { + services.AddSingleton(connection); + } + + services.AddHealthChecks() + .AddNats(); - var serviceProvider = services.BuildServiceProvider(); + using var serviceProvider = services.BuildServiceProvider(); var options = serviceProvider.GetRequiredService>(); var registration = options.Value.Registrations.First(); - registration.Name.ShouldBe(name ?? NatsName); - var check = registration.Factory(serviceProvider); - assert(check); - } - private interface IDependency - { - string ConnectionString { get; } + registration.Name.ShouldBe("nats"); + check.ShouldBeOfType(); + + if (registerAsAbstraction) + { + serviceProvider.GetRequiredService(); + } + else + { + serviceProvider.GetRequiredService(); + } } - private class Dependency : IDependency + private NatsConnection ClientFactory(IServiceProvider _) { - public string ConnectionString => DemoConnectionString; + var options = NatsOpts.Default with + { + Url = DefaultLocalConnectionString, + }; + return new NatsConnection(options); } } diff --git a/test/HealthChecks.Nats.Tests/Functional/NatsHealthCheckTests.cs b/test/HealthChecks.Nats.Tests/Functional/NatsHealthCheckTests.cs index d8b4da6570..5aeb63d843 100644 --- a/test/HealthChecks.Nats.Tests/Functional/NatsHealthCheckTests.cs +++ b/test/HealthChecks.Nats.Tests/Functional/NatsHealthCheckTests.cs @@ -1,8 +1,6 @@ using System.Net; -using System.Text.Json; -using System.Text.Json.Serialization; -using HealthChecks.UI.Client; -using HealthChecks.UI.Core; +using NATS.Client.Core; +using NATS.Client.Hosting; using static HealthChecks.Nats.Tests.Defines; namespace HealthChecks.Nats.Tests.Functional; @@ -10,116 +8,98 @@ namespace HealthChecks.Nats.Tests.Functional; public class nats_healthcheck_should { [Fact] - public Task be_healthy_if_nats_is_available_locally() => - FactAsync( - setup => setup.Url = DefaultLocalConnectionString, - async response => response.StatusCode.ShouldBe(HttpStatusCode.OK, await response.Content.ReadAsStringAsync())); - - [Fact] - public Task be_healthy_for_official_demo_instance() => - FactAsync( - setup => setup.Url = DemoConnectionString, - async response => response.StatusCode.ShouldBe(HttpStatusCode.OK, await response.Content.ReadAsStringAsync())); - - [Fact] - public Task be_healthy_if_nats_is_available_and_has_custom_name() => - FactAsync( - setup => setup.Url = DefaultLocalConnectionString, - async response => response.StatusCode.ShouldBe(HttpStatusCode.OK, await response.Content.ReadAsStringAsync()), - name: "Demo"); - - [Fact] - public Task be_unhealthy_if_nats_endpoint_does_not_exist_or_is_offline() => - FactAsync( - setup => setup.Url = ConnectionStringDoesNotExistOrStopped, - async response => + public async Task be_healthy_when_nats_is_available_using_client_factory() + { + var webHostBuilder = new WebHostBuilder() + .ConfigureServices(services => { - response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable); - var content = await response.Content.ReadAsStringAsync(); - var report = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter() } })!; - report.Status.ShouldBe(UIHealthStatus.Unhealthy); - report.Entries["nats"].Exception.ShouldBe("Failed to connect"); + var options = NatsOpts.Default with + { + Url = DefaultLocalConnectionString, + }; + var natsConnection = new NatsConnection(options); - }); - - [Fact] - public Task be_unhealthy_if_nats_endpoint_is_bogus() => - FactAsync( - setup => setup.Url = "bogus", - async response => + services + .AddHealthChecks() + .AddNats( + clientFactory: sp => natsConnection, tags: new string[] { "nats" }); + }) + .Configure(app => { - response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable); - var content = await response.Content.ReadAsStringAsync(); - var report = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter() } })!; - report.Status.ShouldBe(UIHealthStatus.Unhealthy); - report.Entries["nats"].Exception.ShouldBe("Failed to connect"); + app.UseHealthChecks("/health", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("nats") + }); }); - [Fact] - public Task be_unhealthy_if_nats_is_available_but_credentials_path_doesnt_exist() => - FactAsync( - setup => - { - setup.Url = DefaultLocalConnectionString; - setup.CredentialsPath = CredentialsPathDoesnExist; - }, - response => response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable), - name: CredentialsPathDoesnExist); + using var server = new TestServer(webHostBuilder); - [Fact] - public Task be_unhealthy_if_nats_20_credentials_missing() => - FactAsync( - setup => - { - setup.Url = DefaultLocalConnectionString; - setup.CredentialsPath = string.Empty; - setup.Jwt = "jwt"; - setup.PrivateNKey = CredentialsPathDoesnExist; - }, - response => response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable), - name: CredentialsPathDoesnExist); + using var response = await server.CreateRequest("/health").GetAsync(); + + response.StatusCode.ShouldBe(HttpStatusCode.OK); + } - private async Task FactAsync(Action setupAction, Action assertAction, string? name = null) + [Fact] + public async Task be_healthy_when_nats_is_available_using_singleton() { var webHostBuilder = new WebHostBuilder() - .ConfigureServices(services => services + .ConfigureServices(services => + { + var options = NatsOpts.Default with + { + Url = DefaultLocalConnectionString, + }; + + services + .AddSingleton(new NatsConnection(options)) .AddHealthChecks() - .AddNats( - setupAction, - name: name, - tags: Tags)) - .Configure(ConfigureApplicationBuilder); + .AddNats(tags: new string[] { "nats" }); + }) + .Configure(app => + { + app.UseHealthChecks("/health", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("nats") + }); + }); using var server = new TestServer(webHostBuilder); - var response = await server.CreateRequest(HealthRequestRelativePath).GetAsync().ConfigureAwait(false); + using var response = await server.CreateRequest("/health").GetAsync(); - assertAction(response); + response.StatusCode.ShouldBe(HttpStatusCode.OK); } - private async Task FactAsync(Action setupAction, Func asyncAssertAction, string? name = null) + [Fact] + public async Task be_unhealthy_when_nats_is_unavailable() { var webHostBuilder = new WebHostBuilder() - .ConfigureServices(services => services + .ConfigureServices(services => + { + services .AddHealthChecks() .AddNats( - setupAction, - name: name, - tags: Tags)) - .Configure(ConfigureApplicationBuilder); + clientFactory: sp => + { + var options = NatsOpts.Default with + { + Url = ConnectionStringDoesNotExistOrStopped, + }; + return new NatsConnection(options); + }, tags: new string[] { "nats" }); + }) + .Configure(app => + { + app.UseHealthChecks("/health", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("nats") + }); + }); using var server = new TestServer(webHostBuilder); - var response = await server.CreateRequest(HealthRequestRelativePath).GetAsync().ConfigureAwait(false); + using var response = await server.CreateRequest("/health").GetAsync(); - await asyncAssertAction(response).ConfigureAwait(false); + response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable); } - - private void ConfigureApplicationBuilder(IApplicationBuilder app) => - app.UseHealthChecks(HealthRequestRelativePath, new HealthCheckOptions - { - Predicate = r => r.Tags.Contains(NatsName) || r.Name == NatsName, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, - AllowCachingResponses = false - }); } diff --git a/test/HealthChecks.Nats.Tests/HealthChecks.Nats.approved.txt b/test/HealthChecks.Nats.Tests/HealthChecks.Nats.approved.txt index a27f9084c3..f573601f11 100644 --- a/test/HealthChecks.Nats.Tests/HealthChecks.Nats.approved.txt +++ b/test/HealthChecks.Nats.Tests/HealthChecks.Nats.approved.txt @@ -1,25 +1,15 @@ namespace HealthChecks.Nats { - public sealed class NatsHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck, System.IDisposable + public sealed class NatsHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck { - public NatsHealthCheck(HealthChecks.Nats.NatsOptions natsOptions) { } + public NatsHealthCheck(NATS.Client.Core.INatsConnection connection) { } public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } - public void Dispose() { } - } - public class NatsOptions - { - public NatsOptions() { } - public string? CredentialsPath { get; set; } - public string? Jwt { get; set; } - public string? PrivateNKey { get; set; } - public string Url { get; set; } } } namespace Microsoft.Extensions.DependencyInjection { public static class NatsHealthCheckBuilderExtensions { - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddNats(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? setup, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddNats(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? setup, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddNats(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, string? name = "nats", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } } } \ No newline at end of file