Skip to content

Instantly share code, notes, and snippets.

@HoneyryderChuck
Last active June 5, 2016 08:53
Show Gist options
  • Save HoneyryderChuck/2c44a44fc6858e6f0b58 to your computer and use it in GitHub Desktop.
Save HoneyryderChuck/2c44a44fc6858e6f0b58 to your computer and use it in GitHub Desktop.
mysql patch to make it work with celluloid IO
require 'celluloid/io'
require 'mysql2'
module Mysql2
module Celluloid
# https://github.com/brianmario/mysql2/blob/master/lib/mysql2/em.rb
# Almost direct copy of the eventmachine driver for mysql2. It's even less verbose, which can only be a plus.
class Client < ::Mysql2::Client
def query(sql, opts={})
if ::Celluloid::IO.evented?
::Celluloid.mailbox.reactor.wait_writable(IO.new(self.socket))
puts "Legen..."
super(sql, opts.merge(async: true))
puts "#{self.socket}...wait for it..."
::Celluloid.mailbox.reactor.wait_readable(IO.new(self.socket))
puts "...dary!"
async_result
else
super
end
end
end
end
end
# Here to save from the whole direct sql bla bla bla.
class Sleeper
def initialize
@client = Mysql2::Celluloid::Client.new(host: "localhost", username: "root")
end
def sleep
@client.query("SELECT SLEEP(5);")
end
end
# The real meat is here. The idea is not to multiplex on the same connection, but on different connections.
# So, this is kind of a poor-man connection pool implementation. But it proves that one can effectively have
# concurrent async IO using only one actor.
class Sleepers
include Celluloid::IO
def initialize
@clients = 50.times.map { Sleeper.new }
@counter = 50
end
def decrement(c)
c.sleep
@counter -= 1
if @counter.zero?
@end = Time.now
puts "it took #{@end - @beginning} seconds"
terminate
end
end
def final_countdown
@beginning = Time.now
@clients.each do |c|
async(:decrement, c)
end
end
end
puts "starting my test..."
c = Sleepers.new
c.async(:final_countdown)
puts "waiting for it to be over..."
sleep
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment