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 =
[
  "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

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 enqueued, or running.

Returns:

  • (Boolean)

    whether the migration is active.



65
66
67
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 65

def active?
  enqueued? || running?
end

#attempts_exceeded?Boolean

Returns:

  • (Boolean)


122
123
124
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 122

def attempts_exceeded?
  attempts >= max_attempts
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.



56
57
58
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 56

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

#index_addition?Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 117

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.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 99

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

    true
  else
    false
  end
end

#runObject



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 127

def run
  on_shard_if_present do
    connection = connection_class.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

#stuck?Boolean

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

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
# File 'lib/online_migrations/background_schema_migrations/migration.rb', line 86

def stuck?
  if index_addition?
    running? && !index_build_in_progress?
  else
    stuck_timeout = (statement_timeout || 1.day) + 10.minutes
    running? && updated_at <= stuck_timeout.seconds.ago
  end
end