From 0282e14803798998fbe416b96fe56be6849d1144 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Wed, 30 Oct 2024 22:02:18 +0330 Subject: [PATCH] Try to use qdrant-client health check --- .../Aspire.Hosting.Qdrant.csproj | 4 +++ .../QdrantBuilderExtensions.cs | 17 +++++------- .../AspireQdrantExtensions.cs | 26 +++---------------- .../Aspire.Qdrant.Client/QdrantHealthCheck.cs | 9 ++++--- .../QdrantContainerFixture.cs | 2 +- 5 files changed, 20 insertions(+), 38 deletions(-) diff --git a/src/Aspire.Hosting.Qdrant/Aspire.Hosting.Qdrant.csproj b/src/Aspire.Hosting.Qdrant/Aspire.Hosting.Qdrant.csproj index 27699a9b97..4db984da75 100644 --- a/src/Aspire.Hosting.Qdrant/Aspire.Hosting.Qdrant.csproj +++ b/src/Aspire.Hosting.Qdrant/Aspire.Hosting.Qdrant.csproj @@ -20,4 +20,8 @@ + + + + diff --git a/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs b/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs index f92ca39021..e1178d34ff 100644 --- a/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs +++ b/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs @@ -8,6 +8,7 @@ using Aspire.Qdrant.Client; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; +using Qdrant.Client; namespace Aspire.Hosting; @@ -47,20 +48,21 @@ public static IResourceBuilder AddQdrant(this IDistributed ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $"{name}-Key", special: false); var qdrant = new QdrantServerResource(name, apiKeyParameter); - HttpClient? httpClient = null; + QdrantClient? qdrantClient = null; builder.Eventing.Subscribe(qdrant, async (@event, ct) => { var connectionString = await qdrant.HttpConnectionStringExpression.GetValueAsync(ct).ConfigureAwait(false) ?? throw new DistributedApplicationException($"ConnectionStringAvailableEvent was published for the '{qdrant.Name}' resource but the connection string was null."); - httpClient = CreateQdrantHttpClient(connectionString); + + qdrantClient = CreateQdrantClient(connectionString); }); var healthCheckKey = $"{name}_check"; builder.Services.AddHealthChecks() .Add(new HealthCheckRegistration( healthCheckKey, - sp => new QdrantHealthCheck(httpClient!), + sp => new QdrantHealthCheck(qdrantClient!), failureStatus: default, tags: default, timeout: default)); @@ -142,7 +144,7 @@ public static IResourceBuilder WithReference(this IR return builder; } - private static HttpClient CreateQdrantHttpClient(string? connectionString) + private static QdrantClient CreateQdrantClient(string? connectionString) { if (connectionString is null) { @@ -174,12 +176,7 @@ private static HttpClient CreateQdrantHttpClient(string? connectionString) } } - var client = new HttpClient(); - client.BaseAddress = endpoint; - if (key is not null) - { - client.DefaultRequestHeaders.Add("Api-Key", key); - } + var client = new QdrantClient(endpoint!, key); return client; } } diff --git a/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs b/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs index d63aeb9c12..5be78f0a37 100644 --- a/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs +++ b/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs @@ -84,33 +84,13 @@ private static void AddQdrant( if (!settings.DisableHealthChecks) { - // use http client for register health check - var httpClientName = serviceKey is null ? "qdrant-healthchecks" : $"qdrant-healthchecks_{connectionName}"; - builder.Services.AddHttpClient( - httpClientName, - client => - { - if (settings.Endpoint is null) - { - throw new InvalidOperationException( - $"A QdrantClient could not be configured. Ensure valid connection information was provided in 'ConnectionStrings:{connectionName}' or either " + - $"{nameof(settings.Endpoint)} must be provided " + - $"in the '{DefaultConfigSectionName}' or '{DefaultConfigSectionName}:{connectionName}' configuration section."); - } - - client.BaseAddress = settings.Endpoint; - - if (settings.Key is not null) - { - client.DefaultRequestHeaders.Add("Api-Key", settings.Key); - } - }); - var healthCheckName = serviceKey is null ? "Qdrant.Client" : $"Qdrant.Client_{connectionName}"; builder.TryAddHealthCheck(new HealthCheckRegistration( healthCheckName, - sp => new QdrantHealthCheck(sp.GetRequiredService().CreateClient(httpClientName)), + sp => new QdrantHealthCheck(serviceKey is null ? + sp.GetRequiredService() : + sp.GetRequiredKeyedService(serviceKey)), failureStatus: null, tags: null, timeout: settings.HealthCheckTimeout > 0 ? TimeSpan.FromMilliseconds(settings.HealthCheckTimeout.Value) : null diff --git a/src/Components/Aspire.Qdrant.Client/QdrantHealthCheck.cs b/src/Components/Aspire.Qdrant.Client/QdrantHealthCheck.cs index e9593b9b8c..fea18e5618 100644 --- a/src/Components/Aspire.Qdrant.Client/QdrantHealthCheck.cs +++ b/src/Components/Aspire.Qdrant.Client/QdrantHealthCheck.cs @@ -2,13 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Extensions.Diagnostics.HealthChecks; +using Qdrant.Client; namespace Aspire.Qdrant.Client; internal sealed class QdrantHealthCheck : IHealthCheck { - private readonly HttpClient _client; + private readonly QdrantClient _client; - public QdrantHealthCheck(HttpClient client) + public QdrantHealthCheck(QdrantClient client) { ArgumentNullException.ThrowIfNull(client, nameof(client)); _client = client; @@ -18,9 +19,9 @@ public async Task CheckHealthAsync(HealthCheckContext context { try { - var response = await _client.GetAsync("/readyz", cancellationToken).ConfigureAwait(false); + var response = await _client.HealthAsync(cancellationToken).ConfigureAwait(false); - return response.IsSuccessStatusCode + return !(response is null || response.Title is null) ? HealthCheckResult.Healthy() : new HealthCheckResult(HealthStatus.Unhealthy); } diff --git a/tests/Aspire.Qdrant.Client.Tests/QdrantContainerFixture.cs b/tests/Aspire.Qdrant.Client.Tests/QdrantContainerFixture.cs index 89c456f1c6..a33c570137 100644 --- a/tests/Aspire.Qdrant.Client.Tests/QdrantContainerFixture.cs +++ b/tests/Aspire.Qdrant.Client.Tests/QdrantContainerFixture.cs @@ -32,7 +32,7 @@ public async Task InitializeAsync() _apiKey = PasswordGenerator.Generate(minLength: 16, lower: true, upper: true, numeric: true, special: false, minLower: 1, minUpper: 1, minNumeric: 1, minSpecial: 0); Container = new ContainerBuilder() - .WithImage($"{TestConstants.AspireTestContainerRegistry}/{QdrantContainerImageTags.Image}:{QdrantContainerImageTags.Tag}") + .WithImage($"{ComponentTestConstants.AspireTestContainerRegistry}/{QdrantContainerImageTags.Image}:{QdrantContainerImageTags.Tag}") .WithPortBinding(6333, true) .WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(r => r.ForPort(6333))) .WithEnvironment("QDRANT__SERVICE__API_KEY", _apiKey)