我目前正在构建一个带有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中实现了一些消息总线,但谷歌搜索并没有导致任何结果
答案 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"
}