SlideShare ist ein Scribd-Unternehmen logo
1 von 39
Downloaden Sie, um offline zu lesen
CELLULOID, CELLULOID::IO
AND FRIENDS
Marcelo Correia Pinheiro
@salizzar
Monday, July 15, 13
TOPICS
• Reactor Pattern / Actor Model revisited
• Celluloid
• Celluloid::IO
• DCell
• Reel
• #TODO
Monday, July 15, 13
REACTOR PATTERN REVISITED
• Event Handling for concurrent requests
• Multiplex
• X inputs are combined to a single channel
• Demultiplex
• Single channel is converted to X inputs
• Aka Synchronous Event Loop
Monday, July 15, 13
REACTOR PATTERN REVISITED
• Dispatcher
• Dispatch resources from Demultiplexer to related request
handler
• Request Handler
• An app that handles request
Monday, July 15, 13
ACTOR MODEL REVISITED
• Carl Hewitt paper from 1973
• Mathematical model of Concurrent Computation
• Known first languages:
• Cosmic Cube
• J-Machine
• Most popular implementation: Erlang
Monday, July 15, 13
ACTOR MODEL REVISITED
• Actor is a entity that interact with other actors sending /
receiving messages (mailbox)
• Each actor runs as a independent process
• No shared state
Monday, July 15, 13
CELLULOID
• Ruby Actor Model implementation
• Created byTony Arcieri - @bascule
• Need Fibers support
• MRI 1.9
• Rubinius / JRuby with 1.9 mode enabled
• Use. Only.Thread. Safe. Libs. For.Your. Sanity.
• Heavily inspired on Erlang concurrency approach
Monday, July 15, 13
CELLULOID
• Automatic Synchronization
• Don’t worry with semaphores / mutex, Celluloid manages :)
• Remember: each actor runs in a thread
• Method dispatch using Fibers
• If method call other actors, Fiber is suspended until call chain
returns something
• Example: I/O waiting
Monday, July 15, 13
CELLULOID
# -*- encoding: UTF-8 -*-
require 'celluloid'
class FredFlinstone
include Celluloid
def scream(to)
@scream = "#{to}#{to[-1] * 10}"
@screamed_at = Time.now
end
def resume
"Screamed [#{@scream}] at #{@screamed_at}"
end
end
Monday, July 15, 13
CELLULOID
irb(main):001:0> fred = FredFlinstone.new
=> #<Celluloid::ActorProxy(FredFlinstone:0x9cd7cc)>
irb(main):002:0> fred.async.scream "Wilma"
=> nil
irb(main):003:0> fred.resume
=> "Screamed [Wilmaaaaaaaaaaa] at 2013-07-10 23:01:29 -0300"
Monday, July 15, 13
CELLULOID
• Fault-tolerance
• Erlang philosophy: let it crash
• Celluloid handles crashed actors with these mechanisms:
• Supervisors
• Supervision groups
• Linking
Monday, July 15, 13
CELLULOID
• Supervisors
• How actors crash? Simple: unhandled exceptions
• Warning #1: async calls that raises an error crashes the message
receiver; posterior calls NOT RAISES ANYTHING.
• Warning #2: actors spawns a nativeThread, that are not
automatically cleaned by GC; you *must* explicitly terminate
them if not crashed.
• Supervise to the rescue
Monday, July 15, 13
CELLULOID
# -*- encoding: UTF-8 -*-
require 'celluloid'
class Devops
include Celluloid
def initialize(name)
@name = name
end
def up_to_no_good
@bad_cmd = 'rm-f /'
@command = `#{@bad_cmd}`,
@executed_at = Time.now
end
end
Monday, July 15, 13
CELLULOID
irb(main):001:0> supervisor = Devops.supervise "@salizzar"
=> #<Celluloid::ActorProxy(Celluloid::SupervisionGroup:0x91e6b4) (...)
irb(main):002:0> salizzar = supervisor.actors.first
=> #<Celluloid::ActorProxy(Devops:0x907c84) @name="@salizzar">
irb(main):003:0> salizzar.async.up_to_no_good
=> nil
E, [2013-07-10T23:26:54.507455 #2467] ERROR -- : Devops crashed!
Errno::ENOENT: No such file or directory - rm-f /
! /vagrant/examples/supervisor.rb:14:in ``'
! /vagrant/examples/supervisor.rb:14:in `up_to_no_good'
! (...)
irb(main):004:0> salizzar
=> #<Celluloid::ActorProxy(Devops) dead>
irb(main):005:0> salizzar.terminate
Celluloid::DeadActorError: actor already terminated
(...)
irb(main):006:0> salizzar = supervisor.actors.first
=> #<Celluloid::ActorProxy(Devops:0x4e99b8) @name="@salizzar">
Monday, July 15, 13
CELLULOID
• Supervision Groups
• Supervise many actors at once
• Able to supervise other groups too
• You can create pools of supervised actors
• Transparent GC cleaning (automatic terminate all supervised
actors)
Monday, July 15, 13
CELLULOID
# -*- encoding: UTF-8 -*-
require 'celluloid'
class EyeOfSauron < Celluloid::SupervisionGroup
supervise FredFlinstone, as: :fred
pool Devops, as: :devops_pool
end
Monday, July 15, 13
CELLULOID
irb(main):001:0> eye_of_sauron = EyeOfSauron.run!
=> #<Celluloid::ActorProxy(EyeOfSauron:0xecaab8)
@members=[#<Celluloid::SupervisionGroup::Member:0x00000001d89720
(...)
irb(main):002:0> fred = Celluloid::Actor[:fred]
=> #<Celluloid::ActorProxy(FredFlinstone:0xec39d4)>
irb(main):003:0> devops = Celluloid::Actor[:devops_pool]
=> #<Celluloid::ActorProxy(Devops:0xe3f0e4) @name="hipster">
irb(main):004:0>
Monday, July 15, 13
CELLULOID
• Linking
• Suppose that you have two interdependent actors and want
to be notied if one fails
• Association by linking actor that commonly dies and the
receiver enables a simple callback when failure occurs
• Very useful to terminate broken actors manually
Monday, July 15, 13
CELLULOID
# -*- encoding: UTF-8 -*-
require 'celluloid'
class RobertoBaggio
include Celluloid
class KickedFarAwayError < StandardError; end
def kick_penalty
raise KickedFarAwayError, "OH MAMMA MIA! :'("
end
end
Monday, July 15, 13
CELLULOID
# -*- encoding: UTF-8 -*-
require 'celluloid'
class GalvaoBueno
include Celluloid
trap_exit :penalty_kick
def penalty_kick(player, reason)
puts "#{player.inspect} will kick and... #{reason.class}!"
2.times { puts "ACABOOOOOOU! "; sleep(1) }
3.times { puts "EH TETRAAAA! "; sleep(1) }
end
end
Monday, July 15, 13
CELLULOID
irb(main):001:0> galvao = GalvaoBueno.new
=> #<Celluloid::ActorProxy(GalvaoBueno:0x12e6aac)>
irb(main):002:0> baggio = RobertoBaggio.new
=> #<Celluloid::ActorProxy(RobertoBaggio:0x1312e68)>
irb(main):003:0> galvao.link baggio
=> #<Celluloid::ActorProxy(RobertoBaggio:0x1312e68)>
irb(main):004:0> baggio.async.kick_penalty
=> nil
E, [2013-07-11T00:05:36.212336 #2586] ERROR -- : RobertoBaggio crashed!
RobertoBaggio::KickedFarAwayError: OH MAMMA MIA! :'(
! /vagrant/examples/baggio.rb:11:in `kick_penalty'
! (...)
irb(main):005:0>
#<Celluloid::ActorProxy(RobertoBaggio) dead> will kick and...
RobertoBaggio::KickedFarAwayError!
ACABOOOOOOU!
ACABOOOOOOU!
EH TETRAAAA!
EH TETRAAAA!
EH TETRAAAA!
Monday, July 15, 13
CELLULOID
• Futures
• Kind of lazy computation: request a future on method call
and only execute it when needed
• When value is required, Celluloid internal threadpool
executes method synchronously and returns the result
• Transparent error raising
• No need to explicitly clean up pool, let GC work
Monday, July 15, 13
CELLULOID
# -*- encoding: UTF-8 -*-
require 'celluloid'
require 'restclient'
class LazyConsumer
include Celluloid
def retrieve
RestClient.get('http://www.locaweb.com.br').body
end
end
Monday, July 15, 13
CELLULOID
irb(main):001:0> consumer = LazyConsumer.new
=> #<Celluloid::ActorProxy(LazyConsumer:0x12f4210)>
irb(main):002:0> future = consumer.future.retrieve
=> #<Celluloid::Future:0x000000025957e8>
irb(main):003:0> future.value
=> "<!DOCTYPE html>n<html dir="ltr" lang="pt-BR">n<head>nt <meta http-
equiv="content-type" content="text/html; charset=utf-8" />n <meta name=
"robots" content="index, follow" />n
(...)
”
Monday, July 15, 13
CELLULOID
• Pools
• You can define a pool of actors (ORLY?);
• Default size: cores available on machine (Celluloid.cores)
• Delegates method call to a worker on pool to execute it
• Not sooo great due for GIL on MRI, but is OK when you have async I/O :)
• Main tips:
• Synchronous calls if concurrent access to a resource (via Actor.<#method> or
Actor.future.<#method>)
• Asynchronous calls if parallel computation (via Actor.async.<#method>)
Monday, July 15, 13
CELLULOID
# -*- encoding: UTF-8 -*-
require 'celluloid'
require 'restclient'
class LazyConsumer
include Celluloid
def retrieve
RestClient.get('http://www.locaweb.com.br').body
end
end
Monday, July 15, 13
CELLULOID
irb(main):001:0> Celluloid::Actor.all.size
=> 0
irb(main):002:0> consumer = LazyConsumer.pool size: 4
=> #<Celluloid::ActorProxy(LazyConsumer:0xc69bc0)>
irb(main):003:0> Celluloid::Actor.all.size
=> 5
Monday, July 15, 13
CELLULOID::IO
• Celluloid plus Evented I/O = Celluloid::IO
• Celluloid with steroids =P
• Uses nio4r (libev native extension) as a Reactor to manage
Celluloid Actor Mailboxes
• Great with most-idle connections (sockets, websockets and
friends)
• Multiplex message processing and I/O in a transparent way
Monday, July 15, 13
CELLULOID::IO
• Stream-based:
• Celluloid::IO::TCPSocket
• Celluloid::IO::UnixSocket
• Celluloid::IO::TCPServer
• Celluloid::IO::UnixServer
• SSL
• Celluloid::IO::SSLSocket
• Celluloid::IO::SSLServer
• UDP
• Celluloid::IO::UDPSocket
Monday, July 15, 13
CELLULOID::IO
# -*- encoding: UTF-8 -*-
require 'celluloid/io'
class WhoisServer
include Celluloid::IO
def initialize(host, port)
@server = TCPServer.new host, port
end
def start ; run ; end
def stop ; @server.close if @server ; end
def run ; loop { async.handle_connection @server.accept } ; end
def handle_connection(socket)
_, port, host = socket.peeraddr
domain_id = socket.read.strip
socket.write("I received a query to #{domain_id} at #{Time.now}n")
ensure
socket.close
end
end
Monday, July 15, 13
CELLULOID::IO
irb(main):001:0> ws = WhoisServer.new '0.0.0.0', 4343
=> #<Celluloid::ActorProxy(WhoisServer:0xa2f404)
@server=#<Celluloid::IO::TCPServer:0x00000001652358 @server=#<TCPServer:fd 10>>>
irb(main):002:0> ws.async.start
=> nil
vagrant@vagrant-debian-wheezy:~$ whois -h localhost -p 4343 xalala.com.br
I received a query to xelele.com.br at 2013-07-11 01:00:17 -0300
vagrant@vagrant-debian-wheezy:~$ whois -h localhost -p 4343 xirubiru.com.br
I received a query to xirubiru.com.br at 2013-07-11 01:01:09 -0300
Monday, July 15, 13
DCELL
• Distributed Ruby (wat) objects as network services
• DCell != DRb (Distributed Ruby)
• DRb comes with Ruby STDLIB
• Ruby specific, not interoperatable with CORBA, RMI, etc
• DCell is built on top of Celluloid::ZMQ
• ØMQ protocol implementation with Celluloid Actors
Monday, July 15, 13
DCELL
# -*- encoding: UTF-8 -*-
# example from https://github.com/celluloid/dcell :)
require 'dcell'
DCell.start id: 'itchy', addr: 'tcp://127.0.0.1:9001'
class Itchy
include Celluloid
def initialize
puts "Ready for mayhem!"
@n = 0
end
def fight
@n = (@n % 6) + 1
puts(@n <= 3 ? "Bite!" : "Fight!")
end
end
Itchy.supervise_as :itchy ; sleep
Monday, July 15, 13
DCELL
# -*- encoding: UTF-8 -*-
# example from https://github.com/celluloid/dcell :)
require 'dcell'
DCell.start id: 'scratchy', addr: 'tcp://127.0.0.1:9002'
itchy_node = DCell::Node['itchy']
puts "Fighting itchy! (check itchy's output)"
6.times do
itchy_node[:itchy].fight
sleep 1
end
Monday, July 15, 13
REEL
• Celluloid::IO web server powered
• Similar syntax to EventMachine
• And, of course, weird and potentially ugly after some time
• Rack support is experimental
• Good with websockets
• Not so fast:
• Goliath < Reel <<<<Thin <<< Node.js
Monday, July 15, 13
REEL
• Let’s show code from https://github.com/salizzar/reel-example
Monday, July 15, 13
#TODO
• Great opportunity to create a DCell similar gem using AMQP
• Stable Rack support for Reel
• Not sure, low usage at this time
• Other wrappers are welcome
• Celluloid::Redis is a great example
• Celluloid wrap != EventMachine wrap
• Use Dependency Injection API (if possible) to wrap sockets with
Celluloid::IO instead of STDLIB sockets
Monday, July 15, 13
DOUBTS?
• Questions are free as beer :)
Monday, July 15, 13
THANKYOU! :)
Monday, July 15, 13

