веб-сервисы Amazon — AWS SDK (PHP): асинхронный вызов лямбда-функции, получение статуса

У нас есть лямбда-функция AWS, используемая для обработки и настройки некоторых ужасных проприетарных форматов файлов. внизнагрузка, которая запускается из PHP через AWS SDK. Лямбда извлекает файл из корзины s3, вставляет в него некоторые метаданные, сжимает их и помещает во временную корзину s3, чтобы их можно было загрузить во время проверки покупателем.

Лямбда-часть работает без нареканий вызова / invokeAsync:

use Aws\Sdk;
...
$lambdaclient = $this->sdk->createClient('lambda',$region);

$syncresult = $lambdaclient->invoke([
'FunctionName' => $functionName,
'InvocationType' => 'RequestResponse',
'Payload' => json_encode($payload),
]);

$asyncresult = $lambdaclient->invoke([
'FunctionName' => $functionName,
'InvocationType' => 'Event',
'Payload' => json_encode($payload),
]);

$promise = $lambdaclient->invokeAsync([
'FunctionName' => $functionName,
'Payload' => json_encode($payload),
]);
  • $ syncresult будет содержать статус успешного / сбой лямбда-функции, опционально с журналом (через LogType Tail).

Проблема в том, что лямбда может занять до минуты, что довольно долго для PHP, чтобы вернуть ответ браузеру.

  • $ asyncresult вызовет функцию и вернет HTTP-статус 202, но без возможности позже проверить, действительно ли функция что-то сделала.

  • $ обещает жадность обещание которые широко используются в AWS SDK, к которому в PHP может быть привязана функция, которая будет выполняться по окончании лямбды. Это кажется очень полезным, если PHP не возвращает ответ браузеру, потому что в этот момент вы теряете обещание. Ты можешь позвонить $result = $promise->wait() чтобы разрешить это. Основным преимуществом этих обещаний, по-видимому, является одновременное выполнение нескольких лямбд и объединение результатов в одном запросе PHP.

Я хотел бы вызвать функцию асинхронно и проверить состояние функции в потом PHP-запрос (возможно, хранит некоторую ссылку на вызов в данных сеанса?). Таким образом, я мог бы позже опросить статус, используя Ajax-запрос, и убедиться, что когда я создаю подписанный URL-адрес s3 для окончательного файла, все завершается без ошибок.

Будет ли это возможно с помощью AWS SDK? Или есть лучшие решения?

Редактировать:

Я решил использовать invokeAsync, запускаемый из-за вызова ajax на стороне клиента, который прерывается (не дожидаясь ответа). Сценарию PHP дается довольно много времени для завершения (с использованием settimelimit), потому что вызовы лямбды выполняются одновременно, и браузер больше не ждет.

Я храню обещания в массиве и использую:

$values = array_map(function($result){
return json_decode($result->toArray()['Payload']->getContents());
}, Promise\unwrap($promises));

получить ответные полезные нагрузки (они обернуты в streaminterfaces AWS SDK) и записать их (DynamoDB в моем случае, SQL / session / cache, вероятно, все будет работать).

Когда конечному пользователю нужен результат, я просто проверяю сохраненные данные и существуют ли преобразованные файлы на s3.

Я мог бы улучшить обработку ajax, поиграв с очисткой выходного буфера из PHP, правильно завершив вызов с некоторым возвращенным идентификатором, и позволяя PHP ждать обещаний от AWS.

1

Решение

Да, вы могли бы сделать это, я не уверен, что вы могли бы сделать это только с помощью лямбды. То, как я подхожу к этому:

1) Когда ваш текущий код PHP будет запущен, добавьте сообщение с AWS SNS с подробной информацией о функции и параметрах. Немедленно верните в браузер сообщение с информацией о файле, который нужно посмотреть в s3. Затем сделайте в своем браузере опрос конечной точки, которую я описал в шаге 3.

2) Настройте лямбда-функцию для прослушивания сообщения SNS и запуска автоматически (http://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html)

3) Иметь другую конечную точку PHP, которую вы можете использовать с AJAX, которая проверяет, завершен ли уже созданный файл, созданный лямбда-выражением. Если вы не вернете сообщение о том, что он еще не готов, когда файл появится, верните сообщение о том, что он готов.

Если вы не хотите использовать чисто AWS-подход, вы можете сделать что-то вроде этого:

1) Когда ваш текущий PHP-код будет запущен, добавьте в таблицу базы данных запись с информацией о функции и параметрах, которые необходимо запустить, и статусом чего-то вроде queued, Отправить обратно id для записи в БД в браузер сразу. Затем сделайте в своем браузере опрос конечной точки, которую я описал в шаге 3.

2) Установите отдельный скрипт php, который работает непрерывно или запускается через cron или что-то еще, и каждые несколько секунд проверяет наличие записей в созданной выше таблице со статусом queued, Обновить статус записи на что-то вроде processing так что это не случайно побежит снова. Теперь запустите функцию Lambda и используйте обещание. По завершении обновите статус записи до complete,

3) Иметь другую конечную точку PHP, которую вы можете использовать с помощью AJAX, для которой передается идентификатор, полученный на первом этапе, и просто возвращать статус записи. Как только браузер получает статус complete он знает, что файл готов к загрузке.

1

Другие решения

Других решений пока нет …