SlideShare una empresa de Scribd logo
1 de 63
EventMachine
  EM.run{ awesome_stuff! }




                             Christopher Spring
@autonomous
EventMachine
EventMachine
• Mostly IO bound
• Handle thousands
  concurrent connections
• Stream data
• Real time data delivery
• You’ve got Mad Ruby Skills
What is EventMachine?

• Toolkit for creating evented applications
• Implementation of the Reactor Pattern
• MRI,YARV, jRuby, Rubinius
Evented?
Evented?
puts(1)
puts(2)
puts(3)
Evented?
puts(1)
puts(2)
puts(3)
             puts(1)
             work{ puts(3) }
             puts(2)
Reactor pattern
“Event handling pattern for handling service
requests delivered concurrently to a service
handler by one or more inputs. The service
handler then demultiplexes the incoming
requests and dispatches them synchronously
to the associated request handlers.”




                             http://en.wikipedia.org/wiki/Reactor_pattern
Http   Keyboard     Udp   etc




                   Service handler
                    Demultiplexer

                   Event dispatcher




Event Handler A
Event Handler B
Event Handler C
Event Handler D
Http   Keyboard     Udp   etc




                   Service handler
                    Demultiplexer

                   Event dispatcher




Event Handler A
Event Handler B
Event Handler C
Event Handler D
Http   Keyboard     Udp   etc




                   Service handler
                    Demultiplexer

                   Event dispatcher


                                            Thread 1

Event Handler A                             Thread 2
Event Handler B
                                               ...
Event Handler C
Event Handler D                             Thread 20
Benefits

• Application code separate from reactor
• Non blocking IO
• Single process
• No threads!
Limitations


• Demultiplexing limits
• Some others we’ll cover later...
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
require "rubygems"
require "eventmachine"

EM.run do
  # ...
  EM.stop
end
... don’t do this!

• big ass loops
  •   1_000_000.times{}

  •   while condition?

• sleep
• blocking IO
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
class EchoServer < EM::Connection
  def post_init
    puts "New connection"
  end

  def unbind
    puts "Connection closed"
  end

  def receive_data(data)
    send_data ">> #{data}"
  end
end

EM.run do
  EM.start_server('127.0.0.1', 9000, EchoServer)
  puts "Started server at 127.0.0.1:9000"
end
class EchoServer < EM::Connection
  def post_init
    puts "New connection"
  end

  def unbind
    puts "Connection closed"            #   $ telnet localhost 9000
  end                                   #   Hello
                                        #   >> Hello
  def receive_data(data)                #   Bye
    send_data ">> #{data}"              #   >> Bye
  end
end

EM.run do
  EM.start_server('127.0.0.1', 9000, EchoServer)
  puts "Started server at 127.0.0.1:9000"
end
# TCP
EM.run do
  EM.start_server('127.0.0.1', 9000, EchoServer)
end

# UDP
EM.run do
  EM.open_datagram_socket('127.0.0.1', 9000, EchoServer)
end

# Unix-domain server
EM.run do
  EM.start_unix_domain_server('/tmp/sock', nil, EchoServer)
end
class EchoClient < EM::Connection
  def post_init
    puts "Sending stuff to server"
    send_data("Why, hello there!")
  end

  def unbind
    puts "Connection closed"
  end

  def receive_data(data)
    puts ">> #{data}"
  end
end

EM.run do
  EM.connect('127.0.0.1', 9000, EchoClient)
end
class EchoClient < EM::Connection
  def post_init
    puts "Sending stuff to server"
    send_data("Why, hello there!")
  end

  def unbind
    puts "Connection closed"
  end

  def receive_data(data)
    puts ">> #{data}"
  end
end

EM.run do
  EM.connect('127.0.0.1', 9000, EchoClient)
end
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  EM.next_tick do
    # ... awesome stuff
  end
end
Task 1

Task 2

Task 3
Task 1

Task 2

Task 3



 EM.run{ }
Task 1

Task 2

