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