У нас есть лямбда-функция 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),
]);
Проблема в том, что лямбда может занять до минуты, что довольно долго для 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) Когда ваш текущий код 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
он знает, что файл готов к загрузке.
Других решений пока нет …