Problem with calls to Firebase Storage within Jovo lambda function


#1

Hello,

I’ve been developing a few skills for both Alexa and Google Home using the Jovo framework. However, I have encountered a problem that I just cannot seem to solve. We have a set of audio files (MP3) in Google’s Firebase storage and I’d like to access them and play them in an audio player. I was able to get this working and everything seemed fine…until I tried to run the code in a lambda function. When the model executes in a lambda function, it never returns - the lambda function times out. No matter how high I set the lambda timeout, it still gets stuck. Here is a simple example which demonstrates the problem:

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`);
  },

When I look in cloud storage I can see a good URL printed out and I can see the SSML string constructed. However, I never hear the message and I get a timeout error.

Any thoughts?

I also posted this on stackoverflow here: https://stackoverflow.com/questions/59322763/how-do-i-exit-a-lambda-function-that-has-a-call-to-firebase-storage


#2

Hello! I’m a noobie looking for answers, too. Although I have a ton of experience in programming. OK so awesome what you’re doin’. Are you using Docker? I read that you need to use Docker in order to do this with AWS Lambda. Here’s an article that says “You need to have docker installed.” I can’t find the original forum source that convinced me of that topic. Maybe that will help you. Source: https://medium.com/@samstern_58566/how-to-use-cloud-firestore-on-aws-lambda-4bf6d3a473d9


#3

Adding to what I said, actually, I’ve successfully done what you are trying to do for Alexa Voice, but I actually used environment variables and a dropbox folder. It was a few lines of code and very simple to get the mp3s playing on Alexa. If that helps, too. Good luck!!


#4

Thanks Tony. In a previous version of this skill, I was able to get the MP3 files from an AWS S3 bucket and get them playing on Alexa. However, we have developed a corresponding App for iPhone/Android that stores all the MP3s in Google Firebase - so I have to use that storage if at all possible. There just seems to be something strange with using the Google GetDownloadURL() call within a Lambda function within Jovo. I am not using docker - I’m not sure why that would be necessary, but I will look at the article you posted. Thanks again for helping to look at this issue with me.


#5

No problem!

Is it possible that you’re using an escape key instead of a single quote and that is why it’s breaking after printing the URL? If the URL prints it would make sense:

this.tell('Ok, done with getting the URL');


#6

No, unfortunately, I don’t think the string passed to tell is the problem. I reduced the code to what I’ve listed below, and it still does not return from the Lambda function. I’m beginning to consider hosting on Google instead of AWS:

async LAUNCH() {
    firebase.initializeApp(firebaseConfig);
    const storageFiles = firebase.storage().ref().child('EN');
    const storageFile = storageFiles.child('1.mp3');
    const url = await storageFile.getDownloadURL();
  },

I also tried installing the node modules with docker, but I still had the same issue with the Lambda function timing out. As long as the getDownloadURL() method is in there, it hangs up Lambda. If I comment that line out, the function exits as expected.


#7

Another quick data point: I changed the hosting to Google Cloud (isn’t it great that Jovo makes that so easy?) and my program works fine. However, I still would love to figure out why I cannot use Firebase storage with Lambda, since all of my other Skills are hosted in AWS.

Maybe this is a just a case of Amazon and Google not playing nice with each other…


#8

Ok, I believe I have found the solution. I had to modify the index.js within Jovo to look like this:

// AWS Lambda
exports.handler = async (event, context, callback) => {
    **context.callbackWaitsForEmptyEventLoop = false;**
    await app.handle(new Lambda(event, context, callback));
};

The important line is the one setting callbackWaitsForEmptyEventLoop to false. This changes the default behavior of Lambda and closes the connection that is opened with the getDownloadURL call.

Once I made this change I was able to successfully run the Skill and access audio files from Firestore.