Azure Functions Cosmos DB Trigger を TypeScript で実装する (平成版)
Azure Functions ではさまざまなトリガーを使うことができますが、中でも気に入っているのが Cosmos DB Trigger です。これを気に入っている最大の理由は、クラウドアーキテクチャの代表的なパターンである コマンド クエリ責務分離 (CQRS) パターン や イベントソーシング パターン を実現するために欠かせない技術だからです。
コミッターをやらせてもらっている intelligent-retail/smart-store でも Cosmos DB Trigger を使っていて、在庫管理アーキテクチャを実現するキーテクノロジとなっています。
最近の更新
Cosmos DB Trigger 自体は登場からもう1年以上経過しているので 使っている人もそれなり増えてきた印象がありますが、初期の頃からいくつか更新(改善)されている点があるので紹介したいと思います。
まず、何と言ってもコスト面の改善です。これまで Cosmos DB Trigger を使うには、ChangeFeed の状態管理を行うためのコンテナー(leaseコレクション)に追加コストを払う必要がありました。しかし、Cosmos DB で データベースレベルでの共有スループット がサポートされたことで、leaseコレクションをデータを格納しているコンテナーと同一データベースに含めることができるようになり、追加コスト不要でプロビジョニングすることが可能となりました。
データベースレベルの共有スループット登場直後は、Azure Fucntions の Extensions 側が対応していなかったため、 leaseコレクションを含めることができなかったのですが、Cosmos DB プロダクトチームの Matías Quaranta が Pull Request #520 · Azure/azure-webjobs-sdk-extensions で対応してくれたため、現在では問題なく設定ができるようになっています。
なお、Microsoft.Azure.WebJobs.Extensions.CosmosDB
のバージョンを 3.0.3
以上でこの問題に対応するようになっているので、csproj
で Extensions のバージョンを確認しておきましょう。
Cosmos SDKもメジャーバージョンアップが行われています。まず Node.js の Azure/azure-cosmos-js が V2系 となり、 async/await が使えるようになる等かなり大幅に更新されています。App Service チーム から移ってきた Christopher Anderson が中心になってコードを全面書き換えした効果が大きいと思われます。.NET(C#) SDK についても、V3系となり(執筆時点でプレビュー)、 Node.js 版の V2 と同様にほぼ全面書き換えがされているようです。なお、.NET SDK は V3 からようやくメインのソースがOSSとして公開された点も歓迎すべきでしょう。
Cosmos DB のプロビジョニング
Cosmos DB をデータベースレベルの共有スループットでプロビジョニングしてみます。Azure CLI で作成する方法は以下の通りです。
なお、Cosmos DB アカウントが作成されている前提にしていますので、作成していない場合は、Azure CLI の Microsoft Docs を参照して下さい。
az cosmosdb database create \ |
これで、データベース mykdb
配下に作成するコンテナー(コレクション)は、データベース内で RU が共有されるようになりました(この例は 1000RU
を複数コンテナーで共有する設定)。
Azure Functions 側の実装
Azure Functions 側の実装・設定上のポイントを紹介しておきます。設定ファイルの見やすさから Node.js の Azrue Functions で説明します。
func init |
Node.js
-> TypeScript
と選択します
func new |
Azure Cosmos DB trigger
を選択して関数を新規作成します。
生成された extensions.csproj
の Microsoft.Azure.WebJobs.Extensions.CosmosDB
のバージョンが 3.0.3
以上になっていなければ、バージョンを修正してから再度 func extensions install
を実行して下さい。 npm install
を実行してJS側のリストアも忘れずに。
CLI で生成された設定ファイル function.json
はこんな感じになるはずです。
{ |
ポイントは、leaseコレクションの作成先DB名を明示的に指定しないことと、 createLeaseCollectionIfNotExists
を true
にしておくことです。これで初回実行時にデータ取得元のコレクションと同一DBにleaseコレクションが生成され、追加のコンテナー(コレクション)利用コストが発生しなくなります。
CLIで自動生成されるコードは以下のような感じです。
import { AzureFunction, Context } from "@azure/functions" |
TypeScript なのできちんと型が割り当てられています( AzureFunction
型とかアツいです)。 documents
の型が any[]
になっていますが、ここはトリガーでバインドされるJSONの型に従って自分でクラスを定義しましょう。
TypeScriptのプロジェクトなので、コンパイル(トランスパイル)すると、
npm run build |
/dist
配下にJSの実行コードが生成されます。
あとは、いつものように func host start
で Azure Functions Core Tooles を使ったデバッグ実行ができます。
TypeScript自体は1.0がリリースされてから数年経過しますが、今年は Vue.js の3系でも全面採用される予定ですし、今回のように Azure Functions でも使えるようになったので、個人的には改めて TypeScript を使い倒していくことになりそうです。 TypeScript のコミュニティも企画していたりするので、お楽しみに!