2016-02-28 18 views
5

mam prostą funkcję AWS Lambda, który robi niektóre sprawdzania poprawności na obrazach zapisanych do wiadra S3. Używam async.waterfall, aby pobrać obraz i przetworzyć go, ale zanim wprowadzę pierwszą funkcję wodospadu, wykonuję podstawowe sprawdzanie danych o zdarzeniach, które otrzymuję z wyzwalacza S3 PutObject, w szczególności informacje o rozmiarze (event.Records[0].s3.object.size). Jeśli zdarzenie odwołuje się do obrazu, który jest większy niż mój MAX_SIZE, używam context.fail(new Error("Validation error: the file is too big.")), aby zakończyć egzekucję.funkcja AWS Lambda trwa trochę po context.fail

To wszystko działa poprawnie, ale zauważam, że w moich dziennikach po błędzie jest rejestrowany, funkcja nadal działa na trochę, zanim zostanie zakończony. Na przykład wywoływana jest pierwsza funkcja w moim wywołaniu async.waterfall (to znaczy komunikat z tej funkcji pojawia się w dzienniku). Próbowałem nawet dodać context.done(errorMessage) bezpośrednio po pliku context.fail, a zostanie on wykonany (tj. Wiadomość, którą przekazuję, zostanie pobrana) wraz z kilkoma dodatkowymi liniami kodu.

Czy to oczekiwane zachowanie? Nie mogłem znaleźć żadnej wzmianki o tym w dokumentach. Czy funkcja zajmuje trochę czasu, aby wyjść, czy też nie rozumiem synchronicznej natury kodu w funkcji obsługi przed PRZED async.waterfall?

Poniżej znajduje się część mojego kodu. Wszystkie wiadomości console.log wyświetlane po context.fail zostaną wydrukowane w dzienniku, czego nie oczekiwałbym.

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); 
      } 
     }); 
    }, 
    ... 
    ], ...) 
} 

Odpowiedz

2

Wygląda na to, że oczekuje się zachowania, nawet jeśli nie jest dobrze udokumentowane. Numer context documentation mówi, że fail() "wskazuje na niepowodzenie", ale nie obiecuje zatrzymać dalszego wykonywania.

context.fail()

Wskazuje wykonania funkcji lambda i wszystkie wywołania zwrotne zakończone powodzenia, w wyniku obrabianym wyjątku.

Dobrą wiadomością dla kodu jest to, że powinien on być dość łatwe do return z funkcji po wywołaniu context.fail() aby uniknąć dalszego przetwarzania.

+0

Przepraszamy za długie opóźnienie !! Dzięki za pomoc! 'return' działał (dla środowiska wykonawczego Node.js v0.10.42), ale dlaczego? Czy jest to gdzieś udokumentowane, czy coś, co powinienem wiedzieć o Node.js? http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html – readyornot

+0

Korekta, działa również w najnowszej obsługiwanej wersji Node.js (v4.3). 'return' natychmiast przerywa wykonanie, ale nadal nie rozumiem, dlaczego. Nie jest to udokumentowane tutaj: http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-mode-exceptions.html – readyornot

+0

Oczekuję, że istnieje naturalny rozłącznik między tłumaczem węzła, który obsługuje twoją funkcję a Lambdą infrastruktura nadzorująca środowisko.Mogę tylko polecić tam kodowanie obronne. Odpowiedź @ emispowder zapewnia bardziej precyzyjną kontrolę, możesz chcieć to wypróbować. – James

9

wierzę struktura AWS lambda zmienił się nieco od tego padło pytanie (i odpowiedzi Jamesa).

Teraz program obsługi ma dodatkowo funkcję "oddzwaniania", która może zostać wywołana, aby zatrzymać wykonywanie skryptu. W zależności od tego, jak go nazwiesz, kończy proces pomyślnie lub z błędem. Zobacz te dokumenty dla specyfiki.

Dodatkowo, sprawdź właściwość kontekstowe callbackWaitsForEmptyEventLoop. Domyślnie jest to prawda, ale będziesz chciał ustawić ją na wartość false, tak aby po wywołaniu wywołania proces węzła nie czekał na zakończenie pętli wykonawczej, tzn. Twoje połączenia asynchroniczne zostały odrzucone.

+0

Z wyjątkiem tego, że nie zostaną "wyrzucone", nadal istnieją, nawet jeśli proces zostanie zamrożony, a ich wywołania zwrotne będą działały w następnych wywołaniach lambda. Więc uważaj. – nitely

Powiązane problemy