0

I have one simple rake task that execute some action per user. Something like these:

task users_actions: :environment do ||
    User.all.each { |u|
        # Some actions here
    }
end

The problem it's that it doesn't start with the next user until it finished one. What I want is to execute these in parallel. How can I do that? It's even posible?

Thanks,

Victor
  • 995
  • 1
  • 10
  • 26
  • 1
    Very good answer here: http://stackoverflow.com/questions/56087/does-ruby-have-real-multithreading – Jeremiah Oct 21 '14 at 14:34

1 Answers1

4

If there was a good library available, it would be better to use it rather than implementing everything from scratch. concurrent-ruby has all kinds of utility classes for writing concurrent code, but I'm not sure if they have something suitable for this use case; anyways, I'll show you how to do it from scratch.

First pull in the thread library:

require 'thread'

Make a thread-safe queue, and stick all the users on it:

queue = Queue.new
User.all.each { |user| queue << user }

Start some number of worker threads, and make them process items from the queue until all are done.

threads = 5.times.collect do
  Thread.new do
    while true
      user = queue.pop(true) rescue break
      # do something with the user
      # this had better be thread-safe, or you will live to regret it!
    end
  end
end

Then wait until all the threads finish:

threads.each(&:join)

Again, please make sure that the code which processes each user is thread-safe! The power of multi-threading is in your hands, don't abuse it!

NOTE: If your user-processing code is very CPU-intensive, you might consider running this on Rubinius or JRuby, so that more than one thread can run Ruby code at the same time.

Alex D
  • 29,755
  • 7
  • 80
  • 126
  • While this answer would probably speed up processing using concurrency, it does not provide true parallelism. – Jeremiah Oct 21 '14 at 14:43
  • @Jeremiah, that depends. If you run under JRuby or RBX, it definitely does. – Alex D Oct 21 '14 at 14:49
  • You're absolutely correct sir, I was assuming MRI. Edit? – Jeremiah Oct 21 '14 at 14:57
  • These usually ends on a "Circular dependency detected while autoloading Setting." (Setting is one module name) How can I fix these? – Victor Oct 23 '14 at 13:09
  • @Victor, that has nothing to do with this. That error means that you have a file somewhere which uses `Setting`, but `setting.rb` loads or requires the very same file. – Alex D Oct 23 '14 at 14:06