From a08c18eb8154ecc76dd1ad6f9576794cd769ca29 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Thu, 25 Mar 2021 16:46:18 +0000 Subject: [PATCH] db: fix ActiveStorage migration to Rails 6.1 1. Executing an `update_all` on a lot of records is slow. Instead we backfill the column in batches (without locking the table). 2. We can't mark the colum as not-null, because already running instances still using the old code will not use the service_name column yet. A later migration will backfill the remaining data and make the column non-null. --- ..._to_active_storage_blobs.active_storage.rb | 23 ++++++++++++++----- db/schema.rb | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/db/migrate/20210318090000_add_service_name_to_active_storage_blobs.active_storage.rb b/db/migrate/20210318090000_add_service_name_to_active_storage_blobs.active_storage.rb index 365bafc7f..edf231ebb 100644 --- a/db/migrate/20210318090000_add_service_name_to_active_storage_blobs.active_storage.rb +++ b/db/migrate/20210318090000_add_service_name_to_active_storage_blobs.active_storage.rb @@ -1,16 +1,27 @@ # This migration comes from active_storage (originally 20190112182829) class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0] + disable_ddl_transaction! + def up unless column_exists?(:active_storage_blobs, :service_name) add_column :active_storage_blobs, :service_name, :string + end - if (configured_service = ActiveStorage::Blob.service.name) - # rubocop:disable DS/Unscoped - ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) - # rubocop:enable DS/Unscoped + # rubocop:disable DS/Unscoped + blobs_without_service_name = ActiveStorage::Blob.unscoped.where(service_name: nil) + # rubocop:enable DS/Unscoped + + if (configured_service = ActiveStorage::Blob.service.name && blobs_without_service_name.count > 0) + # Backfill the existing blobs with the service. + # NB: during a continuous deployments, some blobs may still be created + # with an empty service_name. A later migration will fix those later. + + say_with_time('backfill ActiveStorage::Blob.service.name. This could take a while…') do + blobs_without_service_name.in_batches do |relation| + relation.update_all service_name: configured_service + sleep(0.01) # throttle + end end - - change_column :active_storage_blobs, :service_name, :string, null: false end end diff --git a/db/schema.rb b/db/schema.rb index 750d0157b..b4833672b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -44,7 +44,7 @@ ActiveRecord::Schema.define(version: 2021_03_18_090001) do t.bigint "byte_size", null: false t.string "checksum", null: false t.datetime "created_at", null: false - t.string "service_name", null: false + t.string "service_name" t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true end