Weitere ähnliche Inhalte

Andere mochten auch

Curriculum Vitae
Curriculum VitaeCurriculum Vitae
Curriculum Vitae
William Wright
 
Museum Digital - Metadaten
Museum Digital - MetadatenMuseum Digital - Metadaten
Museum Digital - Metadaten
Linus Kohl
 
BGCS Logistics Solutions
BGCS Logistics SolutionsBGCS Logistics Solutions
BGCS Logistics Solutions
Bilcare GCS
 
khalid awaad cv -2016
khalid awaad cv -2016khalid awaad cv -2016
khalid awaad cv -2016
khalid Awaad
 
Oclusion odontologia-restauradora
Oclusion odontologia-restauradoraOclusion odontologia-restauradora
Oclusion odontologia-restauradora
SofĂ­a Landa
 

Andere mochten auch (20)

Hybrid concurrency patterns
Hybrid concurrency patternsHybrid concurrency patterns
Hybrid concurrency patterns
 
Ruby is dying. What languages are cool now?
Ruby is dying. What languages are cool now?Ruby is dying. What languages are cool now?
Ruby is dying. What languages are cool now?
 
cynapspro data endpoint protection 2010 - Installationsleitfaden
cynapspro data endpoint protection 2010 - Installationsleitfadencynapspro data endpoint protection 2010 - Installationsleitfaden
cynapspro data endpoint protection 2010 - Installationsleitfaden
 
