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 bcaff67
Showing 1 changed file with 13 additions and 6 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

0 comments on commit bcaff67

Please sign in to comment.