次の方法で共有


.NET .NET Aspire のカスタム リソース コマンド

.NET .NET Aspire アプリ モデル 内の各リソースは IResource として表され、分散アプリケーション ビルダーに追加されると、IResourceBuilder<T> インターフェイスのジェネリック型パラメーターになります。 リソース ビルダー API を使用して、呼び出しをチェーンしたり、基になるリソースを構成したりします。場合によっては、カスタム コマンドをリソースに追加することもできます。 カスタム コマンドを作成するための一般的なシナリオとして、データベースの移行の実行や、データベースのシード処理/リセットがあります。 この記事では、キャッシュをクリアする Redis リソースにカスタム コマンドを追加する方法について説明します。

大事な

これらの .NET.NET Aspire ダッシュボード コマンドは、ダッシュボードをローカルで実行する場合にのみ使用できます。 Azure Container Appsでダッシュボードを実行している場合は使用できません。

リソースにカスタム コマンドを追加する

まず、使用可能な テンプレートから新しい .NET.NET Aspire スターター アプリ作成します。 このテンプレートからソリューションを作成するには、「クイックスタート: 初めての .NET.NET Aspire ソリューションを構築する」に従いましょう。 このソリューションを作成した後、アプリ ホスト プロジェクトRedisResourceBuilderExtensions.cs という名前の新しいクラスを追加します。 ファイルの内容を次のコードに置き換えます。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;

namespace Aspire.Hosting;

internal static class RedisResourceBuilderExtensions
{
    public static IResourceBuilder<RedisResource> WithClearCommand(
        this IResourceBuilder<RedisResource> builder)
    {
        builder.WithCommand(
            name: "clear-cache",
            displayName: "Clear Cache",
            executeCommand: context => OnRunClearCacheCommandAsync(builder, context),
            updateState: OnUpdateResourceState,
            iconName: "AnimalRabbitOff",
            iconVariant: IconVariant.Filled);

        return builder;
    }

    private static async Task<ExecuteCommandResult> OnRunClearCacheCommandAsync(
        IResourceBuilder<RedisResource> builder,
        ExecuteCommandContext context)
    {
        var connectionString = await builder.Resource.GetConnectionStringAsync() ??
            throw new InvalidOperationException(
                $"Unable to get the '{context.ResourceName}' connection string.");

        await using var connection = ConnectionMultiplexer.Connect(connectionString);

        var database = connection.GetDatabase();

        await database.ExecuteAsync("FLUSHALL");

        return CommandResults.Success();
    }

    private static ResourceCommandState OnUpdateResourceState(
        UpdateCommandStateContext context)
    {
        var logger = context.ServiceProvider.GetRequiredService<ILogger<Program>>();

        if (logger.IsEnabled(LogLevel.Information))
        {
            logger.LogInformation(
                "Updating resource state: {ResourceSnapshot}",
                context.ResourceSnapshot);
        }

        return context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy
            ? ResourceCommandState.Enabled
            : ResourceCommandState.Disabled;
    }
}

上記のコード:

  • Aspire.Hosting 名前空間を共有して、アプリ ホスト プロジェクトに表示できるようにします。
  • 拡張メソッドを含めることができるように設計された static class です。
  • WithClearCommandという名前の 1 つの拡張メソッドを定義し、IResourceBuilder<RedisResource> インターフェイスを拡張します。
  • WithClearCommand メソッドは、clear-cache リソースのキャッシュをクリアする Redis という名前のコマンドを登録します。
  • WithClearCommand メソッドは、チェーンを許可するために IResourceBuilder<RedisResource> インスタンスを返します。

WithCommand API は、.NET.NET Aspire ダッシュボードで使用されるリソースに適切な注釈を追加します。 ダッシュボードでは、これらの注釈を使用して、UI でコマンドをレンダリングします。 これらの詳細に入り込みすぎる前に、まず WithCommand メソッドのパラメーターを理解しておく必要があります。

  • name: 呼び出すコマンドの名前。
  • displayName: ダッシュボードに表示するコマンドの名前。
  • executeCommand: コマンドが呼び出されたときに実行する Func<ExecuteCommandContext, Task<ExecuteCommandResult>>。コマンド ロジックが実装されている場所です。
  • updateState: Func<UpdateCommandStateContext, ResourceCommandState> コールバックが呼び出され、コマンドの "有効" 状態が決定されます。これは、ダッシュボードでコマンドを有効または無効にするために使用されます。
  • iconName: ダッシュボードに表示するアイコンの名前。 アイコンは省略可能ですが、指定する場合は、有効な Fluent UI Blazor アイコン名必要があります。
  • iconVariant: ダッシュボードに表示するアイコンのバリエーション、有効なオプションは Regular (既定) または Filledです。

