Following are my Celluloid codes.
client1.rbOne of the 2 clients. (I named it as client 1)client2.rb2nd of the 2 clients. (named as client 2 )
Note:
the only the difference between the above 2 clients is the text that is passed to the server. i.e ('client-1' and 'client-2' respectively)
On testing this 2 clients (by running them side by side) against following 2 servers (one at time). I found very strange results.
server1.rb(a basic example taken from the README.md of the celluloid-zmq)Using this as the example server for the 2 above clients resulted in parallel executions of tasks.
OUTPUT
ruby server1.rb
Received at 04:59:39 PM and message is client-1
Going to sleep now
Received at 04:59:52 PM and message is client-2
Note:
the client2.rb message was processed when client1.rb request was on sleep.(mark of parallelism)
-
Using this as the example server for the 2 above clients did not resulted in parallel executions of tasks.
OUTPUT
ruby server2.rb
Received at 04:55:52 PM and message is client-1
Going to sleep now
Received at 04:56:52 PM and message is client-2
Note:
the client-2 was ask to wait 60 seconds since client-1 was sleeping(60 seconds sleep)
I ran the above test multiple times all resulted in same behaviour.
Can anyone explain me from the results of the above tests that.
Question: Why is celluloid made to wait for 60 seconds before it can process the other request i.e as noticed in server2.rb case.?
Ruby version
ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]


Using your gists, I verified this issue can be reproduced in
MRI 2.2.1as well asjRuby 1.7.21andRubinius 2.5.8... The difference betweenserver1.rbandserver2.rbis the use of theDisplayMessageandmessageclass method in the latter.Use of
sleepinDisplayMessageis out ofCelluloidscope.When
sleepis used inserver1.rbit is usingCelluloid.sleepin actuality, but when used inserver2.rbit is usingKernel.sleep... which locks up the mailbox forServeruntil 60 seconds have passed. This prevents future method calls on that actor to be processed until the mailbox is processing messages ( method calls on the actor ) again.There are three ways to resolve this:
Use a
defer {}orfuture {}block.Explicitly invoke
Celluloid.sleeprather thansleep( if not explicitly invoked asCelluloid.sleep, usingsleepwill end up callingKernel.sleepsinceDisplayMessagedoes notinclude CelluloidlikeServerdoes )Bring the contents of
DisplayMessage.messageintohandle_messageas inserver1.rb; or at least intoServer, which is inCelluloidscope, and will use the correctsleep.The
defer {}approach:The
Celluloid.sleepapproach:Not truly a scope issue; it's about asynchrony.
To reiterate, the deeper issue is not the scope of
sleep... that's whydeferandfutureare my best recommendation. But to post something here that came out in my comments:Using
deferorfuturepushes a task that would cause an actor to become tied up into another thread. If you usefuture, you can get the return value once the task is done, if you usedeferyou can fire & forget.But better yet, create another actor for tasks that tend to get tied up, and even pool that other actor... if
deferorfuturedon't work for you.I'd be more than happy to answer follow-up questions brought up by this question; we have a very active mailing list, and IRC channel. Your generous bounties are commendable, but plenty of us would help purely to help you.