Task 3



 EM.run{ }



 EM.next_tick{ }
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  EM.defer do
    send_email( user1 )
  end

  EM.defer do
    send_email( user2 )
  end

  EM.defer do
    send_email( user3 )
  end
end
Email 1

Email 2

Email 3
Email 1

Email 2

Email 3



 EM.defer{ }
EM.run do
  get_stuff = Proc.new do
    # ...
    long_running_io()
  end

  use_stuff = Proc.new do |io_results|
    # ...
  end

  # ...
  EM.defer( get_stuff, use_stuff )
end
Teh Basics
• EM.run
• EM.connection
• next_tick; add_timer; add_periodic_timer
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  queue = EM::Queue.new

  # ...
  queue.push( data1, data2 )

  # ...
  queue.pop { |data| puts data } # >> data1

end
EM.run do
  queue = EM::Queue.new

  EM.defer do
    sleep( 2 )
    queue.push( 'some@email.com' )
    sleep( 3 )
    queue.push( 'some@one.com')
  end

  welcomer = Proc.new do |email|
    send_welcome( email )
    EM.next_tick( queue.pop(&welcomer) )
  end

  queue.pop(&welcomer);
end
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  channel = EM::Channel.new

  EM.defer do
    channel.subscribe do |msg|
      puts "Received #{msg}"
    end
  end

  EM.add_periodic_timer(1) do
    channel << Time.now
  end
end
Deferrable
• Light weight concurrency
• Delayed execution with triggers
 • :succeeded
 • :failed
 • nil
• callback and errback
class LoanRequest
  include EM::Deferrable

  def initialize( name )
    @name = name
    callback do |who|
      puts "Approved #{who}!"
    end

    errback do |who|
      puts "Denied #{who}!"
    end
  end

  def approved!
    # succeed( *args )
    set_deferred_status(:succeeded, @name)
  end

  def denied!
    # fail( *args )
    set_deferred_status(:failed, @name)
  end
end
class LoanRequest
  include EM::Deferrable

  def initialize( name )
    @name = name
    callback do |who|              EM.run do
      puts "Approved #{who}!"        s1 = LoanRequest.new('Marc')
    end                              s1.approved!


    errback do |who|                 s2 = LoanRequest.new('Chris')
      puts "Denied #{who}!"          EM.add_timer(2){ s2.denied! }
    end                            end
  end

  def approved!
    # succeed( *args )
    set_deferred_status(:succeeded, @name)
  end

  def denied!
    # fail( *args )
    set_deferred_status(:failed, @name)
  end
end
class LoanRequest
  include EM::Deferrable

  def initialize( name )
    @name = name
    callback do |who|              EM.run do
      puts "Approved #{who}!"        s1 = LoanRequest.new('Marc')
    end                              s1.approved!


    errback do |who|                 s2 = LoanRequest.new('Chris')
      puts "Denied #{who}!"          EM.add_timer(2){ s2.denied! }
    end                            end
  end

  def approved!
    # succeed( *args )
    set_deferred_status(:succeeded, @name)
  end                                        # :00 Approved Marc!
                                             # :02 Denied Chris!
  def denied!
    # fail( *args )
    set_deferred_status(:failed, @name)
  end
end
state: nil
state: nil


callback{}

callback{}

callback{}
state: nil


callback{}                errback{}

callback{}                errback{}

callback{}
state: succeeded


callback{}                      errback{}

callback{}                      errback{}

callback{}
state: succeeded


callback{}

callback{}

callback{}
state: succeeded
state: failed


callback{}                   errback{}

callback{}                   errback{}

callback{}
state: failed


                errback{}

                errback{}
state: failed
class Mailer
  include EM::Deferrable

  def add_mailing(val)
    callback do
      sleep 1
      puts "Sent #{val}"
    end
  end

  def connection_open!
    puts 'Open connection'
    succeed
  end

  def connection_lost!
    puts 'Lost connection'
    set_deferred_status nil
  end
end
EM.run do
                                m = Mailer.new
