Objetos de comando no AWS SDK for PHP Versão 3 - AWS SDK for PHP

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Objetos de comando no AWS SDK for PHP Versão 3

O AWS SDK for PHP usa o padrão de comando para encapsular os parâmetros e o manipulador que serão usados para transferir uma solicitação HTTP em um momento posterior.

Uso implícito de comandos

Se você examinar qualquer classe de cliente, poderá ver que os métodos correspondentes às operações da API na verdade não existem. Eles são implementados usando o método mágico __call(). Na verdade, os pseudométodos são atalhos que encapsulam o uso de objetos de comando pelo SDK.

Normalmente não é necessário interagir diretamente com objetos de comando. Quando você chama métodos, como Aws\S3\S3Client::putObject(), o SDK realmente cria um objeto Aws\CommandInterface com base nos parâmetros fornecidos, executa o comando e retorna um objeto Aws\ResultInterface preenchido (ou gera uma exceção em erro). Um fluxo semelhante ocorre ao chamar qualquer um dos métodos Async de um cliente (por exemplo, Aws\S3\S3Client::putObjectAsync()): o cliente cria um comando com base nos parâmetros fornecidos, serializa uma solicitação HTTP, inicia a solicitação e retorna uma promessa.

Os exemplos a seguir são todos equivalentes funcionalmente.

$s3Client = new Aws\S3\S3Client([ 'version' => '2006-03-01', 'region' => 'us-standard' ]); $params = [ 'Bucket' => 'foo', 'Key' => 'baz', 'Body' => 'bar' ]; // Using operation methods creates a command implicitly $result = $s3Client->putObject($params); // Using commands explicitly $command = $s3Client->getCommand('PutObject', $params); $result = $s3Client->execute($command);

Parâmetros de comando

Todos os comandos são compatíveis com alguns parâmetros especiais que não fazem parte de uma API do serviço, mas que controlam o comportamento do SDK.

@http

Usando esse parâmetro, é possível ajustar a forma como o manipulador HTTP subjacente executa a solicitação. As opções que podem ser incluídas no parâmetro @http são as mesmas que podem ser definidas ao instanciar o cliente com a opção de cliente "http".

// Configures the command to be delayed by 500 milliseconds $command['@http'] = [ 'delay' => 500, ];

@retries

Como a opção de cliente "retries", @retries controla quantas vezes um comando pode ser executado novamente antes que seja considerado com falha. Defina-o como 0 para desabilitar repetições.

// Disable retries $command['@retries'] = 0;
nota

Se tiver desabilitado repetições em um cliente, você não poderá habilitá-las seletivamente em comandos individuais passados para esse cliente.

Criação de objetos de comando

Você pode criar um comando usando um método getCommand() do cliente. Ele não executa imediatamente ou transfere uma solicitação HTTP, mas é executado apenas quando é passado para o método execute() do cliente. Isso fornece a oportunidade de modificar o objeto de comando antes de executar o comando.

$command = $s3Client->getCommand('ListObjects'); $command['MaxKeys'] = 50; $command['Prefix'] = 'foo/baz/'; $result = $s3Client->execute($command); // You can also modify parameters $command = $s3Client->getCommand('ListObjects', [ 'MaxKeys' => 50, 'Prefix' => 'foo/baz/', ]); $command['MaxKeys'] = 100; $result = $s3Client->execute($command);

Comando da HandlerList

Quando um comando é criado a partir de um cliente, ele recebe um clone do objeto Aws\HandlerList do cliente. O comando recebe um clone da lista de manipuladores do cliente para permitir que um comando use manipuladores e middleware personalizado que não afetem outros comandos executados pelo cliente.

Isso significa que você pode usar um cliente HTTP diferente por comando (por exemplo, Aws\MockHandler) e adicionar o comportamento personalizado por comando por meio do middleware. O exemplo a seguir usa um MockHandler para criar modelos de resultados simulados em vez de enviar solicitações HTTP reais.

use Aws\Result; use Aws\MockHandler; // Create a mock handler $mock = new MockHandler(); // Enqueue a mock result to the handler $mock->append(new Result(['foo' => 'bar'])); // Create a "ListObjects" command $command = $s3Client->getCommand('ListObjects'); // Associate the mock handler with the command $command->getHandlerList()->setHandler($mock); // Executing the command will use the mock handler, which returns the // mocked result object $result = $client->execute($command); echo $result['foo']; // Outputs 'bar'

Além de alterar o manipulador usado pelo comando, você também pode injetar middleware personalizado no comando. O exemplo a seguir usa o middleware tap, que funciona como um observador na lista de manipuladores.

use Aws\CommandInterface; use Aws\Middleware; use Psr\Http\Message\RequestInterface; $command = $s3Client->getCommand('ListObjects'); $list = $command->getHandlerList(); // Create a middleware that just dumps the command and request that is // about to be sent $middleware = Middleware::tap( function (CommandInterface $command, RequestInterface $request) { var_dump($command->toArray()); var_dump($request); } ); // Append the middleware to the "sign" step of the handler list. The sign // step is the last step before transferring an HTTP request. $list->append('sign', $middleware); // Now transfer the command and see the var_dump data $s3Client->execute($command);

CommandPool

