Forum BigDB Optimistic Locking and circular reference error

Discussion and help relating to the PlayerIO database solution, BigDB.

Optimistic Locking and circular reference error

Postby capitaljmedia » May 16th, 2012, 7:20 pm

Hi there,

I'm trying to use Optimistic Locking for BigDB in my game and getting this error:
>Error: Cannot create circular references inside database objects

I'm pretty sure the error is because I am sending the same reference to a databaseObject background the same function when it is unable to save to the database. If that is the problem, does anyone have any better suggestions for how to accomplish this or how to copy a DatabaseObject into a new one?

Here's my code for this (it's a function that processes messages that get added to a player's message queue, and sometimes multiple messages are being sent at the same time, hence the optimistic locking):

Code: Select all
        private void SendInfoMessage(string playerID, DatabaseObject messageObject)
        {
            // Add message to the owning player's object
            PlayerIO.BigDB.Load("PlayerObjects", playerID, delegate(DatabaseObject playerObject)
            {
                if (playerObject != null)
                {
                    DatabaseArray messagesArray = playerObject.GetArray("messages");
                    messagesArray.Add(messageObject);

                    playerObject.Save(true, null, delegate(PlayerIOError error)
                    {
                        // if the player object is currently being saved, retry saving by loading fresh version
                        if (error.ErrorCode == ErrorCode.StaleVersion)
                        {
                            SendInfoMessage(playerID, messageObject);
                        }

                    });....
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Optimistic Locking and circular reference error

Postby capitaljmedia » May 21st, 2012, 8:02 pm

Any ideas, anyone?
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Optimistic Locking and circular reference error

Postby FulaFisken » May 29th, 2012, 5:53 am

You can't add the messageObject more than once... You should only retry the actualy save.

Something like this...

Code: Select all
  private void SendInfoMessage(string playerID, DatabaseObject messageObject)
        {
            // Add message to the owning player's object
            PlayerIO.BigDB.Load("PlayerObjects", playerID, delegate(DatabaseObject playerObject)
            {
                if (playerObject != null)
                {
                    DatabaseArray messagesArray = playerObject.GetArray("messages");
                    messagesArray.Add(messageObject);

                    DoSave(playerObject);
                }
           });
      }

  private void DoSave(DatabaseObject playerObject)
        {
       playerObject.Save(true, null, delegate(PlayerIOError error)
                    {
                        // if the player object is currently being saved, retry saving by loading fresh version
                        if (error.ErrorCode == ErrorCode.StaleVersion)
                        {
                            DoSave(playerObject);
                        }

                    });
      }
Fula Fisken
website blog twitter
Play Game
Astroflux
User avatar
FulaFisken
Paid Member
 
Posts: 139
Joined: March 2nd, 2011, 10:15 am

Re: Optimistic Locking and circular reference error

Postby capitaljmedia » May 29th, 2012, 6:57 pm

Hi, thanks for the suggestion. I'm not sure that will work though because the DoSave function will just go into an endless loop as the playerObject will always be stale if it is not refreshed somehow (I just tested this out and it just loops forever). In order to try saving the object into the database again, I think you need to reload the latest version from the database first and then make your modifications again and try saving again. Right? or am I missing something?
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Optimistic Locking and circular reference error

Postby FulaFisken » May 29th, 2012, 11:07 pm

ahh... yes. I was totally wrong here. But i would definetly aggregate messages and save them in chunks is possible. Try to use a dirty flag and save every xx second or so. I don't know how time sensetive this is.
Fula Fisken
website blog twitter
Play Game
Astroflux
User avatar
FulaFisken
Paid Member
 
Posts: 139
Joined: March 2nd, 2011, 10:15 am

Re: Optimistic Locking and circular reference error

Postby capitaljmedia » May 29th, 2012, 11:10 pm

What do you mean by dirty flag?
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Optimistic Locking and circular reference error

Postby FulaFisken » May 30th, 2012, 12:23 am

capitaljmedia wrote:What do you mean by dirty flag?


Nvm.. I think I need to go to bed... to late here :D

But I am curious why you need to save after adding every messageObject? Isn't it better to queue a bunch of messages and then save them all at once? Saving to much is never good and can lead to problems.. I think 5 concurrent saves are allowed on one DatabaseObject.

post7842?hilit=save%20optimistic#p7842

Not sure if that will help.
Fula Fisken
website blog twitter
Play Game
Astroflux
User avatar
FulaFisken
Paid Member
 
Posts: 139
Joined: March 2nd, 2011, 10:15 am

Re: Optimistic Locking and circular reference error

Postby Henrik » May 31st, 2012, 10:40 am

Let's back up a bit. What are you trying to accomplish?

It looks like you want some sort of message queue in BigDB for each player? And you do that by having an array on the PlayerObject of each player? And on one end you add objects to that array, and on some other end you pick them up and.. process them and delete them? Keep them? And then you run into issues when multiple threads want to add a message to the queue at once? Correct?

Don't use the PlayerObject for this. Make a separate table, add an index on your playerid, and then for each message you add, just create a new object in the table, with the correct playerid, perhaps a timestamp, and the message. This way you will never have optimistic locking conflict on the saving end.

And on the other end, you just use LoadRange to grab all messages by playerid, and you can delete them one by one when you've processed them. No conflicts, no locking, no nothing.


And to back up even further... Why are you passing messages to other players through BigDB? Why not use the multiplayer service?
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Optimistic Locking and circular reference error

Postby capitaljmedia » May 31st, 2012, 7:18 pm

Hi Henrik,

Yes, that is pretty much what I am trying to do. I was using the playerObject as the place to store all of the changes to the player's stats on the serverside. The game is a persistent world MMO, so I wanted to keep the playerObject on the DB always saved with the latest state of the player's stats. Now I don't think that was the best way to do things because of all the constant DB writes to the playerObject. It made things easy on one end where it kept the client and server in sync and saved, but I think it introduced some other bugs where the playerObject was being accessed and saved too much. So I'm changing my server code over so that it just stores all of the players stats in the Player object and only updates the DB's playerObject every 30 seconds if there have been changes.

The same thing with the messages, the main reason I want to use the DB for sending certain types of messages to a player is because I still want those messages saved even if the player is not currently online, so the only way to do that is with the DB. For example, if a player made money or lost something while they weren't online, they need to be notified once they log back in of exactly what happened. That said, saving those messages to the playerObject was probably the wrong way to go as you indicated. I'm moving over to creating a new master messages/notifications table and saving all messages to that with the playerID. The one downside to this approach that I can think of is that someone could hack the game and access other player's messages by requesting messages matching their playerIDs. I could prevent this by only having the server send the contents of the message to the player, but that seems like extra overhead which I'm not sure if it outweighs the potential impact of that kind of hack.

I guess this is the learning experience of making your first MMO game.. as a one man dev team :) still thanks to Playerio the game is almost done and can begin testing within the next month :)
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Optimistic Locking and circular reference error

Postby Henrik » May 31st, 2012, 8:28 pm

capitaljmedia wrote:So I'm changing my server code over so that it just stores all of the players stats in the Player object and only updates the DB's playerObject every 30 seconds if there have been changes.

That sounds like a good idea, and that's also what FulaFisken meant with the dirty flag in the comment above.

capitaljmedia wrote:I guess this is the learning experience of making your first MMO game.. as a one man dev team :) still thanks to Playerio the game is almost done and can begin testing within the next month :)

I'm glad you like our service! :-)
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm


Return to BigDB