Discuss Scratch

MegaApuTurkUltra
Scratcher
1000+ posts

Cloud variables and concurrency

I'm planning on a project with a cloud leaderboard. I already made a system for encoding usernames and scores lists as numbers, so that's not a problem.

What I'm worried about is the following. Although there's a very low chance of it happening, it could happen.
  1. Player 1 gets a higher score than everyone else
    score = 10000
  2. Player 2 gets a higher score than everyone else
    score = 9999
  3. Player 1 retrieves and decodes cloud leaderboard
    leaderboard:
    Herp: 5000
    Derp: 4500
    Derpity Derp: 1000
  4. Player 2 retrieves and decodes cloud leaderboard. Note that at this point Player 1 is not on the leaderboard yet.
    leaderboard:
    Herp: 5000
    Derp: 4500
    Derpity Derp: 1000
  5. Player 1 updates the leaderboard with the score and sets the cloud variable
    leaderboard:
    Player1: 10000
    Herp: 5000
    Derp: 4500
    Derpity Derp: 1000
  6. Player 2 still has the leaderboard as
    leaderboard:
    Herp: 5000
    Derp: 4500
    Derpity Derp: 1000
    so when the cloud variable is updated the list now looks like
    leaderboard:
    Player2: 9999
    Herp: 5000
    Derp: 4500
    Derpity Derp: 1000
  7. Player 1's score now has disappeared! The list on the cloud variable is
    leaderboard:
    Player2: 9999
    Herp: 5000
    Derp: 4500
    Derpity Derp: 1000

Is there any way to prevent this?

$(".box-head")[0].textContent = "committing AT crimes since $whenever"
SurgeForce
Scratcher
100+ posts

Cloud variables and concurrency

Before updating the scoreboard, player 2 should check if it still equals the same thing as it did when player 2 first retrieved it to change it.
SurgeForce
Scratcher
100+ posts

Cloud variables and concurrency

If its different, player 2 should delete his edited version and retry
MegaApuTurkUltra
Scratcher
1000+ posts

Cloud variables and concurrency

SurgeForce wrote:

Before updating the scoreboard, player 2 should check if it still equals the same thing as it did when player 2 first retrieved it to change it.
But then you run into the same problem. What if it's updated right after the check?

$(".box-head")[0].textContent = "committing AT crimes since $whenever"
MegaApuTurkUltra
Scratcher
1000+ posts

Cloud variables and concurrency

Bumpity bump. Does anyone have an answer?

$(".box-head")[0].textContent = "committing AT crimes since $whenever"
TheLogFather
Scratcher
1000+ posts

Cloud variables and concurrency

You might find the following posts I made a while back have some helpful info:
http://scratch.mit.edu/discuss/post/293717/
http://scratch.mit.edu/discuss/post/129373/
http://scratch.mit.edu/discuss/post/119793/


Ultimately, though, the way the cloud is implemented at the moment, you can't really guarantee 100% that you will avoid situations like above. You can do things that can help make it less likely, though (see below).

Having said that, I think the simplest thing for something as basic as a cloud-based hi-score, is to just GFI, ignoring the problems, expecting that it's really rare two people will save a hi-score at very nearly the same time (within half a second, usually).


If you do want to make it even less likely to cause trouble, then I'd suggest a kind of ‘locking’ mechanism, something like I was attempting with my cloud locking project, and used in my cloud ping test project (I also put something like it into the hi-score table for InterXeptor 3D).