class Mailer
                                m.add_mailing(1)
  include EM::Deferrable
                                m.add_mailing(2)
                                m.connection_open!
  def add_mailing(val)
    callback do
                                EM.add_timer(1) do
      sleep 1
                                  m.connection_lost!
      puts "Sent #{val}"
                                  EM.add_timer(2) do
    end
                                    m.add_mailing(3)
  end
                                    m.add_mailing(4)
                                    m.connection_open!
  def connection_open!
                                  end
    puts 'Open connection'
                                end
    succeed
                              end
  end

  def connection_lost!
    puts 'Lost connection'
    set_deferred_status nil
  end
end
EM.run do
                                m = Mailer.new
class Mailer
                                m.add_mailing(1)
  include EM::Deferrable
                                m.add_mailing(2)
                                m.connection_open!
  def add_mailing(val)
    callback do
                                EM.add_timer(1) do
      sleep 1
                                  m.connection_lost!
      puts "Sent #{val}"
                                  EM.add_timer(2) do
    end
                                    m.add_mailing(3)
  end
                                    m.add_mailing(4)
                                    m.connection_open!
  def connection_open!
                                  end
    puts 'Open connection'
                                end
    succeed
                              end
  end

  def connection_lost!                      #   Open   connection
    puts 'Lost connection'                  #   Sent   1
    set_deferred_status nil                 #   Sent   2
  end                                       #   Lost   connection
end                                         #   Open   connection
                                            #   Sent   3
                                            #   Sent   4
Gotchas

• Inverted flow of control can make
  debugging difficult
• Synchronous code will slow it down
 • Use/Write libraries for EM
Worth checking out

• EM-Synchrony:
  https://github.com/igrigorik/em-synchrony
• Goliath:
  https://github.com/postrank-labs/goliath
• Async_Sinatra:
  https://github.com/raggi/async_sinatra
Baie Dankie!
Questions?

Más contenido relacionado

La actualidad más candente

Rust Mozlando Tutorial
Rust Mozlando TutorialRust Mozlando Tutorial
Rust Mozlando Tutorialnikomatsakis
 
Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02nikomatsakis
 
Ruby 2.0: to infinity... and beyond!
Ruby 2.0: to infinity... and beyond!Ruby 2.0: to infinity... and beyond!
Ruby 2.0: to infinity... and beyond!Fabio Kung
 
Implementações paralelas
Implementações paralelasImplementações paralelas
Implementações paralelasWillian Molinari
 
Douglas Crockford: Serversideness
Douglas Crockford: ServersidenessDouglas Crockford: Serversideness
Douglas Crockford: ServersidenessWebExpo
 
NativeBoost
NativeBoostNativeBoost
NativeBoostESUG
 
Advanced Python, Part 1
Advanced Python, Part 1Advanced Python, Part 1
Advanced Python, Part 1Zaar Hai
 
Lecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of TwenteLecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of TwenteDirkjan Bussink
 
Rust: Unlocking Systems Programming
Rust: Unlocking Systems ProgrammingRust: Unlocking Systems Programming
Rust: Unlocking Systems ProgrammingC4Media
 
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup itPROIDEA
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programmingRodolfo Finochietti
 
DRYing to Monad in Java8
DRYing to Monad in Java8DRYing to Monad in Java8
DRYing to Monad in Java8Dhaval Dalal
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Lin Yo-An
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)tarcieri
 
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Yan Cui
 

La actualidad más candente (20)

Rust-lang
Rust-langRust-lang
Rust-lang
 
Rustlabs Quick Start
Rustlabs Quick StartRustlabs Quick Start
Rustlabs Quick Start
 
Rust Mozlando Tutorial
Rust Mozlando TutorialRust Mozlando Tutorial
Rust Mozlando Tutorial
 
Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02
 
Ruby basics
Ruby basicsRuby basics
Ruby basics
 
Introduction to Rust
Introduction to RustIntroduction to Rust
Introduction to Rust
 
Ruby 2.0: to infinity... and beyond!
Ruby 2.0: to infinity... and beyond!Ruby 2.0: to infinity... and beyond!
Ruby 2.0: to infinity... and beyond!
 
