Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

Using it in forked / multithreaded env #103

Open
doits opened this issue Jul 15, 2015 · 8 comments
Open

Using it in forked / multithreaded env #103

doits opened this issue Jul 15, 2015 · 8 comments

Comments

@doits
Copy link

doits commented Jul 15, 2015

I'm trying to use DCell in my rails app like the following:

# initializer
DCell.start id: 'sender', addr: 'tcp://127.0.0.1:9002'

# controller
...
def index
  DCell::Node['client'][:xmpp].send_message 'something'
end

The node client is existing and implements the actor :xmpp which has the method send_message. When I start Rails in development mode (unicorn webserver), everything works. DCell connects to the client and calls the method send_message on the existing actor :xmpp.

But when I use passenger as a web server, the line DCell::Node['client'][:xmpp].send_message 'something' hangs forever. In the client node I do not get any connection attempt (... Connected to sender). I think this might be because passenger is using multiple threads and forking. Is there any solution to this? How to use DCell in a multithreaded environment?

@digitalextremist
Copy link
Member

Are you using xmpp4r as your transport gem?

@Asmod4n
Copy link
Contributor

Asmod4n commented Jul 15, 2015

Try to force passenger to never call fork(), e.G. into something of a testing/debugging mode. zeromq, the underlying library which is used to handle the messaging part, doesn't survive a fork() call.

If it works that way you have to setup DCell in a "after_fork" hook or something similar.

@doits
Copy link
Author

doits commented Jul 15, 2015

@digitalextremist The client is using blather, but lives outside of Rails

@Asmod4n good hint, I just managed to get first things working with this:

# initializer
if defined?(PhusionPassenger)
    PhusionPassenger.on_event(:starting_worker_process) do |forked|
      next unless forked
      DCell.start id: 'sender', addr: 'tcp://127.0.0.1:9002'
    end
end

This worked now for the first five minutes, I'll report if it works longer after some testing. Thanks!

@doits
Copy link
Author

doits commented Jul 15, 2015

After some time it appears that DCell.start was called multiple times, because I got the following message in server log:

IOError: couldn't bind to tcp://127.0.0.1:9002: Address already in use

So maybe I have to close an old connection before calling DCell.start again? I tried DCell.stop, but there is no such method, so I can to something like:

if defined?(PhusionPassenger)
    PhusionPassenger.on_event(:starting_worker_process) do |forked|
      next unless forked
      DCell.stop if DCell.running? <--- something like this?
      DCell.start id: 'sender', addr: 'tcp://127.0.0.1:9002'
    end
end

@Asmod4n
Copy link
Contributor

Asmod4n commented Jul 15, 2015

You would have to use a new port for each fork, and also a new name.

@Asmod4n
Copy link
Contributor

Asmod4n commented Jul 15, 2015

Oh and since you are on localhost, you could also use "ipc:///path/to/a/unix.sock" for a little bit better performance and security. But be aware, when different forks bind to the same unix socket only the newest one will own the socket.

@doits doits changed the title Using it with rails and passenger: hang Using it in forked / multithreaded env Jul 15, 2015
@doits
Copy link
Author

doits commented Jul 15, 2015

You would have to use a new port for each fork, and also a new name.

So there'd be n sender connected to client, n = number of forks. This should work.

But what happens if the client wants to send back a message to the sender (the other way around). Ideally I'd only want to have this handled once in my Rails app, so it cannot send it n times (once to each fork) - I'll test if it works to send it only to one of the connected sender randomly ... but maybe this is not in the scope of DCell to handle anymore.

@niamster
Copy link
Contributor

@doits if you are using master branch you don't have to specify port number and put * instead.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants