Periodically updating the game state for all users - ruby-on-rails

I'm working on writing a poker room game in ruby. I'd like to set a time limit on how long each player has to decide what their play is, at the end of which period the game will decide what happens next. (did this particular player time out? did everyone fold? is this the end of the game? etc)
I'd like to poll what's happening on the server from the user's side with JS, but how do I make the server run a background task that advances the state of the game every N minutes? (a value that could be different per each poker room)

This is quite a hard problem to solve. Here might be one of the easiest ways to solve it. Using a background scheduling. For example with sidekiq.
You can schedule a job to update the game state like:
class GameTimoutTrigger
include Sidekiq::Worker
def perform(game_id)
game = Game.find(game_id)
game.timeout!
end
end
And when a game round starts you schedule the timeout trigger
round_timeout = game.round_interval
GameTimoutTrigger.perform_in(round_timeout, game.id)
Be aware that sidekiq will poll jobs in the schedule on intervals (15 secs by default). So there will be always some delay on the timeout.
If the round time must be always exactly 60 seconds for example, you could save the round start and stop timestamps, and user's action timestamp. And only accept user action if it's between the round range. But this might be not necessary. It's just a heads up.

You got the right idea with setInterval().
window.setInterval("javascript function",milliseconds);
The "javascript function" can update the game on the client side and make a request to the server to update. Make sure to clearInterval() if you want to prevent the function from running.
If you're really looking for a way to make the server run a background task, you can maybe try the delayed-jobs gem, but websockets or setInterval is probably a better way to go.

Related

How to setup a "watch" for notifications in Ruby on Rails?

I would like to setup a simple notifications system for my web app that is written in Ruby on Rails. My website is a simple auction site, but each auction has 2 stages: a 5 day "no minimum bid" stage where anyone can bid and a 3 day "$1 minimum bid" stage where only the top 10% of the bidders from the previous stage can bid.
I want to notify my users when the auction goes from the first stage to the second. What is the best way to do this?
I've thought of two design options:
I don't know RoR has this, and whether this is an efficient system (because I want to build a system that will have thousands of users participating in hundreds of auctions - whether it gets that big or not is irrelevant, this is sort of a side project for me to learn to write high quality, scalable RoR) but basically, when a user bids on an auction, they become an observer of some sort on the auction. Then, somehow at the 5 day mark, all the listeners are notified. I don't know how that trigger happens though in RoR (is there some way to say "trigger after 5 days from creation" or some such thing?). To summarize, I would like to use the Observer pattern.
The key issue for me is trying to figure out how to trigger after a set period of time. The best way to do it, I think, would be for each auction to have some set state variable called "auction state". After a certain period of time, that would transition, and at that point every observer on the auction would get notified.
There is a rake task that runs everyday at some set time each day. It goes through each auction and if any auction is on day 6, the observers of that auction are notified. This seems like a pretty bad way of going about it - I like the idea of having a state-ful auction.
Thoughts?
Thanks!
Ringo
You can take a look at https://github.com/pluginaweek/state_machine, specifically transitions callbacks. Alternatively you can also use the standard active record callbacks http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
Have a look at https://github.com/bvandenbos/resque-scheduler, if you haven't heard yet, resque is a gem for creating background processing, having queues in redis. This gem resque-scheduler, lets you specify when to run a task/job.
For example in your model you would have an after_create to schedule the task for changing the bid state.
after_create :shedule_state_change
private
def record_signup
Resque.enqueue_in(5.days, ChangeState)
end
And then you could notify all the bidders for that bid inside that task or create an observer for it.

What language/technique should I use to add a game loop to a Ruby on Rails based webgame?

