1

私はResqueを使用して、Railsアプリケーションでいくつかのバックグラウンドジョブを処理しています。

重要なのは、クライアントがこのジョブをキャンセルできるということです。

  • ジョブがまだキューにある場合:デキューします

    Resque.dequeue(GitHub::Jobs::UpdateNetworkGraph, 'repo:135325')
    
  • ジョブが終了した場合:何もしない

  • ジョブが実行されている場合:???

プログラムでジョブを見つけて、実行中の場合はすぐに停止するように指示する方法はありますか?私の主な関心事は、現在処理中のジョブではなく、目的のジョブを確実に強制終了することです。これは、実行中かどうかを尋ねた瞬間から、強制終了するまで、別のジョブになる可能性があるためです。

4

2 に答える 2

2

resqueprocess idがフォークプロセス logのプロセスIDを保存するとは思いませんが、それは実行しますが、プロセスIDを保存しません。child process forked

ここ139行目で見ることができます

実行中のresqueジョブのプロセスIDをどのように抽出するかという質問に関しては、redisデータ構造を使用してジョブ自体の中でそれを行う方法を考えています。

したがって、以下のコードは、redis hash(running_process)を使用して作成するジョブの実行アクションでprocess_idあり、現在のタイムスタンプを使用して現在のコードを追加することを検討してください。

class MyJob
 @queue = :myjob

 def self.perform
   field = Time.now.to_i
   redis.hsetnx "running_process",field,Process.pid 
   ### Rest of the code



   #### when the code is about to finish 
   ##remove the finish process from the 
   redis.hdel "running_process",field
  end

これで、次のようなredis "running_process"ハッシュをクエリするだけで、実行中のすべてのプロセスのリストを取得できます。

redis.hgetall "running_process"

ここでのresque警告ジョブが失敗した場合、プロセスIDはクリーンになりません。

ハッシュあなたが何をするにしても、process idあなたが収集したものをクロスチェックすることを確認してください

redisハッシュから実際にはrunning resque job

この助けを願っています

于 2012-10-29T14:54:15.790 に答える
0

進行中のジョブを失敗したジョブとしてマークせずに強制終了/停止したい場合は、このハックを使用できます。

class Task

    @queue = :queue_name

    def self.perform(parameters)

        pid = Process.fork do
            Task.work parameters
        end

        #puts "parent, pid #{Process.pid}, waiting on child pid #{pid}"
        Process.wait
    end

    def self.work(parameters)
        #Your perform code here
    end
end

ここで、このコードを停止したい場合は、停止したいジョブを現在実行しているresqueワーカーに連絡してください。子の子プロセスを強制終了します。労働者の孫プロセスを殺すようなもの。

説明:

ワーカーは、perform関数がコードを実行する子プロセスをフォークします。この子プロセスを直接強制終了すると、このジョブは停止しますが、失敗したジョブとしてマークされます。そのため、self.performで別の子プロセスをフォークし、performの子プロセスを強制終了すると、この実行中のジョブが停止し、失敗としてマークされません。これで、ジョブを再びキューに入れることができます。したがって、タスクは、停止する必要のある仕事をしている労働者にどのように連絡するかです(._。 ")

UNIXベースのシステム用に次のコードを書くことでこれを行うことができました。

Resque.workers.each do |worker|
    #If condition : "current worker is working and is working on the job that we want to stop and is operating on the queue that we require " and please change this condition as per your requirement          
    if worker.working? and worker.queues.include?("queue_name") and worker.job["payload"]["args"].first==post_id
            victim = %x[pgrep -P #{worker.pid}] #Getting child's PID
            victim.strip!
            victim = %x[pgrep -P #{victim}] #Getting grandchild's PID of worker
            victim.strip!
            %x[kill -9 #{victim.to_i}]
    end
end
于 2017-01-28T06:51:40.050 に答える