Implementações paralelas
Implementações paralelasImplementações paralelas
Implementações paralelas
 
Douglas Crockford: Serversideness
Douglas Crockford: ServersidenessDouglas Crockford: Serversideness
Douglas Crockford: Serversideness
 
NativeBoost
NativeBoostNativeBoost
NativeBoost
 
Advanced Python, Part 1
Advanced Python, Part 1Advanced Python, Part 1
Advanced Python, Part 1
 
Lecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of TwenteLecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of Twente
 
Rust: Unlocking Systems Programming
Rust: Unlocking Systems ProgrammingRust: Unlocking Systems Programming
Rust: Unlocking Systems Programming
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programming
 
DRYing to Monad in Java8
DRYing to Monad in Java8DRYing to Monad in Java8
DRYing to Monad in Java8
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)
 
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
 

Similar a EventMachine for RubyFuZa 2012

Scaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby undergroundScaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby undergroundOmer Gazit
 
Two Trains and Other Refactoring Analogies
Two Trains and Other Refactoring AnalogiesTwo Trains and Other Refactoring Analogies
Two Trains and Other Refactoring AnalogiesKevin London
 
Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011David Troy
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record.toster
 
Introduction to python programming ( part-2 )
Introduction to python programming ( part-2 )Introduction to python programming ( part-2 )
Introduction to python programming ( part-2 )Ziyauddin Shaik
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
 
Pharo: Syntax in a Nutshell
Pharo: Syntax in a NutshellPharo: Syntax in a Nutshell
Pharo: Syntax in a NutshellMarcus Denker
 
Introducing Elixir and OTP at the Erlang BASH
Introducing Elixir and OTP at the Erlang BASHIntroducing Elixir and OTP at the Erlang BASH
Introducing Elixir and OTP at the Erlang BASHdevbash
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Wen-Tien Chang
 
Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019Michał Kurzeja
 
Nick Sieger JRuby Concurrency EMRubyConf 2011
Nick Sieger JRuby Concurrency EMRubyConf 2011Nick Sieger JRuby Concurrency EMRubyConf 2011
Nick Sieger JRuby Concurrency EMRubyConf 2011Nick Sieger
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v RubyJano Suchal
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebBryan Helmig
 
Async History - javascript
Async History - javascriptAsync History - javascript
Async History - javascriptNishchit Dhanani
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIEleanor McHugh
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...Tom Croucher
 

Similar a EventMachine for RubyFuZa 2012 (20)

Scaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby undergroundScaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby underground
 
Two Trains and Other Refactoring Analogies
Two Trains and Other Refactoring AnalogiesTwo Trains and Other Refactoring Analogies
Two Trains and Other Refactoring Analogies
 
Specs2
Specs2Specs2
Specs2
 
Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
Introduction to python programming ( part-2 )
Introduction to python programming ( part-2 )Introduction to python programming ( part-2 )
Introduction to python programming ( part-2 )
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Pharo: Syntax in a Nutshell
Pharo: Syntax in a NutshellPharo: Syntax in a Nutshell
Pharo: Syntax in a Nutshell
 
Introducing Elixir and OTP at the Erlang BASH
Introducing Elixir and OTP at the Erlang BASHIntroducing Elixir and OTP at the Erlang BASH
Introducing Elixir and OTP at the Erlang BASH
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽
 
Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
Nick Sieger JRuby Concurrency EMRubyConf 2011
Nick Sieger JRuby Concurrency EMRubyConf 2011Nick Sieger JRuby Concurrency EMRubyConf 2011
Nick Sieger JRuby Concurrency EMRubyConf 2011
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
 
Async History - javascript
Async History - javascriptAsync History - javascript
Async History - javascript
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
 

Último

Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024The Digital Insurer
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfOverkill Security
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 

Último (20)

Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 

