online_migrations 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/docs/0.27-upgrade.md +24 -0
  4. data/docs/background_data_migrations.md +200 -101
  5. data/docs/background_schema_migrations.md +2 -2
  6. data/lib/generators/online_migrations/{background_migration_generator.rb → data_migration_generator.rb} +4 -4
  7. data/lib/generators/online_migrations/templates/change_background_data_migrations.rb.tt +34 -0
  8. data/lib/generators/online_migrations/templates/{background_data_migration.rb.tt → data_migration.rb.tt} +8 -9
  9. data/lib/generators/online_migrations/templates/initializer.rb.tt +19 -25
  10. data/lib/generators/online_migrations/templates/install_migration.rb.tt +9 -40
  11. data/lib/generators/online_migrations/upgrade_generator.rb +16 -8
  12. data/lib/online_migrations/active_record_batch_enumerator.rb +8 -0
  13. data/lib/online_migrations/background_data_migrations/backfill_column.rb +50 -0
  14. data/lib/online_migrations/background_data_migrations/config.rb +62 -0
  15. data/lib/online_migrations/{background_migrations → background_data_migrations}/copy_column.rb +15 -28
  16. data/lib/online_migrations/{background_migrations → background_data_migrations}/delete_associated_records.rb +9 -5
  17. data/lib/online_migrations/{background_migrations → background_data_migrations}/delete_orphaned_records.rb +5 -9
  18. data/lib/online_migrations/background_data_migrations/migration.rb +312 -0
  19. data/lib/online_migrations/{background_migrations → background_data_migrations}/migration_helpers.rb +72 -61
  20. data/lib/online_migrations/background_data_migrations/migration_job.rb +158 -0
  21. data/lib/online_migrations/background_data_migrations/migration_status_validator.rb +65 -0
  22. data/lib/online_migrations/{background_migrations → background_data_migrations}/perform_action_on_relation.rb +5 -5
  23. data/lib/online_migrations/{background_migrations → background_data_migrations}/reset_counters.rb +5 -5
  24. data/lib/online_migrations/background_data_migrations/scheduler.rb +78 -0
  25. data/lib/online_migrations/background_data_migrations/ticker.rb +62 -0
  26. data/lib/online_migrations/background_schema_migrations/config.rb +2 -2
  27. data/lib/online_migrations/background_schema_migrations/migration.rb +51 -123
  28. data/lib/online_migrations/background_schema_migrations/migration_helpers.rb +25 -46
  29. data/lib/online_migrations/background_schema_migrations/migration_runner.rb +43 -97
  30. data/lib/online_migrations/background_schema_migrations/scheduler.rb +2 -2
  31. data/lib/online_migrations/change_column_type_helpers.rb +3 -2
  32. data/lib/online_migrations/config.rb +4 -4
  33. data/lib/online_migrations/data_migration.rb +127 -0
  34. data/lib/online_migrations/lock_retrier.rb +5 -2
  35. data/lib/online_migrations/schema_statements.rb +1 -1
  36. data/lib/online_migrations/shard_aware.rb +44 -0
  37. data/lib/online_migrations/version.rb +1 -1
  38. data/lib/online_migrations.rb +18 -11
  39. metadata +22 -21
  40. data/lib/online_migrations/background_migration.rb +0 -64
  41. data/lib/online_migrations/background_migrations/backfill_column.rb +0 -54
  42. data/lib/online_migrations/background_migrations/background_migration_class_validator.rb +0 -29
  43. data/lib/online_migrations/background_migrations/config.rb +0 -74
  44. data/lib/online_migrations/background_migrations/migration.rb +0 -329
  45. data/lib/online_migrations/background_migrations/migration_job.rb +0 -109
  46. data/lib/online_migrations/background_migrations/migration_job_runner.rb +0 -66
  47. data/lib/online_migrations/background_migrations/migration_job_status_validator.rb +0 -29
  48. data/lib/online_migrations/background_migrations/migration_runner.rb +0 -161
  49. data/lib/online_migrations/background_migrations/migration_status_validator.rb +0 -48
  50. data/lib/online_migrations/background_migrations/scheduler.rb +0 -42
