SlideShare a Scribd company logo
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 notified 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

More Related Content

PDF
Celluloid - Beyond Sidekiq
Marcelo Pinheiro
 
PDF
KCDC 2018 - Rapid API Development with Sails
Justin James
 
PPT
All That Jazz
Nick Carter
 
PDF
Java 8 Puzzlers as it was presented at Codemash 2017
Baruch Sadogursky
 
KEY
Sprockets
Christophe Porteneuve
 
PPTX
iSoligorsk #3 2013
Friedrich Boeckh
 
PDF
Es.next
Ignacio Gil
 
PDF
Botsing demo
PouriaDerakhshanfar
 
Celluloid - Beyond Sidekiq
Marcelo Pinheiro
 
KCDC 2018 - Rapid API Development with Sails
Justin James
 
All That Jazz
Nick Carter
 
Java 8 Puzzlers as it was presented at Codemash 2017
Baruch Sadogursky
 
iSoligorsk #3 2013
Friedrich Boeckh
 
Es.next
Ignacio Gil
 
Botsing demo
PouriaDerakhshanfar
 

Viewers also liked (20)

KEY
Hybrid concurrency patterns
Kyle Drake
 
PDF
Ruby is dying. What languages are cool now?
Michał Konarski
 
PDF
cynapspro data endpoint protection 2010 - Installationsleitfaden
cynapspro GmbH
 
PPS
Pater nostrolatinoitaliano
pietroumbro
 
DOCX
Curriculum Vitae
William Wright
 
PDF
Museum Digital - Metadaten
Linus Kohl
 
PDF
Informatics%20 Broschuere Ish[1]
a_peter
 
PDF
BGCS Logistics Solutions
Bilcare GCS
 
PDF
Informe relevamiento oferta del municipio de Pinamar
Santiago Cravero Igarza
 
PPTX
Outsourcing verities
John William
 
PPT
BI 2005 - Caso de excito COPSA y Tarjetas Sin Contacto Mifare
Mario Guedes de Rezende
 
PDF
Kantox - NOAH16 London
NOAH Advisors
 
PDF
IM Farmacias 34
Marcos Alonso Espada
 
DOC
khalid awaad cv -2016
khalid Awaad
 
PDF
Oclusion odontologia-restauradora
Sofía Landa
 
PDF
Social Commerce in der praktischen Umsetzung
Daniel Hoffmann
 
PDF
99 Tipps zur Kundenbindung
ROHINIE.COM Limited
 
PPT
Aluminium Haustüren Türschnitte
proziel
 
PPTX
EML Podcast - Early Conciliation - 281114
Employee Management Ltd [EML]
 
Hybrid concurrency patterns
Kyle Drake
 
Ruby is dying. What languages are cool now?
Michał Konarski
 
cynapspro data endpoint protection 2010 - Installationsleitfaden
cynapspro GmbH
 
Pater nostrolatinoitaliano
pietroumbro
 
Curriculum Vitae
William Wright
 
Museum Digital - Metadaten
Linus Kohl
 
Informatics%20 Broschuere Ish[1]
a_peter
 
BGCS Logistics Solutions
Bilcare GCS
 
Informe relevamiento oferta del municipio de Pinamar
Santiago Cravero Igarza
 
Outsourcing verities
John William
 
BI 2005 - Caso de excito COPSA y Tarjetas Sin Contacto Mifare
Mario Guedes de Rezende
 
Kantox - NOAH16 London
NOAH Advisors
 
IM Farmacias 34
Marcos Alonso Espada
 
khalid awaad cv -2016
khalid Awaad
 
Oclusion odontologia-restauradora
Sofía Landa
 
Social Commerce in der praktischen Umsetzung
Daniel Hoffmann
 
99 Tipps zur Kundenbindung
ROHINIE.COM Limited
 
Aluminium Haustüren Türschnitte
proziel
 
EML Podcast - Early Conciliation - 281114
Employee Management Ltd [EML]
 
Ad

Recently uploaded (20)

PDF
A Day in the Life of Location Data - Turning Where into How.pdf
Precisely
 
PPTX
Smart Infrastructure and Automation through IoT Sensors
Rejig Digital
 
PDF
Software Development Company | KodekX
KodekX
 
PPTX
C Programming Basics concept krnppt.pptx
Karan Prajapat
 
PPTX
The-Ethical-Hackers-Imperative-Safeguarding-the-Digital-Frontier.pptx
sujalchauhan1305
 
PDF
Building High-Performance Oracle Teams: Strategic Staffing for Database Manag...
SMACT Works
 
PDF
Revolutionize Operations with Intelligent IoT Monitoring and Control
Rejig Digital
 
PDF
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
PDF
Event Presentation Google Cloud Next Extended 2025
minhtrietgect
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PPTX
ChatGPT's Deck on The Enduring Legacy of Fax Machines
Greg Swan
 
PDF
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
PDF
Cloud-Migration-Best-Practices-A-Practical-Guide-to-AWS-Azure-and-Google-Clou...
Artjoker Software Development Company
 
PDF
Software Development Methodologies in 2025
KodekX
 
PDF
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
PPTX
How to Build a Scalable Micro-Investing Platform in 2025 - A Founder’s Guide ...
Third Rock Techkno
 
PDF
REPORT: Heating appliances market in Poland 2024
SPIUG
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PDF
Advances in Ultra High Voltage (UHV) Transmission and Distribution Systems.pdf
Nabajyoti Banik
 
PPTX
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
A Day in the Life of Location Data - Turning Where into How.pdf
Precisely
 
Smart Infrastructure and Automation through IoT Sensors
Rejig Digital
 
Software Development Company | KodekX
KodekX
 
C Programming Basics concept krnppt.pptx
Karan Prajapat
 
The-Ethical-Hackers-Imperative-Safeguarding-the-Digital-Frontier.pptx
sujalchauhan1305
 
Building High-Performance Oracle Teams: Strategic Staffing for Database Manag...
SMACT Works
 
Revolutionize Operations with Intelligent IoT Monitoring and Control
Rejig Digital
 
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
Event Presentation Google Cloud Next Extended 2025
minhtrietgect
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
ChatGPT's Deck on The Enduring Legacy of Fax Machines
Greg Swan
 
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
Cloud-Migration-Best-Practices-A-Practical-Guide-to-AWS-Azure-and-Google-Clou...
Artjoker Software Development Company
 
Software Development Methodologies in 2025
KodekX
 
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
How to Build a Scalable Micro-Investing Platform in 2025 - A Founder’s Guide ...
Third Rock Techkno
 
REPORT: Heating appliances market in Poland 2024
SPIUG
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
Advances in Ultra High Voltage (UHV) Transmission and Distribution Systems.pdf
Nabajyoti Banik
 
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
Ad

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 first 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 notified 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 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
  • 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 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
  • 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