Class: OnlineMigrations::BackgroundDataMigrations::Migration
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- OnlineMigrations::BackgroundDataMigrations::Migration
- Includes:
- ShardAware
- Defined in:
- lib/online_migrations/background_data_migrations/migration.rb
Overview
The records of this class should not be created manually, but via
enqueue_background_data_migration helper inside migrations.
Class representing background data migration.
Constant Summary collapse
- STATUSES =
[ "pending", # The migration has been created by the user. "enqueued", # The migration has been enqueued by the scheduler. "running", # The migration is being performed by a migration executor. "pausing", # The migration has been told to pause but is finishing work. "paused", # The migration was paused in the middle of the run by the user. "errored", # The migration raised an error during last run. "failed", # The migration raises an error when running and retry attempts exceeded. "succeeded", # The migration finished without error. "cancelling", # The migration has been told to cancel but is finishing work. "cancelled", # The migration was cancelled by the user. "delayed", # The migration was created, but waiting approval from the user to start running. ]
- COMPLETED_STATUSES =
["succeeded", "failed", "cancelled"]
- ACTIVE_STATUSES =
[ "pending", "enqueued", "running", "failed", "pausing", "paused", "cancelling", ]
- STOPPING_STATUSES =
["pausing", "cancelling", "cancelled"]
Class Method Summary collapse
Instance Method Summary collapse
-
#active? ⇒ Boolean
Returns whether the migration is active, which is defined as having a status of pending, enqueued, running, pausing, paused, or cancelling.
-
#cancel ⇒ Boolean
Cancel this data migration.
- #complete ⇒ Object
-
#completed? ⇒ Boolean
Returns whether the migration is completed, which is defined as having a status of succeeded, failed, or cancelled.
-
#data_migration ⇒ OnlineMigrations::DataMigration
Returns data migration associated with this migration.
-
#enqueue ⇒ Boolean
Enqueue this data migration.
- #migration_name=(class_name) ⇒ Object (also: #name=)
-
#pausable? ⇒ Boolean
Returns whether this migration is pausable.
-
#pause ⇒ Boolean
Pause this data migration.
- #persist_error(error, attempt) ⇒ Object
- #persist_progress(cursor, number_of_ticks, duration) ⇒ Object
-
#progress ⇒ Float?
Returns the progress of the data migration.
-
#resume ⇒ Boolean
Resume this data migration.
-
#retry ⇒ Object
Mark this migration as ready to be processed again.
- #start ⇒ Object
-
#started? ⇒ Boolean
Returns whether the migration has been started, which is indicated by the started_at timestamp being present.
- #stop ⇒ Object
-
#stopping? ⇒ Boolean
Returns whether the migration is stopping, which is defined as having a status of pausing or cancelling.
-
#stuck? ⇒ Boolean
Returns whether a migration is stuck, which is defined as having a status of running, cancelling or pausing, and not having been updated in the last 5 minutes.
Methods included from ShardAware
#connection_class, #connection_class_name=, #on_shard_if_present
Class Method Details
.normalize_migration_name(migration_name) ⇒ Object
64 65 66 67 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 64 def self.normalize_migration_name(migration_name) namespace = ::OnlineMigrations.config.background_data_migrations.migrations_module migration_name.sub(/^(::)?#{namespace}::/, "") end |
Instance Method Details
#active? ⇒ Boolean
Returns whether the migration is active, which is defined as having a status of pending, enqueued, running, pausing, paused, or cancelling.
98 99 100 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 98 def active? ACTIVE_STATUSES.include?(status) end |
#cancel ⇒ Boolean
Cancel this data migration. No-op if migration is completed.
157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 157 def cancel return false if completed? if paused? || delayed? || stuck? update!(status: :cancelled, finished_at: Time.current) elsif pending? || enqueued? || errored? cancelled! else cancelling! end true end |
#complete ⇒ Object
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 218 def complete return false if completed? if running? update!(status: :succeeded, finished_at: Time.current) data_migration.after_complete elsif pausing? update!(status: :paused, finished_at: Time.current) elsif cancelling? update!(status: :cancelled, finished_at: Time.current) data_migration.after_complete end true end |
#completed? ⇒ Boolean
Returns whether the migration is completed, which is defined as having a status of succeeded, failed, or cancelled.
89 90 91 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 89 def completed? COMPLETED_STATUSES.include?(status) end |
#data_migration ⇒ OnlineMigrations::DataMigration
Returns data migration associated with this migration.
285 286 287 288 289 290 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 285 def data_migration @data_migration ||= begin klass = DataMigration.named(migration_name) klass.new(*arguments) end end |
#enqueue ⇒ Boolean
Enqueue this data migration. No-op if migration is not delayed.
144 145 146 147 148 149 150 151 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 144 def enqueue if delayed? pending! true else false end end |
#migration_name=(class_name) ⇒ Object Also known as: name=
69 70 71 72 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 69 def migration_name=(class_name) class_name = class_name.name if class_name.is_a?(Class) write_attribute(:migration_name, self.class.normalize_migration_name(class_name)) end |
#pausable? ⇒ Boolean
Returns whether this migration is pausable.
261 262 263 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 261 def pausable? true end |
#pause ⇒ Boolean
Pause this data migration. No-op if migration is completed.
175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 175 def pause return false if completed? if pending? || enqueued? || delayed? || stuck? || errored? paused! else pausing! end true end |
#persist_error(error, attempt) ⇒ Object
244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 244 def persist_error(error, attempt) backtrace = error.backtrace backtrace_cleaner = OnlineMigrations.config.backtrace_cleaner backtrace = backtrace_cleaner.clean(backtrace) if backtrace_cleaner status = attempt >= max_attempts ? :failed : :errored update!( status: status, finished_at: Time.current, error_class: error.class.name, error_message: error., backtrace: backtrace ) end |
#persist_progress(cursor, number_of_ticks, duration) ⇒ Object
235 236 237 238 239 240 241 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 235 def persist_progress(cursor, number_of_ticks, duration) update!( cursor: cursor, tick_count: tick_count + number_of_ticks, time_running: time_running + duration ) end |
#progress ⇒ Float?
Returns the progress of the data migration.
271 272 273 274 275 276 277 278 279 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 271 def progress if succeeded? 100.0 elsif tick_total == 0 0.0 elsif tick_total ([tick_count.to_f / tick_total, 1.0].min * 100) end end |
#resume ⇒ Boolean
Resume this data migration. No-op if migration is not paused.
191 192 193 194 195 196 197 198 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 191 def resume if paused? pending! true else false end end |
#retry ⇒ Object
Mark this migration as ready to be processed again.
This method marks failed migrations as ready to be processed again, and they will be picked up on the next Scheduler run.
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 297 def retry if failed? update!( status: :pending, started_at: nil, finished_at: nil, error_class: nil, error_message: nil, backtrace: nil, jid: nil ) true else false end end |
#start ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 124 def start if enqueued? # Defer `tick_total` calculation to the migration starting time # instead of the enqueueing time to avoid failed deploys. self.tick_total ||= safely_calculate_tick_total self.status = :running self.started_at = Time.current save! data_migration.after_start true else false end end |
#started? ⇒ Boolean
Returns whether the migration has been started, which is indicated by the started_at timestamp being present.
80 81 82 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 80 def started? started_at.present? end |
#stop ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 201 def stop return false if completed? if cancelling? update!(status: :cancelled, finished_at: Time.current) data_migration.after_cancel data_migration.after_complete elsif pausing? paused! data_migration.after_pause end data_migration.after_stop true end |
#stopping? ⇒ Boolean
Returns whether the migration is stopping, which is defined as having a status of pausing or cancelling. The status of cancelled is also considered stopping since a migration can be cancelled while its job still exists in the queue, and we want to handle it the same way as a cancelling run.
109 110 111 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 109 def stopping? STOPPING_STATUSES.include?(status) end |
#stuck? ⇒ Boolean
Returns whether a migration is stuck, which is defined as having a status of running, cancelling or pausing, and not having been updated in the last 5 minutes.
118 119 120 121 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 118 def stuck? stuck_timeout = OnlineMigrations.config.background_data_migrations.stuck_timeout (running? || cancelling? || pausing?) && updated_at <= stuck_timeout.ago end |