class DynamoDB::Migration::Execute

Constants

DEFAULT_MIGRATION_TABLE_NAME

Attributes

client[R]
tags[R]

Public Class Methods

new(client, migration_table_name, tags) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 6
def initialize(client, migration_table_name, tags)
  @client = client
  @migration_table_name = migration_table_name
  @tags = tags
end

Public Instance Methods

update_all() click to toggle source
# File lib/dynamodb/migration/execute.rb, line 12
def update_all
  ensure_migrations_table_exists
  migration_classes.each do |clazz|
    apply_migration(clazz)
  end
end

Private Instance Methods

apply_migration(clazz) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 23
def apply_migration(clazz)
  return if migration_completed?(clazz)
  record_start_migration(clazz)
  migration = clazz.new
  migration.client = client
  migration.update
  record_successful_migration(clazz)
rescue Aws::DynamoDB::Errors::ServiceError => e
  record_failed_migration(clazz)
  raise
end
clazz_filename(clazz) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 77
def clazz_filename(clazz)
  full_filename = clazz.instance_methods(false)
                       .map { |m| clazz.instance_method(m).source_location }
                       .compact
                       .map { |m| m.first }
                       .uniq
                       .first
  File.basename(full_filename)
end
ensure_migrations_table_exists() click to toggle source
# File lib/dynamodb/migration/execute.rb, line 106
def ensure_migrations_table_exists
  unless table_exists?(client, migration_table_name)
    client.create_table(
      table_name: migration_table_name,
      attribute_definitions: [
        {
          attribute_name: "file",
          attribute_type: "S",
        },
      ],
      key_schema: [
        {
          attribute_name: "file",
          key_type: "HASH",
        },
      ],
      provisioned_throughput: {
        read_capacity_units: 1,
        write_capacity_units: 1,
      },
      stream_specification: {
        stream_enabled: true,
        stream_view_type: "NEW_AND_OLD_IMAGES",
      },
      tags: tags
    )
    puts "Waiting for table #{migration_table_name} to exist..."
    client.wait_until(:table_exists, {:table_name => migration_table_name})
    puts "#{migration_table_name} exists, continuing migration."
  end
rescue Aws::DynamoDB::Errors::ResourceInUseException => e
  raise e unless e.message =~ /preexisting table/i
end
migration_classes() click to toggle source
# File lib/dynamodb/migration/execute.rb, line 87
def migration_classes
  ObjectSpace.each_object(DynamoDB::Migration::Unit.singleton_class)
             .reject { |c| c == DynamoDB::Migration::Unit }
             .sort_by { |c| clazz_filename(c) }
end
migration_completed?(clazz) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 93
def migration_completed?(clazz)
  migration = client.get_item({
    table_name: migration_table_name,
    key: {
      "file" => clazz_filename(clazz),
    },
    attributes_to_get: ["file", "completed"],
    consistent_read: true,
  }).item

  migration && migration["completed"]
end
migration_table_name() click to toggle source
# File lib/dynamodb/migration/execute.rb, line 146
def migration_table_name
  @migration_table_name ||
    ENV['DYNAMODB_MIGRATION_TABLE_NAME'] ||
    DEFAULT_MIGRATION_TABLE_NAME
end
record_failed_migration(clazz) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 35
def record_failed_migration(clazz)
  client.delete_item({
    table_name: migration_table_name,
    key: {
      "file" => clazz_filename(clazz),
    },
    condition_expression: "completed = :false",
    expression_attribute_values: {
      ":false" => false
    }
  })
end
record_start_migration(clazz) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 48
def record_start_migration(clazz)
  client.put_item({
    table_name: migration_table_name,
    item: {
      "file" => clazz_filename(clazz),
      "executed_at" => Time.now.iso8601,
      "created_at" => Time.now.iso8601,
      "updated_at" => Time.now.iso8601,
      "completed" => false,
    },
    return_values: "NONE",
  })
end
record_successful_migration(clazz) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 62
def record_successful_migration(clazz)
  client.update_item({
    table_name: migration_table_name,
    key: {
      "file" => clazz_filename(clazz),
    },
    update_expression: "SET completed = :true",
    condition_expression: "completed = :false",
    expression_attribute_values: {
      ":false" => false,
      ":true"  => true,
    }
  })
end
table_exists?(client, table_name) click to toggle source
# File lib/dynamodb/migration/execute.rb, line 140
def table_exists?(client, table_name)
  client.describe_table(table_name: table_name)
rescue Aws::DynamoDB::Errors::ResourceNotFoundException => e
  false
end