ファンクションの書き方
このページでは Craft Functions のコードの書き方を説明します。
Craft Functions の記法
Craft Functions のコードの記法を説明します。
Craft Functions の実行ランタイム
Craft Functions は Node.js の実行環境上で動作します。現在サポートしているランタイムは以下の通りです。
- Node.js v18
- Node.js v20
ランタイムバージョンの詳細については、Node.jsのドキュメント、ブログ等を参照してください。
Node.js — Run JavaScript Everywhere
Craft Functions のエントリポイント
Craft Functionsでは、次のように定義した関数がエントリポイントとなります。
この関数は次の要件を満たします。
- 関数名は指定しません。
export default
として定義します。 - 引数は
data
とMODULES
要素を持つオブジェクト ({ MODULES }
) の2つです。 - 基本的には async function として定義します。
入力 (data)
Craft Functions は外部からの入力として、引数 data
の値を受け取ります。data の型は object 型もしくは string 型です。多くの場合は object 型で値を受け取りますが、以下の場合は string 型の値となります。
- サーバーサイドアクションで JSON 形式以外の文字列を渡した場合
- Craft Scheduler で Function を定期起動する場合
モジュールの利用
Craft Functions では以下の方法でモジュールが利用できます。
MODULES
引数の要素として取り出して利用する- npm modules をコード内で import する
- Node.js の標準モジュールを利用する
これらのモジュールの使用方法を説明します。
MODULES の利用
Craft Functions の独自モジュールは MODULES
引数の要素として取り出せます。
MODULES
で利用できるモジュールは Craft Functions で利用できるモジュール で説明します。
npm modules を import する
npm modules を利用する際にはファンクション編集画面の modules で利用したいモジュールとバージョンを JSON 形式で指定します。
例えば、Google Cloud Pub/Sub の Node.js ライブラリを利用する場合は modules で以下のように指定します。
複数の npm modules を利用する場合は、 modules で利用する module を JSON 形式で列挙します。
npm modules を Craft Functions 内で利用する際は、Craft Functions のコード内で import
文を使い呼び出します。
npm modules の制限
- 現在 Craft で利用できる npm modules については、 利用できる npm modules をご参照ください。
- 各 module の任意のバージョンが指定できます。ただし、チルダ
~
キャレット^
によるバージョン指定はできないのでご注意ください。- 存在しないバージョンを指定するとファンクションの作成に失敗します。
Node.js の標準モジュールを利用する
Node.js の標準モジュールとして crypto
が利用できます。利用する場合は、Craft Functions のコードで import します。
関数の同期/非同期
Craft の大半のユースケースでは、外部システムへのアクセスが発生します。JavaScript では特に理由がない限り外部へのリクエストは非同期処理で実現するため、多くの場合、Craft Functions は Async Function として定義します。
入力を単純にログとして出力するだけの場合、非同期処理は必要ありません。このような場合、Craft Functions は同期関数として定義できます。
Craft Functions の性質
Craft Functions でプログラムを作成する際に考慮すべき性質について説明します。
Craft Functions は at least once で実行される
Craft は at least once
で Craft Functions を実行します。これはトリガーが発したイベントあたり「少なくとも 1 回」は Function を実行することを意味します。したがって、トリガーあたり 2 回以上 Function が実行されることもあり得ます。
※ exactly once
(トリガーのイベントあたり 1 回だけ Function を実行する)を実現する場合は、トリガーから受け取るリクエスト ID を Craft KVS や外部のデータベースサービスに書き込み、コード内で書き込んだレコードの有無を判定します。
Craft Functions は実行環境を使い回すことがある
Craft Functions は実行環境を使い回すことがあります。同一環境上で実行する場合、Craft Functionsは関数外で定義した値を再計算せず、前回実行時と同じ値を使います。したがって、関数定義の外側で処理時間のかかる処理を行うことで、ファンクションを複数実行した際の平均処理時間を短縮できます。
一方で、実行ごとに異なる値を使う必要がある場合はキャッシュによって意図しない動作を引き起こすので注意してください。次のコードは uuid
にランダムな UUID を設定していますが、同一実行環境では上記の挙動により同じ値を返却してしまいます。
Craft Functions は非同期処理を自動的に完了しない
非同期な処理を行う際は、 必ず関数内で非同期処理の完了を待ってください。 非同期な処理を待機しないと、Craft Functions 実行時に次のような不具合が発生することがあります。
- ファンクションの実行が完了しない、もしくは完了するまでに著しく時間がかかる
- 次回の実行時に未完了の処理を再開するなど、意図しない挙動となる
- エラー発生時にログが記録されない
例えば次のように Promise チェーンで非同期処理を実装した場合、ファンクションは Promise チェーン内の非同期処理の完了を待たずに終了することがあります。加えて、次回の実行時に未完了の処理を再開して意図しない挙動をすることがあります。
この場合、Promise チェーンで書かれた処理を await
で待機することで同期的な処理にできます。
また、一般的に Promise チェーンは async/await を使った処理に書き換えられます。非同期処理を実装する際は、await 式を適切に利用してください。
Craft Functions の制約
Craft Functions には以下の制約があります。
- Craft Functions 実行時に渡せる入力データの最大サイズは、10KB です。
- 入力データのサイズは、UTF-8 エンコードの JSON 文字列として計算します。
- サイズ上限を緩和するプランも用意しておりますので、お問い合わせください。
- Craft Functions の 1 実行あたりの起動時間の上限は 10 秒です。
- Craft Functions では Node.js でサポートされている global object の利用を一部制限しています(
require
やprocess
など)。 - デフォルトで Craft Functions の実行環境の Public IP アドレスは不定です。Public IP アドレスを固定する場合は固定IPアドレスオプションをご利用ください。
Fetch API の利用
Craft Functions 上で外部のリソースにアクセスする場合は、Node.js の fetch()
を利用します。
Global objects | Node.js v20.12.2 Documentation
例: JSON データを取得する
OpenWeatherMap API を呼び出して緯度経度から天気情報データをjson形式で取り出します。
例: CSV ファイルを取得する
内閣府が公開している祝日一覧を取得する例です。
KARTE のサーバーサイド API (API v2) の利用
Craft Functions では KARTE のサーバーサイド API (API v2) が利用できます。利用の際には modules で api
を指定し、API リファレンスの Node の実行例に従ってコードを記述します。
例: Send event to KARTE API (/v2/track/event/write) を実行する
modules で api を指定します。
コードで API を呼び出します。
api()
の引数には API リファレンスの Node のリクエスト例(下図)に基づいて設定します。- 参考:Send event to KARTE