Class: Dynamoid::Adapter

Inherits:
Object
  • Object
show all
Defined in:
lib/dynamoid/adapter.rb

Overview

Adapter’s value-add: 1) For the rest of Dynamoid, the gateway to DynamoDB. 2) Allows switching ‘config.adapter` to ease development of a new adapter. 3) Caches the list of tables Dynamoid knows about.

Instance Method Summary collapse

Constructor Details

#initializeAdapter



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

def initialize
  @adapter_ = Concurrent::Atom.new(nil)
  @tables_ = Concurrent::Atom.new(nil)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

Delegate all methods that aren’t defind here to the underlying adapter.

Since:

  • 0.2.0



159
160
161
162
# File 'lib/dynamoid/adapter.rb', line 159

def method_missing(method, *args, &block)
  return benchmark(method, *args) {adapter.send(method, *args, &block)} if adapter.respond_to?(method)
  super
end

Instance Method Details

#adapterObject

The actual adapter currently in use.

Since:

  • 0.2.0



28
29
30
31
32
33
34
35
36
# File 'lib/dynamoid/adapter.rb', line 28

def adapter
  if !@adapter_.value
    adapter = self.class.adapter_plugin_class.new
    adapter.connect! if adapter.respond_to?(:connect!)
    @adapter_.compare_and_set(nil, adapter)
    clear_cache!
  end
  @adapter_.value
end

#benchmark(method, *args) { ... } ⇒ Object

Shows how long it takes a method to run on the adapter. Useful for generating logged output.

Yields:

  • the actual code to benchmark

Since:

  • 0.2.0



51
52
53
54
55
56
# File 'lib/dynamoid/adapter.rb', line 51

def benchmark(method, *args)
  start = Time.now
  result = yield
  Dynamoid.logger.debug "(#{((Time.now - start) * 1000.0).round(2)} ms) #{method.to_s.split('_').collect(&:upcase).join(' ')}#{ " - #{args.inspect}" unless args.nil? || args.empty? }"
  return result
end

#clear_cache!Object



38
39
40
# File 'lib/dynamoid/adapter.rb', line 38

def clear_cache!
  @tables_.swap{|value, args| nil}
end

#create_table(table_name, key, options = {}) ⇒ Object



127
128
129
130
131
132
# File 'lib/dynamoid/adapter.rb', line 127

def create_table(table_name, key, options = {})
  if !tables.include?(table_name)
    benchmark('Create Table') { adapter.create_table(table_name, key, options) }
    tables << table_name
  end
end

#delete(table, ids, options = {}) ⇒ Object

Delete an item from a table.



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/dynamoid/adapter.rb', line 101

def delete(table, ids, options = {})
  range_key = options[:range_key] # array of range keys that matches the ids passed in
  if ids.respond_to?(:each)
    if range_key.respond_to?(:each)
      # turn ids into array of arrays each element being hash_key, range_key
      ids = ids.each_with_index.map{|id, i| [id, range_key[i]]}
    else
      ids = range_key ? ids.map { |id| [id, range_key] } : ids
    end

    batch_delete_item(table => ids)
  else
    delete_item(table, ids, options)
  end
end

#delete_table(table_name, options = {}) ⇒ Object

Since:

  • 0.2.0



135
136
137
138
139
140
141
# File 'lib/dynamoid/adapter.rb', line 135

def delete_table(table_name, options = {})
  if tables.include?(table_name)
    benchmark('Delete Table') { adapter.delete_table(table_name, options) }
    idx = tables.index(table_name)
    tables.delete_at(idx)
  end
end

#query(table_name, opts = {}) ⇒ Array

Query the DynamoDB table. This employs DynamoDB’s indexes so is generally faster than scanning, but is only really useful for range queries, since it can only find by one hash key at once. Only provide one range key to the hash.

Options Hash (opts):

  • :hash_value (String)

    the value of the hash key to find

  • :range_value (Range)

    find the range key within this range

  • :range_greater_than (Number)

    find range keys greater than this

  • :range_less_than (Number)

    find range keys less than this

  • :range_gte (Number)

    find range keys greater than or equal to this

  • :range_lte (Number)

    find range keys less than or equal to this



179
180
181
# File 'lib/dynamoid/adapter.rb', line 179

def query(table_name, opts = {})
  adapter.query(table_name, opts)
end

#read(table, ids, options = {}, &blk) ⇒ Object

Read one or many keys from the selected table. This method intelligently calls batch_get or get on the underlying adapter depending on whether ids is a range or a single key. If a range key is present, it will also interpolate that into the ids so that the batch get will acquire the correct record.

Since:

  • 0.2.0



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/dynamoid/adapter.rb', line 83

def read(table, ids, options = {}, &blk)
  range_key = options.delete(:range_key)

  if ids.respond_to?(:each)
    ids = ids.collect{|id| range_key ? [id, range_key] : id}
    batch_get_item({table => ids}, options, &blk)
  else
    options[:range_key] = range_key if range_key
    get_item(table, ids, options)
  end
end

#scan(table, query = {}, opts = {}) ⇒ Object

Scans a table. Generally quite slow; try to avoid using scan if at all possible.

Since:

  • 0.2.0



123
124
125
# File 'lib/dynamoid/adapter.rb', line 123

def scan(table, query = {}, opts = {})
  benchmark('Scan', table, query) {adapter.scan(table, query, opts)}
end

#tablesObject



18
19
20
21
22
23
# File 'lib/dynamoid/adapter.rb', line 18

def tables
  if !@tables_.value
    @tables_.swap{|value, args| benchmark('Cache Tables') { list_tables || [] } }
  end
  @tables_.value
end

#write(table, object, options = nil) ⇒ Object

Write an object to the adapter.

Since:

  • 0.2.0



67
68
69
# File 'lib/dynamoid/adapter.rb', line 67

def write(table, object, options = nil)
  put_item(table, object, options)
end