Class: OnlineMigrations::BackgroundMigrations::Migration

Inherits:
ApplicationRecord
  • Object
show all
Defined in:
lib/online_migrations/background_migrations/migration.rb

Overview

Note:

The records of this class should not be created manually, but via enqueue_background_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.
  :paused,      # The migration was paused in the middle of the run by the user.
  :finishing,   # The migration is being manually finishing inline by the user.
  :failed,      # The migration raises an exception when running.
  :succeeded,   # The migration finished without error.
]

Instance Method Summary collapse

Instance Method Details

#completed?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/online_migrations/background_migrations/migration.rb', line 76

def completed?
  succeeded? || failed?
end

#interval_elapsed?Boolean

Returns whether the interval between previous step run has passed.

Returns:

  • (Boolean)


155
156
157
158
159
160
161
162
163
164
165
# File 'lib/online_migrations/background_migrations/migration.rb', line 155

def interval_elapsed?
  last_active_job = migration_jobs.active.order(:updated_at).last

  if last_active_job && !last_active_job.stuck?
    false
  elsif batch_pause > 0 && (job = last_completed_job)
    job.finished_at + batch_pause <= Time.current
  else
    true
  end
end

#last_completed_jobObject



104
105
106
# File 'lib/online_migrations/background_migrations/migration.rb', line 104

def last_completed_job
  migration_jobs.completed.order(:finished_at).last
end

#last_jobObject



100
101
102
# File 'lib/online_migrations/background_migrations/migration.rb', line 100

def last_job
  migration_jobs.order(:max_value).last
end

#migration_classObject



136
137
138
# File 'lib/online_migrations/background_migrations/migration.rb', line 136

def migration_class
  BackgroundMigration.named(migration_name)
end

#migration_modelObject



148
149
150
# File 'lib/online_migrations/background_migrations/migration.rb', line 148

def migration_model
  migration_relation.model
end

#migration_name=(class_name) ⇒ Object Also known as: name=



70
71
72
73
# File 'lib/online_migrations/background_migrations/migration.rb', line 70

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

#migration_objectObject



140
141
142
# File 'lib/online_migrations/background_migrations/migration.rb', line 140

def migration_object
  @migration_object ||= migration_class.new(*arguments)
end

#migration_relationObject



144
145
146
# File 'lib/online_migrations/background_migrations/migration.rb', line 144

def migration_relation
  migration_object.relation
end

#paused!Object

Overwrite enum's generated method to correctly work for composite migrations.



81
82
83
84
85
86
87
88
# File 'lib/online_migrations/background_migrations/migration.rb', line 81

def paused!
  return super if !composite?

  transaction do
    super
    children.each { |child| child.paused! if child.enqueued? || child.running? }
  end
end

#progressFloat?

Returns the progress of the background migration.

Returns:

  • (Float, nil)
    • when background migration is configured to not track progress, returns nil
    • otherwise returns value in range from 0.0 to 100.0


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/online_migrations/background_migrations/migration.rb', line 114

def progress
  if succeeded?
    100.0
  elsif composite?
    rows_counts = children.to_a.pluck(:rows_count)
    if rows_counts.none?(nil)
      total_rows_count = rows_counts.sum

      progresses = children.map do |child|
        child.progress * child.rows_count / total_rows_count # weighted progress
      end

      progresses.sum.round(2)
    end
  elsif rows_count
    jobs_rows_count = migration_jobs.succeeded.sum(:batch_size)
    # The last migration job may need to process the amount of rows
    # less than the batch size, so we can get a value > 1.0.
    ([jobs_rows_count.to_f / rows_count, 1.0].min * 100).round(2)
  end
end

#retry_failed_jobsObject

Manually retry failed jobs.

This method marks failed jobs as ready to be processed again, and they will be picked up on the next Scheduler run.



172
173
174
175
176
177
178
179
180
# File 'lib/online_migrations/background_migrations/migration.rb', line 172

def retry_failed_jobs
  iterator = BatchIterator.new(migration_jobs.failed)
  iterator.each_batch(of: 100) do |batch|
    transaction do
      batch.each(&:retry)
      enqueued!
    end
  end
end

#running!Object

Overwrite enum's generated method to correctly work for composite migrations.



91
92
93
94
95
96
97
98
# File 'lib/online_migrations/background_migrations/migration.rb', line 91

def running!
  return super if !composite?

  transaction do
    super
    children.each { |child| child.running! if child.paused? }
  end
end