anch'io stavo affrontando questo errore frequente:
"Darn - che Slash comando non ha funzionato (messaggio di errore: Timeout was reached
) Gestire il comando a barra-comando."
I stava scrivendo un Slack slash-command "bot" on AWS Lambda che a volte era necessario per eseguire operazioni lente (invocando altre API esterne, ecc.). In alcuni casi, la funzione Lambda potrebbe richiedere più di 3 secondi, causando l'errore Timeout was reached
da Slack.
Ho trovato l'eccellente risposta di @ rcoup qui e l'ho applicata nel contesto di AWS Lambda. L'errore non appare più.
L'ho fatto con due funzioni Lambda separate. Uno è un "dispatcher" o "receptionist" che saluta il comando Slack Slack in entrata con un "200 OK" e restituisce all'utente il semplice tipo di messaggio "Ok, ha ottenuto".L'altra è la funzione Lambda "worker" effettiva che avvia l'operazione long-ish in modo asincrono e registra il risultato di tale operazione su Slack response_url
in seguito.
Questo è il dispatcher/receptionist funzione 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
Come si può vedere da quanto sopra, non ha invocato il lavoratore Lambda funzione direttamente dal dispatcher (anche se questo è possibile). Ho scelto lo use AWS SNS to publish a message that the worker receives and processes.
Basato su this StackOverflow answer, questo è l'approccio migliore in quanto è non bloccante (asincrono) e scalabile. Inoltre è stato più semplice usare SNS per disaccoppiare le due funzioni nel contesto di AWS Lambda, l'invocazione diretta è più complicata per questo caso d'uso.
Infine, ecco come ho consumare l'evento SNS nel mio operaio Lambda Funzione:
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`
Per spiegare eventualmente i downvotes su questa risposta (auto-accettata?): questa risposta non risolve * impedendo * i timeout; il nucleo della tua domanda originale. La vera risposta/soluzione è che dovresti restituire una risposta a Slack immediatamente dopo aver ricevuto la richiesta, e 'POST' la vera risposta (una volta che hai) al parametro' response_url' come nella richiesta originale. –