2016-02-28 29 views
5

Ho una semplice funzione AWS Lambda che esegue alcune convalide sulle immagini salvate in un bucket S3. Sto usando async.waterfall per scaricare l'immagine ed elaborarla, ma prima ancora di inserire la prima funzione waterfall, eseguo alcune convalide di base sui dati degli eventi che ottengo dal trigger S3 PutObject, in particolare le informazioni sulla dimensione (event.Records[0].s3.object.size). Se l'evento fa riferimento a un'immagine che è maggiore del mio MAX_SIZE, io uso context.fail(new Error("Validation error: the file is too big.")) per terminare l'esecuzione.La funzione AWS Lambda continua per un po 'dopo context.fail

Funziona tutto bene, ma ho notato nei miei registri che dopo che l'errore è stato registrato, la funzione continua a funzionare per un po 'prima di uscire. Ad esempio, la prima funzione nella mia chiamata async.waterfall viene chiamata (ad esempio, un messaggio da quella funzione viene visualizzato nel registro). Ho anche provato ad aggiungere uno context.done(errorMessage) immediatamente dopo context.fail, e viene eseguito (cioè il messaggio che ho inserito viene registrato) insieme a qualche altra riga di codice.

È questo comportamento previsto? Non ho trovato alcuna menzione di questo nei documenti. La funzione richiede un po 'di tempo per uscire o sto fraintendendo la natura sincrona del codice nella funzione di gestore che è PRIMA di async.waterfall?

Di seguito è riportato parte del mio codice. Tutti i messaggi console.log visualizzati dopo context.fail vengono stampati nel registro, cosa che non mi aspetto che accada.

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

risposta

2

Sembra essere un comportamento previsto, anche se non ben documentato. Il context documentation dice "fail()" indica un errore "ma non promette di interrompere ulteriori esecuzioni.

context.fail()

Indica dell'esecuzione della funzione lambda e tutte le richiamate completato senza successo, causando un'eccezione gestita.

La buona notizia per il codice è che dovrebbe essere abbastanza facile da return dalla funzione dopo aver chiamato context.fail() per evitare ulteriori elaborazioni.

+0

Ci scusiamo per il lungo ritardo !! Grazie per l'aiuto! 'return' ha funzionato (per il runtime Node.js v0.10.42), ma perché? È documentato da qualche parte o qualcosa che dovrei sapere su Node.js? http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html Correzione – readyornot

+0

, funziona anche nell'ultima versione supportata di Node.js (v4.3). 'return' taglia immediatamente l'esecuzione, ma ancora non capisco perché. Non è documentato qui: http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-mode-exceptions.html – readyornot

+0

Mi aspetto che ci sia una naturale disconnessione tra l'interprete Node che esegue la funzione e il Lambda infrastruttura di supervisione dell'ambiente.Posso solo raccomandare la codifica difensiva lì. La risposta di @ emispowder offre un controllo più preciso, potresti volerlo provare. – James

9

Credo che la struttura aws lambda sia cambiata un po 'da quando è stata posta questa domanda (e la risposta di James).

Ora il gestore ha anche un third argument, "callback", che può essere chiamato per interrompere l'esecuzione dello script. A seconda di come lo si chiama, esce il processo con successo o con un errore. Vedi quei documenti per specifiche.

Inoltre, controlla la proprietà del contesto, callbackWaitsForEmptyEventLoop. Il valore predefinito è true, ma è necessario impostarlo su false in modo che, una volta richiamato il callback, il processo del nodo non attenda il ciclo di runtime da cancellare, cioè le chiamate asincrone vengono eliminate.

+0

Tranne che non saranno "gettati via", sono ancora lì anche se il processo viene bloccato e le loro richiamate verranno eseguite entro le invocazioni lambda. Perciò stai attento. – nitely

Problemi correlati