I'm trying to implement an Alexa skill (written with Jovo) that accesses audio files that we have stored in Google's Firebase storage. However, I cannot get the lambda function to return, no matter what timeout value that I give. I believe my problem is in how I am handling async code within Lambda, but I can't figure out the correct syntax for what I am trying to do, especially within the Jovo framework.
Here's a version of some code which has the issue. In the real code it passes the url to an audio player, but this example is much simpler to demonstrate the problem:
app.setHandler({
async LAUNCH() {
firebase.initializeApp(firebaseConfig);
const storageFiles = firebase.storage().ref().child('EN');
const storageFile = storageFiles.child('1.mp3');
const url = await storageFile.getDownloadURL();
console.log(`My URL: ${url}`);
this.tell(`Ok, done with getting the URL`);
},
... More Jovo intent calls ...
});
module.exports.app = app;
When I run this in a Lambda function, I see the console.log with a good URL printed out. I also see the SSML string constructed, but I never hear the phrase and the Lambda function times out (even with a 20 sec timeout). If I comment out the getDownloadURL line, the function returns just fine. Also, if I run this outside of Lambda with jovo run
, it works ok there as well.
Bottom line: what do I need to do to be able to use the getDownloadURL() method within a lambda function?
I have found a solution to my issue. The Jovo framework creates a Lambda handler function that looks like this (in index.js):
I needed to change the default Lambda behavior by setting the callbackWaitForEmptyEventLoop to false. The handler function now looks like:
Once I made this change I was able to successfully get URLs from Firebase storage and play them on the Alexa audio player via a Lambda function. The default Lambda behavior is to leave certain connections open (I believe for serverless perfomance reasons), and this change modifies that behavior.