Objetos comando deAWS SDK for PHPversión 3 - AWS SDK for PHP

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Objetos comando deAWS SDK for PHPversión 3

AWS SDK for PHP usa el patrón de comandos para encapsular los parámetros y el controlador que se utilizarán para transferir una solicitud HTTP en un momento posterior.

Uso implícito de comandos

Si examina cualquier clase de cliente, verá que los métodos que corresponden a las operaciones de la API no existen en realidad. Se implementan mediante el método mágico __call(). Estos pseudométodos son en realidad accesos directos que encapsulan el uso de objetos comando por parte del SDK.

Normalmente no tendrá que interactuar con objetos comando directamente. Cuando llama a métodos como Aws\S3\S3Client::putObject(), el SDK en realidad crea un objeto Aws\CommandInterface utilizando los parámetros proporcionados, ejecuta el comando y devuelve un objeto Aws\ResultInterface con la información devuelta (o genera una excepción en caso de error). El flujo es similar cuando se llama a cualquiera de los métodos Async de un cliente (por ejemplo, Aws\S3\S3Client::putObjectAsync()): el cliente crea un comando basado en los parámetros proporcionados, serializa una solicitud HTTP, inicia la solicitud y devuelve una promesa.

Los siguientes ejemplos son funcionalmente equivalentes.

$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 los comandos admiten algunos parámetros especiales que no forman parte de una API del servicio, sino que controlan el comportamiento del SDK.

@http

Con este parámetro se puede ajustar la forma en que el controlador HTTP subyacente ejecuta la solicitud. Las opciones que puede incluir en el parámetro @http son las mismas que puede establecer al crear instancias para el cliente con la opción de cliente "http".

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

@retries

Al igual que la opción del cliente "retries", @retries controla cuántas veces un comando se pueden reintentar antes de que se considere que se ha producido un error. Si establece el valor 0, se deshabilitan los reintentos.

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

Cuando se deshabilitan los reintentos en un cliente, no es posible habilitarlos de manera selectiva en los comandos individuales que se pasan a ese cliente.

Crear objetos comando

Puede crear un comando con el método getCommand() de un cliente. No ejecuta ni transfiere inmediatamente una solicitud HTTP, solo se ejecuta cuando se especifica en el método execute() del cliente. Esto le da la oportunidad de modificar el objeto comando antes de ejecutarlo.

$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);

HandlerList de comando

Cuando se crea un comando desde un cliente, se le asigna un clon del objeto Aws\HandlerList del cliente. Se asigna al comando un clon de la lista de controladores del cliente para permitirle usar middleware y controladores personalizados sin afectar a los demás comandos que ejecuta el cliente.

Esto significa que puede utilizar un cliente HTTP diferente para cada comando (por ejemplo, Aws\MockHandler) y añadir un comportamiento personalizado para cada comando mediante middleware. En el ejemplo siguiente se usa MockHandler para crear resultados simulados en lugar de enviar solicitudes HTTP reales.

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'

Además de cambiar el controlador que usa el comando, también puede inyectarle middleware personalizado. En el ejemplo siguiente se usa el middleware tap, que actúa como observador en la lista de controladores.

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

El objeto Aws\CommandPool permite ejecutar comandos de forma simultánea mediante un iterador que proporciona objetos Aws\CommandInterface. CommandPool garantiza la ejecución simultánea de un número constante de comandos mientras se itera por los comandos del grupo (cuando se completen comandos, se ejecutan otros para asegurar el número constante).

El siguiente es un ejemplo muy sencillo de cómo enviar algunos comandos con 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();

Este ejemplo no aprovecha bien CommandPool. Probemos con uno algo más complejo. Supongamos que desea cargar archivos del disco en un bucket de Amazon S3. Para obtener una lista de archivos del disco, podemos usar DirectoryIterator de PHP. Este iterador devuelve objetos SplFileInfo. CommandPool acepta un iterador que devuelve objetos Aws\CommandInterface, por lo que asignamos los objetos SplFileInfo para conseguir 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"; });

Configuración de CommandPool

El constructor Aws\CommandPool acepta distintas opciones de configuración.

concurrency (invocable|entero)

Número máximo de comandos que se ejecutan de forma simultánea. Especifique una función para cambiar el tamaño del grupo de forma dinámica. La función recibe el número actual de solicitudes pendientes y se espera que devuelva un número entero que representa el nuevo límite de tamaño del grupo.

before (invocable)

Function que se invoca antes de enviar cada comando. La función before acepta el comando y la clave del iterador del comando. Puede cambiar el comando de la before como sea necesario antes de enviar el comando.

fulfilled (invocable)

Función que se invoca invocar cuando una promesa se ha cumplido. La función recibe el objeto resultado, el ID del iterador del que proviene el resultado y la promesa agregada que se puede resolver o rechazar si es necesario cerrar el grupo.

rejected (invocable)

Función que se invoca invocar cuando una promesa se ha rechazado. La función recibe un objeto Aws\Exception, el ID del iterador del que proviene la excepción y la promesa agregada que se puede resolver o rechazar si es necesario cerrar el grupo.

Recopilación manual de elementos no utilizados entre comandos

Si se alcanza el límite de memoria al utilizar grupos de comandos de gran tamaño, puede deberse a las referencias cíclicas generadas por el SDK que el recolector de elementos no utilizados de PHP todavía no había recopilado cuando se alcanzó el límite de memoria. Si se invoca manualmente el algoritmo de recopilación entre los comandos, es posible que los ciclos se recopilen antes de alcanzar dicho límite. En el siguiente ejemplo, se crea un CommandPool que invoca el algoritmo de recopilación mediante una devolución de llamada antes del envío de cada de parte. Tenga en cuenta que invocar el recolector de elementos no utilizados conlleva un costo de rendimiento y su uso óptimo dependerá de su caso de uso y su entorno.

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