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 na AWS SDK for PHP versão 3
O AWS SDK for PHP usa o padrão de comando
Uso implícito de comandos
Se você examinar qualquer classe de cliente, verá que os métodos correspondentes às API operações não existem de fato. Eles são implementados usando o método mágico __call()
. Esses pseudo-métodos são, na verdade, atalhos que encapsulam o uso de objetos SDK de comando.
Normalmente não é necessário interagir diretamente com objetos de comando. Quando você chama métodos comoAws\S3\S3Client::putObject()
, na SDK verdade, cria um Aws\CommandInterface
objeto com base nos parâmetros fornecidos, executa o comando e retorna um Aws\ResultInterface
objeto preenchido (ou lança uma exceção em caso de erro). Um fluxo semelhante ocorre ao chamar qualquer um dos Async
métodos de um cliente (por exemplo,Aws\S3\S3Client::putObjectAsync()
): o cliente cria um comando com base nos parâmetros fornecidos, serializa uma HTTP solicitação, 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 oferecem suporte a alguns parâmetros especiais que não fazem parte do serviçoAPI, mas controlam o comportamento SDK do serviço.
@http
Usando esse parâmetro, é possível ajustar a forma como o HTTP manipulador 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 nem transfere imediatamente uma HTTP solicitação, mas só é executado quando é passado para o execute()
método 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 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 HTTP cliente diferente por comando (por exemplo,Aws\MockHandler
) e adicionar comportamento personalizado por comando por meio de middleware. O exemplo a seguir usa a MockHandler
para criar resultados simulados em vez de enviar HTTP solicitações 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, podemos usar PHP'sDirectoryIterator
. 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 = 'amzn-s3-demo-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çãobefore
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ê estiver atingindo o limite de memória com grandes grupos de comandos, isso pode ser devido às referências cíclicas geradas pelo fato de ainda SDK não terem sido coletadas pelo coletor de PHP lixoCommandPool
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(); } ]);