Pater nostrolatinoitaliano
Pater nostrolatinoitalianoPater nostrolatinoitaliano
Pater nostrolatinoitaliano
 
Curriculum Vitae
Curriculum VitaeCurriculum Vitae
Curriculum Vitae
 
Museum Digital - Metadaten
Museum Digital - MetadatenMuseum Digital - Metadaten
Museum Digital - Metadaten
 
Informatics%20 Broschuere Ish[1]
Informatics%20 Broschuere Ish[1]Informatics%20 Broschuere Ish[1]
Informatics%20 Broschuere Ish[1]
 
BGCS Logistics Solutions
BGCS Logistics SolutionsBGCS Logistics Solutions
BGCS Logistics Solutions
 
Informe relevamiento oferta del municipio de Pinamar
Informe relevamiento oferta del municipio de Pinamar Informe relevamiento oferta del municipio de Pinamar
Informe relevamiento oferta del municipio de Pinamar
 
Outsourcing verities
Outsourcing veritiesOutsourcing verities
Outsourcing verities
 
BI 2005 - Caso de excito COPSA y Tarjetas Sin Contacto Mifare
BI 2005 - Caso de excito COPSA y Tarjetas Sin Contacto MifareBI 2005 - Caso de excito COPSA y Tarjetas Sin Contacto Mifare
BI 2005 - Caso de excito COPSA y Tarjetas Sin Contacto Mifare
 
