今日は前回の記事でまとめたAWS Lambda Durable Functions を引き続き触っていきます。
https://serverless.co.jp/blog/ol99-1j-rx/
前回の記事ではREST APIにリクエストを出したのち、5秒間隔で関数を再起動させその処理実行ステータスをポーリングで取得し、200が戻ればステップを続行、というサンプルを作りました。
この記事では、ポーリング型ではなく、外部からPush型で処理を再起動させるcall back 関数を作成します。
さっそくやってみる
1. Request Catcher で Call Back ID を受け取るエンドポイントの作成
https://requestcatcher.com/ にアクセスを行い`kameda`でもなんでも適当な文字列を入れて専用エンドポイントを作成します。

2. Durable Functions の作成
コンソールからLambda関数を作成します。作成方法は前回の記事同様、以下のチェックを付けるだけであとはいつもと同じです。

3. 関数の作成と起動
以下のコードを貼り付けます。
import { withDurableExecution } from "@aws/durable-execution-sdk-js";
// 外部システムにコールバックIDを送信する関数
async function sendApprovalRequest(context, callbackId, orderId) {
const url = "https://kameda.requestcatcher.com";
const data = {
orderId: orderId,
callbackId: callbackId,
message: "承認リクエスト - このcallbackIdを使って承認してください",
timestamp: new Date().toISOString()
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
context.logger.info(`RequestCatcherへPOST完了: ${response.status}`);
context.logger.info(`送信データ: ${JSON.stringify(data)}`);
return response.status;
} catch (error) {
context.logger.error(`RequestCatcherへのPOSTエラー: ${error.message}`);
throw error;
}
}
export const handler = withDurableExecution(async (event, context) => {
const orderId = event.orderId;
// 1. コールバックを作成
const [promise, callbackId] = await context.createCallback("approval", {
timeout: { hours: 24 },
});
context.logger.info("Callback is created!");
context.logger.info(`Generated Callback ID: ${callbackId}`);
// 2. 外部システム(RequestCatcher)にコールバックIDを送信
await sendApprovalRequest(context, callbackId, orderId);
// 3. 外部からの応答を待機
context.logger.info("waiting for approval...");
const approval = await promise;
context.logger.info(`Approval received: ${JSON.stringify(approval)}`);
return {
orderId: orderId,
status: approval.approved ? "approved" : "rejected",
approval: approval,
callbackId: callbackId
};
});適当なテストイベントを作成しテストを行うとRequest Catcher にCall Back IDを出力したのち待ちとなります。待ち状態の間はCPU課金はされません。

Lambdaコンソール Durable executionsタブでは以下の様に実行中となっています。

4. Callback 用 Lambda 関数の作成
Lambda関数は今度は通常用(Durable Functionsのオプションを外す)で作成します。
提供されるSDKのバージョンの関係でローカルでライブラリインポート済のzipを作成してアップロードする必要があるため以下のコマンドをローカル環境で実行します。
npm init
npm add @aws-sdk/client-lambda@latest
vi index.mjsindex.mjsは以下を貼り付けます。
import {
LambdaClient,
SendDurableExecutionCallbackSuccessCommand
} from "@aws-sdk/client-lambda";
const client = new LambdaClient({ region: "us-east-2" });
export const handler = async (event) => {
const command = new SendDurableExecutionCallbackSuccessCommand({
FunctionName: "durablefunction",
CallbackId: event.callbackId,
Result: JSON.stringify({
approved: true,
approver: "test@test.com"
})
});
await client.send(command);
return { statusCode: 200, body: "Callback sent" };
};FunctionName: "durablefunction",としてCallBack先の関数名を指定していますが、試したところ実は何でも動作するようです。Call Back IDが正確であれば問題ありません。
zip -r function.zip index.mjs node_modules/を実行して作成されたfunctiuon.zipをLambdaコンソールにアップロードします。
5. IAM Policy の作成
CallbackはLambda関数の実行の他に専用の権限が必要です。
Callback用関数にアタッチされているIAMロールに以下のポリシーを付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:SendDurableExecutionCallbackSuccess",
"lambda:SendDurableExecutionCallbackFailure"
],
"Resource": "arn:aws:lambda:us-east-2:*:function:*"
}
]
}6. テストイベントの作成とテスト実行
Request Catcher に出力されたCall back IDをもとに以下のテストイベントを作成します。
{
"callbackId": "Ab9hZXijYXJuOmF3czpsYW1iZGE6dXMtZWFzdC0yOjkxNzU2MTA3NTExNDpmdW5jdGlvbjpkdXJhYmxlZnVuY3Rpb25zOiRMQVRFU1QvZHVyYWJsZS1leGVjdXRpb24vZTdlYjJkN2UtYTFiMC00ZGZiLWEyMzAtZDNlYjMxYWJiYjBmLzZmOWYyZTA0LTljZDUtMzE3My04ZWI2LTA0YmMyNjhkYjJkYWFpeCRlNWYzZmVlNS05MTlmLTQ2OWItYTdjOS0zOWEwNGNjMDFiOGL/"
}値は毎回異なりますので適宜入れ替えてください。実行が成功すれば以下の様にCall backが成功します。
Status: Succeeded
Test Event Name: callback
Response:
{
"statusCode": 200,
"body": "Callback sent"
}
The area below shows the last 4 KB of the execution log.
Function Logs:
START RequestId: 658acf42-b1d5-4fec-86a0-75fa51adcafd Version: $LATEST
END RequestId: 658acf42-b1d5-4fec-86a0-75fa51adcafd
REPORT RequestId: 658acf42-b1d5-4fec-86a0-75fa51adcafd Duration: 983.97 ms Billed Duration: 1414 ms Memory Size: 128 MB Max Memory Used: 101 MB Init Duration: 429.18 ms
Request ID: 658acf42-b1d5-4fec-86a0-75fa51adcafdDurable Function用関数の方では無事実行が成功しています。

Call backによりwaitが解除され残りのStepが実行されます。


