Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 有Ruby消息总线gem吗?_Ruby On Rails_Ruby_Message Bus - Fatal编程技术网

Ruby on rails 有Ruby消息总线gem吗?

Ruby on rails 有Ruby消息总线gem吗?,ruby-on-rails,ruby,message-bus,Ruby On Rails,Ruby,Message Bus,我目前正在构建一个带有rails进程和多个工作进程的架构,这些进程需要被告知某些事件(比如对象的创建) 我想做以下几件事 class Article after_creation do MessageBus.send type: "article-created", id: self.id end end 而进程(API、工作进程、守护进程等)只是订阅消息总线,当消息传入时会调用一个块 MessageBus.subscribe do |msg| if msg['type']

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

我想做以下几件事

class Article
  after_creation do
    MessageBus.send type: "article-created", id: self.id
  end
end
而进程(API、工作进程、守护进程等)只是订阅消息总线,当消息传入时会调用一个块

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获取它。启动unix\u domain\u server
。但这只允许双向沟通。我也考虑过使用resque,但这更像是一个消息队列,而我需要一个总线。这取决于redis。我很确定一定有一个gem,它在ruby中实现了一些消息总线,但是google并没有带来任何结果

最后,我使用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"
}
需要“rubygems”
需要“eventmachine”
模块消息总线
类服务器
属性存取器:连接
属性存取器:通道
def初始化
@连接=[]
@channel=EventMachine::channel.new
结束
def启动
@signature=EventMachine.start_unix_domain_server'/tmp/messagebus.sock',连接do|conn|
conn.server=self
结束
结束
def停止
EventMachine.stop_服务器(@signature)
除非等待连接和停止
添加定期计时器(1){等待连接和停止}
结束
结束
def等待连接和停止
如果@connections.empty?
停止
真的
其他的
将“正在等待#{@connections.size}连接完成…”
假的
结束
结束
结束
类连接
您是否尝试过EventMachine频道+1用于EventMachine通道。另一件需要考虑的事情(如果你的工人和主人一样在同一个进程空间运行)是露比对观察者模式的本地支持。
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"
}