Skip to content

Instantly share code, notes, and snippets.

@endzyme
Last active March 31, 2016 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save endzyme/1a5294b16044c869b582bd52b17fce6d to your computer and use it in GitHub Desktop.
Save endzyme/1a5294b16044c869b582bd52b17fce6d to your computer and use it in GitHub Desktop.
very hacky rake semaphore to enable multithreading data migrations in rake tasks
namespace :semaphore do
desc "Basic Semaphore Task"
task :my_task_name => :environment do
# Build list of running threads
@threads = []
@max_threads = 3
# Setup Rails Config to allow concurrency (prelaoding env for models)
Rails.configuration.threadsafe!
Rails.configuration.dependency_loading = true
model_relation = MyModel.where(thing: 'this')
puts model_relation
def thread_work_task(batch)
@threads << Thread.new do
batch.each do |item|
# do my fancy item work with full rails env loaded
item.sometask if item.persisted? # or whatever
AnotherModel.where(my_model_id: item.id).each do |another_model|
another_model.some_method
end
end
@threads.delete Thread.current
end
end
def can_proceed?
if @threads.count >= @max_threads
puts "Sleeping 3 seconds because threads: #{@threads.count}"
p @threads
sleep(3)
return false
end
true
end
model_relation.find_in_batches(batch_size: 1000) do |batch|
# This is where you define how many concurrent threads
# This count must be lower than your total database conn max
redo unless can_proceed?
puts "working batch size #{batch.count}"
thread_work_task(batch)
end
# let's join the last tasks and wait for them to finish
@threads.each &:join
puts "FINISHED"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment