{Status: 202} when running a lambda from code - javascript

This is my code in Javascript:
var params = {
FunctionName: "theTable",
InvokeArgs: JSON.stringify({ "name": "KirklandWA" })
};
lambda.invokeAsync(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
console.log(data);
}
});
This is in Lambda:
exports.handler = async (event, context) => {
return "theReturnedValue";
};
What is happening is that it is not returning the theReturnedValue, instead returns
{Status: 202}
Status: 202
The code in Lambda is getting invoked, I made sure of it at Cloudwatch.

You're invoking with invokeAsync which will only return status code as stated in the documentation. Use invoke with InvocationType: "RequestResponse" instead
Reference:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property
var lambda = new AWS.Lambda({});
var params = {
FunctionName: "function_name",
InvocationType: "RequestResponse"
};
response = lambda.invoke(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});

Verify that your lambda this selected as NodeJs 8.10 runtime, once having verified you must return a promise directly:
exports.handler = async (event, context) => {
return await new Promise((resolve, reject) => {
resolve({ message: "hello world" });
});
};
I was looking invokeAsync method definition in the aws-sdk documentation and the status code is fine:
Callback parameters:
err (Error) — the error object returned from the request. Set to null if the request is successful.
data (Object) — the de-serialized data returned from the request. Set to null if a request error occurs. The data object has the
following properties:
Status — (Integer) It will be 202 upon success.
I prepare you a basic example, please review handler.js file:
https://github.com/ns4lin4s/stackoverflow
Dont forget, that you must specify response body:
So when you finish, let me know how that works!

The problem is that your lambda function is not returning anything back to the caller.
Your handle funtion has a third parameter which is a callback function that is used to return results to the caller.
The callback function takes in two values, an Error and results
callback(Error error, Object result);
If you provide the Error values the lambda will throw the an error you provide to the user, if you dont provide an Error value but the results, its the results that will be returned
Its all documented very well here
Here are basic examples
callback(); // Indicates success but no information returned to the caller.
callback(null); // Indicates success but no information returned to the caller.
callback(null, "success"); // Indicates success with information returned to the caller.
callback(error); // Indicates error with error information returned to the caller.
Your handler function should be.
exports.handler = async (event, context,callback) => {
callback(null, "theReturnedValue");
};

Related

Firebase Admin update function calling multiple callbacks in nodejs

I know for a fact that reading data from firebase with firebase admin returns multiple callbacks. that is why I use ref.once(), like example below:
const ref = db.ref('clients');
ref.once('value', (snapshot) => {
res.send(snapshot.val());
}, (errorObject) => {
console.log('The read failed: ' + errorObject.name);
});
But, when I try to update data I get into the same trouble of receiving multiple callbacks crashing my application, but I can't use once in ref.update, what can I do to prevent receiving multiple callbacks?
app.get('/set-client', (req, res) => {
const ref = db.ref(`users/new_users`)
ref.update({ 'client': uid_client}).then(function(){
console.log("Data saved successfully.");
res.status(200).send("successful")
}).catch(function(error) {
console.log("Data could not be saved." + error);
res.status(201).send("failed")
});
});
Here is a code example.
When interacting with responses in the way you've shown, you might find that using the .then(onFulfilled, onRejected) variant of the then() method may be of use.
Quick note: When using this approach, care must be taken to understand that if the onFulfilled handler throws an exception/rejects, the sibling onRejected handler will not be called with its exception. The exception is instead passed onto the next chained onRejected handler in later then/catch calls. The sibling will only catch exceptions/rejections from steps prior to it in the chain.
Here is an example of the difference:
const somePromise = /* ... */;
const resultPromise = somePromise
.then((data) => { /* handle data */ }) // an error thrown here
.catch((err) => { /* handle error */ }) // gets caught here
// vs.
const resultPromise = somePromise
.then(
(data) => { /* handle data */ }, // an error thrown here, will reject resultPromise
(err) => { /* handle error */ } // instead of being handled here
)
This trait of the onRejected handler in .then(onFulfilled, onRejected) can be applied in a way where headers can't be sent twice for the same response. If for whatever reason the onFulfilled handler throws an exception while trying to send a response, the onRejected handler that is also responsible for sending a response is skipped - preventing any headers already sent errors.
This means that the first code block gets swapped out for:
const ref = db.ref('clients');
ref.once('value')
.then(
(snapshot) => { // got data successfully
console.log('got data successfully');
// don't forget to check snapshot.exists() if data could be missing
res.send(snapshot.val()); // using .json() over .send() is recommended for arbitrary data
},
(error) => { // failed to get data/permission
console.error('Failed to read data at /clients: ', error);
res.status(500).send('Data unavailable.');
}
)
.catch(
(error) => { // if here, either of the above blocks failed - probably due to an error related to the response.
console.error('Failed to send response to client: ', error);
try { res.end() } catch (e) {} // forcefully terminate connection if not already
}
);
and the second code block for:
app.get('/set-client', (req, res) => {
const ref = db.ref(`users/new_users`)
ref.update({ 'client': uid_client }) // uid_client is undefined?
.then(
() => {
console.log("Data updated successfully.");
res.status(200).send("successful");
},
(error) => {
console.error("Data could not be saved.", error);
res.status(500).send("failed"); // don't use HTTP 201 Created here
}
)
.catch(
(error) => { // if here, either of the above blocks failed - probably due to an error related to the response.
console.error('Failed to send response to client: ', error);
try { res.end() } catch (e) {} // forcefully terminate connection if not already
}
);
});
The error handler that logs response errors could be rewritten so that it can be reused by taking in the relevant response object (so it can terminated when needed) and returning the error handler:
const buildResponseErrorHandler = (response) => ((error) => {
console.error('Failed to send response to client: ', error);
try { response.end() } catch (e) {} // forcefully terminate connection if not already
});
// usage:
somePromise
.then(
sendResponseHandlerForSuccess,
sendResponseHandlerForFailure
)
.catch(buildResponseErrorHandler(res)) // buildResponseErrorHandler(res) returns (err) => { /* logs problem */ }

Return value is always undefined - AWS.SES example running in an Express app

I am using some code from an AWS example to send an email via SES, inside an Express app. The email works great, but I want to be able to change the response to the browser based on the success or failure of sending the email.
But the function that sends the email always returns undefined, I think because the calling function is not awaiting the result properly.
In the express app:
app.post('/api/sendEmail', sendEmail);
async function sendEmail(request, response){
//console.dir(request.body);
await emailer(request.body)
.then(result => console.log(result));
//should base response on result
response.json(('{"status": "success"}'));
}
Then I have another file with the emailer function in it, loaded as emailer.
module.exports = async function sendEmailFunction(data) {
console.log('send email function');
let email = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(createEmailParams(buildEmail(data))).promise();
email.then(
function(res) {
console.log(res.MessageId); // works
return res.MessageId; // undefined
}).catch(
function(err) {
console.error('problems', err, err.stack);
return `Error! ${err}, ${err.stack}`;
});
}
in the console I always get:
send email function
undefined
0101017865c6f27b-955661fb-af47-4490-8eb6-7b59a0ec3414-000000
the guid thing is the console log of res.MessageId (email was successful). Undefined is the console log in the first function logging the result. I can see undefined show slightly before the messageid so I think the sendEmail function is not waiting for the emailer to complete.
Fairly sure the functions in the sendEmail function createEmailParams(buildEmail(data) aren't the problem, if I delete them then I still get undefined returned instead of the error message.
On face value it doesn't look like you're returning the promise to be awaited up stream of sendEmailFunction, nor is it being awaited in the function itself. Consider awaiting the response and returning it in sendEmailFunction, or returning the email promise and letting the upstream function await it and tease out the value it's looking for.
For example:
module.exports = async function sendEmailFunction(data) {
console.log('send email function');
let email = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(createEmailParams(buildEmail(data))).promise();
let response = await email.then(
function(res) {
console.log(res.MessageId); // works
return res.MessageId; // undefined
}).catch(
function(err) {
console.error('problems', err, err.stack);
return `Error! ${err}, ${err.stack}`;
});
return response; }

Return value from callback function in AWS Javascript SDK

I'm using the AWS Javascript SDK and I'm following the tutorial on how to send an SQS message. I'm basically following the AWS tutorial which has an example of the sendMessage as follows:
sqs.sendMessage(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.MessageId);
}
});
So the sendMessage function uses a callback function to output whether the operation was successful or not. Instead of printing to the console I want to return a variable, but every value I set is only visible within the callback function, even global variables like window.result are not visible outside the callback function. Is there any way to return values outside the callback?
The only workaround I've found at the moment is to set a data attribute in an HTML element, but I don't think it's really elegant solution.
I would suggest to use Promises and the new async and await keywords in ES2016. It makes your code so much easier to read.
async function sendMessage(message) {
return new Promise((resolve, reject) => {
// TODO be sure SQS client is initialized
// TODO set your params correctly
const params = {
payload : message
};
sqs.sendMessage(params, (err, data) => {
if (err) {
console.log("Error when calling SQS");
console.log(err, err.stack); // an error occurred
reject(err);
} else {
resolve(data);
}
});
});
}
// calling the above and getting the result is now as simple as :
const result = await sendMessage("Hello World");

Node promise-circuitbreaker - Returning a value from called function

I'm trying to use the promise-circuitbreaker node module.
I am able to pass a parameter to the called function, however, I am unable to have the called function return a value back.
Furthermore, I keep getting a timeout which I don't understand. I am obviously missing something, however I can't find any solution in the docs (http://pablolb.github.io/promise-circuitbreaker/)
I've made a very simple sample app to show my difficulties:
var CircuitBreaker = require('promise-circuitbreaker');
var TimeoutError = CircuitBreaker.TimeoutError;
var OpenCircuitError = CircuitBreaker.OpenCircuitError;
function testFcn(input, err) {
console.log('Received param: ', input);
//err('This is an error callback');
return 'Value to return';
}
var cb = new CircuitBreaker(testFcn);
var circuitBreakerPromise = cb.exec('This param is passed to the function');
circuitBreakerPromise.then(function (response) {
console.log('Never reach here:', response);
})
.catch(TimeoutError, function (error) {
console.log('Handle timeout here: ', error);
})
.catch(OpenCircuitError, function (error) {
console.log('Handle open circuit error here');
})
.catch(function (error) {
console.log('Handle any error here:', error);
})
.finally(function () {
console.log('Finally always called');
cb.stopEvents();
});
The output I get from this is:
Received param: This param is passed to the function
Handle timeout here: { [TimeoutError: Timed out after 3000 ms] name: 'TimeoutError', message: 'Timed out after 3000 ms' }
Finally always called
In my case, I want a simple string to be returned. I don't want a timeout error.
If I uncomment the line //err('This is an error callback') in testFcn(), I get the following output:
Received param: This param is passed to the function
Handle any error here: This is an error callback
Finally always called
So it appears that the 2nd parameter in the called function is for error handling.
Any help would be greatly appreciated.

Is stdout/stderror not part of the promise fulfillment from the ssh-promise library?

I have the following code which promisifies a number of functionCalls to various servers. On the return of all the functionCalls the response object is sent to the Mongo database and stored as a single document. The reason for the promises is that all of the functions must complete and their return value be in the response section so that the database can store all of the appropriate responses. (code follows)
Q.all(functionCalls)
.then(function(response) {
//console.log(response);
Q.then(dbHandler(response))
.catch( function(e) {
console.log(e);
})
.finally( function() {
console.log('Execution completed successfully!');
});
}, function() {
console.log('unhandled exception');
});
The problem I am experiencing is with a single function call that involves the ssh-promise library. The issue is that the promise is resolved before the stdout or stderror fields are populated in the response. Here is the code for the ssh call. Snipped code for brevity follows:
var ssh = new Client(config);
var ack = "200 - OK";
var pub = {};
var execString = "java -classpath" + classpath + javaSecurityArgs + " -DAPP_ENV=" + env + javaMainClass + jobString + " date=" + seconds;
ssh.exec( execString )
.then( function(stdout) {
json.parse(stdout.match(/^FulfillmentReportJson:(.*)$/gm))
.catch(function (e) {
console.log(e.message);
pub = {
'type': 'fulfillmentBatch',
'result': 'failed'
};
})
.then(function (response) {
console.log(stdout);
pub = {
'type': 'fulfillmentBatch',
'result': response
};
}
)
})
.catch(function(stderr) {
pub = {
'type': 'fulfillmentBatch',
'result': 'failed' + stderr
};
})
.done();
The promise fulfillment of "then" returns the response from either stdout or stderror and populates it in the pub.result which is returned.
The question is this: When I execute this code the promise finishes before the stdout or stderror is returned by the ssh.exec. It is like the promise fulfills, then nearly 5 seconds later (well after the database object has been written) we see the return of the stdout/stderror data. The database object contains a 'null' from the spot where this function should have populated data and the console.log(stdout) in the 'then' section contains the stdout/stderror data. Any help would be appreciated.
I reviewed the code after the response above realizing I was approaching the ssh command incorrectly.
ssh.exec(execString, {
exit: function(code, stdout, stderr) {
I should have been using the 'exit' instead of 'out' and 'err' responses on the exec. The exit allows the building of the appropriate response object

Categories