Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

EventMachine Notes

Adapted to Markdown format from rom Aman Gupta's gist at: http://gist.github.com/79224

Using:

require 'rubygems'
require 'eventmachine'

EM::run Takes over the Process

puts 1
EM.run{
  require 'mycode'
}
puts 3     this will never happen

Timers and Async Blocks

EM.run{
  timer = EM::PeriodicTimer.new(0.25){
    puts "#{Time.now}: hi!"
  }
  EM.add_timer(2){ timer.cancel }
}

Long Events Block the Reactor

EM.run{
  EM.add_periodic_timer(0.25){
    puts "#{Time.now}: hi!"
    sleep 1
  }
}

The Reactor Is Just a While Loop

while true
 # fire timers
 timers.each{ |t| t.fire if t.time <= Time.now }

 # check network i/o
 select(sockets).each{ |fd|
   fd.connection_completed if fd.connected?
   fd.receive_data(fd.read) if fd.readable?
   fd.unbind if fd.closed?
 }

 # run threads
 rb_thread_schedule() if threads.any?
end

Using Em in Your Webapps

require 'thin'

# or, with mongrel/passenger

$em = Thread.new{ EM.run{} }
%w(INT TERM).each{ |sig|
  old=trap(sig){ EM.stop; old.call }
}

Sending Email

email = EM::Protocols::SmtpClient.send(
  :domain => 'mysite.com',
  :host => 'mail.mysite.com',
  :from => 'ruby@mysite.com',
  :to => 'customer@gmail.com',
  :content => 'hi'
)
email.callback { puts 'sent the email!' }
email.errback  { puts 'email failed!'   }

HTTP Requests

require 'em-http'
http = EM::HttpRequest.new('http://twitter.com/statuses/update.xml')
req = http.post(
  :head => {'Authorization' => ['user', 'pass']},
  :body => 'status=hello world'
)
req.errback{ puts 'failed posting to twitter' }
req.callback{ |http|
  http.response_header.status
  http.response
}

Running External Processes

EM.system("convert -resize 50x50 huge.png thumb.png"){ |output, status|
  if status.exitstatus == 0
  # ...
  end
}

#slow mysql queries

require 'em/mysql'
mysql = EventedMysql.connect(...)
mysql.select('select sleep(15) as num'){ |res|
  res.first['num']
}

Message Queues

require 'mq'
AMQP.start(:host => 'localhost'){
  MQ.queue('logging').subscribe{ |logmsg|
    puts logmsg
  }
}

Custom Servers

module MyServer
  def post_init
    puts "--- someone connected!"
  end
  def receive_data data
    puts "--- someone sent me data: #{data}"
  end
  def unbind
    puts "--- someone disconnected!"
  end
end

EM.start_server '127.0.0.1', 8080, MyServer

Other Features

  • udp servers/clients
  • ssl connections and certificate handling
  • epoll/kqueue for c10k scalability
  • platform compatibility
    • java version for jruby
    • C extension for 1.8 and 1.9
    • pure ruby reactor for everything else

Eventmachine Resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.