如何避免 slack 命令超时错误?

问题描述 投票:0回答:3

我正在使用 slack 命令(Python 代码在其后面运行),它工作正常,但这会产生错误

This slash command experienced a problem: 'Timeout was reached' (error detail provided only to team owning command).

如何避免这种情况?

python slack-api slack
3个回答
56
投票

根据 Slack slash 命令文档,需要在 3000ms(三秒)内做出响应。如果您的命令需要更长的时间,那么您会收到

Timeout was reached
错误。您的代码显然不会停止运行,但用户不会得到对其命令的任何响应。

对于命令可以即时访问数据的快速操作来说,三秒就足够了,但如果您调用外部 API 或执行复杂的操作,则可能不够长。如果您确实需要更长的时间,请参阅文档的延迟响应和多个响应部分:

  1. 验证请求是否正确。
  2. 立即返回
    200
    回复,也许类似于
    {'text': 'ok, got that'}
  3. 的内容
  4. 去执行你想做的实际行动。
  5. 在原始请求中,您会收到一个唯一的
    response_url
    参数。向该 URL 发出
    POST
    请求并附上您的后续消息:
  • Content-type
    必须是
    application/json
  • 将正文作为 JSON 编码的消息:
    {'text': 'all done :)'}
  • 您可以返回临时或频道内回复,并像立即方法一样添加附件

根据文档,“您可以在用户调用后的 30 分钟内响应用户命令最多 5 次”。


14
投票

在我自己处理这个问题并将我的 Flask 应用程序托管在 Heroku 上之后,我发现最简单的解决方案是使用线程。我按照这里的例子: https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xi-email-support

from threading import Thread

def backgroundworker(somedata,response_url):

    # your task

    payload = {"text":"your task is complete",
                "username": "bot"}

    requests.post(response_url,data=json.dumps(payload))    

@app.route('/appmethodaddress',methods=['POST','GET'])
def receptionist():

    response_url = request.form.get("response_url")

    somedata = {}

    thr = Thread(target=backgroundworker, args=[somedata,response_url])
    thr.start()

    return jsonify(message= "working on your request")  

所有缓慢繁重的工作都是由

backgroundworker()
功能完成的。我的 slack 命令指向
https://myappaddress.com/appmethodaddress
,其中
receptionist()
函数获取接收到的 Slack 消息的
response_url
,并将其与任何其他可选数据一起传递到
backgroundworker()
。由于流程现在已拆分,因此它几乎立即将
"working on your request"
消息返回到您的 Slack 频道,并在完成后
backgroundworker()
发送第二条消息
"your task is complete"


12
投票

我也经常遇到这个错误:

“该死 - 斜杠命令不起作用(错误消息:

Timeout was reached
)。在斜杠命令中管理命令”

我正在 AWS Lambda 上编写一个 Slack 斜杠命令“机器人”,有时需要执行缓慢的操作(调用其他外部 API 等)。在某些情况下,Lambda 函数将花费超过 3 秒的时间,从而导致 Slack 出现 Timeout was reached

 错误。 

我在这里找到了 @rcoup 的优秀答案,并将其应用到 AWS Lambda 的上下文中。错误不再出现。

我使用两个单独的 Lambda 函数来完成此操作。一种是“调度员”或“接待员”,用“200 OK”迎接传入的 Slack 斜线命令,并向用户返回简单的“好的,明白了”类型的消息。另一个是实际的“worker”Lambda 函数,它异步启动较长的操作,并稍后将该操作的结果发布到 Slack

response_url

这是调度员/接待员 Lambda 函数:

def lambda_handler(event, context): req_body = event['body'] try: retval = {} # the param_map contains the 'response_url' that the worker will need to post back to later param_map = _formparams_to_dict(req_body) # command_list is a sequence of strings in the slash command such as "slashcommand weather pune" command_list = param_map['text'].split('+') # publish SNS message to delegate the actual work to worker lambda function message = { "param_map": param_map, "command_list": command_list } sns_response = sns_client.publish( TopicArn=MY_SNS_TOPIC_ARN, Message=json.dumps({'default': json.dumps(message)}), MessageStructure='json' ) retval['text'] = "Ok, working on your slash command ..." except Exception as e: retval['text'] = '[ERROR] {}'.format(str(e)) return retval def _formparams_to_dict(req_body): """ Converts the incoming form_params from Slack into a dictionary. """ retval = {} for val in req_body.split('&'): k, v = val.split('=') retval[k] = v return retval

从上面可以看出,我没有直接从调度程序调用worker Lambda 函数(尽管这是可能的)。我选择

使用 AWS SNS 发布工作人员接收和处理的消息

基于

这个 StackOverflow 答案,这是更好的方法,因为它是非阻塞(异步)和可扩展的。此外,在 AWS Lambda 上下文中使用 SNS 来解耦两个函数更容易,对于此用例,直接调用更加棘手。

最后,这是我如何在我的工作人员 Lambda 函数中使用 SNS 事件:

def lambda_handler(event, context): message = json.loads(event['Records'][0]['Sns']['Message']) param_map = message['param_map'] response_url = param_map['response_url'] command_list = message['command_list'] main_command = command_list[0].lower() # process the command as you need to and finally post results to `response_url`
    
© www.soinside.com 2019 - 2024. All rights reserved.