Skip to content

Commit

Permalink
Update migration tasks with batch limit
Browse files Browse the repository at this point in the history
When running the tasks on large DBs it makes sense to limit the
number of records updated on each transaction in order to avoid
locking the records (or the whole table) for too long.

The default batch size is 100'000 and it can be overridden by
passing a different value when invoking the tasks. For example,
this will set the batch size to 1000 rows:

rake solidus:migrations:migrate_default_billing_addresses_to_address_book:up[1000]
  • Loading branch information
spaghetticode committed Jun 18, 2021
1 parent ac3a2f8 commit 45c364b
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@
namespace :solidus do
namespace :migrations do
namespace :migrate_default_billing_addresses_to_address_book do
task up: :environment do
print "Migrating default billing addresses to address book ... "
task :up, [:batch_size] => [:environment] do |_t, args|
batch_size = args[:batch_size] || 100_000
print "Migrating default billing addresses to address book in batches of #{batch_size} ... "
if Spree::UserAddress.where(default_billing: true).any?
Spree.user_class.joins(:bill_address).update_all(bill_address_id: nil) # rubocop:disable Rails/SkipsModelValidations
Spree.user_class.joins(:bill_address).in_batches(of: batch_size).each do |batch|
batch.update_all(bill_address_id: nil) # rubocop:disable Rails/SkipsModelValidations
end
end
Spree::UserAddress.joins(
<<~SQL
JOIN spree_users ON spree_user_addresses.user_id = spree_users.id
AND spree_user_addresses.address_id = spree_users.bill_address_id
SQL
).update_all(default_billing: true)
).in_batches(of: batch_size).each do |batch|
batch.update_all(default_billing: true) # rubocop:disable Rails/SkipsModelValidations
end

puts "Success"
end

task down: :environment do
Spree::UserAddress.update_all(default_billing: false) # rubocop:disable Rails/SkipsModelValidations
task :down, [:batch_size] => [:environment] do |_t, args|
batch_size = args[:batch_size] || 100_000
Spree::UserAddress.in_batches(of: batch_size).update_all(default_billing: false) # rubocop:disable Rails/SkipsModelValidations
puts "Rolled back default billing address migration to address book"
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

it 'runs' do
expect { task.invoke }.to output(
"Migrating default billing addresses to address book ... Success\n"
"Migrating default billing addresses to address book in batches of 100000 ... Success\n"
).to_stdout
end

Expand Down Expand Up @@ -63,7 +63,7 @@

it 'runs' do
expect { task.invoke }.to output(
"Migrating default billing addresses to address book ... Success\n"
"Migrating default billing addresses to address book in batches of 100000 ... Success\n"
).to_stdout
end

Expand Down

0 comments on commit 45c364b

Please sign in to comment.