@@ -78,67 +78,46 @@ module OnlineMigrations
78
78
  # ensure_background_schema_migration_succeeded("index_users_on_email")
79
79
  #
80
80
  def ensure_background_schema_migration_succeeded(migration_name)
81
- migration = Migration.parents.find_by(migration_name: migration_name)
81
+ migrations = Migration.where(migration_name: migration_name).to_a
82
82
 
83
- if migration.nil?
84
- Utils.raise_in_prod_or_say_in_dev("Could not find background schema migration: '#{migration_name}'")
85
- elsif !migration.succeeded?
86
- raise "Expected background schema migration '#{migration_name}' to be marked as 'succeeded', " \
87
- "but it is '#{migration.status}'."
83
+ if migrations.empty?
84
+ Utils.raise_in_prod_or_say_in_dev("Could not find background schema migration(s): '#{migration_name}'.")
85
+ elsif !migrations.all?(&:succeeded?)
86
+ raise "Expected background schema migration(s) '#{migration_name}' to be marked as 'succeeded'."
88
87
  end
89
88
  end
90
89
 
91
- def enqueue_background_schema_migration(name, table_name, **options)
92
- if options[:connection_class_name].nil? && Utils.multiple_databases?
93
- raise ArgumentError, "You must pass a :connection_class_name when using multiple databases."
94
- end
95
-
96
- migration = create_background_schema_migration(name, table_name, **options)
90
+ def enqueue_background_schema_migration(migration_name, table_name, connection_class_name: nil, **options)
91
+ options.assert_valid_keys(:definition, :max_attempts, :statement_timeout)
97
92
 
98
- run_inline = OnlineMigrations.config.run_background_migrations_inline
99
- if run_inline && run_inline.call
100
- runner = MigrationRunner.new(migration)
101
- runner.run
93
+ if Utils.multiple_databases? && !connection_class_name
94
+ raise ArgumentError, "You must pass a :connection_class_name when using multiple databases."
102
95
  end
103
96
 
104
- migration
105
- end
106
-
107
- # @private
108
- def create_background_schema_migration(migration_name, table_name, connection_class_name: nil, **options)
109
- options.assert_valid_keys(:definition, :max_attempts, :statement_timeout)
110
-
111
97
  if connection_class_name
112
- connection_class_name = __normalize_connection_class_name(connection_class_name)
98
+ klass = connection_class_name.constantize
99
+ connection_class = Utils.find_connection_class(klass)
100
+ # Normalize to the real connection class name.
101
+ connection_class_name = connection_class.name
102
+ else
103
+ connection_class = ActiveRecord::Base
113
104
  end
114
105
 
115
- Migration.find_or_create_by!(migration_name: migration_name, shard: nil,
116
- connection_class_name: connection_class_name) do |migration|
117
- migration.assign_attributes(**options, table_name: table_name)
106
+ shards = Utils.shard_names(connection_class)
107
+ shards = [nil] if shards.size == 1
118
108
 
119
- shards = Utils.shard_names(migration.connection_class)
120
- if shards.size > 1
121
- migration.children = shards.map do |shard|
122
- child = migration.dup
123
- child.shard = shard
124
- child
125
- end
109
+ shards.each do |shard|
110
+ migration = Migration.create_with(**options, table_name: table_name)
111
+ .find_or_create_by!(migration_name: migration_name, shard: shard, connection_class_name: connection_class_name)
126
112
 
127
- migration.composite = true
113
+ if Utils.run_background_migrations_inline?
114
+ runner = MigrationRunner.new(migration)
115
+ runner.run
128
116
  end
129
117
  end
130
- end
131
118
 
