繁体   English   中英

AWS Lambda 函数不会第一次发送消息,而是会发送所有后续消息

[英]AWS Lambda function doesn't sendMessage first time but does every subsequent message

我有一个 lambda 函数,它是通过 API Gateway 触发的(这有效)。

然后 lambda 将一些数据添加到 DynamoDB(这有效)

然后我调用我创建的将数据发送到 SQS 的函数

export const AddToQueue = async vehicleId => {
  const QueueParams = {
    DelaySeconds: process.env.QUEUE_DELAY,
    MessageAttributes: {},
  };

  QueueParams.MessageAttributes.vehicleId = {
    DataType: 'String',
    StringValue: vehicleId,
  };

  QueueParams.QueueUrl = 'my-queue-url';
  QueueParams.MessageBody = `vehicle: ${vehicleId} - ${new Date().toISOString()}`;

  try {
    await sqs.sendMessage(QueueParams).promise();
    console.log(`SQS:SUCCESS - AddToQueue - ${vehicleId}`);
  } catch (error) {
    console.log(`SQS:ERROR - AddToQueue - ${error}`);
  }
};

第一次发生这种情况时,消息不会到达 SQS,但任何其他后续消息都会添加到队列中并得到处理。 我已经尝试了很多 IAM 权限、队列设置、重新创建队列,但这些都没有帮助。

我没有收到成功或错误消息,因此无法调试任何问题。

我不是这方面的专家,但我以前经历过这种行为,其中第一次调用中的某些异步代码似乎未执行或其执行似乎延迟(例如,后续调用执行的操作似乎基于上一次通话的数据)。

在所有情况下,这是由于没有正确等待异步代码。 我对 javascript 和 Lambda 的了解不够,无法解释这种行为,尤其是延迟 - 在处理程序返回后但容器仍在运行时,promise 能否解决? 但我所知道的是,如果 lambda 在承诺(异步函数返回承诺)解决之前返回(因此在异步代码完成运行之前,这会导致观察到的代码行为被延迟或未执行),那么它们没有被正确等待。

可能您没有在调用AddToQueue()的异步函数中等待

如果您没有在异步函数中调用AddtoQueue()并在那里等待它,则 AddToQueue 将在执行该代码后运行。

所以让我给你举个例子。

您在测试目录中有 2 个文件。

await.js main.js

await.js 是:

module.exports = async ()=> {

await new Promise((res, rej)=>{
    setTimeout(()=>{
        res(console.log('Running'));
    }, 2000)
})

}

和 main.js

console.log('Hello')
require('./await')();

console.log('World')

当您运行 main.js 时, node main.jsHello world将运行,然后在 promise 解决后,它将从队列推送到您的运行堆栈并运行最后一个。

Hello
World
// After 2 secs
Running

但是如果在 main.js 中

(async ()=>{
console.log('Hello')
await require('./await')();

console.log('World')
})()

你让 javascript 引擎知道,这是一个异步函数并在运行其他任何东西之前等待该模块,你会得到你期望的结果。

Hello
// After 2 seconds
Running
World

基本上你是在告诉 javascript 引擎I do not want you to run it your way, but run it my way

我刚刚遇到了一个与此非常相似的问题,我的问题与没有像接受的答案中提到的@404 那样正确等待有关。

具体来说,我使用forEach遍历数组并在回调中调用await

// causing weird behavior

async function invokeLambdas(teams) {
  teams.forEach(async (team) => {
    await utils.invokeLambda(team) // fn has a Lambda invoke in it
  });

我通过删除forEach并将其替换为常规 for 循环并按照此处的建议内部等待来解决此问题

async function invokeLambdas(teams) {
    for (const team of teams) {
        await utils.invokeLambda(team)
    }
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM