最近、AWS Step Functions を使ってみたのですが、これが中々面白い。ステートマシンというワークフローを定義して、予め作っておいた Lambda 関数群を順に実行して出力値を次の関数に渡したり、分岐・ループ、並列実行等もできちゃう。Lambda 関数を Unix コマンドになぞらえると Step Functions はシェルスクリプトですな。単純な機能の Lambda 関数を組み合わせて複雑な処理が可能になるので、バッチ処理的なユースケースでサーバレス化が捗りそうです。
そんな便利な Step Functions ですが、ステートマシンの作り方等は他に解説がいくらでもあるので、今回は作ったステートマシンを PHP プロうグラムから実行する話。単純な要件だけど、コードサンプルが意外に見つからなかったもので。
以下、ステートマシンを非同期に実行開始して、1秒毎に状態取得・出力するという例です。AWS SDK for PHP 3 が必要なので、下記スクリプトのある場所で composer require aws/aws-sdk-php してある前提です。
<?php
require_once('./vendor/autoload.php');
define('AWS_ACCESS_KEY', <あなたのアクセスキー>);
define('AWS_SECRET_ACCESS_KEY', <あなたのシークレットアクセスキー>);
define('AWS_REGION', <リージョン>);
define('STATEMACHINE_ARN', <あなたのステートマシンのARN>);
$credentials = new Aws\Credentials\Credentials(AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY);
$sfn = new Aws\Sfn\SfnClient([
'region' => AWS_REGION,
'version' => 'latest',
'credentials' => $credentials
]);
$input = [
"var1" => "a",
"var2" => "b",
"var3" => "c",
];
$result = $sfn->startExecution([
'stateMachineArn' => STATEMACHINE_ARN,
'input' => json_encode($input)
]);
$executionArn = $result['executionArn'];
for ($events=[],$expire=time() + 60; time() < $expire;) {
sleep(1);
$result = $sfn->describeExecution([
'executionArn' => $executionArn
]);
$status = $result['status'];
$result = $sfn->getExecutionHistory([
'executionArn' => $executionArn
]);
$newEvents = array_slice($result['events'], count($events));
foreach ($newEvents as $newEvent) {
printf("[%d] %s\n", $newEvent['id'], $newEvent['type']);
}
$events = $result['events'];
if ($status != 'RUNNING') {
break;
}
}
Lambda 関数の内部でもプログレスを DynamoDB 等に出力するようにすれば、より詳しい監視が可能になるかも。逆にそこまで詳しく状態把握する必要がなければ、startExecution() を startSyncExecution() にすると簡単に同期処理できます。