Skip to content

Instantly share code, notes, and snippets.

@hukl
Created September 4, 2010 21:15
Show Gist options
  • Save hukl/565498 to your computer and use it in GitHub Desktop.
Save hukl/565498 to your computer and use it in GitHub Desktop.
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