【问题标题】:AWS Lambda only invoking the first promise functionAWS Lambda 仅调用第一个承诺函数
【发布时间】:2019-11-16 15:43:09
【问题描述】:

我正在尝试使用 lambda 将数据批量插入 sql server,代码仅插入为 promise.all 提供的第一个参数的数据,同时尝试使用无服务器离线运行代码,一切正常。

module.exports = async (context, event, callback) => {
    let bulkInsert = async (table, db) => {
        return new Promise(async function (resolve, reject) {
            const request = null;
            try {
                console.log("Bulk inserting data")
                const request = await db.request();
                try {
                    var result = await request.bulk(table);
                    console.log(result)
                    resolve(result)
                } catch (err) {
                    console.log(err);
                    reject(err)
                }
            } catch (err) {
                console.log("Error Occured while inserting data.")
                console.log(err)
                reject(err)
            }
        });
    };
    //Read file from S3
    var file = s3.getObject(params).createReadStream();
    var buffers = [];

    try {

        //Get the metadata for the object
        let s3Header = await s3.headObject(params)
            .promise()


        let db;
        let insertedTaskID;
        try {
            db = await new sql.ConnectionPool(config).connect();
        } catch (err) {
            console.error("Connection failed: " + err);
            throw err;
        }


        file.on("data", function (data) {
            buffers.push(data);
        });

        file.on("end", async function () {
            var buffer = Buffer.concat(buffers);
            var workbook = xlsx.parse(buffer);
            console.log("No of sheets in workbook are:", workbook.length);


            console.log("Remaining Execution Time ", context.getRemainingTimeInMillis())

                console.log("Validation Completed ")
                let firstTableData = getData("10002", workbook, "0")
                let secondTableData = getData("10002", workbook, "1")
                let thirdTableData = getData("10002", workbook, "2")
                let fourthTableData = getData("10002", workbook, "3")

                console.log("Inserting rows to DB")
                //Bulk insert the data into respective tables
                try {
                    await Promise.all([
                        bulkInsert(firstTableData, db),
                        bulkInsert(secondTableData, db),
                        bulkInsert(thirdTableData, db),
                        bulkInsert(fourthTableData, db)

                    ]).catch(err => {
                        console.log("Error on Bulk Insertion ")
                        console.log(err)
                    })


                    console.log("Completed Insertion")
                } catch (err) {
                    console.log("Bulk Insert Failed")
                    console.log(err)
                }

            }
        });

        callback(null, "OK");

    } catch (err) {
        console.log(err)
        callback(err);
    }
};

这里是 lambda 日志,请求在插入到其他表之前就结束了。

    08:26:42
    2019-07-06T08:26:42.266Z    da7e5fd0-acf9-48f0-8dfc-5a2ac712f035    INFO    Bulk inserting data

    08:26:42
    2019-07-06T08:26:42.266Z    da7e5fd0-acf9-48f0-8dfc-5a2ac712f035    INFO    Bulk inserting data

    08:26:42
    2019-07-06T08:26:42.287Z    da7e5fd0-acf9-48f0-8dfc-5a2ac712f035    INFO    Bulk inserting data

    08:26:42
    2019-07-06T08:26:42.287Z    da7e5fd0-acf9-48f0-8dfc-5a2ac712f035    INFO    Bulk inserting data

    08:26:42
    2019-07-06T08:26:42.387Z    da7e5fd0-acf9-48f0-8dfc-5a2ac712f035    INFO    { rowsAffected: 3 }
    
    08:26:42
    END RequestId: da7e5fd0-acf9-48f0-8dfc-5a2ac712f035

【问题讨论】:

    标签: node.js sql-server amazon-web-services lambda async-await


    【解决方案1】:

    lambda 似乎在其余批量插入有机会完成之前退出,您应该将回调调用移动到 end 事件中,以确保仅在所有批量调用完成后退出 lambda运行例如

    file.on('end', async () => {
      ...
      callback(null, 'OK');
    });
    

    此外,FWIW 如果您的 Lambda 是 async,那么您不需要在该上下文中使用 try/catch 块包装 await 调用,让它们抛出,Lambda 将为您处理它们。

    【讨论】:

    • 谢谢人,这行得通,我假设在发送回调后,lambda 可以在后台工作,因为我有 context.callbackWaitsForEmptyEventLoop = false;
    • @JithinPariyarath 将该标志设置为 false 将在触发回调后立即结束 lambda,这就是默认启用它的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 2017-05-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    相关资源
    最近更新 更多