私と私の猫の他は誰でも隠し事を持っている

野良プログラマ発、日々のアウトプット

PHP プログラムから Step Functions を使う

最近、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>);

// Step Functions クライアント生成
$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() にすると簡単に同期処理できます。