132
- private
133
- def __normalize_connection_class_name(connection_class_name)
134
- if connection_class_name
135
- klass = connection_class_name.safe_constantize
136
- if klass
137
- connection_class = Utils.find_connection_class(klass)
138
- connection_class.name if connection_class
139
- end
140
- end
141
- end
119
+ true
120
+ end
142
121
  end
143
122
  end
144
123
  end
@@ -13,119 +13,65 @@ module OnlineMigrations
13
13
  def run
14
14
  return if migration.cancelled? || migration.succeeded?
15
15
 
16
- mark_as_running if migration.enqueued? || migration.errored?
16
+ migration.running! if migration.enqueued? || migration.errored?
17
+ migration_payload = { migration: migration }
17
18
 
18
- if migration.composite?
19
- migration.children.each do |child_migration|
20
- runner = self.class.new(child_migration)
21
- runner.run
22
- end
19
+ if migration.attempts == 0
20
+ ActiveSupport::Notifications.instrument("started.background_schema_migrations", migration_payload)
23
21
  else
24
- do_run
22
+ ActiveSupport::Notifications.instrument("retried.background_schema_migrations", migration_payload)
25
23
  end
26
- end
27
-
28
- private
29
- def mark_as_running
30
- Migration.transaction do
31
- migration.running!
32
24
 
33
- if (parent = migration.parent)
34
- if parent.started_at
35
- parent.update!(status: :running, finished_at: nil)
36
- else
37
- parent.update!(status: :running, started_at: Time.current, finished_at: nil)
38
- end
39
- end
40
- end
25
+ if should_throttle?
26
+ ActiveSupport::Notifications.instrument("throttled.background_schema_migrations", migration_payload)
27
+ return
41
28
  end
42
29
 
43
- def do_run
44
- migration_payload = notifications_payload(migration)
45
-
46
- if migration.attempts == 0
47
- ActiveSupport::Notifications.instrument("started.background_schema_migrations", migration_payload)
48
- else
49
- ActiveSupport::Notifications.instrument("retried.background_schema_migrations", migration_payload)
50
- end
51
-
52
- if should_throttle?
53
- ActiveSupport::Notifications.instrument("throttled.background_schema_migrations", migration_payload)
54
- return
55
- end
56
-
57
- migration.update!(
58
- attempts: migration.attempts + 1,
59
- status: :running,
60
- started_at: Time.current,
61
- finished_at: nil,
62
- error_class: nil,
63
- error_message: nil,
64
- backtrace: nil
65
- )
66
-
67
- ActiveSupport::Notifications.instrument("run.background_schema_migrations", migration_payload) do
68
- migration.run
69
- end
70
-
71
- # Background schema migrations could take a while to run. It is possible, that the process
72
- # never reaches this (or the rescue below) line of code. E.g., when it is force quitted
73
- # (SIGKILL etc.) and so the migration will end up in the "running" state and the query is
74
- # still executing (or already finished) in the database. This migration can either be safely
75
- # manually retried or will be picked up in the future by scheduler when it decides that
76
- # this migration is stuck.
77
-
78
- migration.update!(status: :succeeded, finished_at: Time.current)
30
+ migration.update!(
31
+ attempts: migration.attempts + 1,
32
+ status: :running,
33
+ started_at: Time.current,
34
+ finished_at: nil,
35
+ error_class: nil,
36
+ error_message: nil,
37
+ backtrace: nil
38
+ )
39
+
40
+ ActiveSupport::Notifications.instrument("run.background_schema_migrations", migration_payload) do
41
+ migration.run
42
+ end
79
43
 
80
- ActiveSupport::Notifications.instrument("completed.background_schema_migrations", migration_payload)
44
+ # Background schema migrations could take a while to run. It is possible, that the process
45
+ # never reaches this (or the rescue below) line of code. E.g., when it is force quitted
46
+ # (SIGKILL etc.) and so the migration will end up in the "running" state and the query is
47
+ # still executing (or already finished) in the database. This migration can either be safely
48
+ # manually retried or will be picked up in the future by scheduler when it decides that
49
+ # this migration is stuck.
81
50
 
