NEXTSCAPE blog

株式会社ネクストスケープの社員による会社公式ブログです。ネスケラボでは、社員が日頃どのようなことに興味をもっているのか、仕事を通してどのような面白いことに取り組んでいるのかなど、会社や技術に関する情報をマイペースに紹介しています。

MENU

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

こんにちは。ソリューションビジネス推進部の小野塚です。 この記事は「NEXTSCAPE Advent Calendar 2022」の8日目の記事になります。

qiita.com

本日は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

今回はVS Codeを使って試してみます。
本来であればAzure Functionsへデプロイを行い、Functions上で動くところまで行きたいのですが、今回はSQL triggerに焦点を当てて、ローカルでの動作に留めます。
ローカルPC上で環境構築を行いますが、以下のCore Toolsを始め、まっさらな状態からVS Codeでビルドができるようにするには幾つかインストールするものがあるのですが、ここでは割愛させてください。
一度環境ができればC#に限らずJavaやJavaScript、様々な言語で簡単にフレームワーク作成できますのでお勧めです。

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

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

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

画像

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

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

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

画像

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

画像

更に必要な情報を入力してSQL Databaseを作成します。
そして今回のテストプログラムで使用するEmployeesテーブルもあらかじめ作っておきます。
1件で良いので適当にデータを入力し、レコードを作っておきましょう。
これもクエリが参考にしたURLに載っているので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を作成します。
Function名は入力バインディングに引き続き(安直ですが)HttpTrigger2にします。
そして入力バインディングと同様、Runメソッドをサンプルの内容に書き換えます。画像

 

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

画像

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

画像

下がプレビュー機能であるAzureポータルのクエリエディタで確認した結果です。
ブラウザに表示された内容と以下の内容が一致している、つまり、Employeeテーブルの内容が取得出来ていることがわかります。

画像

トリガーバインディング

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

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

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

ALTER TABLE dbo.Employees
ENABLE CHANGE_TRACKING;
copy

そして、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}");
            }
        }
    }
}
copy

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

画像

するとそのタイミングでFunctionが動き、以下のようにデータが書き換えられたことがログ出力されます。
面白いですねー。

画像

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

画像

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

画像

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

Functionを作成する時のVSCodeのウィザードでJavaやJavaScriptを選択するとその言語で今回の機能が確認できますので、他の言語を使われる方も是非試してみてください。
機会があれば本ブログでも記事にしてみたいと思います。

「お客様のビジョンに共感し、感動を実現します」を理念に掲げるネクストスケープでは一緒に働く仲間を絶賛募集中です。
興味がありましたらお気軽にご応募いただければと思います。

www.nextscape.net

少しでも興味を持っていただいた方、Microsoft Azureを使用している方は是非今までの、そして、これからのアドベントカレンダーの記事も見てみてください。
本日のアドベントカレンダーの記事は以上となります。