この記事では、既存の Durable Functions アプリを Node.js プログラミング モデルのバージョン 4 にアップグレードするためのガイドを提供します。 この記事では、"ヒント" バナーを使用して、アプリのアップグレードに必要な主要な手順を要約します。
代わりに、新規の v4 アプリの作成に関心がある場合は、JavaScript と TypeScript の Visual Studio Code のクイックスタートに従うことができます。
ヒント
このガイドに従う前に、一般的なバージョン 4 のアップグレード ガイドに従っていることを確認してください。
前提条件
このガイドに従う前に、まず次の手順に従ってください。
- Node.js バージョン 18.x 以降をインストールします。
- TypeScript バージョン 4.x 以降をインストールします。
- Azure Functions ランタイム バージョン 4.25 以降でアプリを実行します。
- Azure Functions Core Tools バージョン 4.0.5382 以降をインストールします。
- 一般的なAzure Functions Node.js プログラミング モデル v4 アップグレード ガイドを確認します。
durable-functions
npm パッケージをアップグレードする
Note
プログラミング モデルのバージョンと durable-functions
パッケージのバージョンを混同しないでください。 v4 プログラミング モデルには durable-functions
パッケージ バージョン 3.x が必要ですが、v3 プログラミング モデルには durable-functions
バージョン 2.x が必要です。
v4 プログラミング モデルは、durable-functions
npm パッケージの v3.x でサポートされています。 プログラミング モデル v3 アプリでは、依存関係に durable-functions
v2.x が一覧表示されている可能性があります。 durable-functions
パッケージの v3.x に更新したことを確認してください。
ヒント
durable-functions
npm パッケージの v3.x にアップグレードします。 これを行うには、次のコマンドを使います。
npm install durable-functions
Durable Functions トリガーを登録する
v4 プログラミング モデルでは、トリガーとバインドを別 function.json
のファイルで宣言することは過去の処理です。 durable-functions
パッケージのルートにある app
名前空間にある新しい API を使用して、Durable Functions のトリガーとバインドをコードで直接登録できるようになりました。 例については、以下のコード スニペットを参照してください。
オーケストレーションの移行
const df = require('durable-functions');
const activityName = 'helloActivity';
df.app.orchestration('durableOrchestrator', function* (context) {
const outputs = [];
outputs.push(yield context.df.callActivity(activityName, 'Tokyo'));
outputs.push(yield context.df.callActivity(activityName, 'Seattle'));
outputs.push(yield context.df.callActivity(activityName, 'Cairo'));
return outputs;
});
import * as df from 'durable-functions';
import { OrchestrationContext, OrchestrationHandler } from 'durable-functions';
const activityName = 'hello';
const durableHello1Orchestrator: OrchestrationHandler = function* (context: OrchestrationContext) {
const outputs = [];
outputs.push(yield context.df.callActivity(activityName, 'Tokyo'));
outputs.push(yield context.df.callActivity(activityName, 'Seattle'));
outputs.push(yield context.df.callActivity(activityName, 'Cairo'));
return outputs;
};
df.app.orchestration('durableOrchestrator', durableHello1Orchestrator);
エンティティの移行
const df = require('durable-functions');
df.app.entity('Counter', (context) => {
const currentValue = context.df.getState(() => 0);
switch (context.df.operationName) {
case 'add':
const amount = context.df.getInput();
context.df.setState(currentValue + amount);
break;
case 'reset':
context.df.setState(0);
break;
case 'get':
context.df.return(currentValue);
break;
}
});
import * as df from 'durable-functions';
import { EntityContext, EntityHandler } from 'durable-functions';
const counterEntity: EntityHandler<number> = (context: EntityContext<number>) => {
const currentValue: number = context.df.getState(() => 0);
switch (context.df.operationName) {
case 'add':
const amount: number = context.df.getInput();
context.df.setState(currentValue + amount);
break;
case 'reset':
context.df.setState(0);
break;
case 'get':
context.df.return(currentValue);
break;
}
};
df.app.entity('Counter', counterEntity);
アクティビティの移行
ヒント
Durable Functions アプリから function.json
ファイルを削除します。 代わりに、app
名前空間の メソッド (df.app.orchestration()
、df.app.entity()
、df.app.activity()
) を使用して Durable Functions を登録します。
Durable Client 入力バインディングを登録する
v4 モデルでは、永続的なクライアントと同様に、セカンダリ入力バインディングの登録もコードで行われます。 input.durableClient()
メソッドを使用して、永続的なクライアント入力バインディングを任意の関数に登録します。 関数の本体で、getClient()
を使用して、以前と同様にクライアント インスタンスを取得します。 次の例は、HTTP によってトリガーされる関数を使用する例を示しています。
const { app } = require('@azure/functions');
const df = require('durable-functions');
app.http('durableHttpStart', {
route: 'orchestrators/{orchestratorName}',
extraInputs: [df.input.durableClient()],
handler: async (_request, context) => {
const client = df.getClient(context);
// Use client in function body
},
});
import { app, HttpHandler, HttpRequest, HttpResponse, InvocationContext } from '@azure/functions';
import * as df from 'durable-functions';
const durableHttpStart: HttpHandler = async (request: HttpRequest, context: InvocationContext): Promise<HttpResponse> => {
const client = df.getClient(context);
// Use client in function body
};
app.http('durableHttpStart', {
route: 'orchestrators/{orchestratorName}',
extraInputs: [df.input.durableClient()],
handler: durableHttpStart,
});
ヒント
input.durableClient()
メソッドを使用して、永続的なクライアントの追加入力をクライアント関数に登録します。 DurableClient
インスタンスを取得するには、通常どおりに getClient()
を使用します。
Durable Client API 呼び出しを更新する
durable-functions
の v3.x
では、DurableClient
クラス上の複数の API (DurableOrchestrationClient
から名前が変更) が簡略化され、呼び出しが容易になり、効率化されました。 多くのオプションの引数を API に渡す場合、複数の個別のオプションの引数ではなく、1 つのオプション オブジェクトを渡すようになりました。 これらの変更の例を次に示します。
すべての変更のリストについては、以下を参照してください。
V3 モデル (Durable Functions v2.x) | V4 モデル (Durable Functions v3.x) |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ヒント
必要に応じて、DurableClient
API 呼び出しを個別のオプションの引数からオプション オブジェクトに更新してください。 影響を受けるすべての API については、上記のリストを参照してください。
callHttp API 呼び出しを更新する
durable-functions
の v3.x では、DurableOrchestrationContext
の callHttp()
API が更新されました。 変更点を次に示します。
- 複数のオプションの引数ではなく、すべての引数に対して 1 つのオプション オブジェクトを受け入れます。これは Express などのフレームワークに近くなっています。
uri
引数の名前をurl
に変更します。content
引数の名前をbody
に変更します。enablePolling
を優先してasynchronousPatternEnabled
フラグを非推奨にしました。
オーケストレーションで callHttp
API を使用していた場合は、上記の変更に準拠するようにこれらの API 呼び出しを更新してください。 次の例をご覧ください:
ヒント
新しいオプション オブジェクトを使用するように、オーケストレーション内で API 呼び出しを callHttp
に更新します。
新しい型を活用する
durable-functions
パッケージで、以前にエクスポートされなかった新しい型が公開されるようになりました。 これにより、関数をより厳密に型指定し、オーケストレーション、エンティティ、およびアクティビティのより強力なタイプ セーフを提供できます。 これにより、これらの関数を作成するための IntelliSense も向上します。
新しくエクスポートされた型の一部を次に示します。
- オーケストレーション用の
OrchestrationHandler
およびOrchestrationContext
- エンティティ用の
EntityHandler
およびEntityContext
- アクティビティ用の
ActivityHandler
- クライアント関数用の
DurableClient
クラス
ヒント
durable-functions
パッケージからエクスポートされた新しい型を利用して、関数を厳密に型指定します。
トラブルシューティング
オーケストレーション コードの実行時に次のエラーが表示される場合は、Azure Functions ランタイムの v4.25
以上を実行しているか、ローカルで実行されている場合は、Azure Functions Core Tools の v4.0.5382
以上を実行していることを確認してください。
Exception: The orchestrator can not execute without an OrchestratorStarted event.
Stack: TypeError: The orchestrator can not execute without an OrchestratorStarted event.
それでも正常に機能しない場合、または他の問題が発生した場合は、いつでも GitHub リポジトリにバグ レポートを提出できます。