Created
April 25, 2022 20:49
-
-
Save Loschcode/d26b34446d56bb0f09bdbe2cfa375bd4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# concurrent migration strategy | |
# when migrating through this script | |
# you can launch it on multiple processes | |
# and they will deal with the concurrency by | |
# themselves without interrupting or crashing | |
class MigrateConcurrently | |
class Error < StandardError; end | |
DELAY_BETWEEN_CYCLES_IN_SECONDS = 3 | |
MAX_CYCLES = 100 | |
def initialize; end | |
def perform | |
return true unless concurrency_error? { run_migrate } | |
wait_and_try_again | |
end | |
private | |
def wait_and_try_again | |
log_cycle | |
wait | |
next_cycle | |
perform | |
end | |
def run_migrate | |
ActiveRecord::Base.connection.migration_context.migrate | |
end | |
def concurrency_error?(&block) | |
yield | |
false | |
rescue ActiveRecord::ConcurrentMigrationError | |
true | |
end | |
def log_cycle | |
Logger.info( | |
message: "Migration is already running, waiting to try again", | |
type: "infrastructure_run_migrate", | |
delay_between_cycles_in_seconds: DELAY_BETWEEN_CYCLES_IN_SECONDS, | |
cycle: cycles.current, | |
max_cycles: cycles.max, | |
) | |
end | |
def wait | |
sleep DELAY_BETWEEN_CYCLES_IN_SECONDS | |
end | |
def next_cycle | |
raise_if_max_cycles_reached | |
cycles.next | |
end | |
def raise_if_max_cycles_reached | |
return unless cycles.max? | |
raise Error, """ | |
Max cycles reached after trying #{cycles.current} times. | |
Something might be wrong with the migration process. | |
""" | |
end | |
def cycles | |
@cycles ||= Cycles.new(max: MAX_CYCLES) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment