Slide 1

Slide 1 text

Practical EventMachine

Slide 2

Slide 2 text

@febuiles

Slide 3

Slide 3 text

http://goo.gl/Oqe4SI

Slide 4

Slide 4 text

Events events

Slide 5

Slide 5 text

$("#door").on("open", function(){ log("We got a new Joe in town..."); });

Slide 6

Slide 6 text

WHY EVENTS?

Slide 7

Slide 7 text

i/o

Slide 8

Slide 8 text

latency

Slide 9

Slide 9 text

MOST APPLICATIONS ARE I/O BOUND I/O BOUND

Slide 10

Slide 10 text

https://github.com/blog/517-unicorn YOUR TYPICAL CONCURRENCY MODEL

Slide 11

Slide 11 text

server = TCPServer.new(1337) ! while client = server.accept message = client.readline client.write "> #{message}" client.close end

Slide 12

Slide 12 text

server = TCPServer.new(1337) ! while true Thread.new(server.accept) do |client| message = client.readline client.write "> #{message}" client.close end end

Slide 13

Slide 13 text

THE REACTOR

Slide 14

Slide 14 text

What is a reactor?

Slide 15

Slide 15 text

while true events.each do |event| event.process end end

Slide 16

Slide 16 text

Chernobyl, 1986

Slide 17

Slide 17 text

New Safe Confinement (NSC)

Slide 18

Slide 18 text

DON’T BLOCK THE REACTOR

Slide 19

Slide 19 text

Reactor.run { on(:receive) do |msg| return if invalid_message(msg)? ! device = Device.find(msg.device_id) device.update(position: msg.position) end }

Slide 20

Slide 20 text

Reactor.run { on(:receive) do |msg| return if invalid_message(msg)? ! device = Device.find(msg.device_id) device.update(position: msg.position) end }

Slide 21

Slide 21 text

What is EventMachine?

Slide 22

Slide 22 text

EventMachine is an event-driven I/O and lightweight concurrency library for Ruby.

Slide 23

Slide 23 text

?

Slide 24

Slide 24 text

EventMachine is a fast, simple event- processing library for Ruby programs

Slide 25

Slide 25 text

A PIMPED REACTOR.

Slide 26

Slide 26 text

Why EventMachine?

Slide 27

Slide 27 text

EventMachine is dead.

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

EventMachine is dead EventMachine is stable.

Slide 30

Slide 30 text

Heroku Thin Campfire GitHub Rainbows EngineYard

Slide 31

Slide 31 text

module Echo def receive_data(message) send_data "> #{message}" end end ! EM.run { EM.start_server "0.0.0.0", 1337, Echo }

Slide 32

Slide 32 text

module Echo def post_init puts "Client connected" end ! def receive_data(message) send_data "> #{message}" end ! def unbind puts "Client disconnected" end end ! EM.run { EM.start_server "0.0.0.0", 1337, Echo }

Slide 33

Slide 33 text

EM HANDLERS VS CALLBACK HELL

Slide 34

Slide 34 text

server = AsyncTCPServer.new("0.0.0.0", 1337) ! server.on(:accept) { message = client.async_read ! message.on(:ready) { client.write "> #{message}" client.close } } ! server.on(:connect) { puts "Client connected" } ! server.on(:disconnect) { puts "Client disconnected" }

Slide 35

Slide 35 text

events
 post_init connection_completed receive_data
 unbind ssl_handshake_completed methods start_tls get_peername
 send_data
 close_connection close_connection_after_writing proxy_incoming_to pause/resume

Slide 36

Slide 36 text

Mixing Paradigms

Slide 37

Slide 37 text

module Echo def receive_data(data) message = parse_data(data) return if invalid_message(message)? ! device = Device.find(message.device_id) device.update(position: message.position) send_data :updated end end ! EM.run { EM.start_server "0.0.0.0", 1337, Echo }

Slide 38

Slide 38 text

module Echo def receive_data(data) message = parse_data(data) return if invalid_message(message)? ! device = Device.find(message.device_id) device.update(position: message.position) send_data :updated end end ! EM.run { EM.start_server "0.0.0.0", 1337, Echo }

Slide 39

Slide 39 text

DON’T BLOCK THE REACTOR

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

DATA STORES ! cassandra couchdb memcached mongodb mysql postgresql redis

Slide 42

Slide 42 text

HTTP ! HttpRequest Faraday

Slide 43

Slide 43 text

PROTOCOLS ! tcp udp amqp smtp stomp xmpp dns websockets and more…

Slide 44

Slide 44 text

Other ! EM.popen EM.defer

Slide 45

Slide 45 text

module Graham def receive_data(number) calculate = proc { graham(number) } ! report = proc { |result| send_data(result) } ! EM.defer(calculate, report) end end

Slide 46

Slide 46 text

EM API

Slide 47

Slide 47 text

EM API ! EM::timer EM::deferrable EM::queue EM::channel EM.watch_file EM.watch_process

Slide 48

Slide 48 text

Closing Thoughts

Slide 49

Slide 49 text

Events are hard.

Slide 50

Slide 50 text

Evented Programming for Evented Problems

Slide 51

Slide 51 text

DON’T BLOCK THE REACTOR !!1

Slide 52

Slide 52 text

Thanks :) ! http://mheroin.com/rubyconfar @febuiles

Slide 53

Slide 53 text

Credits Federico’s illustration: Pablo Pérez Nuclear cooling tower: Jonathan Brennan Some code samples: Aman Gupta & Jeremy Cheung Unicorn diagram: GitHub The rest: Wikipedia