class Cassie::Schema::Migrator

Attributes

after_each[RW]
before_each[RW]
commands[R]
current_version[R]
direction[R]
target_version[R]

Public Class Methods

new(target) click to toggle source
# File lib/cassie/schema/migrator.rb, line 13
def initialize(target)
  @target_version   = build_target_version(target)
  @current_version  = Cassie::Schema.version
  @direction        = build_direction
  @before_each      = Proc.new{}
  @after_each       = Proc.new{}
  @commands         = send("build_#{direction}_commands")
end

Public Instance Methods

applied_versions() click to toggle source

versions applied to the database enumerated in most recent first order

# File lib/cassie/schema/migrator.rb, line 30
def applied_versions
  @applied_versions ||= Cassie::Schema.applied_versions.to_a
end
migrate() click to toggle source
# File lib/cassie/schema/migrator.rb, line 22
def migrate
  commands_with_callbacks do |command|
    command.execute
  end
end

Protected Instance Methods

build_direction() click to toggle source
# File lib/cassie/schema/migrator.rb, line 53
def build_direction
  target_version >= current_version ? :up : :down
end
build_down_commands() click to toggle source

rollback all versions applied past the target and apply missing versions to get to target

0 | a (target) (not applied) | b | c | d (current) | e

# File lib/cassie/schema/migrator.rb, line 82
def build_down_commands
  rollbacks = rollback_versions.map{ |v| RollbackCommand.new(v) }
  missing = missing_versions_before(rollbacks.last.version).map{ |v| ApplyCommand.new(v) }
  rollbacks + missing
end
build_target_version(target) click to toggle source
# File lib/cassie/schema/migrator.rb, line 40
def build_target_version(target)
  case target
  when Version
    target
  when /^[\d\.]+$/
    Version.new(target)
  when nil
    local_versions.last || Cassie::Schema.version
  else
    raise ArgumentError, "Migrator target must be a `Version` object, version string, or nil"
  end
end
build_up_commands() click to toggle source

install all local versions since current

a (current) | b | c | d (target) | e

# File lib/cassie/schema/migrator.rb, line 73
def build_up_commands
  local_versions.select{ |v| v > current_version && v <= target_version }
                .map{ |v| ApplyCommand.new(v) }
end
commands_with_callbacks() { |command| ... } click to toggle source
# File lib/cassie/schema/migrator.rb, line 57
def commands_with_callbacks
  commands.each do |command|
    before_each.call(command.version, command.direction)
    duration = Benchmark.realtime do
      yield(command)
    end
    # Sleep for 50ms to ensure TimeUuid generation jitter
    # doesn't cause out-of-order records
    sleep(0.050)
    after_each.call(command.version, (duration*1000).round(2))
  end
end
local_versions() click to toggle source
# File lib/cassie/schema/migrator.rb, line 36
def local_versions
  Cassie::Schema.local_versions
end
missing_versions_before(last_rollback) click to toggle source

versions that are not applied yet but need to get applied to get up the target version

| 0 (stop) | a (target) | b | c

# File lib/cassie/schema/migrator.rb, line 99
def missing_versions_before(last_rollback)
  return [] unless last_rollback

  rollback_index = applied_versions.index(last_rollback)

  stop = if rollback_index == applied_versions.length - 1
    # rolled back to oldest version, a rollback
    # would put us in a versionless state.
    # Any versions up to target should be applied
    Version.new('0')
  else
    applied_versions[rollback_index + 1]
  end

  return [] if stop == target_version

  local_versions.select{ |v| v > stop && v <= target_version }
end
rollback_versions() click to toggle source

all versions applied since target 0 | a (target) (not applied) | b | c | d (current) | e

# File lib/cassie/schema/migrator.rb, line 90
def rollback_versions
  applied_versions.select{ |a| a > target_version && a <= current_version }
end