File: ServiceBusHealthCheck.cs
Web Access
Project: src\src\Aspire.Hosting.Azure.ServiceBus\Aspire.Hosting.Azure.ServiceBus.csproj (Aspire.Hosting.Azure.ServiceBus)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Azure.Messaging.ServiceBus;
using Microsoft.Extensions.Diagnostics.HealthChecks;
 
namespace Aspire.Hosting.Azure.ServiceBus;
 
/// <summary>
/// The standard ServiceBus health check is not sufficient since it requires predefined knowledge that there is at least one queue or one topic.
/// At the time we register the health check, we may not know if there are any of each.
/// </summary>
internal sealed class ServiceBusHealthCheck : IHealthCheck
{
    private readonly Func<ServiceBusClient> _clientFactory;
    private readonly Func<string?> _nameFactory;
 
    public ServiceBusHealthCheck(Func<ServiceBusClient> clientFactory, Func<string?> nameFactory)
    {
        ArgumentNullException.ThrowIfNull(clientFactory);
        ArgumentNullException.ThrowIfNull(nameFactory);
 
        _clientFactory = clientFactory;
        _nameFactory = nameFactory;
    }
 
    /// <inheritdoc />
    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // The emulator doesn't support ServiceBusAdministrationClient which would be the preferred method to check the health of the service.
        // A ServiceBusClient is used instead.
 
        try
        {
            var serviceBusClient = _clientFactory();
 
            // We can assume that if a queue/topic is up and working then all queues or topics are too
 
            var queueOrTopicName = _nameFactory();
 
            if (!string.IsNullOrWhiteSpace(queueOrTopicName))
            {
                var receiver = serviceBusClient.CreateReceiver(queueOrTopicName);
                await receiver.PeekMessageAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
            }
 
            return HealthCheckResult.Healthy();
        }
        catch (Exception ex)
        {
            return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
        }
    }
}