82
- complete_parent_if_needed(migration) if migration.parent.present?
83
- rescue Exception => e # rubocop:disable Lint/RescueException
84
- backtrace_cleaner = ::OnlineMigrations.config.backtrace_cleaner
51
+ migration.update!(status: :succeeded, finished_at: Time.current)
85
52
 
86
- status = migration.attempts_exceeded? ? :failed : :errored
53
+ ActiveSupport::Notifications.instrument("completed.background_schema_migrations", migration_payload)
54
+ rescue Exception => e # rubocop:disable Lint/RescueException
55
+ backtrace_cleaner = ::OnlineMigrations.config.backtrace_cleaner
87
56
 
88
- migration.update!(
89
- status: status,
90
- finished_at: Time.current,
91
- error_class: e.class.name,
92
- error_message: e.message,
93
- backtrace: backtrace_cleaner ? backtrace_cleaner.clean(e.backtrace) : e.backtrace
94
- )
57
+ status = migration.attempts_exceeded? ? :failed : :errored
95
58
 
96
- complete_parent_if_needed(migration) if migration.parent.present?
59
+ migration.update!(
60
+ status: status,
61
+ finished_at: Time.current,
62
+ error_class: e.class.name,
63
+ error_message: e.message,
64
+ backtrace: backtrace_cleaner ? backtrace_cleaner.clean(e.backtrace) : e.backtrace
65
+ )
97
66
 
98
- ::OnlineMigrations.config.background_schema_migrations.error_handler.call(e, migration)
99
- raise if Utils.run_background_migrations_inline?
100
- end
67
+ ::OnlineMigrations.config.background_schema_migrations.error_handler.call(e, migration)
68
+ raise if Utils.run_background_migrations_inline?
69
+ end
101
70
 
71
+ private
102
72
  def should_throttle?
103
73
  ::OnlineMigrations.config.throttler.call
104
74
  end
105
-
106
- def complete_parent_if_needed(migration)
107
- parent = migration.parent
108
- completed = false
109
-
110
- parent.with_lock do
111
- children = parent.children.select(:status)
112
- if children.all?(&:succeeded?)
113
- parent.update!(status: :succeeded, finished_at: Time.current)
114
- completed = true
115
- elsif children.any?(&:failed?)
116
- parent.update!(status: :failed, finished_at: Time.current)
117
- completed = true
118
- end
119
- end
120
-
121
- if completed
122
- ActiveSupport::Notifications.instrument("completed.background_migrations", notifications_payload(migration))
123
- end
124
- end
125
-
126
- def notifications_payload(migration)
127
- { background_schema_migration: migration }
128
- end
129
75
  end
130
76
  end
131
77
  end
@@ -35,8 +35,8 @@ module OnlineMigrations
35
35
 
36
36
  private
37
37
  def find_migration(**options)
38
- active_migrations = Migration.running.reject(&:stuck?)
39
- runnable_migrations = Migration.runnable.enqueued.queue_order.to_a + Migration.retriable.queue_order.to_a
38
+ stuck_migrations, active_migrations = Migration.running.partition(&:stuck?)
39
+ runnable_migrations = (Migration.enqueued + Migration.errored + stuck_migrations).sort_by(&:created_at)
40
40
 
41
41
  if options.key?(:shard)
42
42
  runnable_migrations = runnable_migrations.select { |migration| migration.shard.to_s == options[:shard].to_s }
@@ -477,10 +477,11 @@ module OnlineMigrations
477
477
  end
478
478
 
479
479
  def __copy_check_constraints(table_name, from_column, to_column)
480
- check_constraints = check_constraints(table_name).select { |c| c.expression.include?(from_column) }
480
+ from_column_re = /\b#{from_column}\b/
481
+ check_constraints = check_constraints(table_name).select { |c| c.expression.match?(from_column_re) }
481
482
 
