to the dispatcher when it can be processed can complete it in a synchronous manner. Listens to Network, File System, Key presses, etc. Dispatcher Registers and unregisters the request handlers. Routes the resource to the proper handler. Request Handler This is the code we write Accomplished mostly with callbacks
go get your food from buffet. You are blocking because you are solely focused on retreiving your foodstuffs. The Reactor Pattern Resturanut Analogy Reactor (Waiter)
to carry on a conversation or watch the game at the bar, etc. Getting Started With EventMachine The Event Loop require 'eventmachine' EM.run do # All your evented code goes here # A while(true) loop is running where you plug your events into end
event loop EM.add_timer(seconds, &block) - A one shot timer that executes the block in the specified number of seconds EM.add_periodic_timer(seconds, &block) - Like add_timer but repeats indefinitely EM.start_server(server, port, handler, &block) - Listens for input on a port and passes that input to the specified handler. EM.stop - Stops the event loop after all callbacks in progress have completed
that will allow you to write evented code for WebSockets, XMPP, DNS, MySQL, Cassandra, MongoDB, Redis, and IRC just to name a few. Libraries need to be written for EventMachine to be non-blocking Net::HTTP blocks EM::HttpClient does not block
iteration of the Reactor on the main thread (regardless of where it is called) Useful if you are writing an evented library that is scheduling it's next action. I.e. needs to retreive the next chunk from the buffer or check queues for new data to process
thread or in another tick of the event loop Not like Resque or RabbitMQ pop is single shot and then the callback is cleared, but the callback is only called when the queue has at least one item to process
# Enqueue some data here... popper = proc do |item| # Do something with the enqueued item # Pass this method address to be called next time an item # needs to be processed EM.next_tick { q.pop(&popper) } end # Set up the callback initially to be called q.pop(&popper) end
you set up success and failure callbacks Deferrable has two callbacks: callback - Executed when the succeed method is called errback - Executed when the fail method is called
'em-http-request' EM.run do http = EM::HttpRequest.new("http://www.google.com/").get http.callback do puts "Status: #{http.response_header.status}" puts "Headers: #{http.response_header.inspect}" puts "Content:" puts http.response EM.stop end http.errback do puts "there was an error" EM.stop end end
in applications by allowing applications to yield and resume execution. # Via Mathias Meyer Fiber.new do f = Fiber.current request = EM::HttpRequest.new('http://jsonip.com').get request.callback {f.resume(request)} request.errback {f.resume(request)} puts Fiber.yield.response end.resume
log trace statistics use Goliath::Rack::DefaultMimeType # cleanup accepted media types use Goliath::Rack::Render, 'json' # auto-negotiate response format use Goliath::Rack::Params # parse & merge query and body parameters use Goliath::Rack::Heartbeat # respond to /status with 200, OK (monitoring, etc) # If you are using Golaith version <=0.9.1 you need to Goliath::Rack::ValidationError # to prevent the request from remaining open after an error occurs #use Goliath::Rack::ValidationError use Goliath::Rack::Validation::RequestMethod, %w(GET POST) # allow GET and POST requests only use Goliath::Rack::Validation::RequiredParam, {:key => 'echo'} # must provide ?echo= query or body param plugin Goliath::Plugin::Latency # output reactor latency every second def process_request logger.info "Processing request" {response: env.params['echo']} end