Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function does not returns until all aSync ends #2747

Closed
mInzamamMalik opened this issue Nov 19, 2016 · 10 comments
Closed

Function does not returns until all aSync ends #2747

mInzamamMalik opened this issue Nov 19, 2016 · 10 comments
Labels

Comments

@mInzamamMalik
Copy link

mInzamamMalik commented Nov 19, 2016

Function does not returns until all aSync ends

I want to make a function which call an api(third party) and return immediately but it is waiting for api response, here is code sample

var requestModule = require('request');

//when i call functionOne it should trigger functionTwo and should end immediately but unfortunatly it is waiting for functionTwo to be end
module.exports.functionOne = (event, context, cb) => {
    requestModule.post({ uri: 'https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/functionTwo' });
    cb(null, "done functionOne");
};

module.exports.functionTwo = (event, context, cb) => {
    console.log("i'm functionTwo");
    setTimeout(function () {
        console.log("i'm functionTwo about to end");
        context.succeed("done functionTwo");
    }, 5000);
};

Moreover, if i try to call context.succeed() instead of cb() it even prevent api call and function return immediately without calling api

i have also asked a question on stackoverflow, any help will be appreciated

Additional Data

  • Serverless Framework Version: 1.0.0-rc.2
  • Node Version: v6.9.1
  • Operating System: windows 10
@pmuens
Copy link
Contributor

pmuens commented Nov 19, 2016

Hey @malikasinger1 thanks for bringing this up.

It seems like your request call is missing a callback. According to their docs you should do smth. like this:

var request = require('request');

request('http://www.google.com', function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body) // Show the HTML for the Google homepage.
  }
})

So your code should look something like this:

module.exports.functionOne = (event, context, cb) => {
    requestModule.post({ uri: 'https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/functionTwo' }, (error, response, body) => {
      if (error) {
        throw new Error(error);
      }
      cb(null, "done functionOne");
    });
};

It's best to use the callback instead of context.succeed. Furthermore you may also want to update your Serverless version (we're about to release v1.2.0 with great new features soon).

Let us know if this helps you or if you still face problems.

@diegozanon
Copy link

diegozanon commented Nov 20, 2016

Sorry @malikasinger1, but you can't achieve what you want, at least not in this way.

When you call another function using request.post(), you must provide a callback and you must wait for it to finish.

What you could do is to call request.abort(), but this is a hacky solution.

module.exports.functionOne = (event, context, cb) => {
    const uri = 'https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/functionTwo';
    const r = request.post({ uri: uri }, (error, response, body) => {
        cb(error, "done functionOne");
    });

    r.abort();
    cb(null, 'forced abort on functionOne');
};

Why is this hacky? Because you can't abort immediately. You need to wait a few milliseconds for the request to be received in the other server, but there is no way to know exactly when it happens.

If you know that the second Lambda will run for 2 minutes, you could add a setTimeout function to abort the request after 5 seconds and avoid having the functionOne running for a long time in a idle state. But again, this is a bad solution.

Why don't you place the functionTwo code inside functionOne to avoid starting a second Lambda?

Another workaround would be to call a SNS topic from functionOne and configure this topic to trigger functionTwo.

@mInzamamMalik
Copy link
Author

FunctionTwo is here just for example, in actual case there is an api which is third party, and i'm sending post request to that api with some data, and actually it is slack api and in my case i dont want response of that api call thats why i want functionOne return immediately without any wait otherwise i have to wait about 6000ms

@pmuens
Copy link
Contributor

pmuens commented Nov 22, 2016

Hey @malikasinger1
You might want to look into webhooks which will send data from e.g. Slack back to your functions.

I'm closing this issue as it's not directly related to Serverless. Feel free to continue the discussion.

@pmuens pmuens closed this as completed Nov 22, 2016
@mInzamamMalik
Copy link
Author

@pmuens my issue is still not solved, please don't mark issue as close
and it is directly related to serverless no doubt because serverless is not returning even have called call back and waiting for complete async call and it is annoying

@diegozanon
Copy link

@malikasinger1, this issue is related with Lambda, Node-Request and Slack, but it's not related with the Serverless Framework.

I believe that Stack Overflow is the best place to receive help about this issue. You could ask another question there being more specific about the Slack API.

@mInzamamMalik
Copy link
Author

@zanon-io great effort, appreciable
but unfortunately your heck is not working for me
let me confirm if you test this heck your own before telling me
if it is really working for you please tell me which version of serverless and node you are using

@diegozanon
Copy link

@malikasinger1, yes, I've tested. It returns immediately.

However, I'm using Lambda-proxy and my callback is:

const response = {
    statusCode: 200,
    body: JSON.stringify({ "message": "done functionOne" })
};

cb(null, response);

Since Lambda-proxy is the default now and it requires that you use this format, your issue can be related with this.

Read more about Lambda-proxy here: https://serverless.com/framework/docs/providers/aws/events/apigateway/#lambda-proxy-integration

@mInzamamMalik
Copy link
Author

@zanon-io can you please tell me what version of serverless you are using?

@diegozanon
Copy link

diegozanon commented Jan 3, 2017

I don't remember which version I was using when this question was created. Probably v1.1, but you should always use the latest stable version. Currently, it's v1.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants