Slack 延迟消息与 Node TypeScript 和 Lambda 的集成

时间:2021-06-23 14:12:30

标签: node.js typescript amazon-web-services serverless slack-api

我开始实施一个不断发展的斜线命令,最终可能会达到 3 秒的松弛响应限制。我将 serverless-stackNodeTypeScript 一起使用。使用 sst(和 vscode 启动文件),它将调试器挂钩并附加到 lambda 函数中,这对于调试来说非常简洁。

当访问 api 端点时,我尝试了各种方法来发回对 slack 的确认,做我的事情并发送一条延迟消息但没有成功。我没有太多运气找到这方面的信息,但一个很好的来源是 SO Answer - 不幸的是它没有用。我没有使用 request-promise ,因为它已被弃用并试图用普通方法实现它(也许这就是我失败的地方?)。但从内部调用第二个 lambda 函数(如帖子的第一个示例)似乎不在 3s 限制内。

我想知道我是否做错了什么,或者调试器是否需要很长时间等等。 但是,在尝试发送延迟消息之前,它可以包括访问和扫描 dynamodb 记录、操作结果,然后在连接调试器时响应 slack,而不会超时。

尝试使用帖子

export const answer: APIGatewayProxyHandlerV2 = async (
    event: APIGatewayProxyEventV2, context, callback
) => {


    const slack = decodeQueryStringAs<SlackRequest>(event.body);


    axios.post(slack.response_url, {
        text: "completed",
        response_type: "ephemeral",
        replace_original: "true"
    });


    return { statusCode: 200, body: '' };
}

承诺从未解决,我猜一旦点击函数的返回值,lambda 函数就会被释放,所以承诺?

调用第二个 Lambda 函数

export const v2: APIGatewayProxyHandlerV2 = async (
    event: APIGatewayProxyEventV2, context, callback
): Promise<any> => {

    //tried with CB here and without
    //callback(null, { statusCode: 200, body: 'processing' });

    const slack = decodeQueryStringAs<SlackRequest>(event.body);
    const originalMessage = slack.text;
    const responseInfo = url.parse(slack.response_url)

    const data = JSON.stringify({
        ...slack,
    })
    const lambda = new AWS.Lambda()
    const params = {
        FunctionName: 'dev-****-FC******SmE7',
        InvocationType: 'Event', // Ensures asynchronous execution
        Payload: data
    }

    return lambda.invoke(params).promise()// Returns 200 immediately after invoking the second lambda, not waiting for the result
        .then(() => callback(null, { statusCode: 200, body: 'working on it' }))
};

查看调试器日志,它确实发送了 200 代码并调用了新的 lambda 函数,尽管 slack 仍然超时。

逻辑上没有什么特别的事情......当前的非延迟消息实现在逻辑上做得更多(访问数据库和操作结果数据)并且设法不超时。

欢迎任何建议或帮助。

1 个答案:

答案 0 :(得分:0)

快速旁注,我在链接的 SO 问题的答案中使用了 request-promise,因为当时 AWS Lambda 的容器上还没有 JS 原生 Promise 对象。

根据我的理解,链接问题中的功能编排与您自己的编排之间存在根本差异,但我认为您有相同的目标:

> 从 Slack 调用一个异步操作,一旦有结果就回发到 slack

这是您当前方法的问题:Slack 向您的(第一个)lambda 函数发送请求,该函数返回对 slack 的响应,然后调用第二个 lambda 函数。

一旦您的第一个 lambda 返回 200,slack 事件将不再接受响应。这就是您的方法和链接的 SO 问题之间的区别。

所需的方法按顺序如下所示:

  1. Slack 向 Lambda 发送请求。 1
  2. Lambda 编号1 向 Slack 返回 200 响应
  3. Lambda 编号1 调用 Lambda 编号。 2
  4. Lambda 编号2 向 slack URL 发送 POST 请求(google 传入的 slack 网络钩子)
  5. Slack 接收 POST 请求并将其显示在您为网络钩子选择的频道中。

代码明智,这将如下所示(没有请求承诺,哈哈):

Lambda 1

module.exports = async (event, context) => {
    // Invoking the second lambda function
    const AWS = require('aws-sdk')
    const lambda = new AWS.Lambda()
    const params = {
        FunctionName: 'YOUR_SECOND_FUNCTION_NAME',
        InvocationType: 'Event', // Ensures asynchronous execution
        Payload: JSON.stringify({
            ... your payload for lambda 2 ...
        })
    }
    await lambda.invoke(params).promise() // Starts Lambda 2

    return {
        text: "working...",
        response_type: "ephemeral",
        replace_original: "true"
    }        
}

Lambda 2

module.exports = async (event, context) => {
    // Use event (payload sent from Lambda 1) and do what you need to do

    return axios.post('YOUR_INCOMING_WEBHOOK_URL', {
        text: 'this will be sent to slack'
    });
}