Created
August 26, 2012 16:55
-
-
Save bsingr/3481633 to your computer and use it in GitHub Desktop.
Different methods to spawn Celluloid Actors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
@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
This has to be the grossest coding sample I've ever seen :)