EventMachine for RubyFuZa 2012

  • 1. EventMachine EM.run{ awesome_stuff! } Christopher Spring
  • 3.
  • 4.
  • 7. • Mostly IO bound • Handle thousands concurrent connections • Stream data • Real time data delivery • You’ve got Mad Ruby Skills
  • 8. What is EventMachine? • Toolkit for creating evented applications • Implementation of the Reactor Pattern • MRI,YARV, jRuby, Rubinius
  • 11. Evented? puts(1) puts(2) puts(3) puts(1) work{ puts(3) } puts(2)
  • 12. Reactor pattern “Event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.” http://en.wikipedia.org/wiki/Reactor_pattern
  • 13. Http Keyboard Udp etc Service handler Demultiplexer Event dispatcher Event Handler A Event Handler B Event Handler C Event Handler D
  • 14. Http Keyboard Udp etc Service handler Demultiplexer Event dispatcher Event Handler A Event Handler B Event Handler C Event Handler D
  • 15. Http Keyboard Udp etc Service handler Demultiplexer Event dispatcher Thread 1 Event Handler A Thread 2 Event Handler B ... Event Handler C Event Handler D Thread 20
  • 16. Benefits • Application code separate from reactor • Non blocking IO • Single process • No threads!
  • 17. Limitations • Demultiplexing limits • Some others we’ll cover later...
  • 18. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 19. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 21. ... don’t do this! • big ass loops • 1_000_000.times{} • while condition? • sleep • blocking IO
  • 22. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 23. class EchoServer < EM::Connection def post_init puts "New connection" end def unbind puts "Connection closed" end def receive_data(data) send_data ">> #{data}" end end EM.run do EM.start_server('127.0.0.1', 9000, EchoServer) puts "Started server at 127.0.0.1:9000" end
  • 24. class EchoServer < EM::Connection def post_init puts "New connection" end def unbind puts "Connection closed" # $ telnet localhost 9000 end # Hello # >> Hello def receive_data(data) # Bye send_data ">> #{data}" # >> Bye end end EM.run do EM.start_server('127.0.0.1', 9000, EchoServer) puts "Started server at 127.0.0.1:9000" end
  • 25. # TCP EM.run do EM.start_server('127.0.0.1', 9000, EchoServer) end # UDP EM.run do EM.open_datagram_socket('127.0.0.1', 9000, EchoServer) end # Unix-domain server EM.run do EM.start_unix_domain_server('/tmp/sock', nil, EchoServer) end
  • 26. class EchoClient < EM::Connection def post_init puts "Sending stuff to server" send_data("Why, hello there!") end def unbind puts "Connection closed" end def receive_data(data) puts ">> #{data}" end end EM.run do EM.connect('127.0.0.1', 9000, EchoClient) end
  • 27. class EchoClient < EM::Connection def post_init puts "Sending stuff to server" send_data("Why, hello there!") end def unbind puts "Connection closed" end def receive_data(data) puts ">> #{data}" end end EM.run do EM.connect('127.0.0.1', 9000, EchoClient) end
  • 28. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 29. EM.run do EM.next_tick do # ... awesome stuff end end
  • 31. Task 1 Task 2 Task 3 EM.run{ }
  • 32. Task 1 Task 2 Task 3 EM.run{ } EM.next_tick{ }
  • 33. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 34. EM.run do EM.defer do send_email( user1 ) end EM.defer do send_email( user2 ) end EM.defer do send_email( user3 ) end end
  • 36. Email 1 Email 2 Email 3 EM.defer{ }
  • 37. EM.run do get_stuff = Proc.new do # ... long_running_io() end use_stuff = Proc.new do |io_results| # ... end # ... EM.defer( get_stuff, use_stuff ) end
  • 38. Teh Basics • EM.run • EM.connection • next_tick; add_timer; add_periodic_timer • EM.defer • EM::Queue • EM::Channel
  • 39. EM.run do queue = EM::Queue.new # ... queue.push( data1, data2 ) # ... queue.pop { |data| puts data } # >> data1 end
  • 40. EM.run do queue = EM::Queue.new EM.defer do sleep( 2 ) queue.push( 'some@email.com' ) sleep( 3 ) queue.push( 'some@one.com') end welcomer = Proc.new do |email| send_welcome( email ) EM.next_tick( queue.pop(&welcomer) ) end queue.pop(&welcomer); end
  • 41. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 42. EM.run do channel = EM::Channel.new EM.defer do channel.subscribe do |msg| puts "Received #{msg}" end end EM.add_periodic_timer(1) do channel << Time.now end end
  • 43. Deferrable • Light weight concurrency • Delayed execution with triggers • :succeeded • :failed • nil • callback and errback
  • 44. class LoanRequest include EM::Deferrable def initialize( name ) @name = name callback do |who| puts "Approved #{who}!" end errback do |who| puts "Denied #{who}!" end end def approved! # succeed( *args ) set_deferred_status(:succeeded, @name) end def denied! # fail( *args ) set_deferred_status(:failed, @name) end end
  • 45. class LoanRequest include EM::Deferrable def initialize( name ) @name = name callback do |who| EM.run do puts "Approved #{who}!" s1 = LoanRequest.new('Marc') end s1.approved! errback do |who| s2 = LoanRequest.new('Chris') puts "Denied #{who}!" EM.add_timer(2){ s2.denied! } end end end def approved! # succeed( *args ) set_deferred_status(:succeeded, @name) end def denied! # fail( *args ) set_deferred_status(:failed, @name) end end
  • 46. class LoanRequest include EM::Deferrable def initialize( name ) @name = name callback do |who| EM.run do puts "Approved #{who}!" s1 = LoanRequest.new('Marc') end s1.approved! errback do |who| s2 = LoanRequest.new('Chris') puts "Denied #{who}!" EM.add_timer(2){ s2.denied! } end end end def approved! # succeed( *args ) set_deferred_status(:succeeded, @name) end # :00 Approved Marc! # :02 Denied Chris! def denied! # fail( *args ) set_deferred_status(:failed, @name) end end
  • 49. state: nil callback{} errback{} callback{} errback{} callback{}
  • 50. state: succeeded callback{} errback{} callback{} errback{} callback{}
  • 53. state: failed callback{} errback{} callback{} errback{} callback{}
  • 54. state: failed errback{} errback{}
  • 56. class Mailer include EM::Deferrable def add_mailing(val) callback do sleep 1 puts "Sent #{val}" end end def connection_open! puts 'Open connection' succeed end def connection_lost! puts 'Lost connection' set_deferred_status nil end end
  • 57. EM.run do m = Mailer.new class Mailer m.add_mailing(1) include EM::Deferrable m.add_mailing(2) m.connection_open! def add_mailing(val) callback do EM.add_timer(1) do sleep 1 m.connection_lost! puts "Sent #{val}" EM.add_timer(2) do end m.add_mailing(3) end m.add_mailing(4) m.connection_open! def connection_open! end puts 'Open connection' end succeed end end def connection_lost! puts 'Lost connection' set_deferred_status nil end end
  • 58. EM.run do m = Mailer.new class Mailer m.add_mailing(1) include EM::Deferrable m.add_mailing(2) m.connection_open! def add_mailing(val) callback do EM.add_timer(1) do sleep 1 m.connection_lost! puts "Sent #{val}" EM.add_timer(2) do end m.add_mailing(3) end m.add_mailing(4) m.connection_open! def connection_open! end puts 'Open connection' end succeed end end def connection_lost! # Open connection puts 'Lost connection' # Sent 1 set_deferred_status nil # Sent 2 end # Lost connection end # Open connection # Sent 3 # Sent 4
  • 59. Gotchas • Inverted flow of control can make debugging difficult • Synchronous code will slow it down • Use/Write libraries for EM
  • 60. Worth checking out • EM-Synchrony: https://github.com/igrigorik/em-synchrony • Goliath: https://github.com/postrank-labs/goliath • Async_Sinatra: https://github.com/raggi/async_sinatra
  • 61.

