SQS 触发器调用的 AWS Lambda 函数不遵守我在函数中手动设置的可见性超时

AWS Lambda Function invoked by SQS trigger is not respecting the visibility timeout I'm manually setting within the function

我正在实施我自己的 webhooks 服务,它将向订阅的 webhooks 发送事件。

架构概览:

据我所知,更改消息可见性的调用成功了。我想知道 SQS 调用的 lambda 中是否包含其他内容。在 lambda 失败后,它是否在内部再次更改消息可见性?或者由 SQS 调用的 lambda 不考虑消息可见性的变化(这对我来说真的没有任何意义)。好奇是否有人对这个问题有任何见解。我很惊讶地发现 lambda 会在成功时自动删除消息,因为它让我的特定用例有点笨拙 - 抛出错误以使 lambda 函数失败以防止消息被删除。

提前致谢!

SQS 与 Lambda 集成的本质是集成控制消息的轮询。用于确定是否应删除消息的机制是来自 lambda 的响应不是错误。 documentation 中没有明确说明,但我相信当发生错误时,集成会将可见性超时设置为零,以便立即可供另一个进程接收。因此,在您的示例中,您将其设置为某个允许您重试的数字,但是当您 return 出现错误时,集成会将超时设置回零。如果您需要对该过程进行更多控制,您可能不应该使用该集成。

更新:实际情况并非如此。我未能正确等待调整超时的调用完成。因此,lambda 在该请求完成之前关闭。我在 lambda 中的消息上设置的超时得到了尊重。然后我抛出一个错误以防止消息被删除。

由于 SQS 批量触发 lambda 处理消息,因此在标准 forEach 中使用 await 不起作用(forEach 不会等待回调,如果它们是异步的)。要绕过它,您可以创建自己的异步 forEach 版本:

var AWS = require('aws-sdk');

exports.handler = async function(event, context) {
    var sqs = new AWS.SQS({apiVersion: '2012-11-05'});
    
    await asyncForEach(event.Records, async record => {
        const { receiptHandle } = record;
            const sqsParams = {
              QueueUrl: '<YOUR_QUEUE_URL>', /* required */
              ReceiptHandle: receiptHandle, /* required */
              VisibilityTimeout: '<in seconds>' /* required */
            };
            try {
                let res = await sqs.changeMessageVisibility(sqsParams).promise();
                console.log(res);
            } catch (err) {
                console.log(err, err.stack);
                throw new Error('Fail.');
            }
        }
    });
    return {};
};

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}