Quantcast
Channel: ほりひログ
Viewing all articles
Browse latest Browse all 44

Azure Functions Node.js の新しいプログラミング モデル

$
0
0

ここの issueで議論されてた新しいプログラミング モデル、情報がまとまって試せるものが出てきたのでローカル PC 環境で動かしてみた。

github.com

注意 : 2022 年 9 月現在、まだ "internal testing" phase (パブリック プレビューですらない) で議論中なので、変更の可能性は大いにあり。

変更ポイント ~ function.jsonの廃止

上述のリンク先でも Say goodbye 👋 to "function.json" files!って言ってる。一番影響でかそう。

function.jsonが廃止されると、function.json内で設定していた

  1. エントリー ポイント
  2. トリガー / バインディング

を他で定義することになるので、簡単にその説明を。

1. エントリー ポイント

今のプログラミング モデルでは function.jsonscriptFileフィールドで定義していた (関数の) エントリー ポイントは、(モジュール全体のエントリー ポイントとして) package.jsonmainフィールドに移動、ロードしたい js ファイルのパスを指定することに。

package.json

{"name": "azure-functions-prototype",
    "version": "1.0.0",
    "description": "",
      :
    "main": "/PATH/TO/ENTRYPOINT.js",
      :
}

ちなみに、この mainフィールドのパスの解析、globbyを使って独自に行っているので、ワイルド カード (** , *) 指定での複数ファイルの読み込みが可能。

2. トリガー / バインディング

現状 function.jsonbindingsフィールドで定義していたトリガー / バインディング設定は、新しいモデルでは上述のエントリー ポイントとして読み込まれたファイル内で、@azure\functionsからインポートできる appにトリガーに対応するメソッド (get, timer, http, storageBlob etc) で登録していく。

以下、サンプルコード。

import{ app, HttpRequest, InvocationContext}from"@azure/functions";

app.get('helloWorld1',async(context: InvocationContext, request: HttpRequest)=>{
    context.log(`Http function processed request for url "${request.url}"`);const name = request.query.get('name')||await request.text()||'world';return{ body: `Hello, ${name}!`};});

app.timer('timerTrigger1',{
    schedule: '0 */5 * * * *',
    handler: (context: InvocationContext, myTimer: Timer)=>{const timeStamp =newDate().toISOString();
        context.log('The current time is: ', timeStamp);}});

バインディングもコードで追加する。
以下、HTTP トリガーで実行して、その時に Blob コンテナーから特定のデータを入力バインディングで取得して、その内容を出力バインディングでキューに保存する、というサンプル。

import{ app, HttpRequest, HttpResponse, input, InvocationContext, output }from"@azure/functions";const queueOutput = output.storageQueue({
  queueName: 'testqueue',
  connection: 'storage_APPSETTING'});const blobInput = input.storageBlob({
  connection: 'storage_APPSETTING',
  path: 'testcontainer/testblob',})asyncfunction helloWorldWithExtraOutputs(context: InvocationContext, request: HttpRequest): Promise<HttpResponse>{
  context.log(`Http function processed request for url "${request.url}"`);const name = request.query.get('name')||await request.text()||'world';if(process.env.storage_APPSETTING){const message = context.extraInputs.get(blobInput);
    context.extraOutputs.set(queueOutput, message);}return{ body: `Hello, ${name}!`};}const extraOutputs =[];if(process.env.storage_APPSETTING){
  extraOutputs.push(queueOutput);}const extraInputs =[];if(process.env.storage_APPSETTING){
  extraInputs.push(blobInput);}

app.http('helloWorldWithExtraInputsOutputs',{
  authLevel: "anonymous",
  methods: ['GET','POST'],
  extraOutputs,
  extraInputs,
  handler: helloWorldWithExtraOutputs
});

outputinput@azure/functionsからインポートして、そこから取得したバインディング定義のオブジェクトを httpトリガーの関数 (handler) と一緒に extraOutputs, extraInputsとして登録、という流れ。

その他諸々は上述のリンクをご参照くださいませ。

プロトタイプ

このリポジトリで公開中。

github.com

手順通りにやれば特に問題な動くことが確認できる。

注意 : Azure Functions 上にデプロイしてもまだ動かない

funcコマンドの注意点

通常のインストール方法で入れた Azure Functions Core Tools の funcコマンドから直接実行しちゃいけない。

WikiSetupの項目に

"func-cli-nodejs-v4": "4.0.4764": A preview build of the func cli that contains support for the new framework on the worker/host side of things

と書いてある通り、このプログラミング モデルでの実行には dev 版の Node.js Lauguage Worker が必要。
通常のインストール方法で入れた Azure Functions Core Tools 同梱の funcを実行してしまうと、いつも通り function.jsonを探そうとして、当然見つからないので、結果「No job functions found.」となるだけ。

上記リポジトリの場合、この dev 版 Worker は package.jsondevDependenciesにある func-cli-nodejs-v4@4.0.4764に含まれているので、npm start経由で func startを実行することで、dev 版 Worker を起動できる。

感想

だいぶ変わった印象だけど、関数登録処理自体を自前のコードでやるので、その処理の前(恐らく Worker が起動してエントリー ポイントがロードされた直後の状態)にオリジナルの処理を挟みやすくなる*1

まだ議論中の部分もありそうなので、いつ Public Preview、GA になるか、その時にはこの通り動くのかは不透明だけど、大きく変えようとしていることだけでも知っておいた方がよさそう。
他の言語も function.json廃止の方向になるんだろうか。

*1:Top-level await はまだ使えないかも


Viewing all articles
Browse latest Browse all 44

Trending Articles