482
483
  check_constraints.each do |check|
483
- new_expression = check.expression.gsub(from_column, to_column)
484
+ new_expression = check.expression.gsub(from_column_re, to_column)
484
485
 
485
486
  add_check_constraint(table_name, new_expression, validate: false)
486
487
 
@@ -210,10 +210,10 @@ module OnlineMigrations
210
210
 
211
211
  # Configuration object to configure background migrations
212
212
  #
213
- # @return [BackgroundMigrationsConfig]
214
- # @see BackgroundMigrationsConfig
213
+ # @return [BackgroundDataMigrations::Config]
214
+ # @see BackgroundDataMigrations::Config
215
215
  #
216
- attr_reader :background_migrations
216
+ attr_reader :background_data_migrations
217
217
 
218
218
  attr_reader :background_schema_migrations
219
219
 
@@ -230,7 +230,7 @@ module OnlineMigrations
230
230
  lock_timeout: 0.2.seconds
231
231
  )
232
232
 
233
- @background_migrations = BackgroundMigrations::Config.new
233
+ @background_data_migrations = BackgroundDataMigrations::Config.new
234
234
  @background_schema_migrations = BackgroundSchemaMigrations::Config.new
235
235
 
236
236
  @checks = []
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem "sidekiq", ">= 7.3.3"
4
+ require "sidekiq"
5
+
6
+ module OnlineMigrations
7
+ # Base class that is inherited by the host application's data migration classes.
8
+ class DataMigration
9
+ class NotFoundError < NameError; end
10
+
11
+ class << self
12
+ # Finds a Data Migration with the given name.
13
+ #
14
+ # @param name [String] the name of the Data Migration to be found.
15
+ #
16
+ # @return [DataMigration] the Data Migration with the given name.
17
+ #
18
+ # @raise [NotFoundError] if a Data Migration with the given name does not exist.
19
+ #
20
+ def named(name)
21
+ namespace = OnlineMigrations.config.background_data_migrations.migrations_module.constantize
22
+ internal_namespace = ::OnlineMigrations::BackgroundDataMigrations
23
+
24
+ migration = "#{namespace}::#{name}".safe_constantize ||
25
+ "#{internal_namespace}::#{name}".safe_constantize
26
+
27
+ raise NotFoundError.new("Data Migration #{name} not found", name) if migration.nil?
28
+ if !(migration.is_a?(Class) && migration < self)
29
+ raise NotFoundError.new("#{name} is not a Data Migration", name)
30
+ end
31
+
32
+ migration
33
+ end
34
+
35
+ # @private
36
+ attr_accessor :active_record_enumerator_batch_size
37
+
38
+ # Limit the number of records that will be fetched in a single query when
39
+ # iterating over an Active Record collection migration.
40
+ #
41
+ # @param size [Integer] the number of records to fetch in a single query.
42
+ #
43
+ def collection_batch_size(size)
44
+ self.active_record_enumerator_batch_size = size
45
+ end
46
+ end
47
+
48
+ # A hook to override that will be called when the migration starts running.
49
+ #
50
+ def after_start
51
+ end
52
+
53
+ # A hook to override that will be called around 'process' each time.
54
+ #
55
+ # Can be useful for some metrics collection, performance tracking etc.
56
+ #
57
+ def around_process
58
+ yield
59
+ end
60
+
61
+ # A hook to override that will be called when the migration resumes its work.
62
+ #
63
+ def after_resume
64
+ end
65
+
66
+ # A hook to override that will be called each time the migration is interrupted.
67
+ #
68
+ # This can be due to interruption or sidekiq stopping.
69
+ #
70
+ def after_stop
71
+ end
72
+
73
+ # A hook to override that will be called when the migration finished its work.
74
+ #
75
+ def after_complete
76
+ end
77
+
78
+ # A hook to override that will be called when the migration is paused.
79
+ #
80
+ def after_pause
81
+ end
82
+
83
+ # A hook to override that will be called when the migration is cancelled.
84
+ #
85
+ def after_cancel
86
+ end
87
+
88
+ # The collection to be processed.
89
+ #
90
+ # @return [ActiveRecord::Relation, ActiveRecord::Batches::BatchEnumerator, Array, Enumerator]
91
+ #
92
+ # @raise [NotImplementedError] with a message advising subclasses to override this method.
93
+ #
94
+ def collection
95
+ raise NotImplementedError, "#{self.class.name} must implement a 'collection' method"
96
+ end
97
+
98
+ # The action to be performed on each item from the collection.
99
+ #
100
+ # @param _item the current item from the collection being iterated
101
+ # @raise [NotImplementedError] with a message advising subclasses to override this method.
102
+ #
103
+ def process(_item)
104
+ raise NotImplementedError, "#{self.class.name} must implement a 'process' method"
105
+ end
106
+
107
+ # Total count of iterations to be performed (optional, to be able to show progress).
108
+ #
109
+ # @return [Integer, nil]
110
+ #
111
+ def count
112
+ end
113
+
114
+ # Enumerator builder. You may override this method to return any Enumerator yielding
115
+ # pairs of `[item, item_cursor]`, instead of using `collection`.
116
+ #
117
+ # It is useful when it is not practical or impossible to define an explicit collection
118
+ # in the `collection` method.
119
+ #
120
+ # @param cursor [Object, nil] cursor position to resume from, or nil on initial call.
121
+ #
122
+ # @return [Enumerator]
123
+ #
124
+ def build_enumerator(cursor:)
125
+ end
126
+ end
127
+ end
@@ -91,10 +91,13 @@ module OnlineMigrations
91
91
  else
