2017-01-29 18 views
1

開発中のLambdaでpromise.all()が実行されていない理由を理解できません。AWSラムダでPromise.all()を使用

AWS Lambdaでは、Promise.all()が完了せず、SQSキューに新しいメッセージが届かないため、すでにタイムアウトしています。 2017-01-29T22:55:46.191Z 0e82eeaf-e676-11e6-b69d-73a6bbd86272 [ Promise { <pending> } ]

var url = require('url'); 
var AWS = require('aws-sdk'); 
// var Promise = require("bluebird"); 

exports.handler = function (event, context, callback) { 

    AWS.config = { 
     region: 'us-east-1', 
     apiVersions : { 
      sqs: '2012-11-05' 
     } 
    }; 

    if (typeof Promise === 'undefined') { 
     AWS.config.setPromisesDependency(require('bluebird')); 
    } 

    var sqs = new AWS.SQS(); // système de queue 
    var date = new Date(); 

    var knex = require('knex')({ 
     client: 'mysql', 
     connection: { 
      host : event.database.host, 
      user : event.database.user, 
      password : event.database.pwd, 
      database : event.database.name 
     } 
    }); 

    var sqsQueueUrl = event.sqsQueueUrl; 
    var keywords = event.keywords; 

    knex.select('keywords').from('keyword') 
     .timeout(1000) 
     .then(function(results) 
     { 
      var keywordsInDbArray = returnArrayWithOnlyKeywords(results); 

      var keywordsWillBeStored = []; 

      for (var i in keywords) 
      { 
       var isInDb = keywordsInDbArray.indexOf(keywords[i]); 

       if(isInDb == -1) 
        keywordsWillBeStored.push({ 
         keywords: keywords[i], 
         'created_at': date, 
         'updated_at': date 
        }); 
      } 
      if(keywordsWillBeStored.length > 0) 
      { 
       knex.batchInsert('keyword', keywordsWillBeStored, keywordsWillBeStored.length) 
        .then(function(firstId) 
        { 
         var newKeywordsStored = dataStoredInDb(firstId, keywordsWillBeStored); 
         console.log(newKeywordsStored); 

         sendKeywordInqueue(newKeywordsStored); 
        }) 
        .catch(function(error) 
        { 
         console.error(error); 
         context.fail(error); 
         knex.destroy(); 
        }); 
      } 
      else 
      { 
       context.succeed('Aucun nouveau keyword a enregistré'); 
      } 
     }) 
     .catch(function(error) 
     { 
      console.error(error); 
      context.fail(error); 
      knex.destroy(); 
     }); 

    function sendKeywordInqueue(array) 
    { 
     var promises = []; 
     for(var i in array) 
     { 
      var promise = sqs.sendMessage({ 
       MessageBody: JSON.stringify(array[i]), 
       QueueUrl: sqsQueueUrl 
      }).promise().catch(function(error) 
      { 
       console.error(error); 
      }); 
      promises.push(promise); 
     } 

     console.log(promises); 

     Promise.all(promises) 
      .catch(function(error) 
      { 
       console.error(error); 
      }) 
      .then(function() 
      { 
       callback(null, "DONE"); 
       context.succeed('Il y a eu '+array.length+' nouveau keywords enregistré et qui va être scrapé'); 
       knex.destroy(); 
      }); 
    } 

    function dataStoredInDb(firstIdSavedInDb, arrayWithKeywords) 
    { 
     id = firstIdSavedInDb -1; 
     return arrayWithKeywords.map(function (obj, i) { 
      var rObj = {}; 
      rObj.id = id + i + 1; 
      rObj.keywords = obj.keywords; 
      return rObj; 
     }) 
    } 

    function returnArrayWithOnlyKeywords(resultDb) 
    { 
     var dataKeywords = []; 

     for(var key in resultDb) 
     { 
      dataKeywords.push(resultDb[key].keywords); 
     } 

     return dataKeywords; 
    } 
}; 
+0

呼び出されるLambdaハンドラ全体を表示します。 – idbehold

+0

あなたの未来援助に感謝しました – timothylhuillier

+0

「Promise」という単語は、そのコードのいずれにも表示されません。 – idbehold

答えて

0

私たちはあなたの実際のラムダハンドラを参照する必要がありますが、あなたの非同期操作が完了する前、あなたはおそらく、ラムダを終了:

しかし、console.log(promises)が返さ。 コールバックパラメータを試しましたか?あなたが完了した後

