0

私は RoR アプリを開発しており、ベースとコントローラーで動作するバックグラウンド サービスを作成する必要があります。キューで何らかの作業を行う必要があるスレッドを持つクラスがあります。したがって、次のようになります。

class ServerThread

   def initialize(name)
       @name = name
       @queue = Queue.new
       @thread = Thread.new do
          while true
              if @queue.empty?
                  Thread.stop
              end
              item = @queue.pop
              log = `run #{item}` 
              save_log(log)    #save into DB
          end    
       end
   end

   def add_to_queue(item)
       @queue << item
       @thread.run
   end

end

そして今、このように機能しています。一部のファイルにグローバル変数を作成するだけです:

$threads = SomeService.new
Server.all.each do |server|                    #servers from DB
    $threads << ServerThread.new(server.name)
end

また、ブラウザー ユーザーがコントローラーによってアイテムをキューに追加する場合もあります。

class ServerController < ApplicationController

   def add_to_queue       
       $threads.get_thread_by_name(params['server']).add_to_queue(params['item'])       
       render :nothing => true
   end    

end

アイテムをキューに追加するユーザーが何人かいて、アプリのすべてのスレッドを監視する必要があります。Rails アプリを起動するときにこの $threads を作成する必要があり、このスレッドはすべてのブラウザー ユーザーに共通である必要があります。今、apache2 とパッセンジャーを使用してアプリをデプロイしようとしているので、このグローバル変数は機能しません!

グローバル変数なしでそれを行う方法は?

RoR 3.2、ルビー 1.9.2

4

1 に答える 1

0

@Sergioがすでに述べたように。このようなものを最初から書かない方がよいでしょう。並行プログラムを確実に作成することは、実行するのが最も簡単なタスクの 1 つではなく、デバッグするのが非常に困難です。ruby には本当に優れた代替手段がいくつかあります。ruby-toolbox をご覧ください: https://www.ruby-toolbox.com/categories/Background_Jobs

自分でやりたい場合は、グローバル変数を、同じマシンまたは異なるマシン上の複数のプロセスで共有できるものに置き換える必要があります。この問題に対する本当に簡単な解決策は、redis のキューイング機能を使用し、その上にバックグラウンド ワーカーを実装することだと思います。

于 2013-10-14T14:05:26.307 に答える