在ruby中并行运行脚本

时间:2015-12-16 13:26:28

标签: ruby-on-rails ruby multithreading ruby-on-rails-4

我需要转换4个帖子中的视频

例如我有Active Record模型带标题的视频:Video1,Video2,Video3,Video4,Video5

所以,我需要执行类似这样的事情

bundle exec script/video_converter start

其中脚本将处理4个线程的未转换视频,例如

Video.where(state: 'unconverted').first.process

但如果转换了4个视频中的一个,则必须自动将下一个视频添加到帖子

最佳解决方案是什么? Sidekiq宝石? Daemons gem + Ruby Threads手动?

现在我正在使用这个脚本:

THREAD_COUNT = 4
SLEEP_TIME = 5
logger = CONVERTATION_LOG
spawns = []
loop do
  videos = Video.where(state:'unconverted').limit(THREAD_COUNT).reorder("ID DESC")
  videos.each do |video|
    spawns << Spawnling.new do
      result = video.process
      if result.nil?
        video.create_thumbnail!
      else
        video.failured!
      end
    end
  end
  Spawnling.wait(spawns)
  sleep(SLEEP_TIME)
end

但是这个脚本会等待4个视频,之后需要另外4个视频。我希望,在第4个视频转换之后,它会自动添加到新线程中,这是空的。

1 个答案:

答案 0 :(得分:1)

如果您的目标是仅使用4个线程(或者任何Spawnling配置使用它 - 因为它支持fork和thread)继续处理视频,那么,您可以使用Queue对所有视频记录进行排队要处理,产生4个线程,让它们一个接一个地处理记录,直到队列为空。

require "rails"
require "spawnling"

# In your case, videos are read from DB, below array is for illustration
videos = ["v1", "v2", "v3", "v4", "v5", "v6", "..."]


THREAD_COUNT = 4

spawns = []

q = Queue.new 

videos.each {|i| q.push(i) }

THREAD_COUNT.times do
  spawns << Spawnling.new do
    until q.empty? do
      v = q.pop

      # simulate processing
      puts "Processing video #{v}"

      # simulate processing time
      sleep(rand(10))
    end
  end
end

Spawnling.wait(spawns)

这个答案的灵感来自this answer

PS:我添加了一些需求和定义的videos数组,以使上面的代码成为自包含的运行示例。