online_migrations 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +10 -6
  4. data/docs/{background_migrations.md → background_data_migrations.md} +4 -33
  5. data/docs/background_schema_migrations.md +163 -0
  6. data/docs/configuring.md +30 -1
  7. data/lib/generators/online_migrations/templates/create_background_schema_migrations.rb.tt +29 -0
  8. data/lib/generators/online_migrations/templates/initializer.rb.tt +24 -11
  9. data/lib/generators/online_migrations/templates/install_migration.rb.tt +24 -0
  10. data/lib/generators/online_migrations/upgrade_generator.rb +5 -0
  11. data/lib/online_migrations/application_record.rb +11 -0
  12. data/lib/online_migrations/background_migrations/config.rb +27 -24
  13. data/lib/online_migrations/background_migrations/migration.rb +1 -8
  14. data/lib/online_migrations/background_migrations/migration_job_runner.rb +1 -1
  15. data/lib/online_migrations/background_migrations/migration_runner.rb +1 -1
  16. data/lib/online_migrations/background_schema_migrations/config.rb +40 -0
  17. data/lib/online_migrations/background_schema_migrations/migration.rb +205 -0
  18. data/lib/online_migrations/background_schema_migrations/migration_helpers.rb +76 -0
  19. data/lib/online_migrations/background_schema_migrations/migration_runner.rb +110 -0
  20. data/lib/online_migrations/background_schema_migrations/migration_status_validator.rb +33 -0
  21. data/lib/online_migrations/background_schema_migrations/scheduler.rb +30 -0
  22. data/lib/online_migrations/config.rb +32 -0
  23. data/lib/online_migrations/schema_statements.rb +1 -0
  24. data/lib/online_migrations/utils.rb +7 -0
  25. data/lib/online_migrations/version.rb +1 -1
  26. data/lib/online_migrations.rb +19 -2
  27. metadata +12 -4
  28. data/lib/online_migrations/background_migrations/application_record.rb +0 -13
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlineMigrations
4
+ module BackgroundSchemaMigrations
5
+ # Class representing background schema migration.
6
+ #
7
+ # @note The records of this class should not be created manually, but via
8
+ # `enqueue_background_schema_migration` helper inside migrations.
9
+ #
10
+ class Migration < ApplicationRecord
11
+ STATUSES = [
12
+ :enqueued, # The migration has been enqueued by the user.
13
+ :running, # The migration is being performed by a migration executor.
14
+ :failed, # The migration raises an exception when running.
15
+ :succeeded, # The migration finished without error.
16
+ ]
17
+
18
+ MAX_IDENTIFIER_LENGTH = 63
19
+
20
+ self.table_name = :background_schema_migrations
21
+
22
+ scope :queue_order, -> { order(created_at: :asc) }
23
+ scope :runnable, -> { where(composite: false) }
24
+ scope :active, -> { where(status: [statuses[:enqueued], statuses[:running]]) }
25
+ scope :except_succeeded, -> { where.not(status: :succeeded) }
26
+
27
+ scope :stuck, -> do
28
+ runnable.active.where(<<~SQL)
29
+ updated_at <= NOW() - interval '1 second' * (COALESCE(statement_timeout, 60*60*24) + 60*10)
30
+ SQL
31
+ end
32
+
33
+ scope :retriable, -> do
34
+ failed_retriable = runnable.failed.where("attempts < max_attempts")
35
+
36
+ stuck_sql = connection.unprepared_statement { stuck.to_sql }
37
+ failed_retriable_sql = connection.unprepared_statement { failed_retriable.to_sql }
38
+
39
+ from(Arel.sql(<<~SQL))
40
+ (
41
+ (#{failed_retriable_sql})
42
+ UNION
43
+ (#{stuck_sql})
44
+ ) AS #{table_name}
45
+ SQL
46
+ end
47
+
48
+ alias_attribute :name, :migration_name
49
+
50
+ # Avoid deprecation warnings.
51
+ if Utils.ar_version >= 7
52
+ enum :status, STATUSES.index_with(&:to_s)
53
+ else
54
+ enum status: STATUSES.index_with(&:to_s)
55
+ end
56
+
57
+ belongs_to :parent, class_name: name, optional: true
58
+ has_many :children, class_name: name, foreign_key: :parent_id
59
+
60
+ validates :migration_name, presence: true, uniqueness: { scope: :shard }
61
+ validates :table_name, presence: true, length: { maximum: MAX_IDENTIFIER_LENGTH }
62
+ validates :definition, presence: true
63
+
64
+ validate :validate_children_statuses, if: -> { composite? && status_changed? }
65
+ validate :validate_connection_class, if: :connection_class_name?
66
+ validate :validate_table_exists
67
+ validates_with MigrationStatusValidator, on: :update
68
+
69
+ before_validation :set_defaults
70
+
71
+ def completed?
72
+ succeeded? || failed?
73
+ end
74
+
75
+ # Returns the progress of the background schema migration.
76
+ #
77
+ # @return [Float] value in range from 0.0 to 100.0
78
+ #
79
+ def progress
80
+ if succeeded?
81
+ 100.0
82
+ elsif composite?
83
+ progresses = children.map(&:progress)
84
+ (progresses.sum.to_f / progresses.size).round(2)
85
+ else
86
+ 0.0
87
+ end
88
+ end
89
+
90
+ # Mark this migration as ready to be processed again.
91
+ #
92
+ # This is used to manually retrying failed migrations.
93
+ #
94
+ def retry
95
+ if composite?
96
+ children.failed.each(&:retry)
97
+ elsif failed?
98
+ update!(
99
+ status: self.class.statuses[:enqueued],
100
+ attempts: 0,
101
+ started_at: nil,
102
+ finished_at: nil,
103
+ error_class: nil,
104
+ error_message: nil,
105
+ backtrace: nil
106
+ )
107
+ end
108
+ end
109
+
110
+ # @private
111
+ def connection_class
112
+ if connection_class_name && (klass = connection_class_name.safe_constantize)
113
+ Utils.find_connection_class(klass)
114
+ else
115
+ ActiveRecord::Base
116
+ end
117
+ end
118
+
119
+ # @private
120
+ def attempts_exceeded?
121
+ attempts >= max_attempts
122
+ end
123
+
124
+ # @private
125
+ def run
126
+ on_shard do
127
+ connection = connection_class.connection
128
+
129
+ connection.with_lock_retries do
130
+ statement_timeout = self.statement_timeout || OnlineMigrations.config.statement_timeout
131
+
132
+ with_statement_timeout(connection, statement_timeout) do
133
+ case definition
134
+ when /create (unique )?index/i
135
+ index = connection.indexes(table_name).find { |i| i.name == name }
136
+ if index
137
+ # Use index validity from https://github.com/rails/rails/pull/45160
138
+ # when switching to ActiveRecord >= 7.1.
139
+ schema = connection.send(:__schema_for_table, table_name)
140
+ if connection.send(:__index_valid?, name, schema: schema)
141
+ return
142
+ else
143
+ connection.remove_index(table_name, name: name)
144
+ end
145
+ end
146
+ end
147
+
148
+ connection.execute(definition)
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ private
155
+ def validate_children_statuses
156
+ if composite?
157
+ if succeeded? && children.except_succeeded.exists?
158
+ errors.add(:base, "all child migrations must be succeeded")
159
+ elsif failed? && !children.failed.exists?
160
+ errors.add(:base, "at least one child migration must be failed")
161
+ end
162
+ end
163
+ end
164
+
165
+ def validate_connection_class
166
+ klass = connection_class_name.safe_constantize
167
+ if !(klass < ActiveRecord::Base)
168
+ errors.add(:connection_class_name, "is not an ActiveRecord::Base child class")
169
+ end
170
+ end
171
+
172
+ def validate_table_exists
173
+ # Skip this validation if we have invalid connection class name.
174
+ return if errors.include?(:connection_class_name)
175
+
176
+ on_shard do
177
+ if !connection_class.connection.table_exists?(table_name)
178
+ errors.add(:table_name, "'#{table_name}' does not exist")
179
+ end
180
+ end
181
+ end
182
+
183
+ def set_defaults
184
+ config = ::OnlineMigrations.config.background_schema_migrations
185
+ self.max_attempts ||= config.max_attempts
186
+ self.statement_timeout ||= config.statement_timeout
187
+ end
188
+
189
+ def on_shard(&block)
190
+ shard = (self.shard || connection_class.default_shard).to_sym
191
+ connection_class.connected_to(shard: shard, role: :writing, &block)
192
+ end
193
+
194
+ def with_statement_timeout(connection, timeout)
195
+ return yield if timeout.nil?
196
+
197
+ prev_value = connection.select_value("SHOW statement_timeout")
198
+ connection.execute("SET statement_timeout TO #{connection.quote(timeout.in_milliseconds)}")
199
+ yield
200
+ ensure
201
+ connection.execute("SET statement_timeout TO #{connection.quote(prev_value)}")
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlineMigrations
4
+ module BackgroundSchemaMigrations
5
+ module MigrationHelpers
6
+ def add_index_in_background(table_name, column_name, **options)
7
+ migration_options = options.extract!(:max_attempts, :statement_timeout, :connection_class_name)
8
+
9
+ if index_exists?(table_name, column_name, **options)
10
+ Utils.say("Index creation was not enqueued because the index already exists.")
11
+ return
12
+ end
13
+
14
+ options[:algorithm] = :concurrently
15
+ index, algorithm, if_not_exists = add_index_options(table_name, column_name, **options)
16
+
17
+ create_index = ActiveRecord::ConnectionAdapters::CreateIndexDefinition.new(index, algorithm, if_not_exists)
18
+ schema_creation = ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaCreation.new(self)
19
+ definition = schema_creation.accept(create_index)
20
+
21
+ enqueue_background_schema_migration(index.name, table_name, definition: definition, **migration_options)
22
+ end
23
+
24
+ def remove_index_in_background(table_name, column_name = nil, name:, **options)
25
+ raise ArgumentError, "Index name must be specified" if name.blank?
26
+
27
+ migration_options = options.extract!(:max_attempts, :statement_timeout, :connection_class_name)
28
+
29
+ if !index_exists?(table_name, column_name, **options, name: name)
30
+ Utils.say("Index deletion was not enqueued because the index does not exist.")
31
+ return
32
+ end
33
+
34
+ definition = "DROP INDEX CONCURRENTLY IF EXISTS #{quote_column_name(name)}"
35
+ enqueue_background_schema_migration(name, table_name, definition: definition, **migration_options)
36
+ end
37
+
38
+ def enqueue_background_schema_migration(name, table_name, **options)
39
+ if options[:connection_class_name].nil? && Utils.multiple_databases?
40
+ raise ArgumentError, "You must pass a :connection_class_name when using multiple databases."
41
+ end
42
+
43
+ migration = create_background_schema_migration(name, table_name, **options)
44
+
45
+ run_inline = OnlineMigrations.config.run_background_migrations_inline
46
+ if run_inline && run_inline.call
47
+ runner = MigrationRunner.new(migration)
48
+ runner.run
49
+ end
50
+
51
+ migration
52
+ end
53
+
54
+ # @private
55
+ def create_background_schema_migration(migration_name, table_name, **options)
56
+ options.assert_valid_keys(:definition, :max_attempts, :statement_timeout, :connection_class_name)
57
+ migration = Migration.new(migration_name: migration_name, table_name: table_name, **options)
58
+
59
+ shards = Utils.shard_names(migration.connection_class)
60
+ if shards.size > 1
61
+ migration.children = shards.map do |shard|
62
+ child = migration.dup
63
+ child.shard = shard
64
+ child
65
+ end
66
+
67
+ migration.composite = true
68
+ end
69
+
70
+ # This will save all the records using a transaction.
71
+ migration.save!
72
+ migration
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlineMigrations
4
+ module BackgroundSchemaMigrations
5
+ # Runs single background schema migration.
6
+ class MigrationRunner
7
+ attr_reader :migration
8
+
9
+ def initialize(migration)
10
+ @migration = migration
11
+ end
12
+
13
+ def run
14
+ mark_as_running if migration.enqueued? || migration.failed?
15
+
16
+ if migration.composite?
17
+ migration.children.each do |child_migration|
18
+ runner = self.class.new(child_migration)
19
+ runner.run
20
+ end
21
+ else
22
+ do_run
23
+ end
24
+ end
25
+
26
+ private
27
+ def mark_as_running
28
+ Migration.transaction do
29
+ migration.running!
30
+ migration.parent.running! if migration.parent
31
+ end
32
+ end
33
+
34
+ def do_run
35
+ migration_payload = notifications_payload(migration)
36
+
37
+ if migration.attempts == 0
38
+ ActiveSupport::Notifications.instrument("started.background_schema_migrations", migration_payload)
39
+ else
40
+ ActiveSupport::Notifications.instrument("retried.background_schema_migrations", migration_payload)
41
+ end
42
+
43
+ if should_throttle?
44
+ ActiveSupport::Notifications.instrument("throttled.background_schema_migrations", migration_payload)
45
+ return
46
+ end
47
+
48
+ migration.update!(
49
+ attempts: migration.attempts + 1,
50
+ status: :running,
51
+ started_at: Time.current,
52
+ finished_at: nil,
53
+ error_class: nil,
54
+ error_message: nil,
55
+ backtrace: nil
56
+ )
57
+
58
+ ActiveSupport::Notifications.instrument("run.background_schema_migrations", migration_payload) do
59
+ migration.run
60
+ end
61
+
62
+ migration.update!(status: :succeeded, finished_at: Time.current)
63
+
64
+ ActiveSupport::Notifications.instrument("completed.background_schema_migrations", migration_payload)
65
+
66
+ complete_parent_if_needed(migration) if migration.parent.present?
67
+ rescue Exception => e # rubocop:disable Lint/RescueException
68
+ backtrace_cleaner = ::OnlineMigrations.config.backtrace_cleaner
69
+
70
+ migration.update!(
71
+ status: :failed,
72
+ finished_at: Time.current,
73
+ error_class: e.class.name,
74
+ error_message: e.message,
75
+ backtrace: backtrace_cleaner ? backtrace_cleaner.clean(e.backtrace) : e.backtrace
76
+ )
77
+
78
+ ::OnlineMigrations.config.background_schema_migrations.error_handler.call(e, migration)
79
+ end
80
+
81
+ def should_throttle?
82
+ ::OnlineMigrations.config.throttler.call
83
+ end
84
+
85
+ def complete_parent_if_needed(migration)
86
+ parent = migration.parent
87
+ completed = false
88
+
89
+ parent.with_lock do
90
+ children = parent.children.select(:status)
91
+ if children.all?(&:succeeded?)
92
+ parent.succeeded!
93
+ completed = true
94
+ elsif children.any?(&:failed?)
95
+ parent.failed!
96
+ completed = true
97
+ end
98
+ end
99
+
100
+ if completed
101
+ ActiveSupport::Notifications.instrument("completed.background_migrations", notifications_payload(migration))
102
+ end
103
+ end
104
+
105
+ def notifications_payload(migration)
106
+ { background_schema_migration: migration }
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlineMigrations
4
+ module BackgroundSchemaMigrations
5
+ # @private
6
+ class MigrationStatusValidator < ActiveModel::Validator
7
+ VALID_STATUS_TRANSITIONS = {
8
+ # enqueued -> running occurs when the migration starts performing.
9
+ "enqueued" => ["running"],
10
+ # running -> succeeded occurs when the migration completes successfully.
11
+ # running -> failed occurs when the migration raises an exception when running and retry attempts exceeded.
12
+ "running" => ["succeeded", "failed"],
13
+ # failed -> enqueued occurs when the failed migration is enqueued to be retried.
14
+ # failed -> running occurs when the failed migration is retried.
15
+ "failed" => ["enqueued", "running"],
16
+ }
17
+
18
+ def validate(record)
19
+ return if !record.status_changed?
20
+
21
+ previous_status, new_status = record.status_change
22
+ valid_new_statuses = VALID_STATUS_TRANSITIONS.fetch(previous_status, [])
23
+
24
+ if !valid_new_statuses.include?(new_status)
25
+ record.errors.add(
26
+ :status,
27
+ "cannot transition background schema migration from status #{previous_status} to #{new_status}"
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlineMigrations
4
+ module BackgroundSchemaMigrations
5
+ # Class responsible for scheduling background schema migrations.
6
+ # It selects a single migration and runs it if there is no currently running migration.
7
+ #
8
+ # Scheduler should be configured to run periodically, for example, via cron.
9
+ # @example Run via whenever
10
+ # # add this to schedule.rb
11
+ # every 1.minute do
12
+ # runner "OnlineMigrations.run_background_schema_migrations"
13
+ # end
14
+ #
15
+ class Scheduler
16
+ def self.run
17
+ new.run
18
+ end
19
+
20
+ # Runs Scheduler
21
+ def run
22
+ migration = Migration.runnable.enqueued.queue_order.first || Migration.retriable.queue_order.first
23
+ if migration
24
+ runner = MigrationRunner.new(migration)
25
+ runner.run
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -181,6 +181,26 @@ module OnlineMigrations
181
181
  #
182
182
  attr_accessor :run_background_migrations_inline
183
183
 
184
+ # Allows to throttle background data or schema migrations based on external signal (e.g. database health)
185
+ #
186
+ # It will be called before each run.
187
+ # If throttled, the current run will be retried next time.
188
+ #
189
+ # @return [Proc]
190
+ #
191
+ # @example
192
+ # OnlineMigrations.config.throttler = -> { DatabaseStatus.unhealthy? }
193
+ #
194
+ attr_reader :throttler
195
+
196
+ # The Active Support backtrace cleaner that will be used to clean the
197
+ # backtrace of a background data or schema migration that errors.
198
+ #
199
+ # @return [ActiveSupport::BacktraceCleaner, nil] the backtrace cleaner to
200
+ # use when cleaning a background migrations's backtrace. Defaults to `Rails.backtrace_cleaner`
201
+ #
202
+ attr_accessor :backtrace_cleaner
203
+
184
204
  # Configuration object to configure background migrations
185
205
  #
186
206
  # @return [BackgroundMigrationsConfig]
@@ -188,6 +208,8 @@ module OnlineMigrations
188
208
  #
189
209
  attr_reader :background_migrations
190
210
 
211
+ attr_reader :background_schema_migrations
212
+
191
213
  def initialize
192
214
  @table_renames = {}
193
215
  @column_renames = {}
@@ -202,6 +224,7 @@ module OnlineMigrations
202
224
  )
203
225
 
204
226
  @background_migrations = BackgroundMigrations::Config.new
227
+ @background_schema_migrations = BackgroundSchemaMigrations::Config.new
205
228
 
206
229
  @checks = []
207
230
  @start_after = 0
@@ -213,6 +236,7 @@ module OnlineMigrations
213
236
  @enabled_checks = @error_messages.keys.index_with({})
214
237
  @verbose_sql_logs = defined?(Rails.env) && (Rails.env.production? || Rails.env.staging?)
215
238
  @run_background_migrations_inline = -> { Utils.developer_env? }
239
+ @throttler = -> { false }
216
240
  end
217
241
 
218
242
  def lock_retrier=(value)
@@ -223,6 +247,14 @@ module OnlineMigrations
223
247
  @small_tables = table_names.map(&:to_s)
224
248
  end
225
249
 
250
+ def throttler=(value)
251
+ if !value.respond_to?(:call)
252
+ raise ArgumentError, "throttler must be a callable."
253
+ end
254
+
255
+ @throttler = value
256
+ end
257
+
226
258
  # Enables specific check
227
259
  #
228
260
  # For the list of available checks look at the `error_messages.rb` file.
@@ -4,6 +4,7 @@ module OnlineMigrations
4
4
  module SchemaStatements
5
5
  include ChangeColumnTypeHelpers
6
6
  include BackgroundMigrations::MigrationHelpers
7
+ include BackgroundSchemaMigrations::MigrationHelpers
7
8
 
8
9
  # Updates the value of a column in batches.
9
10
  #
@@ -135,6 +135,13 @@ module OnlineMigrations
135
135
  connection.select_value(query) == "v"
136
136
  end
137
137
 
138
+ def find_connection_class(model)
139
+ model.ancestors.find do |parent|
140
+ parent == ActiveRecord::Base ||
141
+ (parent.is_a?(Class) && parent.abstract_class?)
142
+ end
143
+ end
144
+
138
145
  def shard_names(model)
139
146
  model.ancestors.each do |ancestor|
140
147
  # There is no official method to get shard names from the model.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OnlineMigrations
4
- VERSION = "0.15.0"
4
+ VERSION = "0.16.0"
5
5
  end
@@ -4,6 +4,7 @@ require "active_record"
4
4
 
5
5
  require "online_migrations/version"
6
6
  require "online_migrations/utils"
7
+ require "online_migrations/background_schema_migrations/migration_helpers"
7
8
  require "online_migrations/change_column_type_helpers"
8
9
  require "online_migrations/background_migrations/migration_helpers"
9
10
  require "online_migrations/schema_statements"
@@ -22,6 +23,7 @@ module OnlineMigrations
22
23
 
23
24
  extend ActiveSupport::Autoload
24
25
 
26
+ autoload :ApplicationRecord
25
27
  autoload :BatchIterator
26
28
  autoload :VerboseSqlLogs
27
29
  autoload :ForeignKeysCollector
@@ -52,7 +54,6 @@ module OnlineMigrations
52
54
  autoload :DeleteOrphanedRecords
53
55
  autoload :PerformActionOnRelation
54
56
  autoload :ResetCounters
55
- autoload :ApplicationRecord
56
57
  autoload :MigrationJob
57
58
  autoload :Migration
58
59
  autoload :MigrationJobRunner
@@ -60,6 +61,16 @@ module OnlineMigrations
60
61
  autoload :Scheduler
61
62
  end
62
63
 
64
+ module BackgroundSchemaMigrations
65
+ extend ActiveSupport::Autoload
66
+
67
+ autoload :Config
68
+ autoload :Migration
69
+ autoload :MigrationStatusValidator
70
+ autoload :MigrationRunner
71
+ autoload :Scheduler
72
+ end
73
+
63
74
  class << self
64
75
  # @private
65
76
  attr_accessor :current_migration
@@ -72,10 +83,16 @@ module OnlineMigrations
72
83
  @config ||= Config.new
73
84
  end
74
85
 
75
- # Run background migrations
86
+ # Run background data migrations
76
87
  def run_background_migrations
77
88
  BackgroundMigrations::Scheduler.run
78
89
  end
90
+ alias run_background_data_migrations run_background_migrations
91
+
92
+ # Run background schema migrations
93
+ def run_background_schema_migrations
94
+ BackgroundSchemaMigrations::Scheduler.run
95
+ end
79
96
 
80
97
  def deprecator
81
98
  @deprecator ||=
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: online_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - fatkodima
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-19 00:00:00.000000000 Z
11
+ date: 2024-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -34,19 +34,21 @@ files:
34
34
  - CHANGELOG.md
35
35
  - LICENSE.txt
36
36
  - README.md
37
- - docs/background_migrations.md
37
+ - docs/background_data_migrations.md
38
+ - docs/background_schema_migrations.md
38
39
  - docs/configuring.md
39
40
  - lib/generators/online_migrations/background_migration_generator.rb
40
41
  - lib/generators/online_migrations/install_generator.rb
41
42
  - lib/generators/online_migrations/templates/add_sharding_to_online_migrations.rb.tt
42
43
  - lib/generators/online_migrations/templates/background_migration.rb.tt
44
+ - lib/generators/online_migrations/templates/create_background_schema_migrations.rb.tt
43
45
  - lib/generators/online_migrations/templates/initializer.rb.tt
44
46
  - lib/generators/online_migrations/templates/install_migration.rb.tt
45
47
  - lib/generators/online_migrations/templates/migration.rb.tt
46
48
  - lib/generators/online_migrations/upgrade_generator.rb
47
49
  - lib/online_migrations.rb
50
+ - lib/online_migrations/application_record.rb
48
51
  - lib/online_migrations/background_migration.rb
49
- - lib/online_migrations/background_migrations/application_record.rb
50
52
  - lib/online_migrations/background_migrations/backfill_column.rb
51
53
  - lib/online_migrations/background_migrations/background_migration_class_validator.rb
52
54
  - lib/online_migrations/background_migrations/config.rb
@@ -63,6 +65,12 @@ files:
63
65
  - lib/online_migrations/background_migrations/perform_action_on_relation.rb
64
66
  - lib/online_migrations/background_migrations/reset_counters.rb
65
67
  - lib/online_migrations/background_migrations/scheduler.rb
68
+ - lib/online_migrations/background_schema_migrations/config.rb
69
+ - lib/online_migrations/background_schema_migrations/migration.rb
70
+ - lib/online_migrations/background_schema_migrations/migration_helpers.rb
71
+ - lib/online_migrations/background_schema_migrations/migration_runner.rb
72
+ - lib/online_migrations/background_schema_migrations/migration_status_validator.rb
73
+ - lib/online_migrations/background_schema_migrations/scheduler.rb
66
74
  - lib/online_migrations/batch_iterator.rb
67
75
  - lib/online_migrations/change_column_type_helpers.rb
68
76
  - lib/online_migrations/command_checker.rb
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OnlineMigrations
4
- module BackgroundMigrations
5
- # Base class for all records used by this gem.
6
- #
7
- # Can be extended to setup different database where all tables related to
8
- # online_migrations will live.
9
- class ApplicationRecord < ActiveRecord::Base
10
- self.abstract_class = true
11
- end
12
- end
13
- end