MicroBatchFrameworkを試す 3 - バッチ終了のハンドル
前回の記事では MicroBatchFramework で設定ファイルを読み込む方法を書いてみました。この記事は MicroBatchFramework を使用した際の、バッチアプリ終了をハンドルして何か処理を挟み込む方法です。
試用環境
- Windows 10 x64 (1809)
- Visual Studio 2019
- .NET Core SDK 2.2.202
バッチアプリ終了をハンドルする
MicroBatchFrameworkを使用すると HostBuilder
を拡張してバッチアプリを作ることができます。この HostBuilder
は ASP.NET Core をホストしている WebHost
を Web アプリ以外でも汎用的に使えるようにしたもので、実行に関する設定方法で両者に大きな違いはありません(私が無いと思っているだけですが)。
.NET Core には IApplicationLifetime
インタフェースを通じてアプリの実行開始や終了をハンドルできる機能があります。また MicroBatchFramework 自体にもインターセプターを通じて、バッチの開始や終了をハンドルする機能が実装されています。
IApplicationLifetime
を使用する
先にも記した通り、 IApplicationLifetime
は .NET Core の HostBuilder
でホストされるアプリケーションの開始や終了をハンドルすることができるインターフェースです。アプリケーションの終了は ApplicationStopping
に対してリスナーを登録します。
BatchApp のルート階層に ShutdownHandler
クラスを追加し、以下のように実装します。
src\BatchApp\ShutdownHandler.cs using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; namespace BatchApp { public class ShutdownHandler : IHostedService { public ShutdownHandler(IApplicationLifetime applicationLifetime) { applicationLifetime.ApplicationStopping.Register(OnApplicationStopping); } private void OnApplicationStopping() { // アプリ終了時の処理 } public Task StartAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } } }
IHostedService
は .NET Core の汎用ホスト上で実行されるバックグラウンドサービスを実装するためのインターフェースです。これを実装することで、他のコンポーネントからの依存が無くてもアプリケーションの起動と同時にこのサービスが開始されます。
アプリ終了をハンドルするサービスを実装したら、次にこれをシングルトンコンポーネントとして登録します。 Program.cs
を開き、 ConfigureServices
に登録するためのコードを追加します。
src\BatchApp\Program.cs using System; using System.Threading.Tasks; using MicroBatchFramework; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; namespace BatchApp { class Program { static async Task Main(string[] args) { await BatchHost.CreateDefaultBuilder() .ConfigureServices((hostContext, services) => { services.Configure<SampleConfig>(hostContext.Configuration); services.AddSingleton<IHostedService, ShutdownHandler>(); // 追加 }) .RunBatchEngineAsync<HelloWorldBatch>(args); } } ... }
インターセプターを使用する
MicroBatchFramework にはバッチアプリの開始と終了をハンドルするインターセプター機能が実装されています。 IBatchInterceptor
を実装して RunBatchEngineAsync
の引数に指定することで動作します。 IoC コンテナに登録するコンポーネントではないことに注意が必要です。IBatchInterceptor
には4つのメソッドが用意されており、「バッチホストの開始」「バッチ処理の開始」「バッチ処理の終了」「バッチホストの終了」時に呼び出されます。
実装を書いていたら面倒臭くなってきたので、試した結果、こんなライフサイクルでした。そりゃそうだよね、という感じ以外の何者でも無いですが。
IHostedService:Start IBatchInterceptor:BatchEngineBegin IBatchInterceptor:BatchRunBegin Batch:Constructor Batch:Run IBatchInterceptor:BatchRunComplete IApplicationLifetime:ApplicationStopping IApplicationLifetime:ApplicationStarted IBatchInterceptor:BatchEngineEnd IHostedService:Stop IApplicationLifetime:ApplicationStopped
おわりに
この記事では MicroBatchFramework でバッチアプリの終了をハンドルする方法についてでした。私は MicroBatchFramework を使用して Azure AD から認証を取りつつ REST API を叩くだけのバッチを作ったのですが、実行ログを ApplicationInsights に対して送信する際に、バッチアプリの終了が取れずにログが未送信のまま終了してしまうのを防ぐために使用しています。試した時点ではまだドキュメントが不完全でインターセプターに関する情報が無かったため IApplicationLifetime
を使用してハンドルしました。