AWS SDK for PHP バージョン 3 の promise - AWS SDK for PHP

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS SDK for PHP バージョン 3 の promise

AWS SDK for PHP では promise を使用して非同期ワークフローの使用を許可します。この非同期性により、HTTP リクエストの同時送信が可能になります。SDK によって使用される promise の仕様は Promises/A+ です。

promise とは何ですか?

promise は、非同期オペレーションの最終結果を表します。promise を操作する主な方法は、その then メソッドを介するものです。このメソッドは、promise の最終結果または実行できない理由を受け取るコールバックを登録します。

AWS SDK for PHP は、promise の実装を guzzlehttp/promises Composer パッケージに依存します。Guzzle promise はブロッキングとノンブロッキングワークフローをサポートし、ノンブロッキングループで使用できます。

注記

AWS SDK for PHP で 1 つのスレッドを使用して、HTTP リクエストが同時に送信されます。ノンブロッキング呼び出しは、状態の変更 (promise の実行または拒否など) に対応する間に、1 つ以上の HTTP リクエストを転送するために使用されます。

SDK での promise

promise は、SDK 全体で使用されます。例えば、promise は SDK で提供されるほとんどの高レベル抽象化、ページネーターウェーターコマンドプールマルチパートアップロードS3 ディレクトリ/バケット転送などで使用されます。

SDK が提供するすべてのクライアントは、Async が付いたメソッドのいずれかを呼び出した場合に promise を返します。例えば、次のコードでは、Amazon DynamoDB DescribeTable オペレーションの結果を取得するために promise を作成する方法を示しています。

$client = new Aws\DynamoDb\DynamoDbClient([ 'region' => 'us-west-2', 'version' => 'latest', ]); // This will create a promise that will eventually contain a result $promise = $client->describeTableAsync(['TableName' => 'mytable']);

describeTable または describeTableAsync のどちらかを呼び出すことができることに注意してください。これらのメソッドは、クライアントのマジック __call メソッドで、クライアントに関連付けられている version 番号と API モデルで動いています。describeTable のような Async が付いていないメソッドを呼び出すことにより、HTTP リクエストを送信する間、クライアントはブロックし、Aws\ResultInterface オブジェクトを返すか Aws\Exception\AwsException をスローします。オペレーション名の後ろに Async を付けると (describeTableAsync など)、クライアントは promise を作成します。これは最終的に実行されると Aws\ResultInterface オブジェクト、または拒否されると Aws\Exception\AwsException になります。

重要

promise が返されるとき、結果がすでに到着しています (たとえば、モックハンドラーを使用する場合)、または HTTP リクエストが開始されません。

then メソッドを使用して、promise とコールバックを登録できます。このメソッドは、2 つのコールバック、$onFulfilled$onRejected (どちらも省略可能) を受け付けます。promise が実行される場合に、$onFulfilled コールバックが呼び出され、promise が拒否される (失敗した) 場合に、$onRejected コールバックが呼び出されます。

$promise->then( function ($value) { echo "The promise was fulfilled with {$value}"; }, function ($reason) { echo "The promise was rejected with {$reason}"; } );

コマンドの同時実行

複数の promise は同時に実行されるようにまとめて構成できます。これを行うには、SDK とノンブロッキングイベントループを統合する、複数の promise を作成し、同時に完了するまで待機します。

use GuzzleHttp\Promise\Utils; $sdk = new Aws\Sdk([ 'version' => 'latest', 'region' => 'us-east-1' ]); $s3 = $sdk->createS3(); $ddb = $sdk->createDynamoDb(); $promises = [ 'buckets' => $s3->listBucketsAsync(), 'tables' => $ddb->listTablesAsync(), ]; // Wait for both promises to complete. $results = Utils::unwrap($promises); // Notice that this method will maintain the input array keys. var_dump($results['buckets']->toArray()); var_dump($results['tables']->toArray());
注記

CommandPool には複数の API オペレーションを同時に実行するためのさらに強力なメカニズムが用意されています。

promise の連鎖

promise のすばらしい特徴の 1 つは、組み合わせられること、つまり変換パイプラインを作成することができます。複数の promise は then コールバックと後続の then コールバックを連結することで構成されます。then メソッドの戻り値が promise です。指定したコールバックの結果に基づいて、実行されるか拒否されます。

