はじめに
Hangfireは、時間のかかる処理をキューさせてバックグラウンドで実行するような構成を実現できるOSSです。
概要は前回の記事を御覧ください↓
Hangfireに.NET Core 3.1で最速入門する
特にリソースも時間も多く必要なタスクの場合、
受け付けるサーバーとは別に実行するサーバーを実装できたりしてなかなか便利です。
ドキュメントによるサーバー実装
公式ドキュメントによれば、
using(var server = new BackgroundJobServer()) {
Console.WriteLine("Started BackgroundJobServer. Press Enter to exit.");
Console.ReadLine();
}
といった感じで Console.ReadLine()
でスレッドをブロックするコードがサンプルとして提供されています。
何が問題か?
Console.ReadLine
を使う都合上、dockerで起動する際にttyをアタッチする必要があります。
ttyをアタッチすると、下記のようにjournald で loggingしようとしたときに [Blob Data] として記録されてしまいます。
コンソールでは正しく出力されるのに、何でだろう?と詰まったのですが、
上記Issueにたどり着き、tty: falseでも実行できるようにしようと思って調べた次第です。
Hangfire.NetCore
コンソールを使用せずともGeneric Hostを使用すればサービスが終了するまで、
バックグラウンドで動かし続けられるのではないか?と思い、調べてみたんですが、
今まで使用していた Hangfire.Core には AddHangfireServer
という関数が用意されておらず、
以下の選択が迫られました。
- 自分でConfigureServices
で使用する関数を実装する
- Hangfire.AspNetCore
パッケージを使用する
1つ目は 自前実装となると品質に不安が残ること。
2つ目は 無駄にASP.NET Coreに依存してしまうことが理由として挙がり、どうするかな~と悩んでいましたが
よくよく調べてみるとありましたパッケージ。
その名も Hangfire.NetCore
! リリースノート見ると
1.7.1
• Added – Worker Service host support for .NET Core without unnecessary dependencies to ASP.NET Core.
とあります。 つまり、 ASP.NET Coreへの依存を入れずに .Net Core アプリでワーカーサービス(Hangfire Server)を構築できるということです。
実装
実装はHostBuilderを使うだけのかんたんな構成。
static async Task Main(string[] args) {
var hostBuilder = new HostBuilder()
// Add configuration
.ConfigureServices((context, services) => {
services.AddHangfire(config => {
// 中略
config.UseMongoStorage(connectionString, databaseName, storageOptions);
});
services.AddHangfireServer(options => {
options.WorkerCount = cientWorkerCount;
});
})
.ConfigureLogging(logging => {
// 中略
});
await hostBuilder.RunConsoleAsync();
}
こんな感じです。私はジョブのキューに Hangfire.Mongo
を使用しているので余計なのが含まれていますが、
重要なのは ConfigureServices
で AddHangfire
と AddHangfireServer
する部分です。
終わりに
以上、Generic Host を使用した Hangfire Server の実装方法でした~。
(Hangfire.NetCore
の存在に1年も気づけていなくて悔しい。)
追記(2020/04/10)
リポジトリに反映しました↓