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

On Thu, Mar 29, 2012 at 7:28 PM, [email protected]
[email protected]wrote:

I guess if I do everything inside of a EM that doesn’t take too long,

    client.subscribe('/messages/public') do |message|
   client.publish('/messages/public', 'username' => 'Joe',

sleep 30

puts ‘end of client’

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)

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

#########################

require ‘eventmachine’

require ‘faye’

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

thr = nil

if !EM.reactor_running?
thr = Thread.new do
EM.run do

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

    puts '1'

    client.publish('/messages/public', 'username' => 'Joe',
                  'msg' => "hey there againzoggle")
    sleep 10
    puts '2'

    client.publish('/messages/public', 'username' => 'Joe',
                  'msg' => "hey there again")
    puts 'end of ev machine block'
  end
end

end

puts ‘wait for running’
sleep 0.1 until EM.reactor_running?

sleep 30

puts ‘end of client’