I'm building a web game in Ruby on Rails that relies on a choose-your-own-adventure mechanic coupled with a time-waiting system (a la Zynga and the come back in 15m, 30m, 1hr, etc concept).
However, I need a game loop to run in the background to constantly run and check if the "quests" that players are waiting on are ready and if so, ping the user(email/smartphone push notification/whatever they want). I obviously need it to do more than just this, but this is the core functionality.
I don't want to throw this into a Rails controller because I don't need the game logic running on every single page view or for it to be hammered when tons of users are on, rather I just need a loop to run continuously (at a set interval) and handle all of the small tasks that will be necessary to run the backend of a multiplayer game.
What language/technique is best for this, or do I even need to leave my Ruby/Rails foundation at all?
EDIT: This game does not feature a "persistent" world and has no real need of persistent connections with clients. The game is spread out over many pages and it will feature some asynchronous functionality (a news 'ticker' at the top that has updates pushed to it, etc).
Sounds like you're looking for a background worker of some sort. Heroku supports a scheduler that you can set to run every ten minutes; documentation is here: http://devcenter.heroku.com/articles/scheduler?preview=1
Otherwise, a system like Resque ( https://github.com/defunkt/resque ) or DelayedJob ( https://github.com/tobi/delayed_job ) would be good plugins for handling periodic introspection without tying up your controllers.
Check out either PusherApp or PrivatePub
My idea is that the player will conduct a movement, and then broadcast out (via pusher or private pub) to the other players that it is their turn.
Check on page load or by JS request if the event is finished already. In example when you show page that inform your user about time to end process then you will update it with JA, when time come to 0.0s then refresh page or use AJAX and show info that process is finished. If user leave the page and return back you will know that he finished that process.

How to find out when user-created calendar events are about to start [Rails]

I'm building an online calendar in Ruby on Rails that needs to send out email notifications whenever a user-created event is about to start/finish (i.e you get a reminder when a meeting is 5 minutes away). What's the best way of figuring out when an event is about to start? Would there be a cron task that checks through all events to find out which ones are starting within a certain threshold (i.e 5 minutes) ? A cron task seems inefficient to me, so I'm wondering what might be a better solution. My events are stored in a mySQL database. There must be a design pattern for this... I'm just at a loss for what to search for.
Any help would be greatly appreciated. Thanks.
In all likelihood you will probably implement some background queuing mechanism to actually deliver the notifications - at least you certain should be considering this approach.
Assuming this, why not create your delayed notification jobs at event creation time to be delivered when the associated event is starting or finishing. The background queue, which is already waking up periodically to look for work, will pick these up and run them.
However adopting this approach requires you to consider the following (at least):
Removing queued notification job if the associated event is removed
Amending the notification job if the associated event is amended (say a new time)
Ensuring that the polling resolution of the queuing system does not allow notifications to be delivered so late as to be useless.
If you haven't picked a queuing solution for your application you should consider these options

Timed server events with ruby on rails

I am attempting to create a web-based game in Ruby on Rails. I have a model named 'Game', which has a datetime in the database entry that corresponds to a time that I would like the server to call the Game model's update_game function. Depending on the game's settings, this could be every 30 seconds to every 12 hours.
Ruby on Rails only seems to work when it receives an HTTP request; is there a slick way to get my game to update on a periodic basis independent of HTTP requests?
I'd look into delayed_job for this. When the game starts, you can create a delayed_job for the first update, and every run after that can add a new job at the correct interval until it's done.
I'd do lots of testing though ;) - you don't want to let the jobs get away from you.
Rails itself doesn't do this; cron does this. Ruby does, however, have a gem named Whenever to make easier the declaration and deployment of new cron jobs.
However, if you are really going to expect a large amount of games to reliably update every 30 seconds, you may want to take a different approach if updating a game would take any significant amount of time. Perhaps once the game is accessed, the game could run the update as many times as necessary (e.g. if 3 minutes had passed and the interval is 30 seconds, run 6 updates once requested). This may or may not be a good option for your setup, however, so figure out which method is more viable for your purposes.
Look into background processing options and possibly cron.
I like the gem 'rufus-scheduler' which works within Rails, though I'm not sure you can programmatically add more tasks to it.

Letting something happen at a certain time with Rails

Like with browser games. User constructs building, and a timer is set for a specific date/time to finish the construction and spawn the building.
I imagined having something like a deamon, but how would that work? To me it seems that spinning + polling is not the way to go. I looked at async_observer, but is that a good fit for something like this?
If you only need the event to be visible to the owning player, then the model can report its updated status on demand and we're done, move along, there's nothing to see here.
If, on the other hand, it needs to be visible to anyone from the time of its scheduled creation, then the problem is a little more interesting.
I'd say you need two things. A queue into which you can put timed events (a database table would do nicely) and a background process, either running continuously or restarted frequently, that pulls events scheduled to occur since the last execution (or those that are imminent, I suppose) and actions them.
Looking at the list of options on the Rails wiki, it appears that there is no One True Solution yet. Let's hope that one of them fits the bill.
I just did exactly this thing for a PBBG I'm working on (Big Villain, you can see the work in progress at MadGamesLab.com). Anyway, I went with a commands table where user commands each generated exactly one entry and an events table with one or more entries per command (linking back to the command). A secondary daemon run using script/runner to get it started polls the event table periodically and runs events whose time has passed.
So far it seems to work quite well, unless I see some problem when I throw large number of users at it, I'm not planning to change it.
To a certian extent it depends on how much logic is on your front end, and how much is in your model. If you know how much time will elapse before something happens you can keep most of the logic on the front end.
I would use your model to determin the state of things, and on a paticular request you can check to see if it is built or not. I don't see why you would need a background worker for this.
I would use AJAX to start a timer (see Periodical Executor) for updating your UI. On the model side, just keep track of the created_at column for your building and only allow it to be used if its construction time has elapsed. That way you don't have to take a trip to your db every few seconds to see if your building is done.

Resources