Kantox - NOAH16 London
Kantox - NOAH16 LondonKantox - NOAH16 London
Kantox - NOAH16 London
 
IM Farmacias 34
IM Farmacias 34IM Farmacias 34
IM Farmacias 34
 
khalid awaad cv -2016
khalid awaad cv -2016khalid awaad cv -2016
khalid awaad cv -2016
 
Oclusion odontologia-restauradora
Oclusion odontologia-restauradoraOclusion odontologia-restauradora
Oclusion odontologia-restauradora
 
Sangre
SangreSangre
Sangre
 
Social Commerce in der praktischen Umsetzung
Social Commerce in der praktischen UmsetzungSocial Commerce in der praktischen Umsetzung
Social Commerce in der praktischen Umsetzung
 
99 Tipps zur Kundenbindung
99 Tipps zur Kundenbindung99 Tipps zur Kundenbindung
99 Tipps zur Kundenbindung
 
Aluminium HaustĂźren TĂźrschnitte
Aluminium HaustĂźren TĂźrschnitte Aluminium HaustĂźren TĂźrschnitte
Aluminium HaustĂźren TĂźrschnitte
 
EML Podcast - Early Conciliation - 281114
EML Podcast - Early Conciliation - 281114EML Podcast - Early Conciliation - 281114
EML Podcast - Early Conciliation - 281114
 