コマンド ロジックの実行

executeCommand デリゲートは、コマンド ロジックが実装される場所です。 このパラメーターは、Func<ExecuteCommandContext, Task<ExecuteCommandResult>>として定義されます。 ExecuteCommandContext には、次のプロパティがあります。

  • ExecuteCommandContext.ServiceProvider: サービスの解決に使用される IServiceProvider インスタンス。
  • ExecuteCommandContext.ResourceName: コマンドが実行されているリソース インスタンスの名前。
  • ExecuteCommandContext.CancellationToken: コマンドの実行を取り消すために使用される CancellationToken

前の例では、executeCommand デリゲートは、async リソースのキャッシュをクリアする Redis メソッドとして実装されています。 これは、実際のキャッシュクリアを実行するために、OnRunClearCacheCommandAsync という名前のプライベートクラススコープ関数にデリゲートします。 次のコードについて考えてみましょう。

private static async Task<ExecuteCommandResult> OnRunClearCacheCommandAsync(
    IResourceBuilder<RedisResource> builder,
    ExecuteCommandContext context)
{
    var connectionString = await builder.Resource.GetConnectionStringAsync() ??
        throw new InvalidOperationException(
            $"Unable to get the '{context.ResourceName}' connection string.");

    await using var connection = ConnectionMultiplexer.Connect(connectionString);

    var database = connection.GetDatabase();

    await database.ExecuteAsync("FLUSHALL");

    return CommandResults.Success();
}

上記のコード:

  • Redis リソースから接続文字列を取得します。
  • Redis インスタンスに接続します。
  • データベース インスタンスを取得します。
  • FLUSHALL コマンドを実行してキャッシュをクリアします。
  • コマンドが成功したことを示す CommandResults.Success() インスタンスを返します。

コマンド状態ロジックを更新する

updateState デリゲートは、コマンドの状態が決定される場所です。 このパラメーターは、Func<UpdateCommandStateContext, ResourceCommandState>として定義されます。 UpdateCommandStateContext には、次のプロパティがあります。

  • UpdateCommandStateContext.ServiceProvider: サービスの解決に使用される IServiceProvider インスタンス。
  • UpdateCommandStateContext.ResourceSnapshot: コマンドが実行されているリソース インスタンスのスナップショット。

変更できないスナップショットは CustomResourceSnapshotのインスタンスであり、リソース インスタンスに関するあらゆる種類の重要な詳細が公開されます。 次のコードについて考えてみましょう。

private static ResourceCommandState OnUpdateResourceState(
    UpdateCommandStateContext context)
{
    var logger = context.ServiceProvider.GetRequiredService<ILogger<Program>>();

    if (logger.IsEnabled(LogLevel.Information))
    {
        logger.LogInformation(
            "Updating resource state: {ResourceSnapshot}",
            context.ResourceSnapshot);
    }

    return context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy
        ? ResourceCommandState.Enabled
        : ResourceCommandState.Disabled;
}

上記のコード:

  • サービス プロバイダーからロガー インスタンスを取得します。
  • リソース スナップショットの詳細をログに記録します。
  • リソースが正常な場合は ResourceCommandState.Enabled を返します。それ以外の場合は、ResourceCommandState.Disabledを返します。

カスタム コマンドをテストする

カスタム コマンドをテストするには、アプリ ホスト プロジェクトの Program.cs ファイルを更新して、次のコードを含めます。

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache")
                   .WithClearCommand();

var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

builder.AddProject<Projects.AspireApp_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WaitFor(cache)
    .WithReference(apiService)
    .WaitFor(apiService);

builder.Build().Run();

上記のコードは、WithClearCommand 拡張メソッドを呼び出して、カスタム コマンドを Redis リソースに追加します。 アプリを実行し、.NET.NET Aspire ダッシュボードに移動します。 Redis リソースの下にカスタム コマンドが一覧表示されます。 ダッシュボードの [リソース] ページで、[アクション] 列の下にある省略記号ボタンを選択します。

.NET Aspire ダッシュボード: カスタム コマンドで表示された Redis のキャッシュ リソース。

上の図は、 リソースに追加された Redis コマンドを示しています。 アイコンは、依存するリソースの速度がクリアされていることを示すために、ウサギが出て行く際に表示されます。

リソースのキャッシュをクリアするには、Redis コマンドを選択します。 コマンドが正常に実行され、キャッシュがクリアされます。

.NET Aspire ダッシュボード: カスタムコマンドが実行されたキャッシュリソース Redis 。

関連項目