Not sure about event machine workings

I found this example of using faye for a chatroom type app as I am trying to get a feel for push servers:

I got some of that to work, although multiuser from the same browser doesn't exactly make sense. I then tried to look into a server side client. I am using a windows laptop for everything.

I have the following code below which publishes a message to the chatroom fine, but it never really exits. The last statement "puts 'end'" is never reached. If I put EM.stop or an exit statement inside the event machine block, then the messages don't make it to the chat room.

The other thin I noticed is if I have a loop that puts say 5 messages to the chat room, but sleeps for several seconds between each. They don't show up until they have all been published. It's like it needs to reach the bottom of the block, but once there it never exits the block.

require 'eventmachine'

require 'faye'

client = Faye::Client.new('http://localhost:9292/faye’)

EM.run {

  client.subscribe('/messages/public') do |message|     puts message.inspect   end

  client.publish('/messages/public', 'username' => 'Joe',                    'msg' => "hey there again")

}

puts 'end'

When you enter a eventmachine block it never return control to your app. You have to turn it on but dont stay inside the evented block.

Use this method before initializing comunication to faye

def self.ensure_reactor_running

Thread.new { EM.run } unless EM.reactor_running?

sleep 0.1 until EM.reactor_running?

end

this will start eventmachine in a thread that is not the one your rails app is running if not already running.

Just call

ensure_reactor_running

before subscribing

Your post has been very helpful, I tried something like what you posted, but it didn't quite make sense to me.

If you look at what I have currently below, I have to have this sleep(30) at the bottom which is not optimal. a join on the thread doesn't work.

I also tried run_block() instead of run() with no luck.

I guess if I do everything inside of a EM that doesn't take too long, it wouldn't matter, but I am trying to get an idea of how this sort of thing should work

Ok, Rails is a single threaded application, once you start event machine inside the application flow, control is lost until a event triggers a return somehow.

Do not put your code inside the EM block.

This is how i do it

class CommBridge

def self.set_connection

ensure_reactor_running

@@client ||= self.set

@@client

end

private

def self.set

client = Faye::Client.new(“http://localhost:9292/faye”, {timeout: 20})

client.add_extension(ClientAuth.new)

return client

end

def self.ensure_reactor_running

Thread.new { EM.run } unless EM.reactor_running?

sleep 0.1 until EM.reactor_running?

end

end

class ClientAuth

def outgoing(message, callback)

if message['channel'] !~ %r{^/meta/}

  message['ext'] ||= {}

message[‘ext’][‘authToken’] = “#{FAYE_TOKEN}”

	end

	callback.call(message)

end

end

This calls takes care of creating a client fot he rails server.

Then anywhere in your app

client = CommBridge.set_connection client.publish(“/user/#{channel}”,msg.to_json)