Class: OnlineMigrations::BackgroundSchemaMigrations::Migration

Inherits:
ApplicationRecord
  • Object
show all
Includes:
ShardAware
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 =
[
  "pending",     # The migration has been created 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.
  "delayed",     # The migration was created, but waiting approval from the user to start running.
]
MAX_IDENTIFIER_LENGTH =
63

Instance Method Summary collapse

Methods included from ShardAware

#connection_class, #connection_class_name=, #on_shard_if_present

Instance Method Details

#active?Boolean

Returns whether the migration is active, which is defined as having a status of pending, or running.

Returns:

  • (Boolean)

    whether the migration is active.



67
68
69
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 67

def active?
  pending? || running?
end

#attempts_exceeded?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 143

def attempts_exceeded?
  attempts >= max_attempts
end

#cancelBoolean

Cancel this schema migration. No-op if migration is completed.

Returns:

  • (Boolean)

    whether this schema migration was cancelled.



129
130
131
132
133
134
135
136
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 129

def cancel
  if completed?
    false
  elsif pending? || errored? || delayed? || stuck?
    cancelled!
    true
  end
end

#completed?Boolean

Returns whether the migration is completed, which is defined as having a status of succeeded, failed, or cancelled.

Returns:

  • (Boolean)

    whether the migration is completed.



58
59
60
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 58

def completed?
  succeeded? || failed? || cancelled?
end

#enqueueBoolean

Enqueue this data migration. No-op if migration is not delayed.

Returns:

  • (Boolean)

    whether this data migration was enqueued.



116
117
118
119
120
121
122
123
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 116

def enqueue
  if delayed?
    pending!
    true
  else
    false
  end
end

#index_addition?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 138

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

#pausable?Boolean

Returns whether this migration is pausable.

Returns:

  • (Boolean)


73
74
75
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 73

def pausable?
  false
end

#progressnil

Dummy method to support the same interface as background data migrations.

Returns:

  • (nil)


81
82
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 81

def progress
end

#retryObject

Mark this migration as ready to be processed again.

This is used to manually retrying failed migrations.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 94

def retry
  if failed?
    update!(
      status: :pending,
      attempts: 0,
      started_at: nil,
      finished_at: nil,
      error_class: nil,
      error_message: nil,
      backtrace: nil
    )

    true
  else
    false
  end
end

#runObject



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 148

def run
  on_shard_if_present do
    with_connection do |connection|
      connection.with_lock_retries do
        statement_timeout = self.statement_timeout || OnlineMigrations.config.statement_timeout

        with_statement_timeout(connection, statement_timeout) do
          if index_addition?
            index = connection.indexes(table_name).find { |i| name.match?(/\b#{i.name}\b/) }
            if index
              if index.valid?
                return
              else
                connection.remove_index(table_name, name: index.name, algorithm: :concurrently)
              end
            end
          end

          connection.execute(definition)

          # Outdated statistics + a new index can hurt performance of existing queries.
          if OnlineMigrations.config.auto_analyze
            connection.execute("ANALYZE #{table_name}")
          end
        end
      end
    end
  end
end

#stuck?Boolean

Whether the migration is considered stuck.

Returns:

  • (Boolean)


86
87
88
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 86

def stuck?
  index_addition? && running? && !index_build_in_progress?
end