Class: OnlineMigrations::BackgroundSchemaMigrations::Migration

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

Overview

Note:

The records of this class should not be created manually, but via enqueue_background_schema_migration helper inside migrations.

Class representing background schema migration.

Constant Summary collapse

STATUSES =
[
  :enqueued,    # The migration has been enqueued by the user.
  :running,     # The migration is being performed by a migration executor.
  :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.
  :cancelled,   # The migration was cancelled by the user.
]
MAX_IDENTIFIER_LENGTH =
63

Instance Method Summary collapse

Instance Method Details

#can_be_cancelled?Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 98

def can_be_cancelled?
  !succeeded? && !cancelled?
end

#can_be_paused?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 94

def can_be_paused?
  false
end

#cancelled!Object Also known as: cancel

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



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

def cancelled!
  return super if !composite?

  transaction do
    super
    children.each { |child| child.cancelled! if !child.succeeded? }
  end
end

#completed?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 75

def completed?
  succeeded? || failed?
end

#index_addition?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 167

def index_addition?
  definition.match?(/create (unique )?index/i)
end

#pausable?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 90

def pausable?
  false
end

#progressFloat

Returns the progress of the background schema migration.

Returns:

  • (Float)

    value in range from 0.0 to 100.0



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 106

def progress
  if succeeded?
    100.0
  elsif composite?
    progresses = children.map(&:progress)
    # There should not be composite migrations without children,
    # but children may be deleted for some reason, so we need to
    # make a check to avoid 0 division error.
    if progresses.any?
      (progresses.sum.to_f / progresses.size).round(2)
    else
      0.0
    end
  else
    0.0
  end
end

#retryObject

Mark this migration as ready to be processed again.

This is used to manually retrying failed migrations.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 138

def retry
  if composite? && failed?
    transaction do
      update!(status: :enqueued, finished_at: nil)
      children.failed.each(&:retry)
    end

    true
  elsif failed?
    transaction do
      parent.update!(status: :enqueued, finished_at: nil) if parent

      update!(
        status: :enqueued,
        attempts: 0,
        started_at: nil,
        finished_at: nil,
        error_class: nil,
        error_message: nil,
        backtrace: nil
      )
    end

    true
  else
    false
  end
end

#stuck?Boolean

Whether the migration is considered stuck (is running for some configured time).

Returns:

  • (Boolean)


126
127
128
129
130
131
132
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 126

def stuck?
  # Composite migrations are not considered stuck.
  return false if composite?

  stuck_timeout = (statement_timeout || 1.day) + 10.minutes
  running? && updated_at <= stuck_timeout.seconds.ago
end