1
votes

I'm trying to write a quiz game where Alexa asks 10 random questions from a list, and keeps track of the score, then announces it. I'm using a Node.js Lambda function to do so.

I wrote a class, QuizMaster, which runs the quiz: it asks the user their preferred categories and difficulty level, creates the randomized list of question with randomized A/B/C answer slots, and checks whether a supplied answer is correct for the last-spoken question.

Here's where things get tricky for me: where can I save the reference to that QuizMaster instance? If I create it as a variable outside the intent handlers, it works fine for the first time, but then the quizmaster is still around if the user re-invokes the skill, and will immediately re-announce their final score and end the game. This confuses me a bit, because my mental model was that every time a Lambda endpoint is hit it's like Amazon is running node index.js and when the session ends, execution ends. But I suppose I'm wrong -- is it more like Amazon runs node index.js once, keeping it open in a loop listening for events, and every event goes to the handler function? So if I run it twice in a row, I've still got those old variables around with their old values? Does that mean if 10 users run my Alexa skill simultaneously, they all share the same values for those variables/modify each other's state? Or would it be like AWS running the file 10 times and charging me for 10x the memory of a single execution?

So, I guess I'm meant to store state in a database or directly attached to the session (in the Alexa Node SDK, this.attributes). So do I need to rewrite my application in such a way that I can serialize the state, attach it to the session, then pull the state out -- I can't keep a QuizMaster instance around to keep track of things per-user-session?

3

3 Answers

1
votes

I need to rewrite my application in such a way that I can serialize the state, attach it to the session, then pull the state out -- I can't keep a QuizMaster instance around to keep track of things per-user-session

Yes, that's exactly what you need to do.

Each invocation is independent and subsequent invocations may or may not be handled by the same container.

The only reliable way to keep state across invocations is to use an external store such as DynamoDB, RDS, etc.

0
votes

Amazon and a lot of other folks have posted instructions and examples of saving state using dynamoDB. Try doing a search on "Alexa dynamoDB".

0
votes

You don't need to use their Node or Java SDK's, nor do you have to use AWD Lambda to host your skill responses. I self host my skill's interactions on a normal web server running Apache/PHP.

Alexa just requires that you send back a JSON response.

I wrote my own handler using just PHP. It's pretty straightforward. I was even able to implement progressive responses for when there is a short delay in bringing back the data that the user requested. Alexa says, "Hold on while i look that up." so the user doesn't think the session has lagged or ended. I post to the directives API endpoint using stream_context_create and file_get_contents in PHP before I run the lookup. I also maintain session and state using PHP session variables. The session ends when the user quits. If I wanted to store the specific user's current state I would just write the current state to a MySQL database using PHP.

Someone wrote a PHP handler to do all this. I don't use this one but it's a good start for people who are more familiar with PHP vs Node or Java.

https://github.com/Fever905/amazon-alexa-php

Mine is a little different. To maintain my sessions I use the following code:

 $json = file_get_contents('php://input');
 $data = json_decode($json);

 $sessionid = str_replace("amzn1.echo-api.session.","",$data->session->sessionId);

 session_id($sessionid);
 session_start();

This allows me to store session vars like $_SESSION['count'] = 10; which persist throughout the user's session in my Skill.