kintone から webhook で Azure Function を呼ぶ連携処理を開発時のメモです。
VSCode を使うとローカルPCで開発・デバッグが可能で、Azure Functions 本番環境への反映もできます。
手軽に API を開発可能かつサーバー管理が不要で運用も楽です。kintone の外部連携にぴったり。
とりあえず、調べたことを書いておきます。
開発環境
Azure Function は、クラウド上で動作しますが VSCode で使うとローカルPC上で開発・デバッグが出来ます。
VSCode は、Mac でも動きますので、Mac でも同じように開発できると思います。
- Windows 10
- Visual Studio Code
- JavaScript, node.js
- kintone
Azure Functions
Azure 実行環境
OS は、Windows と Linux(プレビュー) から選択できますが、Linux は、App Service プランのみで従量制は選択できません。
既定値は、 Windows です。今回はそのまま Windows を使います。
実際に動作している環境は、Azure Functions のコンソール画面から確認できます。
Windows10 ですね。
D:\home\site\wwwroot\HttpTriggerJS1> ver
Microsoft Windows [Version 10.0.14393]
Azure Functions 価格
サーバーレスがはやりといっても、料金がいくらかで採用するかどうかの判断が必要です。
従量課金プランと Azure App Service プランがあり、kintone で扱うレコードなら従量課金プランの無料枠でいけそうです。ただし、関数毎ではなくアカウントの合計で 100 万回/月までです。
メモリやストレージ、帯域幅などを想定して、料金計算ツールを使えば、計算できます。
Functions では、すべての関数に対して各月にリクエストされた実行の総数に基づいて課金されます。実行回数は、バインドによってトリガーされたイベントに応じて関数が実行されるたびにカウントされます。毎月、最初の 100 万回は無料で実行できます。
Azure Functions 従量課金プランでは、1 秒あたりのリソースの使用量と実行回数に基づいて課金されます。従量課金プランの価格には、月間無料使用分として、月あたり 100 万回のリクエストと、400,000 GB 秒のリソース使用量が含まれています。標準の App Service プランの料金で、Functions を App Service プランの中で実行することもできます。
帯域幅の料金詳細
Azure Files の料金
料金計算ツール
VSCode 関連
関数を作成する方法には、Azure ポータル画面、Visual Studio, Visual Studio Code 等がありますが、JavaScript を使う場合は、Visual Studio Code が便利です。
Visual Studio Code を使用した初めての関数の作成
node.js 関連
- Node のバージョンとパッケージの管理 >アクティブ LTS と現在の Node.js のバージョン (8.11.1 と 10.6.0 を推奨)。
ローカルPCも、バージョンを合わせて node.js 8.11.1 を使う。
npm : Node.jsのモジュールを管理するツール
npm入門nodist: node.js のバージョン管理
最新の node.js を入れたのに、なぜか古いバージョンが使われてしまうときは、nodist を使うと便利です。
複数のバージョンがインストールされていても、nodist で切り替えられます。
kintone 関連
kintoneとMicrosoft Azureを連携してみよう (Azure Functionsその1)
kintoneとMicrosoft Azureを連携してみよう (Azure Functionsその2)
kintoneとMicrosoft Azureを連携してみよう (Azure Functionsその3)
npm で使用するライブラリのインストール
VSCode のターミナルで、コマンドを実行します。
- request-promise:API Request で使用
> npm install request --save-dev
> npm install request-promise --save-dev
ローカルPC での開発・デバッグ
VSCode でデバッグ実行すると、ローカルPC上で HTTP が立ち上がり、API を呼び出せます。
VSCode のソースにブレークポイントを設定して、ステップ実行して変数の内容も確認できます。
例:
Http Functions:
HttpTriggerJS1: http://localhost:7071/api/HttpTriggerJS1
Azure Functions 環境への反映
VSCode で deploy to Function App... を使うと、Azure Functions 環境へ反映してくれます。
npm でインストールしたライブラリも丸ごと反映してくれますので、便利です。
起動時間
コンテナ起動は、やはりある程度時間がかかります。
今回は、webhook を使って、kintone からファイルをダウンロード後に微信にアップロードする処理で、kintone レコード更新から微信にファイルが表示されるまで約30秒かかりました。
その後に同じファイルを処理すると、約3秒程度で表示されますので、起動時は30秒近くかかっています。
即時対応が必要な場合は、プランを従量課金ではなく App Serviceプランにするとよさそうです。
あとは、予算次第ですね。
Azure Functions のログ
context.log で、ログ出力できます。用途によって、info, warm, error 等を指定できます。
ただし、ログが格納される領域がそれほど大きくないようなので、必要最小限のログにしておいた方がよさそうです。
context オブジェクト
トレース出力をコンソールに書き込む
module.exports = function (context, req) { context.log.verbose(context.invocationId, ': verbose'); context.log.info(context.invocationId, ': info'); context.log.warn(context.invocationId, ': warn'); context.log.error(context.invocationId, ': error'); context.res = { status: 200, body: "invoked" }; context.done(); };
いろいろと、はまったこと
node.js 関連、Azure Functions 関連ではまったことを上げておきます。
request による kintone ファイルダウンロード
画像等のファイルを kintone REST API でダウンロードする際に、バイナリーデータとして扱う方法がわからず、ファイル書き込み等で試行錯誤した。
結局は、 request の encoding に null を指定すると、バイナリーデータとして扱えると判明。
当初は、画像データとして一時ファイルに書き込んでいた処理が不要になりました。
"encoding": null,
ファイルダウンロードのファイル書き込み
今回は、不要になったファイル書き込み処理ですが、今後のためコードを残しておきます。
一時ファイルは、Azure functions で使える一時ディレクトリ TMP を使用しました。
一時ファイル使用後に、削除しました。削除エラー時は、ログだけ出力してとりあえずほっとく。
process.env は、環境変数。Azure Functions 実行時の環境変数を取得出来ます。
※Azure Functionsでtemp fileを使う
ファイルダウンロードのファイル書き込みコード抜粋
const uuid = require('uuid-v4')
const rp = require('request-promise')
const fs = require('fs')
...
// request ファイルダウンロード
return rp(getFile(fileKey));
}).then(function(resp) {
// write tmp file
var image_id = uuid();
ctl.tmp_name = process.env.TMP + '\\T' + image_id + '_.tmp';
return new Promise(function(resolve, reject) {
let writeStream = fs.createWriteStream(ctl.tmp_name);
writeStream.write(resp, 'binary');
writeStream.on('finish', function() {
resolve(ctl.tmp_name);
});
writeStream.end();
});
}).then(function(resp) {
...
}).then(function(resp) {
// delete tmp file
fs.unlink(ctl.tmp_name, function (err) {
if (err) {
context.log('delete tmp file error: ', ctl.tmp_name, err);
}
});
あとがき
Auzre Functions は、思ったより簡単に API が作成できます。
ローカルPCで開発・デバッグが簡単にできると作業効率がいいですね。
今回は、webhook での利用でしたが、タイマー処理を使うとスケジュール実行が可能です。
kintone で定期的にバッチ処理を起動する場合に、便利そうです。