class Sequent::Migrations::Planner

Constants

Plan

Attributes

versions[R]

Public Class Methods

new(versions) click to toggle source
# File lib/sequent/migrations/planner.rb, line 24
def initialize(versions)
  @versions = versions
end

Public Instance Methods

plan(old, new) click to toggle source
# File lib/sequent/migrations/planner.rb, line 28
def plan(old, new)
  migrations = versions.slice(*Range.new(old + 1, new).to_a.map(&:to_s))

  Plan.new(
    migrations.yield_self(&method(:select_projectors)),
    migrations
      .yield_self(&method(:create_migrations))
      .yield_self(&method(:remove_redundant_migrations)),
  )
end

Private Instance Methods

create_migrations(migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 94
def create_migrations(migrations)
  migrations
    .yield_self(&method(:map_to_migrations))
    .values
    .compact
    .flatten
end
group_identical_migrations(migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 60
def group_identical_migrations(migrations)
  migrations
    .group_by { |migration| {migration_type: migration.class, record_class: migration.record_class} }
end
map_to_migrations(migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 102
      def map_to_migrations(migrations)
        migrations.reduce({}) do |memo, (version, ms)|
          unless ms.is_a?(Array)
            fail InvalidMigrationDefinition,
                 "Declared migrations for version #{version} must be an Array. For example: {'3' => [FooProjector]}"
          end

          memo[version] = ms.flat_map do |migration|
            if migration.is_a?(AlterTable)
              alter_table_sql_file_name = <<~EOS.chomp
                #{Sequent.configuration.migration_sql_files_directory}/#{migration.table_name}_#{version}.sql
              EOS
              unless File.exist?(alter_table_sql_file_name)
                fail InvalidMigrationDefinition,
                     "Missing file #{alter_table_sql_file_name} to apply for version #{version}"
              end

              migration.copy(version)
            elsif migration < Sequent::Projector
              migration.managed_tables.map { |table| ReplayTable.create(table, version) }
            else
              fail InvalidMigrationDefinition, "Unknown Migration #{migration}"
            end
          end

          memo
        end
      end
order_by_version_desc(migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 89
def order_by_version_desc(migrations)
  migrations.sort_by { |m| m.version.to_i }
    .reverse
end
remove_alter_tables_before_replay_table(migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 69
def remove_alter_tables_before_replay_table(migrations)
  migrations - migrations
    .each_with_index
    .select { |migration, _index| migration.instance_of?(AlterTable) }
    .select do |migration, index|
      migrations
        .slice((index + 1)..-1)
        .find { |m| m.instance_of?(ReplayTable) && m.record_class == migration.record_class }
    end.map(&:first)
end
remove_redundancy(grouped_migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 80
def remove_redundancy(grouped_migrations)
  grouped_migrations.reduce({}) do |memo, (key, ms)|
    memo[key] = ms
      .yield_self(&method(:order_by_version_desc))
      .slice(1..-1)
    memo
  end
end
remove_redundant_migrations(migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 48
def remove_redundant_migrations(migrations)
  redundant_migrations = migrations
    .yield_self(&method(:group_identical_migrations))
    .yield_self(&method(:select_redundant_migrations))
    .yield_self(&method(:remove_redundancy))
    .values
    .flatten

  (migrations - redundant_migrations)
    .yield_self(&method(:remove_alter_tables_before_replay_table))
end
select_projectors(migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 41
def select_projectors(migrations)
  migrations
    .values
    .flatten
    .select { |v| v.is_a?(Class) && v < Sequent::Projector }.uniq
end
select_redundant_migrations(grouped_migrations) click to toggle source
# File lib/sequent/migrations/planner.rb, line 65
def select_redundant_migrations(grouped_migrations)
  grouped_migrations.select { |type, ms| type[:migration_type] == ReplayTable && ms.length > 1 }
end