Consider implementing poker on Google App Engine. Suppose a player is allowed only 10 seconds to check/fold/raise.
That is, if 10 seconds pass with no response from the player then some timer should fire which executes code that writes to DataStore declaring that the player folded. What is the idiomatic way to implement this on Google App Engine.
The GAE has a feature called "Tasks". Sadly, they have no guaranteed resolution, so a task scheduled for now+10 seconds can execute in 10 seconds or any later time.
Solution: Write the current time-stamp along with the information about the current player into the database. If any of the players request updated information about the current game, you can check this time-stamp, compare it with the current one, and therefore determine if these 10 seconds have passed and update the database accordingly.
You can combine this solution with tasks to ensure, that even if nobody "watches" that game, its still updated sometime.
This needs to be done on a backend, as that's the only code that can persist outside of a request handler.
Player is dealt. Timer starts on backend. Timer expires. Player
status updated.
Backends are special App Engine instances that have no request deadlines, higher memory and CPU limits, and persistent state across requests. They are started automatically by App Engine and can run continously for long periods. Each backend instance has a unique URL to use for requests, and you can load-balance requests across multiple instances.
https://developers.google.com/appengine/docs/python/backends/
No need to act synchronously - i.e. do some action exactly 10 seconds after last user action.
Just record the time of last user action and act accordingly next time the user action happens: if <10s let user do next move, if >10s notify user he folded.
To keep things more responsive, e.g. to show user how much time he hes before folding, you should also track this on client.
Related
Google describes basic scaling like this:
I don't really have any other choice, as I'm using a B1 instance, so automatic scaling is not allowed.
That raises the question though, if I have an endpoint that takes a variable amount of time (could be minutes, could be hours), and I basically have to set an idle_timeout, will App Engine calculate idle_timeout from the time the request was made in the first place or when the app is done handling the request?
If the former is right, then it feels a bit unfair to have to guess how long requests will take when thread activity is a usable indicator of whether or not to initiate shutdown of an app.
Here you are mixing up two different terms.
idle_timeout is the time that the instance will wait before shutting down after receiving its last request
Request timeout is the amount of time that App Engine will wait for the return of a request from your app
As per the documentation:
Requests can run for up to 24 hours. A manually-scaled instance can
choose to handle /_ah/start and execute a program or script for many
hours without returning an HTTP response code. Task queue tasks can
run up to 24 hours.
I want to send a particular HTTP request (or otherwise communicate a message) to every (dynamic/autoscaled) instance which is currently running for a particular App Engine application.
My goal is to trigger each instance to discard some locally cached data (because I have just modified the underlying data and want them to reload it).
One possible solution is to store a value in Memcache, and have instances check this each time they handle a request to see if they should flush their cache. But this adds latency to every request.
Another possible solution would be to somehow stop all running instances. No fixed overhead, but some impact while instances are restarted.
An even less desirable solution would be to redeploy the application code in order to cause all instances to be stopped. This now adds additional delay on my end as a deployment takes some time.
You could use the management API to list instances for a given version, but I'd suggest that you'd probably want to use something like the PubSub API to create a subscription on each of your App Engine instances. Since each instance has its own subscription, any messages sent to the monitored queue will be received by all instances.
You can create the subscription at startup (the /_ah/start endpoint may be useful), and then delete it at shutdown (using the /_ah/stop endpoint).
I am developing a app that chooses a user and has a 15 sec. timer for that user to respond. The user app queries the db every 5 sec to see if that user is chosen. If so The mobile app begins a 15 sec. timer. The problem is that the timers will never match up because the user app can be on a different timer cycle that the backend and can query the db at a later time. I use Angular, NodeJS, and expressJS + MongoDB to develop this app.
any suggestion on how I can get the timers to be synchronized?
You need to create API for requesting current server time and use that server time as basis of your timer.
You also need to take into account condition when browser pauses javascript execution. This is true for mobile device. When mobile device is paused/sleep, browser stops javascript execution causing timer not sync anymore.
Every tick, check last tick millisecond with current tick millisecond. If difference is greater than some threshold value then assume timer not sync anymore and need to be sync by requesting current server time and recalculate timer value
I'm building a simple "play against a random opponent" back-end using Goole App Engine. So far I'm adding each user that wants to play into a "table" in the Datastore. As soon as there are more than 1 player in the Datastore, I can start to match them.
The Schedule Tasks with Cron looked promising for this work until I saw that the lowest resolution seems to be minutely. If there are plenty of players signing up I want them to be matched quickly and not have to wait a whole minute (worst case).
I thought about having the servlet that recives the "play against random opponent" request POST to a Task Queue that would do the match making, but I think this will lead to a lot of contention when reading from the Datastore and deleting the enteties from the "random" table after they have been matched?
Basically I want a single worker that will do the matching, and I want to signal this worker from time to time that now is a good time to try to match opponents.
Any suggestions on what would be the right course of action here?
You can guarantee exclusive access via transactions:
Receive a request to play via REST. Check (within a transaction) if there is any request in database.
If there is, notify both users to start the play and delete request (transactionaly) from database.
If there isn't, add it to the database and wait for the next request.
Update:
Alternativelly you can achieve what you need via pull queue. Same scenario as above, just instead of datastore you'd check if there is a task in the pull queue, retrieve if there is or create a new one if there isn't one.
Can we start a dynamic backend programatically? mean while when a backend is starting how can i handle the request by falling back on the application(i mean app.appspot.com).
When i stop a backend manually in admin console, and send a request to it, its not starting "dynamically"
Dynamic backends come into existence when they receive a request, and
are turned down when idle; they are ideal for work that is
intermittent or driven by user activity.
Resident backends run continuously, allowing you to rely on the state
of their memory over time and perform complex initialization.
http://code.google.com/appengine/docs/python/backends/overview.html
I recently started executing a long running task on a dynamic backend and noticed a dramatic increase in the performance of the frontends. I assume this was because the long running task was competing for resources with normal user requests.
Backends are documented quite thoroughly here. Backends have to be started and stopped with appcfg or the admin console, as documented here. A stopped backend will not handle requests - if you want this, you should probably be using the Task Queue instead.
It appears that a dynamic backend need not be explicitly stopped. The overvicew (http://code.google.com/appengine/docs/python/backends/overview.html) states that the billing for a dynamic backend stops 15 minutes after the last request is processed. So, if your app has a cron job, for example, that requires 5 minutes to complete, and needs to run every hour, then you could configure a backend to do this. The cost you'll incur is 15+5 minutes every hour, or 8 hours for the whole day. I suppose the free quota allows you 9 backend hours. So, this type of scenario would be free for you. The backend will start when you send your first request to it through a queue, and will stop 15 minutes after the last request you send is processed completely.