question

Frank Giuffrida avatar image
Frank Giuffrida asked

DynamoDB trouble

I have a db class based on one of the examples that logs the object it is saving: Game.prototype = { log: function () { console.log('Game.save currentGame = ' + JSON.stringify(this.data)); }, save: function (callback) { //save the game states in the session, //so next time we can save a read from dynamoDB this._session.attributes.currentGame = this.data; console.log('Game.save currentGame = ' + JSON.stringify(this.data)); dynamodb.putItem({ TableName: 'CooterTranslatorData', Item: { CustomerId: { S: this._session.user.userId }, Data: { S: JSON.stringify(this.data) } } }, function (err, data) { if (err) { console.log(err, err.stack); } if (callback) { callback(); } }); } }; Suddenly yesterday and today, I seem to be calling save according to the logs, but when I look in the dynamo db afterwards, there is nothing there. I don't see throttled invocations, database errors, or other issues. This has been working for weeks, and I don't think I tweaked that part of the code. Anyone have any ideas? 2015-07-30T15:09:01.214Z e8a16e0e-36cc-11e5-a705-3551eb3b1e5c CyberDartSkill handleNewGameIntent end load teams, current gameTypeSlot = CRICKET 2015-07-30T15:09:01.214Z e8a16e0e-36cc-11e5-a705-3551eb3b1e5c Game.save currentGame = { } 2015-07-30T15:09:01.214Z e8a16e0e-36cc-11e5-a705-3551eb3b1e5c Game.save currentGame = { } 2015-07-30T15:09:01.218Z e8a16e0e-36cc-11e5-a705-3551eb3b1e5c CyberDartSkill handleNewGameIntent end load teams, game saved = { "data": { }, "_session": { "new": false, "sessionId": "amzn1.echo-api.session.61b0639c-813b-4f67-8ffd-1abd461068e6", "application": { "applicationId": "amzn1.echo-sdk-ams.app.2a1ebff1-1e00-471c-b591-1ddad98d1fdf" }, "attributes": { "currentGame": { }, "oneShot": false }, "user": { "userId": "amzn1.account.AFGMMAPABJ3DL6A3NXNMIDVQPS6A" } } } 2015-07-30T15:09:01.218Z e8a16e0e-36cc-11e5-a705-3551eb3b1e5c CyberDartSkill handleNewGameIntent ask team names... 2015-07-30T15:09:01.218Z e8a16e0e-36cc-11e5-a705-3551eb3b1e5c CyberDartSkill handleNewGameIntent ask player names... END RequestId: e8a16e0e-36cc-11e5-a705-3551eb3b1e5c REPORT RequestId: e8a16e0e-36cc-11e5-a705-3551eb3b1e5c Duration: 96.63 ms Billed Duration: 100 ms Memory Size: 640 MB Max Memory Used: 14 MB START RequestId: f4d77ffd-36cc-11e5-a935-63298e59a975 Message was edited by: Frank Giuffrida
alexa skills kitsubmission testing certification
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
If I continue the interaction, I find it in the database, but if I end right there nothing seems to be saved, even though the logs show it being done.
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've got it to work in Java. I'm not familiar with the JavaScript interface. Does it fork stuff off into the background? I tried this originally in Java, then found out that when the Lambda function returns, the system halts the JVM, killing all my background processes. Could something like that be a problem?
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
Looks like I figured it out. Changing the end of the function from: // TEAM NAMES if (currentGame.data.withTeamNames) { // TEAM NAMES console.log("CyberDartSkill handleNewGameIntent ask team names..."); speechOutput = "Say the word team, followed by the team name for team number one? "; response.ask(speechOutput, "Again. " + speechOutput); } else { // PLAYER NAMES console.log("CyberDartSkill handleNewGameIntent ask player names..."); speechOutput = "Hello, Who is the first player "; if (currentGame.data.withTeamNames) { speechOutput += "for team " + currentGame.data.teamnames[0] + ". "; } else { speechOutput += "for team number one. "; } response.ask(speechOutput, "Again. " + speechOutput); } }); } to: // TEAM NAMES if (currentGame.data.withTeamNames) { // TEAM NAMES console.log("CyberDartSkill handleNewGameIntent ask team names..."); speechOutput = "Say the word team, followed by the team name for team number one? "; //response.ask(speechOutput, "Again. " + speechOutput); } else { // PLAYER NAMES console.log("CyberDartSkill handleNewGameIntent ask player names..."); speechOutput = "Hello, Who is the first player "; if (currentGame.data.withTeamNames) { speechOutput += "for team " + currentGame.data.teamnames[0] + ". "; } else { speechOutput += "for team number one. "; } //response.ask(speechOutput, "Again. " + speechOutput); } // save game currentGame.save(function () { if (session.attributes.oneShot) { console.log("CyberDartSkill handleAddTeamNameIntent sessionId: " + session.sessionId + " tell..."); response.tell(speechOutput, "Again, " + speechOutput); } else { console.log("CyberDartSkill handleAddTeamNameIntent sessionId: " + session.sessionId + " ask..."); response.ask(speechOutput, "Again, " + speechOutput); } }); }); } worked. Now I need to figure out why.
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
Is it possible you are exiting the lambda function via some other path before the putItem callback is being invoked (i.e. before putItem has completed)? (A console.log from within the putItem callback would be helpful).
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
Here is my save, note that it does putItem and then looks at the err code before doing the callback: Game.prototype = { log: function () { console.log('Game.save currentGame = ' + JSON.stringify(this.data)); }, save: function (callback) { //save the game states in the session, //so next time we can save a read from dynamoDB this._session.attributes.currentGame = this.data; console.log('Game.save currentGame = ' + JSON.stringify(this.data)); dynamodb.putItem({ TableName: 'CooterTranslatorData', Item: { CustomerId: { S: this._session.user.userId }, Data: { S: JSON.stringify(this.data) } } }, function (err, data) { if (err) { console.log(err, err.stack); } if (callback) { callback(); } }); } My log file shows the result of this: console.log('Game.save currentGame = ' + JSON.stringify(this.data)); And I see no error being reported. But if I stop the app there and then look in the db manually, I do not see this updated record. I see the update before this one. -Frank PS why do I see code formatting when I am editing my forum reply, but not after I save null
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
putItem is ansynchronous - execution of your code does not pause waiting for putItem to finish (i.e. putItem is not blocking). The function passed to putItem is only called *after* putItem has added your item to the database (or after there is an error trying to do so). Before that point though, other code of yours, after the call to putItem will be executed and perhaps there is a code path that exits. Try a log message inside the function you are passing to putItem (outside of the err conditional) - I am guessing you won't see that message in the logs, because the function passed to putItem isn't being called before your code exits.
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 think I have found a save call in my intentHandler which was not passed to putItem. I think this save is competing with the save which is properly passed to putItem and timing is causing the weird results to not happen every time. I will look at changing the logic. 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.