.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 リソースの下にカスタム コマンドが一覧表示されます。 ダッシュボードの [リソース] ページで、[アクション] 列の下にある省略記号ボタンを選択します。
上の図は、 リソースに追加された Redis コマンドを示しています。 アイコンは、依存するリソースの速度がクリアされていることを示すために、ウサギが出て行く際に表示されます。
リソースのキャッシュをクリアするには、Redis コマンドを選択します。 コマンドが正常に実行され、キャッシュがクリアされます。
関連項目
.NET Aspire