Class: Dynamoid::Adapter
- Inherits:
-
Object
- Object
- Dynamoid::Adapter
- 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.
Class Method Summary collapse
Instance Method Summary collapse
-
#adapter ⇒ Object
The actual adapter currently in use.
-
#benchmark(method, *args) { ... } ⇒ Object
Shows how long it takes a method to run on the adapter.
- #clear_cache! ⇒ Object
- #create_table(table_name, key, options = {}) ⇒ Object
-
#delete(table, ids, options = {}) ⇒ Object
Delete an item from a table.
- #delete_table(table_name, options = {}) ⇒ Object
-
#initialize ⇒ Adapter
constructor
A new instance of Adapter.
-
#method_missing(method, *args, &block) ⇒ Object
Delegate all methods that aren’t defind here to the underlying adapter.
-
#query(table_name, key_conditions, non_key_conditions = {}, options = {}) ⇒ Enumerable
Query the DynamoDB table.
-
#read(table, ids, options = {}, &blk) ⇒ Object
Read one or many keys from the selected table.
-
#scan(table, query = {}, opts = {}) ⇒ Object
Scans a table.
- #tables ⇒ Object
-
#write(table, object, options = nil) ⇒ Object
Write an object to the adapter.
Constructor Details
#initialize ⇒ Adapter
Returns a new instance of Adapter.
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.
157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/dynamoid/adapter.rb', line 157 def method_missing(method, *args, &block) # Don't use keywork arguments delegating (with **kw). It works in # different way in different Ruby versions: <= 2.6, 2.7, 3.0 and in some # future 3.x versions. Providing that there are no downstream methods # with keyword arguments in adapter. # # https://eregon.me/blog/2019/11/10/the-delegation-challenge-of-ruby27.html return benchmark(method, *args) { adapter.send(method, *args, &block) } if adapter.respond_to?(method) super end |
Class Method Details
.adapter_plugin_class ⇒ Object
195 196 197 |
# File 'lib/dynamoid/adapter.rb', line 195 def self.adapter_plugin_class Dynamoid::AdapterPlugin.const_get(Dynamoid::Config.adapter.camelcase) end |
Instance Method Details
#adapter ⇒ Object
The actual adapter currently in use.
28 29 30 31 32 33 34 35 36 |
# File 'lib/dynamoid/adapter.rb', line 28 def adapter unless @adapter_.value adapter = self.class.adapter_plugin_class.new adapter.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.
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?}" 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
125 126 127 128 129 130 131 132 133 134 |
# File 'lib/dynamoid/adapter.rb', line 125 def create_table(table_name, key, = {}) unless tables.include?(table_name) result = nil benchmark('Create Table') { result = adapter.create_table(table_name, key, ) } tables << table_name result else false end end |
#delete(table, ids, options = {}) ⇒ Object
Delete an item from a table.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/dynamoid/adapter.rb', line 99 def delete(table, ids, = {}) range_key = [:range_key] # array of range keys that matches the ids passed in if ids.respond_to?(:each) ids = if range_key.respond_to?(:each) # turn ids into array of arrays each element being hash_key, range_key ids.each_with_index.map { |id, i| [id, range_key[i]] } else range_key ? ids.map { |id| [id, range_key] } : ids end batch_delete_item(table => ids) else delete_item(table, ids, ) end end |
#delete_table(table_name, options = {}) ⇒ Object
137 138 139 140 141 142 143 |
# File 'lib/dynamoid/adapter.rb', line 137 def delete_table(table_name, = {}) if tables.include?(table_name) benchmark('Delete Table') { adapter.delete_table(table_name, ) } idx = tables.index(table_name) tables.delete_at(idx) end end |
#query(table_name, key_conditions, non_key_conditions = {}, options = {}) ⇒ Enumerable
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.
Dynamoid.adapter.query('users', { id: [[:eq, '1']], age: [[:between, [10, 30]]] }, { batch_size: 1000 })
191 192 193 |
# File 'lib/dynamoid/adapter.rb', line 191 def query(table_name, key_conditions, non_key_conditions = {}, = {}) adapter.query(table_name, key_conditions, non_key_conditions, ) 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.
83 84 85 86 87 88 89 |
# File 'lib/dynamoid/adapter.rb', line 83 def read(table, ids, = {}, &blk) if ids.respond_to?(:each) batch_get_item({ table => ids }, , &blk) else get_item(table, ids, ) end end |
#scan(table, query = {}, opts = {}) ⇒ Object
Scans a table. Generally quite slow; try to avoid using scan if at all possible.
121 122 123 |
# File 'lib/dynamoid/adapter.rb', line 121 def scan(table, query = {}, opts = {}) benchmark('Scan', table, query) { adapter.scan(table, query, opts) } end |
#tables ⇒ Object
18 19 20 21 22 23 |
# File 'lib/dynamoid/adapter.rb', line 18 def tables unless @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.
67 68 69 |
# File 'lib/dynamoid/adapter.rb', line 67 def write(table, object, = nil) put_item(table, object, ) end |