92
92
  yield
93
93
  end
94
- rescue ActiveRecord::LockWaitTimeout
94
+ rescue ActiveRecord::LockWaitTimeout, ActiveRecord::Deadlocked => e
95
95
  if current_attempt <= attempts
96
96
  current_delay = delay(current_attempt)
97
- Utils.say("Lock timeout. Retrying in #{current_delay} seconds...")
97
+
98
+ problem = e.is_a?(ActiveRecord::Deadlocked) ? "Deadlock detected." : "Lock timeout."
99
+ Utils.say("#{problem} Retrying in #{current_delay} seconds...")
100
+
98
101
  sleep(current_delay)
99
102
  retry
100
103
  end
@@ -3,7 +3,7 @@
3
3
  module OnlineMigrations
4
4
  module SchemaStatements
5
5
  include ChangeColumnTypeHelpers
6
- include BackgroundMigrations::MigrationHelpers
6
+ include BackgroundDataMigrations::MigrationHelpers
7
7
  include BackgroundSchemaMigrations::MigrationHelpers
8
8
 
9
9
  # Updates the value of a column in batches.
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlineMigrations
4
+ module ShardAware
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ before_validation :set_connection_class_name
9
+ end
10
+
11
+ def on_shard_if_present(&block)
12
+ if shard
13
+ connection_class.connected_to(shard: shard.to_sym, role: :writing, &block)
14
+ else
15
+ yield
16
+ end
17
+ end
18
+
19
+ def connection_class_name=(value)
20
+ if value && (klass = value.safe_constantize)
21
+ if !(klass <= ActiveRecord::Base)
22
+ raise ArgumentError, "connection_class_name is not an ActiveRecord::Base child class"
23
+ end
24
+
25
+ connection_class = Utils.find_connection_class(klass)
26
+ super(connection_class.name)
27
+ end
28
+ end
29
+
30
+ # @private
31
+ def connection_class
32
+ if connection_class_name && (klass = connection_class_name.safe_constantize)
33
+ Utils.find_connection_class(klass)
34
+ else
35
+ ActiveRecord::Base
36
+ end
37
+ end
38
+
39
+ private
40
+ def set_connection_class_name
41
+ self.connection_class_name ||= "ActiveRecord::Base"
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OnlineMigrations
4
- VERSION = "0.26.0"
4
+ VERSION = "0.27.0"
5
5
  end
