しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Functions の Cosmos DB Extension v4 が GA したので v3 からの移行を確認した

Preview が公開されてから 1 年以上が経過しましたが、ようやく Azure Functions の Cosmos DB Extension v4 が正式リリースされました。信頼性とパフォーマンスが大幅に改善、更に機能が追加された Cosmos DB SDK v3 ベースになっているので、現在 Extension v3 を使っている場合には早急な移行をお勧めします。

移行方法や新機能については Cosmos DB SDK チームの Matias がブログに書いてくれているので、こちらをしっかりと参照しておいて貰えれば問題ありません。

正式リリースのブロッカーとなっていた Consumption Plan でのサポートが先日無事に有効化されていますので、ゼロスケールからの Change Feed でのトリガー起動も問題なく動作します。

そして少し前にも書きましたが、Cosmos DB Extension v4 では CosmosDBTrigger での Retry Policy が正式にサポートされている一方、Extension v3 を使っている場合は間もなく Retry Policy が無効化されるため特に急ぐ必要があります。Change Feed と Retry Policy は必須の組み合わせなので最重要です。

このエントリを書いたときには C# 以外の言語では Cosmos DB Extension v4 が利用できなかったのですが、正式リリースに伴って公開された Extension Bundle v4 では問題なく動作するようになっていますので、今回はそちらが話のメインとなります。

C# から利用する場合

これまで通り C# で Azure Functions を書いている場合には、以下の NuGet パッケージを最新へと更新すればビルドエラーが出るので、何を修正すればいいのか分かるようになっています。Cosmos DB SDK が v3 ベースとなっているので、もし v2 SDK を使っていた場合には同時に更新しておくのが良いです。

既に何回かこのブログでも紹介しているので、具体的な移行方法や特徴については以下のエントリを参照してください。Preview バージョンをベースで書いていますが大きな変化はありません。

Visual Studio から CosmosDBTrigger の Function を追加した時に生成されるコードを、今回の Extension v4 向けに修正すると以下のようになります。入力のバインドに使われていた Document クラスが無くなっていますが、POCO のマッピングに対応しているので無問題です。

public class Function1
{
    [FunctionName(nameof(Function1))]
    public void Run([CosmosDBTrigger(
                               databaseName: "my-database",
                               containerName: "my-item",
                               Connection = "CosmosConnection",
                               LeaseContainerName = "leases")]
                           IReadOnlyList<MyItem> input,
                           ILogger log)
    {
        if (input is { Count: > 0 })
        {
            log.LogInformation("Documents modified " + input.Count);
            log.LogInformation("First document Id " + input[0].Id);
        }
    }
}

public class MyItem
{
    [JsonProperty("id")]
    public string Id { get; set; }
}

Cosmos DB を C# から利用する際には必ずクラスを定義しているはずなので、理想的な形で実装出来るようになっています。CosmosDB バインディングでは CosmosClient のキャッシュされたインスタンスが取得できるため、DI を使わずともベストプラクティスに従った実装となっています。

C# 以外から利用する場合

正式リリースまでは実行時にエラーとなってしまっていた C# 以外の言語から利用するケースですが、Extension Bundle v4 の正式リリースと同時にエラーも修正されていました。

以下のリリースノートでは v4-rc が含まれていることになっていますが、正式版とコードベースは同一なので利用には問題ありません。あくまでも Consumption Plan のサポートが遅れていただけです。

現在は Cosmos DB Extension v4 に対応したテンプレートがリリースされていませんので、Extension v3 向けに生成された定義とコードを v4 向けに修正する必要があります。具体的にはまず Extension Bundle のバージョンを v4 にアップグレードすることから始めます。

Extension Bundle のバージョンは host.json で定義されているので、以下の例のように version の指定を v4 の最新バージョンを使うように書き換えます。

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}

このバージョン指定によって、Azure Functions Runtime は必要に応じて Extension Bundle をダウンロードします。稀に特定バージョン以降に固定する必要が出てきますので、書き方は覚えておいて損はありません。

C# 以外の言語では function.json ファイルにトリガーの設定を書く必要があるので、C# の時と同様に CollectionContainer に変えるといった置き換えを行います。

{
  "bindings": [
    {
      "type": "cosmosDBTrigger",
      "name": "documents",
      "direction": "in",
      "leaseContainerName": "leases",
      "connection": "CosmosConnection",
      "databaseName": "my-database",
      "containerName": "my-item",
      "createLeaseContainerIfNotExists": false
    }
  ],
  "scriptFile": "../dist/CosmosTrigger1/index.js"
}

入力補完は効きませんが書き間違いがある場合にはローカルデバッグ時に Function が見つからないエラーが表示されるので、ある程度はエラーの有無を把握することが出来ます。この辺りはテンプレートの更新が待ち遠しいですが、まずは手動で頑張ります。

ちなみに Function の本体は修正不要です。ここまでの状態でローカル実行をしてみると、以下のように問題なく Change Feed を読み取って動いていることが確認出来ます。

C# 以外の言語では実際に Cosmos DB Extension v4 が使われているのか確認するのが難しいですが、Cosmos DB に保存された leases コンテナーのフォーマットが変わっているのかを調べることで Extension v4 (Cosmos DB SDK v3) が使われていることを確認出来ます。

具体的には以下のようにプロパティに FeedRange があれば Extension v4 が使われています。leases コンテナーのフォーマットは下位互換が無く、一度 Extension v4 にすると戻せないため注意が必要です。

当然ながら、作成した Function を Azure 上にデプロイすると問題なく動作します。Consumption Plan を利用している場合でも、変更があればインスタンスが自動的に起動されるのでこれまで通り利用できます。

今回の Cosmos DB Extension v4 の正式リリースで DocumentDB 自体の SDK は一掃できたので、既に利用しているアプリケーションでの更新を優先度高めでやっていきましょう。