$promise = $client->describeTableAsync(['TableName' => 'mytable']); $promise ->then( function ($value) { $value['AddedAttribute'] = 'foo'; return $value; }, function ($reason) use ($client) { // The call failed. You can recover from the error here and // return a value that will be provided to the next successful // then() callback. Let's retry the call. return $client->describeTableAsync(['TableName' => 'mytable']); } )->then( function ($value) { // This is only invoked when the previous then callback is // fulfilled. If the previous callback returned a promise, then // this callback is invoked only after that promise is // fulfilled. echo $value['AddedAttribute']; // outputs "foo" }, function ($reason) { // The previous callback was rejected (failed). } );
注記

promise コールバックの戻り値は $value 引数で、ダウンストリームの promise に渡されます。ダウンストリームの promise チェーンに値を指定する場合は、コールバック関数に値を返す必要があります。

拒否の転送

promise が拒否されたときに呼び出すコールバックを登録することができます。任意のコールバックで例外がスローされた場合、promise は例外で拒否され、チェーンの次の promise も例外で拒否されます。$onRejected コールバックから正常な値を返す場合、promise チェーンの次の promise が $onRejected コールバックからの戻り値で実行されます。

promise の待機

promise の wait メソッドを使用すると、promise が同期的に完了するように強制できます。

$promise = $client->listTablesAsync(); $result = $promise->wait();

promise の wait 関数を呼び出している間に例外が発生した場合は、例外により promise が拒否され、例外がスローされます。

use Aws\Exception\AwsException; $promise = $client->listTablesAsync(); try { $result = $promise->wait(); } catch (AwsException $e) { // Handle the error }

実行された promise での wait の呼び出しは wait 関数をトリガーしません。以前に配信された値だけを返します。

$promise = $client->listTablesAsync(); $result = $promise->wait(); assert($result ### $promise->wait());

拒否された promise での wait の呼び出しでは例外がスローされます。拒否理由が \Exception のインスタンスである場合、その理由がスローされます。それ以外の場合は、GuzzleHttp\Promise\RejectionException がスローされ、例外の getReason メソッドを呼び出して理由を取得できます。

注記

AWS SDK for PHP での API オペレーションの呼び出しは Aws\Exception\AwsException クラスのサブクラスで拒否されます。ただし、then メソッドが配信する理由が異なる場合もあります。拒否理由を変更するカスタムミドルウェアを追加できるためです。

promise のキャンセル

promise の cancel() メソッドを使用して、promise をキャンセルできます。promise がすでに解決された場合、cancel() を呼び出しても何も起きません。promise のキャンセルは、promise 自体とそこからの配信を待機している promise をキャンセルします。キャンセルされた promise は GuzzleHttp\Promise\RejectionException で拒否されます。

promise の結合

promise を組み合わせて複合 promise を作成し、複雑なワークフローを構築できます。guzzlehttp/promise パッケージには、promise を結合するために使用できるさまざまな関数が含まれています。

promise コレクション関数のすべての API ドキュメントを見つけるには、namespace-GuzzleHttp.Promise を参照してください。

each および each_limit

Aws\CommandInterface コマンドのタスクキューがあるとき、CommandPool を使用して、固定プールサイズ (コマンドをメモリに格納または遅延イテレーターで出力可能) で同時に実行します。CommandPool により、固定数のコマンドは、指定されたイテレーターを使い果たすまで同時に送信されます。

CommandPool は、同じクライアントで実行されたコマンドの場合にのみ機能します。固定プールサイズを使用して、異なるクライアントにコマンドを同時に送信するために、GuzzleHttp\Promise\each_limit 関数を使用できます。

use GuzzleHttp\Promise; $sdk = new Aws\Sdk([ 'version' => 'latest', 'region' => 'us-west-2' ]); $s3 = $sdk->createS3(); $ddb = $sdk->createDynamoDb(); // Create a generator that yields promises $promiseGenerator = function () use ($s3, $ddb) { yield $s3->listBucketsAsync(); yield $ddb->listTablesAsync(); // yield other promises as needed... }; // Execute the tasks yielded by the generator concurrently while limiting the // maximum number of concurrent promises to 5 $promise = Promise\each_limit($promiseGenerator(), 5); // Waiting on an EachPromise will wait on the entire task queue to complete $promise->wait();

promise コルーチン

Guzzle promise ライブラリの強力な機能の 1 つは、従来の同期のワークフローを記述するように、非同期ワークフローを記述できる promise コルーチンを使用できることです。実際、AWS SDK for PHP ではほとんどの高レベルの抽象化で、コルーチン promise を使用します。

複数のバケットを作成し、バケットが利用可能になったときに、バケットにファイルをアップロードする場合、できる限り迅速に完了するようにすべて同時に実行することを考えます。これを行うには、all() promise 関数を使用して複数のコルーチン promise を組み合わせます。

use GuzzleHttp\Promise; $uploadFn = function ($bucket) use ($s3Client) { return Promise\coroutine(function () use ($bucket, $s3Client) { // You can capture the result by yielding inside of parens $result = (yield $s3Client->createBucket(['Bucket' => $bucket])); // Wait on the bucket to be available $waiter = $s3Client->getWaiter('BucketExists', ['Bucket' => $bucket]); // Wait until the bucket exists yield $waiter->promise(); // Upload a file to the bucket yield $s3Client->putObjectAsync([ 'Bucket' => $bucket, 'Key' => '_placeholder', 'Body' => 'Hi!' ]); }); }; // Create the following buckets $buckets = ['foo', 'baz', 'bar']; $promises = []; // Build an array of promises foreach ($buckets as $bucket) { $promises[] = $uploadFn($bucket); } // Aggregate the promises into a single "all" promise $aggregate = Promise\all($promises); // You can then() off of this promise or synchronously wait $aggregate->wait();