exports.handler = function(event, context, callback) { 
    handleWhatever(context, callback); 
}; 

その後、あなたはあなたがこれでそれを試すことができます

callback(null, "DONE"); 
+0

ご協力ありがとうございますが、すでに同じです:タイムアウト。 'context.succeed'もコールバックを返します。 'Then()'は決して実行されず、SQSメッセージを受け取ったことがないので、問題は本当に 'Promise.all()'に関するものです。なぜか分からない。 – timothylhuillier

0

を呼び出すことができます。

var url = require('url'); 
var AWS = require('aws-sdk'); 
var knex = require('knex'); 
AWS.config = { 
    region: 'us-east-1', 
    apiVersions : { 
    sqs: '2012-11-05' 
    } 
}; 
var sqs = new AWS.SQS(); // système de queue 

exports.handler = function (event, context, callback) { 
    var db = knex({ 
    client: 'mysql', 
    connection: { 
     host : event.database.host, 
     user : event.database.user, 
     password : event.database.pwd, 
     database : event.database.name 
    } 
    }); 

    function destroyDb (out) { 
    return db.destroy().catch(function (err) { 
     console.error('Unable to close connection to database', err) 
    }).return(out) 
    } 

    return performKeywordQuery(db, event) 
    .then(destroyDb) 
    .then(context.succeed) 
    .catch(function (error) { 
    return destroyDb(error).then(context.fail) 
    }) 
}; 

function performKeywordQuery (db, event) { 
    var sqsQueueUrl = event.sqsQueueUrl; 
    var keywords = event.keywords; 

    return db.select('keywords').from('keyword') 
    .timeout(1000) 
    .then(function(results) 
    { 
    var date = new Date(); 
    var keywordsInDbArray = returnArrayWithOnlyKeywords(results); 

    var keywordsWillBeStored = []; 

    for (var i in keywords) 
    { 
     var isInDb = keywordsInDbArray.indexOf(keywords[i]); 

     if(isInDb == -1) 
     keywordsWillBeStored.push({ 
     keywords: keywords[i], 
     created_at: date, 
     updated_at: date 
     }); 
    } 
    if (keywordsWillBeStored.length > 0) 
    { 
     return knex.batchInsert('keyword', keywordsWillBeStored, keywordsWillBeStored.length) 
     .then(function(firstId) 
     { 
     var newKeywordsStored = dataStoredInDb(firstId, keywordsWillBeStored); 
     console.log(newKeywordsStored); 

     return Promise.all(newKeywordsStored.map(function (body) { 
      return sqs.sendMessage({ 
      MessageBody: JSON.stringify(body), 
      QueueUrl: sqsQueueUrl 
      }).promise() 
     })); 
     }) 
     .then(function (array) { 
     return 'Il y a eu '+array.length+' nouveau keywords enregistré et qui va être scrapé'; 
     }) 
    } 
    else 
    { 
     return 'Aucun nouveau keyword a enregistré'; 
    } 
    }) 
} 

function dataStoredInDb(firstIdSavedInDb, arrayWithKeywords) 
{ 
    var id = firstIdSavedInDb -1; 
    return arrayWithKeywords.map(function (obj, i) { 
    var rObj = {}; 
    rObj.id = id + i + 1; 
    rObj.keywords = obj.keywords; 
    return rObj; 
    }) 
} 

function returnArrayWithOnlyKeywords(resultDb) 
{ 
    var dataKeywords = []; 

    for(var key in resultDb) 
    { 
    dataKeywords.push(resultDb[key].keywords); 
    } 

    return dataKeywords; 
} 
+0

ご協力ありがとうございます。それはテストで私のコンピュータ上で完璧に動作しますが、プロダクションでは再びタイムアウトします。 Promise.all()はSQSでは動作しません。 array.map()...は完璧に動作しました。私は本体をconsole.log()で見ました。 – timothylhuillier

0

私は同じ問題を持っていたし、これがなるまでポリフィルを導入することになりました解決済み:

function promiseAll(promises) { 
    return new Promise((resolve, reject) => { 
    const result = []; 
    let count = promises.length; 
    const checkDone =() => { 
     if (--count === 0) resolve(result); 
    }; 
    promises.forEach((promise, i) => { 
     promise 
     .then(x => { 
      result[i] = x; 
     }, reject) 
     .then(checkDone); 
    }); 
    }); 
} 

[source:https://codereview.stackexchange.com/questions/134224/pseudo-promise-all-polyfill]