Created
September 4, 2010 21:15
-
-
Save hukl/565498 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'async_sinatra' | |
class App < Sinatra::Base | |
register Sinatra::Async | |
@next_id = 0 | |
def self.next_id | |
@next_id += 1 | |
end | |
@connected_clients = {} | |
def self.connected_clients | |
@connected_clients | |
end | |
aget '/' do | |
timed_out = false | |
# If you cluster, this needs to come from a global id provider or be a | |
# uuid of some kind to avoid collisions. | |
my_id = self.class.next_id | |
# Add ourselves to the connection list | |
self.class.connected_clients[my_id] = self | |
cleanup = lambda do | |
# Remove ourselves from the connection list | |
self.class.connected_clients.delete my_id | |
end | |
timeout = EM::Timer.new(7) do | |
timed_out = true | |
# Tell the database we're no longer waiting | |
db.remove_client my_id | |
body { '{"state": "not_found"}' } | |
cleanup.call | |
end | |
# Add this client to the list of waiting clients, n.b. if can be hard to | |
# "match" clients accross a cluster, you'll need some kind of inter-server | |
# protocol to pipe data between them if that's the plan. | |
db.add_client my_id | |
# Try to find a matching client: | |
db.find_matching_clients my_id do |matching_client| | |
# presumably, after we've matched up with someone, we don't want to be | |
# matched ourselves. N.B. I have casually skirted around the concurrency | |
# issue of finding a matching client /THEN/ removing ourselves, which | |
# has bad concurrency implications, in that we could end up getting | |
# paired with another client between finding one, and removing this | |
# client. This should be avoided by clients doing one or the other, or | |
# some kind of shared lock between trying to find a client or not. An | |
# example would be to use a function that instead does a "find or add | |
# this client" method that is atomic (e.g. in a single transaction). | |
db.remove_client my_id | |
other = self.class.connected_clients[matching_client] | |
# here we do something with other... | |
body { ... whatver ... } | |
cleanup.call | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment