Module: TinyDyno::Adapter

Extended by:
ActiveSupport::Concern, Adapter
Included in:
Adapter
Defined in:
lib/tiny_dyno/adapter.rb,
lib/tiny_dyno/adapter/items.rb,
lib/tiny_dyno/adapter/tables.rb,
lib/tiny_dyno/adapter/attributes.rb

Overview

Interactions with the DynamoDB store through aws-sdk-v2

Defined Under Namespace

Classes: AttributeValue

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#table_namesObject (readonly)

Returns the value of attribute table_names.



14
15
16
# File 'lib/tiny_dyno/adapter.rb', line 14

def table_names
  @table_names
end

Instance Method Details

#aws_attribute(field_type:, value:) ⇒ Object



151
152
153
154
# File 'lib/tiny_dyno/adapter/attributes.rb', line 151

def aws_attribute(field_type:, value:)
  av = TinyDyno::Adapter::AttributeValue.new
  av.marshal(type: field_type, value: value)
end

#connectObject



18
19
20
21
# File 'lib/tiny_dyno/adapter.rb', line 18

def connect
  connection
  connected?
end

#connected?Boolean

Returns:



23
24
25
26
27
28
29
30
31
# File 'lib/tiny_dyno/adapter.rb', line 23

def connected?
  begin
    connection.list_tables(limit: 1)
  rescue Errno::ECONNREFUSED, Aws::DynamoDB::Errors::UnrecognizedClientException => e
    return false
  end
  return true if @connection.class == Aws::DynamoDB::Client
  return false
end

#create_table(create_table_request) ⇒ true

docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#create_table-instance_method expect create_table_request to conform to above schema

Send the actual table creation to DynamoDB

Examples:

Create the table for the class

Person.create_table

Returns:

  • (true)

    if the operation succeeds



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/tiny_dyno/adapter/tables.rb', line 33

def create_table(create_table_request)
  table_settings = {
      provisioned_throughput: {
          read_capacity_units: 200,
          write_capacity_units: 200,
      },
  }.merge!(create_table_request)

  # Should or shouldn't we?
  # begin
  #   resp = connection.describe_table(table_name: table_settings[:table_name])
  # rescue Aws::DynamoDB::Errors::ResourceNotFoundException
  # ensure
  #   if resp.respond_to?(:table)
  #     p "Warning, table was already present : #{ table_settings[:table_name]}"
  #   end
  # end
  connection.create_table(table_settings)
  if wait_on_table_status(table_status: :table_exists, table_name: table_settings[:table_name])
    update_table_cache
    return true
  else
    return false
  end
end

#delete_item(request:) ⇒ Object



21
22
23
# File 'lib/tiny_dyno/adapter/items.rb', line 21

def delete_item(request:)
  connection.delete_item(request).successful?
end

#delete_table(table_name:) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/tiny_dyno/adapter/tables.rb', line 59

def delete_table(table_name:)
  begin
    connection.describe_table(table_name: table_name)
  rescue Aws::DynamoDB::Errors::ResourceNotFoundException
    # table not there anyway
    return true
  end
  if wait_on_table_status(table_status: :table_exists, table_name: table_name)
    connection.delete_table(table_name: table_name)
  else
    return false
  end
  wait_on_table_status(table_status: :table_not_exists, table_name: table_name)
  update_table_cache
  return true unless table_exists?(table_name: table_name)
  return false
end

#disconnect!Object



33
34
35
# File 'lib/tiny_dyno/adapter.rb', line 33

def disconnect!
  @connection = nil
end

#doc_attribute(value) ⇒ Object



156
157
158
159
160
# File 'lib/tiny_dyno/adapter/attributes.rb', line 156

def doc_attribute(value)
  return nil if value.nil?
  av = TinyDyno::Adapter::AttributeValue.new
  av.unmarshal(value)
end

#get_item(get_item_request:) ⇒ Object



13
14
15
16
17
18
19
# File 'lib/tiny_dyno/adapter/items.rb', line 13

def get_item(get_item_request:)
  resp = connection.get_item(get_item_request)
  return nil if resp.item.nil?
  typed_attributes = {}
  resp.item.each {|k,v| typed_attributes[k] = TinyDyno::Adapter.doc_attribute(v) }
  typed_attributes
end

#put_item(put_item_request:) ⇒ Object



9
10
11
# File 'lib/tiny_dyno/adapter/items.rb', line 9

def put_item(put_item_request:)
  connection.put_item(put_item_request).successful?
end

#query(body:) ⇒ Object



37
38
39
# File 'lib/tiny_dyno/adapter.rb', line 37

def query(body:)
  @connection.query(body)
end

#simple_attribute(field_type:, value:) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/tiny_dyno/adapter/attributes.rb', line 162

def simple_attribute(field_type:, value:)
  raw_attribute = aws_attribute(field_type: field_type, value: value)

  case field_type.to_s
    when 'Fixnum', 'Integer' then simple_value = doc_attribute(raw_attribute).to_i
    when 'Float' then simple_value = doc_attribute(raw_attribute).to_f
    when 'Numeric', 'String', 'Array', 'Hash', 'TinyDyno::Boolean' then simple_value = doc_attribute(raw_attribute)
  else
    raise ArgumentError, "unhandled type #{ field_type.inspect }"
  end
  simple_value
end

#table_exists?(table_name:) ⇒ true

Answer, whether a table is present, first by cache lookup and if miss on datastore

Examples:

Does the table exists?

TinyDyno::Adapter.table_exists?(table_name: Person.table_name)

Returns:

  • (true)

    if the table is present



17
18
19
20
21
# File 'lib/tiny_dyno/adapter/tables.rb', line 17

def table_exists?(table_name:)
  return true if @table_names.include?(table_name)
  update_table_cache
  @table_names.include?(table_name)
end

#update_item(update_item_request:) ⇒ Object



5
6
7
# File 'lib/tiny_dyno/adapter/items.rb', line 5

def update_item(update_item_request:)
  connection.update_item(update_item_request).successful?
end

#update_table_cacheObject

Hold a cache of available table names in an instance variable



79
80
81
82
83
# File 'lib/tiny_dyno/adapter/tables.rb', line 79

def update_table_cache
  return unless connected?
  new_table_names = connection.list_tables.table_names
  @table_names = new_table_names
end