Slack slash command delayed response on AWS Lambda

0 votes

I'm trying to make an integration for Slack that queries a server and gets back some results to the user. The search sometimes takes longer than the window Slack allows for responses, so I need to immediately return status 200.

How can I do this with a lambda function? I tried using the callback function and then sending the data to another lambda service, but the original function waits for it to return, meaning I'm still getting held up by the server I'm querying.

Here's what I'm working with

var rp = require('request-promise');

exports.handler = (event, context, callback) =>{
  //I wanted this to send back my STATUS 200 so the command wouldn't time out
  callback(null, "Working...");
	
  //I want this post to happen asynchronously so that slack gets the callback response while the search is happening
  //but this still waits until the post comes back before resolving the callback
  var options = {
    method: 'POST',
    uri: "https://url-to-other.service",
    body:{
    	"team": event.team,
    	 "label": event.label,
    	 "url": event.aresponse_url
    },
    json:true
  };
  rp(options);
};

When I run this, the callback text shows up after the result from the other function, meaning this service is waiting for the other to stop running before returning the status.

Sep 5, 2018 in AWS by bug_seeker
• 15,360 points
314 views

1 answer to this question.

0 votes

That won't work in a single lambda function because as soon as you invoke callback() the lambda container dies. What you could do is have this lambda function invoke another lambda functionbefore calling callback() which in turn will POST to your slack channel url.

Here's an example of how that would work (it's not a 100% but should give you a good idea of how it'll work.)

Function 1: (receive slack event, invoke second function, immediatly return 200

let AWS = require('aws-sdk')
exports.handler = (event, context, callback) => {
    let lambda = new AWS.Lambda()
    let params = {
        FunctionName: 'YOUR_SECOND_FUNCTION_NAME',
        InvocationType: 'Event', // Ensures asynchronous execution
        Payload: JSON.stringify({
            team: event.team,
            label: event.label,
            url: event.aresponse_url
        })
    }
    return lambda.invoke(params).promise() // Returns 200 immediately after invoking the second lambda, not waiting for the result
    .then(() => callback(null, 'Working...'))
}

Function 2: (receive first lambda event, wait for search to complete, POST to slack channel)

let rp = require('request-promise')

exports.handler = (event, context, callback) => {
    let searchOptions = {
        method: 'POST',
        uri: 'https://url-to-other.service',
        body: {
            'team': event.team,
            'label': event.label,
            'url': event.aresponse_url
        },
        json:true
    }
    return rp(searchOptions)
    .then(result => {
        let slackOptions = {
            method: 'POST',
            uri: 'YOUR_SLACK_CHANNEL_URL',
            body: {
                text: JSON.stringify(result) // I stringified the search result for you for ease's sake, not sure what you need here
            },
            json: true
        }
        return rp(slackOptions)
    })
    .then(() => { callback(null, 'good measure') })
}
answered Sep 5, 2018 by Priyaj
• 56,940 points

Related Questions In AWS

0 votes
1 answer
0 votes
1 answer

How to get aws lambda response as an HTML page

Store the HTML markup in a variable and return ...READ MORE

answered Dec 4, 2018 in AWS by Archana
• 5,560 points
143 views
+1 vote
10 answers
0 votes
1 answer
0 votes
1 answer
0 votes
1 answer
0 votes
1 answer