Following are my Celluloid codes.
client1.rb One of the 2 clients. (I named it as client 1)
client2.rb 2nd of the 2 clients. (named as client 2
Managed to reproduce and fix the issue.
Deleting my previous answer.
Apparently, the problem lies in sleep
.
Confirmed by adding logs "actor/kernel sleeping"
to the local copy of Celluloids.rb's sleep().
In server1.rb
,
the call to
sleep
is withinserver
- a class that includes Celluloid.Thus Celluloid's implementation of
sleep
overrides the nativesleep
.
class Server
include Celluloid::ZMQ
...
def run
loop { async.handle_message @socket.read }
end
def handle_message(message)
...
sleep 60
end
end
Note the log actor sleeping
from server1.rb
. Log added to Celluloids.rb's sleep()
This suspends only the current "actor" in Celluloid i.e. only the current "Celluloid thread" handling the client1 sleeps.
In server2.rb
,
the call to
sleep
is within a different classDisplayMessage
that does NOT include Celluloid.Thus it is the native
sleep
itself.
class DisplayMessage
def self.message(message)
...
sleep 60
end
end
Note the ABSENCE of any actor sleeping
log from server2.rb
.
This suspends the current ruby task i.e. the ruby server sleeps (not just a single Celluloid actor).
In server2.rb, the appropriate
sleep
must be explicitly specified.
class DisplayMessage
def self.message(message)
puts "Received at #{Time.now.strftime('%I:%M:%S %p')} and message is #{message}"
## Intentionally added sleep to test whether Celluloid block the main process for 60 seconds or not.
if message == 'client-1'
puts 'Going to sleep now'.red
# "sleep 60" will invoke the native sleep.
# Use Celluloid.sleep to support concurrent execution
Celluloid.sleep 60
end
end
end