Azure SQL trigger for Functionsを試してみました

本日は11月中旬にプレビューとなったAzure SQL trigger for Functionsを試してみましたのでその内容を書いてみたいと思います。

何らかのイベントによって処理をしたいといったことはシステム開発では度々起こり得ると思います。
APIを叩いたタイミング、AzureであればStorageのキューに投入されたタイミング、様々なものが考えられます。
データベースのこのテーブル・このカラムが更新されたタイミングで何か処理したいということもあるかと思いますが、そんな時は皆さんどうしているでしょうか。
恐らくはバッチ等を定期的に起動、もしくはループ内でデータベースを監視するといったことが方法として挙げられると思います。
しかしながら、他に処理することがあればまだしも、ただ単にテーブルを監視するだけのプロセスを作成するのはなかなかに手間ですし、管理も面倒です。

今回紹介するAzure SQL trigger for Functionsはその名の通り、SQLデータベースそのものがトリガーとなり、Azure Functionsを実行するという今までありそうでなかった、かつ、非常に使えそうな機能になります。

今回は以下のページを参考に進めています。
言語についてはC#だけでなく、JavaやJavaScript等、様々な言語で実現可能ですが、今回はC#で進めてみたいと思います。
https://github.com/Azure/azure-functions-sql-extension
https://github.com/Azure/azure-functions-sql-extension/blob/main/docs/BindingsGuide_Dotnet.md

本来であればAzure Functionsへデプロイを行い、Functions上で動くところまで行きたいのですが、今回はSQL triggerに焦点を当てて、ローカルでの動作に留めます。
まずはローカルのPC上で環境構築を行いますが、今回は(今回も)VS Codeを使って試してみます。
今回のポイントとしてはCore Toolsとなります。皆さんの環境に応じて適切な種類をインストールしましょう。私の場合はWindows64bit版をインストールしています。

次にプロジェクトを作成します。
Functionsアプリケーションを作成するのでコマンドプロンプトから以下の内容を入力してください。

mkdir MyApp
cd MyApp
func init --worker-runtime dotnet

すると以下のようにプロジェクトが作られます。

更に今回の機能を試すためにプロジェクトに対して以下のパッケージ・拡張機能をインストールします。

dotnet add package Microsoft.Azure.WebJobs.Extensions.Sql --prerelease

次にデータベースを作成します。
データベースのバージョン、種類については上で挙げた一番最初のURLに記載があるので確認してください。
今回は以下の手順に従ってSQL Databaseを作成します。
https://github.com/Azure/azure-functions-sql-extension/blob/main/docs/GeneralSetup.md#create-a-sql-server

上の画面で「単一データベース」を選択し、

更に必要な情報を入力してSQL Databaseを作成します。
そして今回のテストプログラムで使用するEmployeesテーブルもあらかじめ作っておきます。
1件で良いので適当にデータを入力し、レコードを作っておきましょう。
これもクエリが載っているのでSMSS、もしくはAzureポータルのクエリエディタ(これもプレビューです)を使って作ります。

これでプロジェクトとデータベースが作成できましたのでこの2つを結びつけるためにプロジェクト内のlocal.settings.json内に以下の内容を記述します。「{connection_string}」は言わずもがなですが上で作成したSQL Databaseの接続文字列を入力してください。

入力バインディング

さて、SQL triggerを試す前に更に幾つか試してみたいと思います。
それが入力バインディングと出力バインディングです。
これを試しておくとSQL triggerの前のデータ作成・準備も行えますのでお勧めです。
まずは先ほど作成したプロジェクトをVS Codeで開きます。

F1を押して画面上部のコマンドパレットで「Create Function…」を選択し、更に必要な項目を入力して、入力バインディングを実行するFunctionクラスを作成します。

以下のようにFunctionクラスが作成されるので、

サンプルの内容をそのまま貼り付けて書き変えます。

そのままですとコード内の「Employee」クラスでエラーが出るのでEmployee.csを作成し、クラスを作成します。

そして実行します。以下のようなダイアログが表示されますが、「Debug anyway」で継続します。

するとターミナル上に以下の内容が表示されますので、HttpTrigger1の後に続くURLを叩きます。

するとブラウザ上で以下のような表示が出てくると思います。
データベース上のEmployeesテーブルの内容をFunctionsで読み込んで表示しています。

出力バインディング

次に「出力バインディング」です。
これも同じようにF1を押して必要事項を入力してFunctionを作成します。

先ほどは省略しましたが、「HTTP  trigger」を入力し、

クラス名を入力します。

名前空間も入力し、

アクセス権はAnonymousで良いです。

そして入力バインディングと同様、Runメソッドをサンプルの内容に書き換えます。

そして実行。

また以下のようにターミナルに表示されますので、今度は先ほど作成した、下の例では「HttpTrigger2」のURLを叩きます。

Runメソッド内でEmployeesテーブルの書き換え、レコードの追加を行っているのですが、その結果がブラウザ上に表示されます。

下がプレビュー機能であるAzureポータルのクエリエディタで確認した結果です。

トリガーバインディング

さて、いよいよSQL trigger、トリガーバインディングを試しましょう。
まず、SQL データベースでの変更を追跡するための設定を有効化する必要があります。
以下のクエリを実行します。'your database name'はその名の通り実際のデータベース名を入力してください。

ALTER DATABASE ['your database name']
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

次にデータベースだけでなく、テーブルに対しても変更追跡を有効にします。Employeesテーブルに対して以下のクエリを実行します。

ALTER TABLE dbo.Employees
ENABLE CHANGE_TRACKING;

そして、Runメソッドを書き換えます。

以下がその内容です。
テーブルが書き換えられたタイミングでこのメソッドが呼び出され、ログにその内容が出力されます。

using System.Collections.Generic;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.WebJobs.Extensions.Sql;

namespace Company.Function
{
    public static class EmployeeTrigger
    {
        [FunctionName("EmployeeTrigger")]
        public static void Run(
            [SqlTrigger("[dbo].[Employees]", ConnectionStringSetting = "SqlConnectionString")]
            IReadOnlyList<SqlChange<Employee>> changes,
            ILogger logger)
        {
            foreach (SqlChange<Employee> change in changes)
            {
                Employee employee = change.Item;
                logger.LogInformation($"Change operation: {change.Operation}");
                logger.LogInformation($"EmployeeID: {employee.EmployeeId}, FirstName: {employee.FirstName}, LastName: {employee.LastName}, Company: {employee.Company}, Team: {employee.Team}");
            }
        }
    }
}

それでは実行してみましょう。
テーブルをSMSS等で書き換えてもいいのですが、今回は入力バインディングを作成しましたのでそれをもう一度実行してみます。

すると以下のようにデータが書き換えられたことがログ出力されます。
素晴らしいですねー。

では、別の方法で試してみましょう。
クエリエディタで2番目のレコードを書き換えます。カラム「Team」を「Functions」から「Azure SQL」に書き換えます。

すると以下の選択部分の内容が出力されます。

いかがでしょうか。
まだプレビューではありますが、この機能が使えればわざわざ監視用のバッチ等を作成する手間が省けます。
注意点として、このSQL triggerは現状「Premium と Dedicated プランでのみサポートされます。 従量課金はサポートされていません。」とあります。
できればGA時には従量課金がサポートされるといいですねー。

では、今回は以上となります。

この記事が気に入ったらサポートをしてみませんか?