class Dynamoid::AdapterPlugin::AwsSdkV3::CreateTable

Attributes

client[R]
key[R]
options[R]
table_name[R]

Public Class Methods

new(client, table_name, key, options) click to toggle source
# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 12
def initialize(client, table_name, key, options)
  @client = client
  @table_name = table_name
  @key = key
  @options = options
end

Public Instance Methods

call() click to toggle source
# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 19
def call
  billing_mode = options[:billing_mode]
  read_capacity = options[:read_capacity] || Dynamoid::Config.read_capacity
  write_capacity = options[:write_capacity] || Dynamoid::Config.write_capacity

  secondary_indexes = options.slice(
    :local_secondary_indexes,
    :global_secondary_indexes
  )
  ls_indexes = options[:local_secondary_indexes]
  gs_indexes = options[:global_secondary_indexes]

  key_schema = {
    hash_key_schema: { key => (options[:hash_key_type] || :string) },
    range_key_schema: options[:range_key]
  }
  attribute_definitions = build_all_attribute_definitions(
    key_schema,
    secondary_indexes
  )
  key_schema = aws_key_schema(
    key_schema[:hash_key_schema],
    key_schema[:range_key_schema]
  )

  client_opts = {
    table_name: table_name,
    key_schema: key_schema,
    attribute_definitions: attribute_definitions
  }

  if billing_mode == :on_demand
    client_opts[:billing_mode] = 'PAY_PER_REQUEST'
  else
    client_opts[:billing_mode] = 'PROVISIONED'
    client_opts[:provisioned_throughput] = {
      read_capacity_units: read_capacity,
      write_capacity_units: write_capacity
    }
  end

  if ls_indexes.present?
    client_opts[:local_secondary_indexes] = ls_indexes.map do |index|
      index_to_aws_hash(index)
    end
  end

  if gs_indexes.present?
    client_opts[:global_secondary_indexes] = gs_indexes.map do |index|
      index_to_aws_hash(index)
    end
  end
  resp = client.create_table(client_opts)
  options[:sync] = true if !options.key?(:sync) && ls_indexes.present? || gs_indexes.present?

  if options[:sync]
    status = PARSE_TABLE_STATUS.call(resp, :table_description)
    if status == TABLE_STATUSES[:creating]
      UntilPastTableStatus.new(client, table_name, :creating).call
    end
  end

  # Response to original create_table, which, if options[:sync]
  # may have an outdated table_description.table_status of "CREATING"
  resp
end

Private Instance Methods

api_type(type) click to toggle source

Converts from symbol to the API string for the given data type E.g. :number -> ā€˜N’

# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 170
def api_type(type)
  case type
  when :string then STRING_TYPE
  when :number then NUM_TYPE
  when :binary then BINARY_TYPE
  else raise "Unknown type: #{type}"
  end
end
attribute_definition_element(name, dynamoid_type) click to toggle source

Builds an aws attribute definition based on name and dynamoid type @param [Symbol] name - eg: :id @param [Symbol] dynamoid_type - eg: :string @return [Hash]

# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 159
def attribute_definition_element(name, dynamoid_type)
  aws_type = api_type(dynamoid_type)

  {
    attribute_name: name.to_s,
    attribute_type: aws_type
  }
end
aws_key_schema(hash_key_schema, range_key_schema) click to toggle source

Converts hash_key_schema and range_key_schema to aws_key_schema @param [Hash] hash_key_schema eg: {:id => :string} @param [Hash] range_key_schema eg: {:created_at => :number} @return [Array]

# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 230
def aws_key_schema(hash_key_schema, range_key_schema)
  schema = [{
    attribute_name: hash_key_schema.keys.first.to_s,
    key_type: HASH_KEY
  }]

  if range_key_schema.present?
    schema << {
      attribute_name: range_key_schema.keys.first.to_s,
      key_type: RANGE_KEY
    }
  end
  schema
end
build_all_attribute_definitions(key_schema, secondary_indexes = {}) click to toggle source

Builds aws attributes definitions based off of primary hash/range and secondary indexes

@param key_schema @option key_schema [Hash] hash_key_schema - eg: {:id => :string} @option key_schema [Hash] range_key_schema - eg: {:created_at => :number} @param [Hash] secondary_indexes @option secondary_indexes [Array<Dynamoid::Indexes::Index>] :local_secondary_indexes @option secondary_indexes [Array<Dynamoid::Indexes::Index>] :global_secondary_indexes

# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 97
def build_all_attribute_definitions(key_schema, secondary_indexes = {})
  ls_indexes = secondary_indexes[:local_secondary_indexes]
  gs_indexes = secondary_indexes[:global_secondary_indexes]

  attribute_definitions = []

  attribute_definitions << build_attribute_definitions(
    key_schema[:hash_key_schema],
    key_schema[:range_key_schema]
  )

  if ls_indexes.present?
    ls_indexes.map do |index|
      attribute_definitions << build_attribute_definitions(
        index.hash_key_schema,
        index.range_key_schema
      )
    end
  end

  if gs_indexes.present?
    gs_indexes.map do |index|
      attribute_definitions << build_attribute_definitions(
        index.hash_key_schema,
        index.range_key_schema
      )
    end
  end

  attribute_definitions.flatten!
  # uniq these definitions because range keys might be common between
  # primary and secondary indexes
  attribute_definitions.uniq!
  attribute_definitions
end
build_attribute_definitions(hash_key_schema, range_key_schema = nil) click to toggle source

Builds an attribute definitions based on hash key and range key @param [Hash] hash_key_schema - eg: {:id => :string} @param [Hash] range_key_schema - eg: {:created_at => :datetime} @return [Array]

# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 137
def build_attribute_definitions(hash_key_schema, range_key_schema = nil)
  attrs = []

  attrs << attribute_definition_element(
    hash_key_schema.keys.first,
    hash_key_schema.values.first
  )

  if range_key_schema.present?
    attrs << attribute_definition_element(
      range_key_schema.keys.first,
      range_key_schema.values.first
    )
  end

  attrs
end
index_to_aws_hash(index) click to toggle source

Converts a Dynamoid::Indexes::Index to an AWS API-compatible hash. This resulting hash is of the form:

{
  index_name: String
  keys: {
    hash_key: aws_key_schema (hash)
    range_key: aws_key_schema (hash)
  }
  projection: {
    projection_type: (ALL, KEYS_ONLY, INCLUDE) String
    non_key_attributes: (optional) Array
  }
  provisioned_throughput: {
    read_capacity_units: Integer
    write_capacity_units: Integer
  }
}

@param [Dynamoid::Indexes::Index] index the index. @return [Hash] hash representing an AWS Index definition.

# File lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb, line 200
def index_to_aws_hash(index)
  key_schema = aws_key_schema(index.hash_key_schema, index.range_key_schema)

  hash = {
    index_name: index.name,
    key_schema: key_schema,
    projection: {
      projection_type: index.projection_type.to_s.upcase
    }
  }

  # If the projection type is include, specify the non key attributes
  if index.projection_type == :include
    hash[:projection][:non_key_attributes] = index.projected_attributes
  end

  # Only global secondary indexes have a separate throughput.
  if index.type == :global_secondary && options[:billing_mode] != :on_demand
    hash[:provisioned_throughput] = {
      read_capacity_units: index.read_capacity,
      write_capacity_units: index.write_capacity
    }
  end
  hash
end