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 =
[ "enqueued", # The migration has been enqueued by the user. "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. "failed", # The migration raises an exception when running. "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. ]
- COMPLETED_STATUSES =
["succeeded", "failed", "cancelled"]
- ACTIVE_STATUSES =
[ "enqueued", "running", "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 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.
- #migration_name=(class_name) ⇒ Object (also: #name=)
-
#pausable? ⇒ Boolean
Returns whether this migration is pausable.
-
#pause ⇒ Boolean
Pause this data migration.
- #persist_error(error) ⇒ 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 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
59 60 61 62 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 59 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 enqueued, running, pausing, paused, or cancelling.
93 94 95 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 93 def active? ACTIVE_STATUSES.include?(status) end |
#cancel ⇒ Boolean
Cancel this data migration. No-op if migration is completed.
137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 137 def cancel return false if completed? if paused? || stuck? update!(status: :cancelled, finished_at: Time.current) elsif enqueued? cancelled! else cancelling! end true end |
#complete ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 198 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.
84 85 86 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 84 def completed? COMPLETED_STATUSES.include?(status) end |
#data_migration ⇒ OnlineMigrations::DataMigration
Returns data migration associated with this migration.
264 265 266 267 268 269 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 264 def data_migration @data_migration ||= begin klass = DataMigration.named(migration_name) klass.new(*arguments) end end |
#migration_name=(class_name) ⇒ Object Also known as: name=
64 65 66 67 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 64 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.
240 241 242 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 240 def pausable? true end |
#pause ⇒ Boolean
Pause this data migration. No-op if migration is completed.
155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 155 def pause return false if completed? if enqueued? || stuck? paused! else pausing! end true end |
#persist_error(error) ⇒ Object
224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 224 def persist_error(error) backtrace = error.backtrace backtrace_cleaner = OnlineMigrations.config.backtrace_cleaner backtrace = backtrace_cleaner.clean(backtrace) if backtrace_cleaner update!( status: :failed, finished_at: Time.current, error_class: error.class.name, error_message: error., backtrace: backtrace ) end |
#persist_progress(cursor, number_of_ticks, duration) ⇒ Object
215 216 217 218 219 220 221 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 215 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.
250 251 252 253 254 255 256 257 258 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 250 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.
171 172 173 174 175 176 177 178 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 171 def resume if paused? enqueued! 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.
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 276 def retry if failed? update!( status: :enqueued, started_at: nil, finished_at: nil, error_class: nil, error_message: nil, backtrace: nil, jid: nil ) true else false end end |
#start ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 119 def start if running? && !started? update!(started_at: Time.current) data_migration.after_start true elsif enqueued? update!(status: :running, started_at: Time.current) 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.
75 76 77 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 75 def started? started_at.present? end |
#stop ⇒ Object
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 181 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.
104 105 106 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 104 def stopping? STOPPING_STATUSES.include?(status) end |
#stuck? ⇒ Boolean
Returns whether a migration is stuck, which is defined as having a status of cancelling or pausing, and not having been updated in the last 5 minutes.
113 114 115 116 |
# File 'lib/online_migrations/background_data_migrations/migration.rb', line 113 def stuck? stuck_timeout = OnlineMigrations.config.background_data_migrations.stuck_timeout (cancelling? || pausing?) && updated_at <= stuck_timeout.ago end |