【问题标题】:Suggest approach for handling multiple lambda invocations建议处理多个 lambda 调用的方法
【发布时间】:2019-07-18 18:03:20
【问题描述】:

主要问题: 外部 API 调用成功后 Lambda 函数未退出,随后触发多个外部 API 调用。

我有一个 lambda 函数,它在事件发生时侦听松弛事件,调用 lambda 函数。我使用一些条件检查过滤这些事件,当目标事件发生时,我进行外部 API 调用。

以上所有方法都有效,但是,每个事件都会触发多次外部 API 调用(如果成功,则应该为 1 次,约为 4 次)。

幂等 - 人们通常将此问题与幂等性联系起来,但是,鉴于它在条件块内的外部 API 调用会被触发多次,我不认为这是一个问题。

  • 我可以确认条件检查是否正确过滤了相应的事件
  • 我可以确认我在后续(额外)外部 API 调用之前收到了 statusCode 200
  • 我已经包含了context.done() 和多余的callback(),但没有运气

寻找一些建议的方法

  • 是否有人提出了解决此问题的建议方法?
  • 我听说有些人使用 DynamoDB 来跟踪执行请求,但这听起来不是一个好方法

我在下面附上了 lambda 函数:

const axios = require('axios');

const sendMessages = async(event, context, callback) => {
    // test the message for a match
    if (event.type === 'message' && event.bot_id !== undefined) {
        console.log("filter events for specific event");

        let URL = 'https://someurl.com/slack/events';
        let response = await axios.post(URL, {
            events: event,
        });
        console.log("response success :: ", response.status);
        if (response.status === 200) {
            console.log("condition met");
            context.done();
            callback(null, 'successful request');
        }
    }
    callback(null, 'successful request');
};

// Lambda handler
exports.server = (data, context, callback) => {
    let eventData = JSON.parse(data.body);
    switch (data.path) {
        case "/slack-events": sendMessages(eventData.event, context, callback); break;
        default: callback(null);
    }
};

预期行为

  • 在调用和条件检查时进行单个外部 API 调用; response.status === 200 后退出

【问题讨论】:

  • @JohnRotenstein,请您联系文档团队,看看他们是否可以更新文档?我联系过@SebastienStomarq 一次,他说他已经和文档团队谈过了,但到目前为止还没有文档更新。这些天我们在 SO 上回答的大多数问题都是关于 async/awaitcontextcallback 通话一起使用,造成绝对混乱。如果文档不修复,这些问题将不断出现。
  • @ThalesMinussi 您可以单击文档页面上的“反馈”按钮,该按钮将发送给文档团队。但是,如果您想写出更详细的解释,请随时通过电子邮件发送给我,我会向文档团队提出。 (我不是 Node 人,所以最好让熟悉大多数问题的人为他们记录问题。)
  • @JohnRotenstein 完美。当我有空闲时间写一个详细的解释时,我会这样做。感谢您花时间回复我。也许将文档开源是个好主意……
  • @ThalesMinussi AWS 文档在 github 上可用,因此您可以提交拉取请求(但我不确定 ALL 手册是否在其中)。
  • @JohnRotenstein github.com/awsdocs/aws-doc-sdk-examples/issues/754 我已经创建了一个 PR。让我们看看你们在 AWS 和社区的反应如何。

标签: aws-lambda slack


【解决方案1】:

问题(您不是第一个也不会是最后一个提出此类问题的人,AWS 需要尽快修复文档)是因为您混淆了 async/awaitcontext.donecallback() 调用.

如果你的函数已经是async,那么一直使用await,忘记contextcallback对象。

看到sendMessagesasync,因此它返回一个Promise,但你不会对该Promise 做任何事情。你应该在上面await。我已经相应地更改了您的代码并删除了 contextcallback 对象,您不需要它们。

const axios = require('axios');

const sendMessages = async (event) => {
  // test the message for a match
  if (event.type === 'message' && event.bot_id !== undefined) {
    console.log('filter events for specific event');

    let URL = 'https://someurl.com/slack/events';
    let response = await axios.post(URL, {
      events: event,
    });
    console.log('response success :: ', response.status);
    return response;
  }
  return Promise.resolve({});
};

// Lambda handler
exports.server = async (event) => {
  let eventData = JSON.parse(event.body);
  switch (event.path) {
    case '/slack-events':
      await sendMessages(eventData.event);
      break;
  }
  return {
    message: 'Success',
  }
};

如果此 Lambda 由 API Gateway 调用,则您需要返回带有字符串化主体的 2xx 状态代码(或 4xx 和 5xx),以便它可以正确终止,如下所示:

return {
        statusCode: 200,
        body: JSON.stringify({message: 'Success'})
      }

【讨论】:

  • 感谢您的回复。这很有意义,我已经相应地重构了 lambda 函数,但是问题仍然存在。现在我正在正确地等待 sendMessages 承诺,我应该对响应执行任何操作以终止/退出 lambda 处理程序中的函数吗?
  • 不客气。不是真的...... return { message: 'Success } 块应该能够处理它。除非这是来自 API 网关的调用。是这样吗?如果是这样,您需要添加 statusCode 并对正文进行字符串化。我会更新我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多