Notas del editor

  1. \n
  2. \n
  3. ScaleConf: Doing anything at scale requires better decisions about the tools you use.\nJust because the fit seemed ok at first, when things get rolling you really want to have the right kind of hammer.\n
  4. ... and to achieve dramatic results, you need to orchestrate a specialized set of components\n\ncomplexity is a tradeoff based on the domain of your problem.\n
  5. \n
  6. \n
  7. c10k problem\n
  8. c++ reactor: mri, yarv, Rubinius\n\njava reactor for, um, java\n
  9. used to sequential code\nevented code stores some block...\nand executes at some later stage\n
  10. used to sequential code\nevented code stores some block...\nand executes at some later stage\n
  11. \n
  12. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  13. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  14. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  15. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  16. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  17. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  18. \n
  19. Limitations ito select/epoll and the number of open file descriptors\n\n&amp;#x201C;First, you need to tell EventMachine to use epoll instead of select. Second, you need to prepare your program to use more than 1024 descriptors, an operation that generally requires superuser privileges. Third, you will probably want your process to drop the superuser privileges after you increase your process&amp;#x2019;s descriptor limit.&amp;#x201D; - See: http://eventmachine.rubyforge.org/docs/EPOLL.html\n
  20. connection -&gt; servers and clients and shit\nnext_tick -&gt; run code at the next opportunity (always run in main thread)\ndefer -&gt; defer work to run on a thread (green) - 20 by default\nQueue -&gt; data\nChannel -&gt; comms\n
  21. next_tick -&gt; run code at the next opportunity (always run in main thread)\ndefer -&gt; defer work to run on a thread (green) - 20 by default\nQueue -&gt; data\nChannel -&gt; comms\n
  22. Main reactor is single threaded - similar to while reactor_running?; ... end\nEM.run takes over the process...\nit&amp;#x2019;s blocking\n\n
  23. ... anything that blocks the main reactor is a no-no\n\nAnything that takes more than a few millisecond...\nrun on separate thread or broken into smaller blocks...\nand run on next_tick\n
  24. Used for creating clients and servers\n
  25. EM interchangeable with EventMachine\nreceive_data is unbuffered\nthese methods are the only ones that will be called by the event loop\n\ncan have a module, and it&amp;#x2019;s behaviour will be mixed into an EM:: Connection\n
  26. \n
  27. EM interchangeable with EventMachine\nreceive_data is unbuffered\n
  28. Schedules work to happen on the main thread\non the next iteration of the reactor\n
  29. Next tick is a tool for bringing data/work back into the run loop\n\nUm, wtf for? You may find yourself asking...\n
  30. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  31. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  32. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  33. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  34. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  35. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  36. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  37. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  38. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  39. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  40. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  41. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  42. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  43. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  44. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  45. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  46. schedules work to take place on a different thread\n
  47. defer runs on thread in thread pool (20 by default)\n
  48. defer allows work to be done on one of the thread pool threads\n
  49. defer allows work to be done on one of the thread pool threads\n
  50. defer allows work to be done on one of the thread pool threads\n
  51. defer allows work to be done on one of the thread pool threads\n
  52. get_stuff run in separate thread,\nData is brought back to the main thread\nand passed on to the callback\nCallback executes on the main thread\nKinda like a future\n
  53. Ordered message queue\nThread safe\n
  54. Popped data is brought back to the main thread\npush/pop scheduled next iteration of the main reactor thread\n
  55. Infinite processing - always do work if there is some available\ndata pops off the queue only when data is available (no blocking)\n\n
  56. next_tick -&gt; run code at the next opportunity (always run in main thread)\ndefer -&gt; defer work to run on a thread (green) - 20 by default\nQueue -&gt; data\nChannel -&gt; comms\n
  57. Pub/Sub mechanism\n
  58. :succeeded -&gt; callback\n:failed -&gt; errback\nnil -&gt; reset (slate wiped clean)\n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  69. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  70. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  71. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  72. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  73. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  74. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  75. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  76. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  77. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n\n
  85. \n
  86. \n