O Aws\CommandPool permite executar comandos simultaneamente usando um iterador que produz objetos Aws\CommandInterface. O CommandPool garante que um número constante de comandos sejam executados simultaneamente durante a iteração dos comandos no grupo (conforme os comandos são concluídos, mais são executados para garantir um tamanho constante do grupo).

Este é um exemplo muito simples de envio de alguns comandos usando um CommandPool.

use Aws\S3\S3Client; use Aws\CommandPool; // Create the client $client = new S3Client([ 'region' => 'us-standard', 'version' => '2006-03-01' ]); $bucket = 'example'; $commands = [ $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'a']), $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'b']), $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'c']) ]; $pool = new CommandPool($client, $commands); // Initiate the pool transfers $promise = $pool->promise(); // Force the pool to complete synchronously $promise->wait();

Esse exemplo é extremamente insuficiente para o CommandPool. Vamos tentar um exemplo mais complexo. Vamos supor que você queira fazer upload de arquivos no disco em um bucket do Amazon S3. Para obter uma lista de arquivos do disco, você pode usar o DirectoryIterator do PHP. Esse iterador produz objetos SplFileInfo. O CommandPool aceita um iterador que produz objetos Aws\CommandInterface, portanto, mapeamos pelos objetos SplFileInfo para retornar objetos Aws\CommandInterface.

<?php require 'vendor/autoload.php'; use Aws\Exception\AwsException; use Aws\S3\S3Client; use Aws\CommandPool; use Aws\CommandInterface; use Aws\ResultInterface; use GuzzleHttp\Promise\PromiseInterface; // Create the client $client = new S3Client([ 'region' => 'us-standard', 'version' => '2006-03-01' ]); $fromDir = '/path/to/dir'; $toBucket = 'my-bucket'; // Create an iterator that yields files from a directory $files = new DirectoryIterator($fromDir); // Create a generator that converts the SplFileInfo objects into // Aws\CommandInterface objects. This generator accepts the iterator that // yields files and the name of the bucket to upload the files to. $commandGenerator = function (\Iterator $files, $bucket) use ($client) { foreach ($files as $file) { // Skip "." and ".." files if ($file->isDot()) { continue; } $filename = $file->getPath() . '/' . $file->getFilename(); // Yield a command that is executed by the pool yield $client->getCommand('PutObject', [ 'Bucket' => $bucket, 'Key' => $file->getBaseName(), 'Body' => fopen($filename, 'r') ]); } }; // Now create the generator using the files iterator $commands = $commandGenerator($files, $toBucket); // Create a pool and provide an optional array of configuration $pool = new CommandPool($client, $commands, [ // Only send 5 files at a time (this is set to 25 by default) 'concurrency' => 5, // Invoke this function before executing each command 'before' => function (CommandInterface $cmd, $iterKey) { echo "About to send {$iterKey}: " . print_r($cmd->toArray(), true) . "\n"; }, // Invoke this function for each successful transfer 'fulfilled' => function ( ResultInterface $result, $iterKey, PromiseInterface $aggregatePromise ) { echo "Completed {$iterKey}: {$result}\n"; }, // Invoke this function for each failed transfer 'rejected' => function ( AwsException $reason, $iterKey, PromiseInterface $aggregatePromise ) { echo "Failed {$iterKey}: {$reason}\n"; }, ]); // Initiate the pool transfers $promise = $pool->promise(); // Force the pool to complete synchronously $promise->wait(); // Or you can chain the calls off of the pool $promise->then(function() { echo "Done\n"; });

Configuração de CommandPool

O construtor Aws\CommandPool aceita várias opções de configuração.

concurrency (callable|int)

O número máximo de comandos a serem executados simultaneamente. Forneça uma função para redimensionar o grupo dinamicamente. A função recebe o número atual de solicitações pendentes e deverá retornar um número inteiro que representa o novo limite de tamanho do grupo.

before (callable)

Função a ser invocada antes de enviar cada comando. A função before aceita o comando e a chave do iterador do comando. Você pode modificar o comando conforme necessário na função before antes de enviar o comando.

fulfilled (callable)

Função a ser invocada quando uma promessa é cumprida. A função recebe o objeto de resultado, o ID do iterador do qual o resultado foi enviado e a promessa agregada que pode ser resolvida ou rejeitada se você precisar dar um curto circuito no grupo.

rejected (callable)

Função a ser invocada quando uma promessa é rejeitada. A função recebe um objeto Aws\Exception, o ID do iterador no qual o exceção foi gerada e a promessa agregada que pode ser resolvida ou rejeitada se você precisar dar um curto circuito no grupo.

Coleta de resíduos manual entre comandos

Se você atingir o limite de memória com grandes grupos de comandos, isso pode ser devido a referências cíclicas geradas pelo SDK ainda não terem sido coletadas pelo coletor de lixo do PHP quando o limite de memória foi atingido. Invocar manualmente o algoritmo de coleta entre comandos pode permitir que os ciclos sejam coletados antes que esse limite seja atingido. O exemplo a seguir cria um CommandPool que invoca o algoritmo de coleta usando um retorno de chamada antes de enviar cada comando. Observe que a invocação do coletor de lixo não vêm com um custo de desempenho e o uso ideal dependerá do seu caso de uso e do ambiente.

$pool = new CommandPool($client, $commands, [ 'concurrency' => 25, 'before' => function (CommandInterface $cmd, $iterKey) { gc_collect_cycles(); } ]);