The idea is to have a single ‘locking’ cloud variable, that you set to a unique value for a user (based on an encoded version of their username, or a long string of random digits), but wait for it to be zero before trying to set it (with a timeout of a few seconds). Once ‘locked’, read the hi-scores from cloud (to ensure got latest values), prepare the new hi-score encoded string (but don't put into actual cloudvar yet). After a second or two, check that the locking cloudvar still has the correct value (if not, start the whole process again). If it does, then update the hi-score cloudvar, and release the locking cloudvar (set it back to zero).

Hope there's some useful thoughts there…

Last edited by TheLogFather (Aug. 16, 2014 20:11:07)


Siggy the Kumquat slayer:
Main account: DadOfMrLog –– Frameworks for basic pen-rendered 3D in scratch (see studio). Examples:

- - - - 3D Text - - - - - - Simple shapes - - - Controllable structures - - - On the ground - - - - - - In space - - - -

AonymousGuy
Scratcher
1000+ posts

Cloud variables and concurrency

My way of cloud engines was designed to prevent any of this ever.

How it works - each client gets an “id” when first starting the project. There is then a cloud variable which contains the “id” whose turn it is to save. If someone disconnects, eventually the “id” will get around to someone still connected.

However, it makes it much slower - I'm guessing that there's basically a tradeoff - either the possibility of data overwrite with higher speeds, or safer cloud data with much slower speeds.

I, of course, am by no means an expert.
TheLogFather
Scratcher
1000+ posts

Cloud variables and concurrency

@AonymousGuy: Beware of saying “ever” - yes, making it turn-based can help reduce risks, but I can think of at least two potential ways that it could go wrong…

1) Think about loopholes in the first essential part - getting an ‘id’. What happens if two users try to get an id at very nearly the same time? Is there really no way they could end up with the same id…? (I don't know exactly how your engine works, but I'm guessing it's quite likely there's a potential loophole…)

2) What happens if a user doesn't take their turn? Does it eventually give up and ‘skip’, moving on to the next user? If so, I suspect there will be a loophole where a user with a slow/dodgy connection could end up seeing their ‘turn’ after it's already moved on to someone else - and they then make their changes to the cloudvar, overwriting anything else done by the subsequent user(s) - and presumably resetting the ‘turn id’ back to a user who's just had their turn…


One of the things to remember is that the order values are sent from the server to users is not necessarily the order the users will receive those values. Similarly, the order users send values to the server is not necessarily the order the server will receive them - it all depends on networks, etc.

Of course, most of the time these won't be so much of a problem (if you don't have too many people making changes at once). But are either of the above two scenarios possible, do you think…?

Last edited by TheLogFather (Aug. 17, 2014 15:18:36)


Siggy the Kumquat slayer:
Main account: DadOfMrLog –– Frameworks for basic pen-rendered 3D in scratch (see studio). Examples:

- - - - 3D Text - - - - - - Simple shapes - - - Controllable structures - - - On the ground - - - - - - In space - - - -

AonymousGuy
Scratcher
1000+ posts

Cloud variables and concurrency

TheLogFather wrote:

@AonymousGuy: Beware of saying “ever” - I can think of at least two potential ways that the method you describe could go wrong…

AonymousGuy wrote:

I, of course, am by no means an expert.


TheLogFather wrote:

1) Think about loopholes in the first essential part - getting an ‘id’. What happens if two users try to get an id at very nearly the same time? Is there really no way they could end up with the same id…? (I don't know exactly how your engine works, but I'm guessing it's quite likely there's a potential loophole…)
Yes, that could be a problem - I guess I never thought about it before. I guess I'll just have to hope that nobody tries to connect at the exact same time…

TheLogFather wrote:

2) What happens if a user doesn't take their turn? Does it eventually give up and ‘skip’, moving on to the next user? If so, I suspect there will be a loophole where a user with a slow/dodgy connection could end up seeing their ‘turn’ after it's already moved on to someone else - and they then make their changes to the cloudvar, overwriting anything else done by the subsequent user(s) - and presumably resetting the ‘turn id’ back to a user who's just had their turn…
It will skip them and actually remove them from the queue, basically disconnecting them. I've tried to keep this minimal by waiting something like 4 seconds to wait for their connection, but if they don't take their turn, the person next will eventually take their own, and add the previous user to a list of user ids to skip.

Of course, they would still overwrite the data once, but after that they would be virtually disconnected, without the ability to write data.

The only way they would be added back on is if they were also re-writing the list of user ids to skip - which would be unlikely.
Ante22
Scratcher
100+ posts

Cloud variables and concurrency

I have the simmilar problem.
You could make update before saving. (Not very helpfull ha ?)

Check out my game ☁ Cloud Farm: http://scratch.mit.edu/projects/25278669/

Powered by DjangoBB