Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.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 轨道&x2B;后台的XMPP bot_Ruby_Ruby On Rails 3_Xmpp_Resque_Xmpp4r - Fatal编程技术网

Ruby 轨道&x2B;后台的XMPP bot

Ruby 轨道&x2B;后台的XMPP bot,ruby,ruby-on-rails-3,xmpp,resque,xmpp4r,Ruby,Ruby On Rails 3,Xmpp,Resque,Xmpp4r,我正在构建一个服务,它基本上允许用户与机器人聊天,然后机器人会对用户发送的聊天进行一些奇怪的处理,并最终回复一些有意义的数据。基本上类似于土豚过去的工作方式 我已经让机器人工作了,现在正在听,我有一个单独的rails应用程序,它将完成所有其他繁重的工作。这两个部分各自都工作得很好,现在我被困在两者的接口上。我的想法是通过Resque将bot(基本上是一个小的ruby脚本)与rails应用程序连接起来——任何进入的东西都会进入队列,被拾取,然后结果再次推回到队列,然后脚本会用结果回复 我不太清楚如

我正在构建一个服务,它基本上允许用户与机器人聊天,然后机器人会对用户发送的聊天进行一些奇怪的处理,并最终回复一些有意义的数据。基本上类似于土豚过去的工作方式

我已经让机器人工作了,现在正在听,我有一个单独的rails应用程序,它将完成所有其他繁重的工作。这两个部分各自都工作得很好,现在我被困在两者的接口上。我的想法是通过Resque将bot(基本上是一个小的ruby脚本)与rails应用程序连接起来——任何进入的东西都会进入队列,被拾取,然后结果再次推回到队列,然后脚本会用结果回复

我不太清楚如何建立这个接口:

  • 我是否需要编写一个rake任务来启动/停止/重新加载bot
  • 如果我在没有rake的情况下运行它(被认为是由Monit监控的一个独立进程),那么我如何与Resque接口或访问我的rails模型

  • 我知道这些可能是非常琐碎的问题,但我很难理解哪个更好,以及如何进行设置。

    在Rails应用程序和这个机器人守护进程之间有三种通信方式:

  • 通过以HTTP请求的形式调用Rails应用程序(从Rails应用程序推/拉数据)
  • 通过直接与Rails应用程序使用的数据库交互(可能是Mysql/Postgres)
  • 通过与Redis数据库支持的Resque工作队列系统交互
  • 当您排队并从各种作业队列中提取Resque作业时,您只是通过API读/写共享Redis数据库。机器人和Rails应用程序都通过网络与Redis DB通信


    我建议将bot直接作为ruby进程或monit管理的rake任务运行。听起来您已经知道如何做到这一点。

    我认为这里的主要问题是,您需要另一种消息传递解决方案(类似IPC,而不是IM),而不是尝试弯曲“只是”一个队列的Resque。有些选项是(AMQP协议)或(ZeroMQ协议),但也可以通过Ruby标准库套接字类()使用普通的旧UNIX套接字。他们都有不同的优点和缺点,所以这取决于你和你的需要

    交互可能如下所示:

  • 机器人启动
  • Bot开始侦听IPC消息
  • Bot接收来自发送方的查询(通过XMPP)
  • Bot通过Resque将作业排队
  • Job通过HTTP调用Rails应用程序
  • Rails应用程序完成了自己的工作
  • 某人或某物解析任何查询,并通过Rails应用程序输入结果
  • Rails应用程序使用某种IPC方法将结果发送给机器人
  • Bot将结果发送给原始发送者(通过XMPP)
  • 像往常一样,可能会有一些变化。例如,我认为您根本不需要重新调整。机器人可以简单地将请求立即传递给Rails应用程序。但是,这取决于负载、您想要实现的响应时间、您当前的体系结构等。可能Resque作业可以等待Rails应用程序返回结果,然后作业(而不是Rails应用程序)将使用IPC。还有其他的变化

    我是否需要编写一个rake任务来启动/停止/重新加载bot

    不,你没有。这取决于你如何以及何时运行它。毕竟,Rake可以被看作是一种将多个Ruby脚本放在一起并在它们之间创建依赖关系的方便方法。如果您认为除了运行bot之外还有其他任务(一些清理、部署等),那么为了方便起见,最好使用Rake。若您还并没有,那个么重构bot的逻辑来初始化,并使用Rake任务来初始化它。但如果您不使用它,只按原样运行脚本(使用monit、自定义init.d脚本、ad-hoc等),也可以

    如果我在没有rake的情况下运行它(被认为是由Monit监控的一个独立进程),那么我如何与Resque接口或访问我的rails模型

    Rake对此没有任何影响。从操作系统的角度来看,通过Rake运行Resque和通过Rake运行bot或作为独立脚本运行Resque并不重要。无论如何,它们将是不同的过程。另外,请记住,Resque需要Redis在某个地方运行

    我知道这些可能是非常琐碎的问题


    完全没有。我认为这类问题需要一段时间才能被视为无关紧要。

    您可以将代码放在初始值设定项上运行,并完全访问所有Rails模型或库

    这样,你就不需要在你的机器人和你的Rails应用程序之间“通信”,因为你的机器人就在你的Rails应用程序中

    样板代码如下所示:

    config/initializers/background_app_tasks.rb

    class BackgroundWorker
    
          #-------------------------------
          def initialize(operation='normal')
            @exit = false
            @lock = Mutex.new  # For thread safety
            @thread = nil
            say "Starting in '#{operation}' mode..."
            case operation
              when 'normal'
                @thread = Thread.new() {    loopme     }
              when 'cleanup'
                @thread = Thread.new() {    cleanup     }
              when 'nothing'
                #startup without threads
            end
            @thread.run if @thread
          end
    
          #-------------------------------
          def exit!
            begin
                return if @exit # #stop?
                say   "Exiting #{}, waiting for mutex..."
                @lock.synchronize {
                    say "exiting thread #{@thread.to_s || '<sem nome>' }..."
                    @exit = true # #stop
                }
            rescue Exception => e
                exceptme(e)
            end
          end
    
          #-------------------------------
          def loopme
    
            at_exit { exit! }
            i=0;  ok=false;
    
            nap = 30
    
            while true do
              begin
                  break if @exit
                  i+=1
    
                  #lock mutex for processing...
                  @lock.synchronize {
    
                      #.... do some work ....
    
                  }
              rescue StandardError => e
    
                  #....
    
              end
    
              sleep(nap)
            end 
          end
    
    end #class
    
    # ------ M A I N --------
    
    Thread.abort_on_exception=false
    e = BackgroundWorker.new(OPERATION)
    
    类后台工作程序
    #-------------------------------
    def初始化(操作=“正常”)
    @退出=错误
    @lock=Mutex.new#用于线程安全
    @线程=零
    说“以“#{operation}”模式启动…”
    案例操作
    当‘正常’时
    @thread=thread.new(){loopme}
    什么时候“清理”
    @thread=thread.new(){cleanup}
    当“什么都没有”
    #无线程启动
    结束
    @thread.run如果@thread
    结束
    #-------------------------------
    def出口!
    开始
    如果@exit##停止返回?
    说“正在退出#{},等待互斥…”
    @锁定。同步{
    说“正在退出线程{@thread.to_s | |''''}”
    @退出=正确##停止
    }
    救援异常=>e
    例外情况(e)
    结束
    结束
    #-------------------------------
    def loopme
    在_出口{exit!}
    i=0;ok=假;
    nap=30
    尽管如此
    开始
    退出时中断
    i+=1