2016-02-28 4 views
5

У меня есть простая функция AWS Lambda, которая выполняет некоторую проверку на изображениях, сохраненных в ведро S3. Я использую async.waterfall для загрузки изображения и обработки его, но прежде чем я даже войду в первую функцию водопада, я делаю некоторую базовую проверку данных событий, которые я получаю от своего триггера S3 PutObject, в частности информацию о размере (event.Records[0].s3.object.size). Если событие ссылается на изображение, которое больше моего MAX_SIZE, я использую context.fail(new Error("Validation error: the file is too big.")) для завершения выполнения.Функция AWS Lambda продолжается немного после context.fail

Все это работает нормально, но в моих журналах я замечаю, что после регистрации ошибки функция продолжает работать немного до ее выхода. Например, вызывается первая функция в моем вызове async.waterfall (т. Е. Сообщение из этой функции отображается в журнале). Я даже попытался добавить context.done(errorMessage) сразу же после файла context.fail, и он запускается (т. Е. Сообщение, которое я передаю, регистрируется), а также несколько строк кода.

Ожидается ли такое поведение? Я не мог найти упоминания об этом в документах. Занимает ли функция немного времени для выхода, или я не понимаю синхронный характер кода в функции обработчика, которая выше async.waterfall?

Ниже приведена часть моего кода. Все сообщения console.log, которые отображаются после context.fail, печатаются в журнале, чего я бы не ожидал.

exports.handler = function(event, context) { 
    console.log('Received event:', JSON.stringify(event, null, 2)); 

    if (event.Records[0].s3.object.size > MAX_FILE_SIZE) { 
    var error = new Error("Validation error: the file is too big.") 
    context.fail(error); 
    } 
    console.log('Event validation complete.') 

    var bucket = event.Records[0].s3.bucket.name; 
    var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); 
    var fileName = key.split("/")[1]; 
    var params = { 
    Bucket: bucket, 
    Key: key 
    }; 
    console.log('Starting processing of the following file: ' + JSON.stringify(params, null, 2)); 

    async.waterfall([ 
    function download(callback) { 
     // Download the image from S3 into a buffer. 
     console.log("Downloading the image from S3..."); 
     s3.getObject(params, function(err, data) { 
      if (err) { 
       callback(err); 
      } else { 
       callback(null, data); 
      } 
     }); 
    }, 
    ... 
    ], ...) 
} 

ответ

2

Ожидается, что поведение ожидается, даже если оно не задокументировано. context documentation действительно говорит, что fail() «указывает на сбой», но не обещает прекратить дальнейшее выполнение.

context.fail()

Указывает выполнение функции Лямбда и все обратные вызовы завершена неудачно, в результате чего обрабатываются исключения.

Хорошие новости для вашего кода является то, что она должна быть достаточно легко return из функции после вызова context.fail(), чтобы избежать дальнейшей обработки.

+0

Извините за долгую задержку !! Спасибо за помощь! 'return' работал (для среды выполнения Node.js v0.10.42), но почему? Это где-то документально или что-то, что я должен знать о Node.js? http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html – readyornot

+0

Коррекция, это также работает в последней поддерживаемой версии Node.js (v4.3). 'return' немедленно сокращает выполнение, но я до сих пор не понимаю, почему. Это не описано здесь: http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-mode-exceptions.html – readyornot

+0

Я ожидаю, что существует естественное отключение между интерпретатором узла, выполняющим вашу функцию, и лямбдой инфраструктура, контролирующая окружающую среду.Я могу только рекомендовать защитную кодировку там. Ответ @ emispowder предлагает более точный контроль, вы можете попробовать это. – James

9

Я считаю, что структура лямбда aws немного изменилась с тех пор, как был задан этот вопрос (и ответ Джеймса).

Теперь обработчик дополнительно имеет third argument, «обратный вызов», который можно вызвать для прекращения выполнения сценария. В зависимости от того, как вы это называете, он успешно завершает процесс или с ошибкой. См. Эти документы для уточнения.

Кроме того, ознакомьтесь с контекстным свойством, callbackWaitsForEmptyEventLoop. Он по умолчанию имеет значение true, но вы хотите установить его в false, чтобы после вызова callback процесс узла не дождался, когда цикл выполнения будет очищен, т. Е. Ваши вызовы Async будут удалены.

+0

За исключением того, что они не будут «выброшены», они все еще существуют, даже если процесс замерзает, и их обратные вызовы будут выполняться в следующих лямбда-вызовах. Так что будь осторожен. – nitely

Смежные вопросы