online_migrations 0.15.0 → 0.16.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 (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