@@ -6,7 +6,8 @@ require "online_migrations/version"
6
6
  require "online_migrations/utils"
7
7
  require "online_migrations/background_schema_migrations/migration_helpers"
8
8
  require "online_migrations/change_column_type_helpers"
9
- require "online_migrations/background_migrations/migration_helpers"
9
+ require "online_migrations/background_data_migrations/migration_helpers"
10
+ require "online_migrations/active_record_batch_enumerator"
10
11
  require "online_migrations/schema_statements"
11
12
  require "online_migrations/schema_cache"
12
13
  require "online_migrations/migration"
@@ -29,7 +30,8 @@ module OnlineMigrations
29
30
  autoload :ForeignKeysCollector
30
31
  autoload :IndexDefinition
31
32
  autoload :CommandChecker
32
- autoload :BackgroundMigration
33
+ autoload :DataMigration
34
+ autoload :ShardAware
33
35
 
34
36
  autoload_at "online_migrations/lock_retrier" do
35
37
  autoload :LockRetrier
@@ -40,24 +42,21 @@ module OnlineMigrations
40
42
 
41
43
  autoload :CopyTrigger
42
44
 
43
- module BackgroundMigrations
45
+ module BackgroundDataMigrations
44
46
  extend ActiveSupport::Autoload
45
47
 
46
48
  autoload :Config
47
49
  autoload :MigrationStatusValidator
48
- autoload :MigrationJobStatusValidator
49
- autoload :BackgroundMigrationClassValidator
50
50
  autoload :BackfillColumn
51
51
  autoload :CopyColumn
52
52
  autoload :DeleteAssociatedRecords
53
53
  autoload :DeleteOrphanedRecords
54
54
  autoload :PerformActionOnRelation
55
55
  autoload :ResetCounters
56
- autoload :MigrationJob
57
56
  autoload :Migration
58
- autoload :MigrationJobRunner
59
- autoload :MigrationRunner
57
+ autoload :MigrationJob
60
58
  autoload :Scheduler
59
+ autoload :Ticker
61
60
  end
62
61
 
63
62
  module BackgroundSchemaMigrations
@@ -70,6 +69,10 @@ module OnlineMigrations
70
69
  autoload :Scheduler
71
70
  end
72
71
 
72
+ # Make aliases for less typing.
73
+ DataMigrations = BackgroundDataMigrations
74
+ SchemaMigrations = BackgroundSchemaMigrations
75
+
73
76
  class << self
74
77
  # @private
75
78
  attr_accessor :current_migration
@@ -87,10 +90,10 @@ module OnlineMigrations
87
90
  # @option options [String, Symbol, nil] :shard The name of the shard to run
88
91
  # background data migrations on. By default runs on all shards.
89
92
  #
90
- def run_background_migrations(**options)
91
- BackgroundMigrations::Scheduler.run(**options)
93
+ def run_background_data_migrations(**options)
94
+ BackgroundDataMigrations::Scheduler.run(**options)
92
95
  end
93
- alias run_background_data_migrations run_background_migrations
96
+ alias run_background_migrations run_background_data_migrations
94
97
 
95
98
  # Run background schema migrations
96
99
  #
@@ -122,6 +125,10 @@ module OnlineMigrations
122
125
  else
123
126
  ActiveRecord::ConnectionAdapters::SchemaCache.prepend(OnlineMigrations::SchemaCache)
124
127
  end
128
+
129
+ if !ActiveRecord::Batches::BatchEnumerator.method_defined?(:use_ranges)
130
+ ActiveRecord::Batches::BatchEnumerator.include(OnlineMigrations::ActiveRecordBatchEnumerator)
131
+ end
125
132
  end
126
133
  end
127
134
  end