Клиент Faye ruby ​​публикуется только один раз

У меня есть сервер faye (nodejs), работающий на локальном хосте, и я пытаюсь настроить ruby-клиент на стороне сервера, который необходимо регулярно публиковать на сервере. Это код, который я пытаюсь использовать. (Пожалуйста, для начала игнорируйте закомментированный код).
Я создаю переменную класса @@client и инициализирую ее, как только класс загружается. Я определяю метод класса pub, задачей которого является публикация чего-либо на сервере faye.
В конце концов, я просто дважды вызываю метод pub. Обратный вызов первой публикации получен успешно, но вторая публикация не делает ни callback, ни errback. И так как управление не было возвращено приложению, приложение просто зависло там.
Если я создаю глобальную переменную $client (сейчас прокомментирована), поведение будет таким же. Но если я делаю клиент каждый раз, когда вызывается pub, то публикация проходит гладко. Я инициирую его в цикле EM.run или снаружи, поведение такое же. (как и ожидалось)

Я не хочу устанавливать новое соединение каждый раз, когда хочу что-то опубликовать, так как это противоречит цели. Кроме того, если я создаю нового клиента в EM.run каждый раз, когда я вызываю метод, клиентские соединения не закрываются сами по себе. Я вижу, что они открыты в команде lsof как открытые файлы, и скоро я начну получать ошибку too many open files, я думаю.

Я не совсем правильно понимаю Event Machine, может быть, я что-то упустил.

require 'faye'
require 'eventmachine'

# $client = Faye::Client.new('http://localhost:5050/faye')
class Fayeclient
  puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s

  # if !defined? @@client or @@client.nil?
    @@client = Faye::Client.new('http://localhost:5050/faye')
    puts "Created client: " + @@client.inspect
  # end

  def self.pub
    puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
    # client = Faye::Client.new('http://localhost:5050/faye') #$client
    # client = @@client
    EM.run {
      #client = Faye::Client.new('http://localhost:5050/faye') #$client
      puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
      puts @@client.inspect

      publication = @@client.publish('/foo', 'text' =>'Hello world')
      puts "Publishing: #{publication.inspect}"
      # puts "Publication methods: #{publication.methods}"

      publication.callback do
        puts "Did it #{publication.inspect}"
        EM.stop_event_loop
        puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
        # puts "#{client.methods}"
#        puts client.inspect
#        client.remove_all_listeners
#        puts client.inspect
      end
      publication.errback do |error |
          puts error.inspect
          EM.stop_event_loop
      end
    }
    puts "Outside event loop"
    puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
  end
end

Fayeclient.pub
Fayeclient.pub

person neeraj    schedule 16.09.2014    source источник


Ответы (1)


EM.run вызов блокируется, вы должны запустить его в отдельном потоке и в конце концов присоединиться к нему, когда все закончится. В примере я использую Singleton, но ты.

Это правильно делает 2 вызова Faye.

#!/usr/bin/env ruby
#
require 'faye'
require 'singleton'
require 'eventmachine'


class Fayeclient
  include Singleton
  attr_accessor :em_thread, :client

  def initialize
    self.em_thread = Thread.new do
      EM.run
    end
    self.client = Faye::Client.new('http://localhost:8890/faye')
  end

  def pub
    puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
    puts client.inspect

    publication = client.publish('/foo', 'text' =>'Hello world')
    puts "Publishing: #{publication.inspect}"

    publication.callback do
      puts "Did it #{publication.inspect}"
      EM.stop_event_loop
      puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
    end
    publication.errback do |error |
        puts error.inspect
        EM.stop_event_loop
    end
  end
end

Fayeclient.instance.pub
Fayeclient.instance.pub

Fayeclient.instance.em_thread.join

В любом случае, по моему личному опыту, иметь дело с EventMachine внутри приложения Rails может быть беспорядок, некоторые веб-серверы используют EM, другие - нет, и когда вы хотите протестировать из консоли, это может работать не так, как ожидалось.

Мое решение - вернуться к http-вызовам:

RestClient.post "http://localhost:#{Rails.configuration.faye_port}/faye", message: {foo: 'bar'}.to_json

Я нашел это решение более простым и легким в настройке, если вам не нужно получать сообщение от этого фрагмента кода.

person Enrico Carlesso    schedule 22.09.2014