question

Randy King avatar image
Randy King asked

Allocating resources in OnSessionStarted

I need to retrieve user specific resources from a database on new session start. I need to do this whether it is a LaunchRequest or an IntentRequest. The OnSessionStarted event handler seems the obvious place to do this. However, it appears from looking through AlexaSkills.js that an OnSessionStarted even handler cannot have asynchronous calls. Can this be right? I am new to the whole asynchronous callback thing in Node.js and to the object-oriented JavaScript approach. However, I moved my first project to ver. 1.0 of the SDK (AlexaSkill.js) specifically because I was having problem getting this to work in the beta SDK framework. Please let me know what people are doing when they need asynchronous resources regardless of whether it is a LaunchRequest or IntentRequest - just duplicating the code? Thanks for the guidance!
alexa skills kitdebugging
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Greg Crawford avatar image
Greg Crawford answered
Edit: I didn't read your post thoroughly. Why not do the the required async database access in the LaunchRequest event? Message was edited by: Greg Crawford
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Greg Crawford avatar image
Greg Crawford answered
Note that in the sample code, onSessionStarted is not being called as a request type distinct from LaunchRequest or IntentRequest. There is a check for event.session.new made in the handler, no matter the request type. When onSessionStarted is completed, control continues on to the request handlers and both LaunchRequest or IntentRequest (as well as SessionEndedRequest) allow for async calls. So you shouldn't have any problems.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Randy King avatar image
Randy King answered
"Why not do the the required async database access in the LaunchRequest event?" Well, there are several problems with that approach. First you have to do it in both LaunchRequest and IntentRequest, because LaunchRequest may not be called if it is a one shot command. In addition, putting the check in IntentRequest is very messy for several reasons. For example, you have to override the onIntent even handler in your code and not just rely on the intentHandlers array. Also, since several IntentRequests may be called in a session, you have to have some check at the top of the IntentHandler function that checks if the user context profile as been initialized (or maybe just checks the new session flag). Since the call to retrieve the user context data from DynamoDB is Asynchronous, this is ugly code, e.g.: If (session.new) { getUserProfileData(session.user.userid, callback) } else { callback(session.attributes.userprofiledata) } function callback(userprofiledata) { if (userprofiedata is null) { handle missing user profile data } else { session.attributes.userprofiledata = userprofiledata dispatch intent code (from the class) } } This is, of course, on top of coding up something very similar in the onLaunch function. Why not just architect OnSessionStarted so it can handle an asynchronous call, and do the coding to retrieve the user profile data and handle missing data in one place? Frankly, without async calls, I don't really see how OnSessionStarted is good for setting up session resources as it states. Of course, this only really matters if you are coding in node.js like I am. Maybe it makes perfect sense in Java or other models. Message was edited by: Randy King
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Frank Giuffrida avatar image
Frank Giuffrida answered
I use the approach from the scoreKeeper example in the AlexaLambdaExamples. Calls to the database are given a callback function which launches when the db call is completed. Code to be executed after the db call completes is placed in the callback. return { loadGame: function (session, callback) { if (session.attributes.currentGame) { console.log('get game from session=' + session.attributes.currentGame); callback(new Game(session, session.attributes.currentGame)); return; } dynamodb.getItem({ TableName: 'ScoreKeeperUserData', Key: { CustomerId: { S: session.user.userId } } }, function (err, data) { var currentGame; if (err) { console.log(err, err.stack); currentGame = new Game(session); session.attributes.currentGame = currentGame.data; callback(currentGame); } else if (data.Item === undefined) { currentGame = new Game(session); session.attributes.currentGame = currentGame.data; callback(currentGame); } else { console.log('get game from dynamodb=' + data.Item.Data.S); currentGame = new Game(session, JSON.parse(data.Item.Data.S)); session.attributes.currentGame = currentGame.data; callback(currentGame); } }); }, newGame: function (session) { return new Game(session); } };
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

jjaquinta avatar image
jjaquinta answered
I route my onSessionStarted and onIntent through the same code. Saves headaches like that. Also, since Alexa drops sessions at the drop of a hat, I don't trust it for session management and do my own. Saves all the hassle. And, yes, it's a lot easier to do in Java (or any other language) with a WebService. You can then cache things, run things on the background, and all sort of the stuff you expect if you are used to coding enterprise applications. Running Javascript (or even Java) from Lambda may be cheap, but its really restricted.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Rand M avatar image
Rand M answered
> I route my onSessionStarted and onIntent through the > same code. Did you mean "onLaunch" and "onIntent?" I'm trying to understand session management (it's time for me to reread your book). Thanks
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

jjaquinta avatar image
jjaquinta answered
Yes, sorry. onLaunch and onIntent. I was writing too quickly. I don't think the book says much more than "I route them both through the same code". :-) I'm trying to close down the August updates. Maybe I should go through and see if I can say more about session management. Right now the new stuff is on business development, test suites, and some tips for lambda development.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Greg Crawford avatar image
Greg Crawford answered
You are correct. I admit I wasn't thinking much of the "one shot command" scenario. But it's not too hard to call a session setup sequence in both LaunchRequest and IntentRequest which can get user profile, etc from database before continuing. I suppose it might not be the cleanest code, but code is never as clean as we want :)
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.