Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@bsingr
Created August 26, 2012 16:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bsingr/3481633 to your computer and use it in GitHub Desktop.
Save bsingr/3481633 to your computer and use it in GitHub Desktop.
Different methods to spawn Celluloid Actors.
# instantiate a cat object named 'Garfield' within its own actor thread
cat = Cat.new 'Garfield'
# blocking (the main thread waits until the cat has finished..)
cat.spray
# non-blocking
cat.spray!
# cats do what cats do
7.times { cat.spray }
# this will kill the actor thread (because spraying ain't petty crime!)
# however, when using the non-blocking call the main thread won't receive
# any exceptions raised within the actor thread (even a dead actor call is not
# harmful)
cat.spray!
# false, the actor thread died
puts cat.alive?
class Cat
include Celluloid
class DeadCatError < StandardError; end
def initialize name=nil
@name = name
@lives_left = 9
end
def spray
† if @lives_left == 0
# spraying is dangerous
# http://www.youtube.com/watch?v=uIbkLjjlMV8
@lives_left -= 1
end
def †
who = if name
"known as '#{@name}'"
else
"unknown vagrant"
end
raise DeadCatError, "Yet another cat in heaven.. (#{who})"
end
end
# a pool of actors spawns one additional thread for the pool manager. the pool
# manager then spawns (and respawns in case of failure) the actor threads.
# per default the pool size (the number of actor threads) is equal to the number
# of cpu cores.
gang_of_cats = Cat.pool size: 2
cats_died = 0
50.times do
begin
gang_of_cats.spray
rescue Cat::DeadCatError => e
cats_died += 1
sleep 0.05
end
end
puts cats_died # more than 1
# define a gang of cats with a leader
class CatGangWithLeader < Celluloid::SupervisionGroup
# this
supervise Cat, as: :alpha_leader, args: 'Garfield'
supervise Cat, as: :gang_of_cats, size: 2, method: 'pool'
end
# this starts 5 threads in total:
# - 2x for the alpha leader (supervisor + actor)
# - 3x for the gang member (supervisor + 2x actor)
CatGangWithLeader.run!
sleep 0.05
alpha_leader_died = 0
member_died = 0
200.times do
begin
# most of the time a member will be used
if rand > 0.1
Celluloid::Actor[:gang_of_cats].spray
else
Celluloid::Actor[:alpha_leader].spray
end
# as soon as the alpha leader dies, the whole supervision group is dead
# then this error will happen and we can stop the loop
rescue Celluloid::DeadActorError => e
break
rescue Cat::DeadCatError => e
if e.message =~ /Garfield/
alpha_leader_died += 1
else
member_died += 1
end
sleep 0.01
end
end
# this is a strange or interesting behaviour. death of a vagrant (a pool member)
# usally happens more than 1 time (max. 20). but as soon as the leader dies, the
# whole supervision group dies and the loop ends. so the typical ratio is 9:1.
puts "The gang members died #{member_died} times.\n"\
"The leader (Garfield) died #{alpha_leader_died} times."
# here there are two threads, one for the actor and one for the supervisor, that
# will respawn the actor if the actor dies
Cat.supervise_as :cat, 'Garfield'
cats_died = 0
50.times do
begin
Celluloid::Actor[:cat].spray
rescue Cat::DeadCatError => e
cats_died += 1
sleep 0.05 # wait a bit to let respawn take place
end
end
# when cat actors die, the supervisor will respawn..
puts cats_died # more than 1
@cpuguy83
Copy link

This has to be the grossest coding sample I've ever seen :)

@jrdi
Copy link

jrdi commented Feb 19, 2014

@dpree I hope you can help me, I'm trying to kill all futures of a pool if one of the fails. After try a lot of combinations with supervisors I arrive to a solution using a simple pool but I don't know if it's as proper as using supervisors. Here is the solution:

gang_of_cats = Cat.pool size: 4

futures = (0..50).to_a.map do
  gang_of_cats.future.spray
end

futures.map do |future|
  begin
    future.value
  rescue Cat::DeadCatError => e
    break
  end
end

gang_of_cats.terminate

PS: Thanks a lot for all those examples!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment