タイトル通りです。
最近ちょっとしたプロダクトを作る時にDurable Functionsを採用したのですが、Azure Functions v3環境下において、 Azure Functions Core Tools@3 で生成されるTemplateでは期待通りの動作をしませんでした。
時間が経てば解決しそうな事象ではありますが、それまでに使う場合に辛いことにならないようにメモとして残しておきます。
ちなみに作ったプロダクトがこちら
github.com
環境
- Azure Functions Core Tools 3.0.2630
- Azure Functions Runtime ~3
- durable-functions 1.4.3 (JSのPackage)
entityTrigger が動作しない
原因
JavaScriptのDurableFunctions packageで提供されているentityメソッドを発火するためのentityTrigger
ですが、こちらが実行できません。
原因としては func init
を実行した際に出力されるhost.jsonの中身のextensionBundle
の値が古いために、バンドルされる Microsoft.Azure.WebJobs.Extensions.DurableTask
のバージョンが古すぎて entityTrigger
のbindingがサポートされていないためです。
$ func --version
3.0.2630
な環境で作られる host.json の中身がこちらになります。
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
このバージョンレンジの中での現時点での最新は
azure-functions-extension-bundles/extensions.json at bd7c5b8adfb740dd8aaa1e60ec9f78b3c3c739cb · Azure/azure-functions-extension-bundles · GitHub
こちらで確認できるのですが、ここにバンドルされている Microsoft.Azure.WebJobs.Extensions.DurableTask
のバージョンが 1.8.6
となっています。
entityのTriggerは2.0.0以降でのサポートとなっているため、利用が出来ない、というわけです。
解決策
host.jsonから extensionBundle
の記述を削除し、必要なExtensionを自分で追加していくのが一番安心かと思います。
私はextensionBundleの記述を削除した後、
$ func extensions install -p Microsoft.Azure.WebJobs.Extensions.DurableTask -v 2.2.2
で最新のDurableTaskを導入し動作が確認できました。
この場合 .NET Coreがローカルに入っていないとextensionのビルドが出来ないため、インストールしておくのが良いでしょう。
ちなみにextensionBundleの記述がある状態で最新のDurableTaskをインストールしようとすると
No action performed. Extension bundle is configured in HERE_IS_AZURE_FUNCTIONS_FILE_PATH/host.json.
みたいな感じでインストールが出来ません。
continueAsNew でループを行えない
docs.microsoft.com
whileループなどを用いずに無限ループのようなものを作るパターンで利用するメソッドです。
2020年7月28日現在のドキュメントに記載されている
const df = require("durable-functions");
const moment = require("moment");
module.exports = df.orchestrator(function*(context) {
yield context.df.callActivity("DoCleanup");
const nextCleanup = moment.utc(context.df.currentUtcDateTime).add(1, "h");
yield context.df.createTimer(nextCleanup.toDate());
context.df.continueAsNew(undefined);
});
だと2度しかこのOrchestratorが実行されません。
解決策
すでにIssueとして報告されています。
github.com
context.df.continueAsNew()
を yield
やreturn
なしで実行すると起こってしまうようです。
例えば
const df = require("durable-functions");
const moment = require("moment");
module.exports = df.orchestrator(function*(context) {
yield context.df.callActivity("DoCleanup");
const nextCleanup = moment.utc(context.df.currentUtcDateTime).add(1, "h");
yield context.df.createTimer(nextCleanup.toDate());
yield context.df.continueAsNew(undefined);
return '';
});
こんな感じでorchestrator関数で明示的に値を返すようにしてcontinueAsNewにyieldを付けてあげることで正常に動作しました。
これに関しては durable-functions
パッケージにパッチが当たればいずれなくなる問題なので待つか、上記のような対処法で解決しましょう。
おわりに
C# とかでのDurableFunctionsの情報は調べれば割と出てくるのですが、JSのハマってしまった情報とかはあまり出てこなくて解決するのが大変でした…
この記事を見た方はぜひJSでDurableFunctions使って色々とハマりそうな点を見つけて共有していってください。
おまけとか追記
JavaScript + Webpack なファイルを Azure Functions で起動する時の function.json とwebpack.config.js の libraryTarget の対応 · GitHub
そう言えば今年もMicrosoft MVP Developer Technologiesを受賞できました。
更新頻度は低いですが、誰かの役に立てるような情報を発信したり出来るよう頑張りたいと思います。