是否有Ruby Message Bus宝石?

时间:2012-04-20 14:12:56

标签: ruby-on-rails ruby message-bus

我目前正在构建一个带有rails进程和多个工作进程的架构,需要通知某些事件(如创建对象)。

Rails
  |         API   Worker  
  +----------o------o--------o------ - - -
                        Some other
                          daemon

我想做以下

class Article
  after_creation do
    MessageBus.send type: "article-created", id: self.id
  end
end

虽然进程(API,Worker,Daemons,...)只是订阅消息总线,但是当消息进入时会调用一个块。

MessageBus.subscribe do |msg|
  if msg['type'] == 'article-created'
    # if this is my websocket daemon, I would push the article to the browser
    # if this is my indexing daemon, I would reindex the full-text search
    # if this is ... you get the deal.
  end
end

目前我正在使用本地unix域套接字,我使用UNIXSocket推送JSON并使用EventMachine.start_unix_domain_server获取它。但这只允许双向沟通。我还想过使用resque,但是当我需要总线时,这更像是一个消息队列。这取决于redis。我很确定必须有一个gem,它在ruby中实现了一些消息总线,但谷歌搜索并没有导致任何结果

1 个答案:

答案 0 :(得分:2)

最后,我使用Eventmachine频道破解了一个快速自己的解决方案。

这是我的服务器。基本上,客户端连接到/tmp/messagebus.sock并发送数据。推入套接字的所有内容都会发送给所有其他客户端。

require 'rubygems'
require 'eventmachine'

module Messagebus
  class Server
    attr_accessor :connections
    attr_accessor :channel

    def initialize
      @connections = []
      @channel = EventMachine::Channel.new
    end

    def start
      @signature = EventMachine.start_unix_domain_server '/tmp/messagebus.sock', Connection do |conn|
        conn.server = self
      end
    end

    def stop
      EventMachine.stop_server(@signature)

      unless wait_for_connections_and_stop
        EventMachine.add_periodic_timer(1) { wait_for_connections_and_stop }
      end
    end

    def wait_for_connections_and_stop
      if @connections.empty?
        EventMachine.stop
        true
      else
        puts "Waiting for #{@connections.size} connection(s) to finish ..."
        false
      end
    end
  end

  class Connection < EventMachine::Connection
    attr_accessor :server

    def post_init
      log "Connection opened"
    end

    def server=(server)
      @server = server

      @subscription = server.channel.subscribe do |data|
        self.log "Sending #{data}"
        self.send_data data 
      end
    end

    def receive_data(data)
      log "Received #{data}"
      server.channel.push data
    end

    def unbind
      server.channel.unsubscribe @subscription
      server.connections.delete(self)
      log "Connection closed"
    end

    def log(msg)
      puts "[#{self.object_id}] #{msg}"
    end
  end
end

EventMachine::run {
  s = Messagebus::Server.new
  s.start
  puts "New server listening"
}