KĂźrzlich hochgeladen

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

KĂźrzlich hochgeladen (20)

Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
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
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

Celluloid, Celluloid::IO and Friends

  • 1. CELLULOID, CELLULOID::IO AND FRIENDS Marcelo Correia Pinheiro @salizzar Monday, July 15, 13
  • 2. TOPICS • Reactor Pattern / Actor Model revisited • Celluloid • Celluloid::IO • DCell • Reel • #TODO Monday, July 15, 13
  • 3. REACTOR PATTERN REVISITED • Event Handling for concurrent requests • Multiplex • X inputs are combined to a single channel • Demultiplex • Single channel is converted to X inputs • Aka Synchronous Event Loop Monday, July 15, 13
  • 4. REACTOR PATTERN REVISITED • Dispatcher • Dispatch resources from Demultiplexer to related request handler • Request Handler • An app that handles request Monday, July 15, 13
  • 5. ACTOR MODEL REVISITED • Carl Hewitt paper from 1973 • Mathematical model of Concurrent Computation • Known rst languages: • Cosmic Cube • J-Machine • Most popular implementation: Erlang Monday, July 15, 13
  • 6. ACTOR MODEL REVISITED • Actor is a entity that interact with other actors sending / receiving messages (mailbox) • Each actor runs as a independent process • No shared state Monday, July 15, 13
  • 7. CELLULOID • Ruby Actor Model implementation • Created byTony Arcieri - @bascule • Need Fibers support • MRI 1.9 • Rubinius / JRuby with 1.9 mode enabled • Use. Only.Thread. Safe. Libs. For.Your. Sanity. • Heavily inspired on Erlang concurrency approach Monday, July 15, 13
  • 8. CELLULOID • Automatic Synchronization • Don’t worry with semaphores / mutex, Celluloid manages :) • Remember: each actor runs in a thread • Method dispatch using Fibers • If method call other actors, Fiber is suspended until call chain returns something • Example: I/O waiting Monday, July 15, 13
  • 9. CELLULOID # -*- encoding: UTF-8 -*- require 'celluloid' class FredFlinstone include Celluloid def scream(to) @scream = "#{to}#{to[-1] * 10}" @screamed_at = Time.now end def resume "Screamed [#{@scream}] at #{@screamed_at}" end end Monday, July 15, 13
  • 10. CELLULOID irb(main):001:0> fred = FredFlinstone.new => #<Celluloid::ActorProxy(FredFlinstone:0x9cd7cc)> irb(main):002:0> fred.async.scream "Wilma" => nil irb(main):003:0> fred.resume => "Screamed [Wilmaaaaaaaaaaa] at 2013-07-10 23:01:29 -0300" Monday, July 15, 13
  • 11. CELLULOID • Fault-tolerance • Erlang philosophy: let it crash • Celluloid handles crashed actors with these mechanisms: • Supervisors • Supervision groups • Linking Monday, July 15, 13
  • 12. CELLULOID • Supervisors • How actors crash? Simple: unhandled exceptions • Warning #1: async calls that raises an error crashes the message receiver; posterior calls NOT RAISES ANYTHING. • Warning #2: actors spawns a nativeThread, that are not automatically cleaned by GC; you *must* explicitly terminate them if not crashed. • Supervise to the rescue Monday, July 15, 13
  • 13. CELLULOID # -*- encoding: UTF-8 -*- require 'celluloid' class Devops include Celluloid def initialize(name) @name = name end def up_to_no_good @bad_cmd = 'rm-f /' @command = `#{@bad_cmd}`, @executed_at = Time.now end end Monday, July 15, 13
  • 14. CELLULOID irb(main):001:0> supervisor = Devops.supervise "@salizzar" => #<Celluloid::ActorProxy(Celluloid::SupervisionGroup:0x91e6b4) (...) irb(main):002:0> salizzar = supervisor.actors.first => #<Celluloid::ActorProxy(Devops:0x907c84) @name="@salizzar"> irb(main):003:0> salizzar.async.up_to_no_good => nil E, [2013-07-10T23:26:54.507455 #2467] ERROR -- : Devops crashed! Errno::ENOENT: No such file or directory - rm-f / ! /vagrant/examples/supervisor.rb:14:in ``' ! /vagrant/examples/supervisor.rb:14:in `up_to_no_good' ! (...) irb(main):004:0> salizzar => #<Celluloid::ActorProxy(Devops) dead> irb(main):005:0> salizzar.terminate Celluloid::DeadActorError: actor already terminated (...) irb(main):006:0> salizzar = supervisor.actors.first => #<Celluloid::ActorProxy(Devops:0x4e99b8) @name="@salizzar"> Monday, July 15, 13
  • 15. CELLULOID • Supervision Groups • Supervise many actors at once • Able to supervise other groups too • You can create pools of supervised actors • Transparent GC cleaning (automatic terminate all supervised actors) Monday, July 15, 13
  • 16. CELLULOID # -*- encoding: UTF-8 -*- require 'celluloid' class EyeOfSauron < Celluloid::SupervisionGroup supervise FredFlinstone, as: :fred pool Devops, as: :devops_pool end Monday, July 15, 13
  • 17. CELLULOID irb(main):001:0> eye_of_sauron = EyeOfSauron.run! => #<Celluloid::ActorProxy(EyeOfSauron:0xecaab8) @members=[#<Celluloid::SupervisionGroup::Member:0x00000001d89720 (...) irb(main):002:0> fred = Celluloid::Actor[:fred] => #<Celluloid::ActorProxy(FredFlinstone:0xec39d4)> irb(main):003:0> devops = Celluloid::Actor[:devops_pool] => #<Celluloid::ActorProxy(Devops:0xe3f0e4) @name="hipster"> irb(main):004:0> Monday, July 15, 13
  • 18. CELLULOID • Linking • Suppose that you have two interdependent actors and want to be notied if one fails • Association by linking actor that commonly dies and the receiver enables a simple callback when failure occurs • Very useful to terminate broken actors manually Monday, July 15, 13
  • 19. CELLULOID # -*- encoding: UTF-8 -*- require 'celluloid' class RobertoBaggio include Celluloid class KickedFarAwayError < StandardError; end def kick_penalty raise KickedFarAwayError, "OH MAMMA MIA! :'(" end end Monday, July 15, 13
  • 20. CELLULOID # -*- encoding: UTF-8 -*- require 'celluloid' class GalvaoBueno include Celluloid trap_exit :penalty_kick def penalty_kick(player, reason) puts "#{player.inspect} will kick and... #{reason.class}!" 2.times { puts "ACABOOOOOOU! "; sleep(1) } 3.times { puts "EH TETRAAAA! "; sleep(1) } end end Monday, July 15, 13
  • 21. CELLULOID irb(main):001:0> galvao = GalvaoBueno.new => #<Celluloid::ActorProxy(GalvaoBueno:0x12e6aac)> irb(main):002:0> baggio = RobertoBaggio.new => #<Celluloid::ActorProxy(RobertoBaggio:0x1312e68)> irb(main):003:0> galvao.link baggio => #<Celluloid::ActorProxy(RobertoBaggio:0x1312e68)> irb(main):004:0> baggio.async.kick_penalty => nil E, [2013-07-11T00:05:36.212336 #2586] ERROR -- : RobertoBaggio crashed! RobertoBaggio::KickedFarAwayError: OH MAMMA MIA! :'( ! /vagrant/examples/baggio.rb:11:in `kick_penalty' ! (...) irb(main):005:0> #<Celluloid::ActorProxy(RobertoBaggio) dead> will kick and... RobertoBaggio::KickedFarAwayError! ACABOOOOOOU! ACABOOOOOOU! EH TETRAAAA! EH TETRAAAA! EH TETRAAAA! Monday, July 15, 13
  • 22. CELLULOID • Futures • Kind of lazy computation: request a future on method call and only execute it when needed • When value is required, Celluloid internal threadpool executes method synchronously and returns the result • Transparent error raising • No need to explicitly clean up pool, let GC work Monday, July 15, 13
  • 23. CELLULOID # -*- encoding: UTF-8 -*- require 'celluloid' require 'restclient' class LazyConsumer include Celluloid def retrieve RestClient.get('http://www.locaweb.com.br').body end end Monday, July 15, 13
  • 24. CELLULOID irb(main):001:0> consumer = LazyConsumer.new => #<Celluloid::ActorProxy(LazyConsumer:0x12f4210)> irb(main):002:0> future = consumer.future.retrieve => #<Celluloid::Future:0x000000025957e8> irb(main):003:0> future.value => "<!DOCTYPE html>n<html dir="ltr" lang="pt-BR">n<head>nt <meta http- equiv="content-type" content="text/html; charset=utf-8" />n <meta name= "robots" content="index, follow" />n (...) ” Monday, July 15, 13
  • 25. CELLULOID • Pools • You can dene a pool of actors (ORLY?); • Default size: cores available on machine (Celluloid.cores) • Delegates method call to a worker on pool to execute it • Not sooo great due for GIL on MRI, but is OK when you have async I/O :) • Main tips: • Synchronous calls if concurrent access to a resource (via Actor.<#method> or Actor.future.<#method>) • Asynchronous calls if parallel computation (via Actor.async.<#method>) Monday, July 15, 13
  • 26. CELLULOID # -*- encoding: UTF-8 -*- require 'celluloid' require 'restclient' class LazyConsumer include Celluloid def retrieve RestClient.get('http://www.locaweb.com.br').body end end Monday, July 15, 13
  • 27. CELLULOID irb(main):001:0> Celluloid::Actor.all.size => 0 irb(main):002:0> consumer = LazyConsumer.pool size: 4 => #<Celluloid::ActorProxy(LazyConsumer:0xc69bc0)> irb(main):003:0> Celluloid::Actor.all.size => 5 Monday, July 15, 13
  • 28. CELLULOID::IO • Celluloid plus Evented I/O = Celluloid::IO • Celluloid with steroids =P • Uses nio4r (libev native extension) as a Reactor to manage Celluloid Actor Mailboxes • Great with most-idle connections (sockets, websockets and friends) • Multiplex message processing and I/O in a transparent way Monday, July 15, 13
  • 29. CELLULOID::IO • Stream-based: • Celluloid::IO::TCPSocket • Celluloid::IO::UnixSocket • Celluloid::IO::TCPServer • Celluloid::IO::UnixServer • SSL • Celluloid::IO::SSLSocket • Celluloid::IO::SSLServer • UDP • Celluloid::IO::UDPSocket Monday, July 15, 13
  • 30. CELLULOID::IO # -*- encoding: UTF-8 -*- require 'celluloid/io' class WhoisServer include Celluloid::IO def initialize(host, port) @server = TCPServer.new host, port end def start ; run ; end def stop ; @server.close if @server ; end def run ; loop { async.handle_connection @server.accept } ; end def handle_connection(socket) _, port, host = socket.peeraddr domain_id = socket.read.strip socket.write("I received a query to #{domain_id} at #{Time.now}n") ensure socket.close end end Monday, July 15, 13
  • 31. CELLULOID::IO irb(main):001:0> ws = WhoisServer.new '0.0.0.0', 4343 => #<Celluloid::ActorProxy(WhoisServer:0xa2f404) @server=#<Celluloid::IO::TCPServer:0x00000001652358 @server=#<TCPServer:fd 10>>> irb(main):002:0> ws.async.start => nil vagrant@vagrant-debian-wheezy:~$ whois -h localhost -p 4343 xalala.com.br I received a query to xelele.com.br at 2013-07-11 01:00:17 -0300 vagrant@vagrant-debian-wheezy:~$ whois -h localhost -p 4343 xirubiru.com.br I received a query to xirubiru.com.br at 2013-07-11 01:01:09 -0300 Monday, July 15, 13
  • 32. DCELL • Distributed Ruby (wat) objects as network services • DCell != DRb (Distributed Ruby) • DRb comes with Ruby STDLIB • Ruby specic, not interoperatable with CORBA, RMI, etc • DCell is built on top of Celluloid::ZMQ • ØMQ protocol implementation with Celluloid Actors Monday, July 15, 13
  • 33. DCELL # -*- encoding: UTF-8 -*- # example from https://github.com/celluloid/dcell :) require 'dcell' DCell.start id: 'itchy', addr: 'tcp://127.0.0.1:9001' class Itchy include Celluloid def initialize puts "Ready for mayhem!" @n = 0 end def fight @n = (@n % 6) + 1 puts(@n <= 3 ? "Bite!" : "Fight!") end end Itchy.supervise_as :itchy ; sleep Monday, July 15, 13
  • 34. DCELL # -*- encoding: UTF-8 -*- # example from https://github.com/celluloid/dcell :) require 'dcell' DCell.start id: 'scratchy', addr: 'tcp://127.0.0.1:9002' itchy_node = DCell::Node['itchy'] puts "Fighting itchy! (check itchy's output)" 6.times do itchy_node[:itchy].fight sleep 1 end Monday, July 15, 13
  • 35. REEL • Celluloid::IO web server powered • Similar syntax to EventMachine • And, of course, weird and potentially ugly after some time • Rack support is experimental • Good with websockets • Not so fast: • Goliath < Reel <<<<Thin <<< Node.js Monday, July 15, 13
  • 36. REEL • Let’s show code from https://github.com/salizzar/reel-example Monday, July 15, 13
  • 37. #TODO • Great opportunity to create a DCell similar gem using AMQP • Stable Rack support for Reel • Not sure, low usage at this time • Other wrappers are welcome • Celluloid::Redis is a great example • Celluloid wrap != EventMachine wrap • Use Dependency Injection API (if possible) to wrap sockets with Celluloid::IO instead of STDLIB sockets Monday, July 15, 13
  • 38. DOUBTS? • Questions are free as beer :) Monday, July 15, 13