dynamini 2.9.1 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d5e2c24bc6e120e7bb25eebcc819ec7081aef462
4
- data.tar.gz: e484085550e7692f05431a5b79b38a6f4f002cda
3
+ metadata.gz: 4da5852711d8ecb8a226a9ae7c987f2ea0324927
4
+ data.tar.gz: eec0aaae89719060294b9ae055f8effabf79dd9b
5
5
  SHA512:
6
- metadata.gz: 5e82d4a69eb80db5534cd3a70e4c1f795ba13651202ca6b228945a7fb58fd5c7289c173f7cbf12a8ca9b3a255f986b14c7b6410e63d8e8e44168c82f417dbf18
7
- data.tar.gz: 387de4884bedfed45b9a475a617d2666382271221288eb45ae2d9d32fb3bcdf51f8f05e5fe5d7e511533526e7c4b7166a11977984a923abf61e9453eb71aae03
6
+ metadata.gz: f6eaf764f422c931ae8e5d669f2b26349cfaffedfcabb6c13654f06ac40b758ea371b0328149d1f3c0914de67972fa7971d7a01d89bef94b6ab825b3bd1527c3
7
+ data.tar.gz: d97dab7690b1c371052bff3c1c1a7b8d39107281b2ed71c90e6eb05b3dc18998d9f51c8ad81307ebb249de1d4924f56245ef8f4e85100d42d4fd71b870f5081c
@@ -1,30 +1,29 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dynamini (2.9.1)
4
+ dynamini (2.9.2)
5
5
  activemodel (>= 3, < 5.0)
6
6
  aws-sdk (~> 2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (4.2.9)
12
- activesupport (= 4.2.9)
11
+ activemodel (4.2.5.1)
12
+ activesupport (= 4.2.5.1)
13
13
  builder (~> 3.1)
14
- activesupport (4.2.9)
14
+ activesupport (4.2.5.1)
15
15
  i18n (~> 0.7)
16
+ json (~> 1.7, >= 1.7.7)
16
17
  minitest (~> 5.1)
17
18
  thread_safe (~> 0.3, >= 0.3.4)
18
19
  tzinfo (~> 1.1)
19
- aws-sdk (2.10.44)
20
- aws-sdk-resources (= 2.10.44)
21
- aws-sdk-core (2.10.44)
22
- aws-sigv4 (~> 1.0)
20
+ aws-sdk (2.2.22)
21
+ aws-sdk-resources (= 2.2.22)
22
+ aws-sdk-core (2.2.22)
23
23
  jmespath (~> 1.0)
24
- aws-sdk-resources (2.10.44)
25
- aws-sdk-core (= 2.10.44)
26
- aws-sigv4 (1.0.2)
27
- builder (3.2.3)
24
+ aws-sdk-resources (2.2.22)
25
+ aws-sdk-core (= 2.2.22)
26
+ builder (3.2.2)
28
27
  coderay (1.1.0)
29
28
  diff-lcs (1.2.5)
30
29
  ffi (1.9.10)
@@ -49,14 +48,15 @@ GEM
49
48
  guard-shell (0.7.1)
50
49
  guard (>= 2.0.0)
51
50
  guard-compat (~> 1.0)
52
- i18n (0.8.6)
53
- jmespath (1.3.1)
51
+ i18n (0.7.0)
52
+ jmespath (1.1.3)
53
+ json (1.8.3)
54
54
  listen (3.0.3)
55
55
  rb-fsevent (>= 0.9.3)
56
56
  rb-inotify (>= 0.9)
57
57
  lumberjack (1.0.9)
58
58
  method_source (0.8.2)
59
- minitest (5.10.3)
59
+ minitest (5.8.4)
60
60
  nenv (0.2.0)
61
61
  notiffany (0.0.8)
62
62
  nenv (~> 0.1)
@@ -85,8 +85,8 @@ GEM
85
85
  shellany (0.0.1)
86
86
  slop (3.6.0)
87
87
  thor (0.19.1)
88
- thread_safe (0.3.6)
89
- tzinfo (1.2.3)
88
+ thread_safe (0.3.5)
89
+ tzinfo (1.2.2)
90
90
  thread_safe (~> 0.1)
91
91
 
92
92
  PLATFORMS
@@ -99,6 +99,3 @@ DEPENDENCIES
99
99
  guard-shell
100
100
  pry (~> 0)
101
101
  rspec (~> 3)
102
-
103
- BUNDLED WITH
104
- 1.16.0.pre.2
data/README.md CHANGED
@@ -204,18 +204,27 @@ Table scanning is a very expensive operation, and should not be undertaken witho
204
204
 
205
205
  The following options are supported:
206
206
 
207
- * consistent_read (default: false)
208
- * start_key (hash key of first desired item, default will scan from beginning)
209
- * index_name (if scanning a secondary index - see below)
210
- * limit
207
+ * :consistent_read (default: false)
208
+ * :start_key (key of first desired item, if unset will scan from beginning)
209
+ * :index_name (if scanning a secondary index - see below)
210
+ * :limit (default: no limit except for AWS chunk size)
211
+ * :segment (for multiprocess scanning)
212
+ * :total_segments (for multiprocess scanning)
213
+
214
+ Note that start_key can be either a hash { "AttributeName" => "Value" } or a value literal. If start_key is a literal then the attribute name will be inferred automatically, either being the main hash_key of your model or the key of the secondary index matching the provided index_name.
215
+
216
+ For more information about using segment and total_segments for parallelization, see: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html
211
217
 
212
- These two options are to support paralellization of table scanning, see: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html
213
- * segment
214
- * total_segments
215
218
 
216
219
  ```ruby
217
- products_page_one = Product.scan(limit: 100)
218
- products_page_one.found # [product, product...]
220
+ products_page_one = Product.scan(limit: 100, start_key: 'abcd')
221
+
222
+ products_page_one.found
223
+ > [product, product...]
224
+
225
+ products_page_one.last_evaluated_key
226
+ > {'id' => 'wxyz'}
227
+
219
228
  page_two = Product.scan(start_key: products_page_one.last_evaluated_key)
220
229
  ```
221
230
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'dynamini'
3
- s.version = '2.9.1'
3
+ s.version = '2.9.2'
4
4
  s.summary = 'DynamoDB interface'
5
5
  s.description = 'Lightweight DynamoDB interface gem designed as
6
6
  a drop-in replacement for ActiveRecord.
@@ -36,14 +36,9 @@ module Dynamini
36
36
  def scan(options = {})
37
37
  validate_scan_options(options)
38
38
  response = dynamo_scan(options)
39
- if options[:index_name]
40
- last_evaluated_key = response.last_evaluated_key[secondary_index[options[:index_name]][:hash_key_name].to_s]
41
- else
42
- last_evaluated_key = response.last_evaluated_key[hash_key.to_s]
43
- end
44
39
  OpenStruct.new(
45
- last_evaluated_key: last_evaluated_key,
46
- items: response.items.map { |i| new(i.symbolize_keys, false) }
40
+ items: response.items.map { |i| new(i.symbolize_keys, false) },
41
+ last_evaluated_key: response.last_evaluated_key
47
42
  )
48
43
  end
49
44
 
@@ -72,9 +67,18 @@ module Dynamini
72
67
  end
73
68
 
74
69
  def dynamo_scan(options)
70
+ if options[:start_key] && !options[:start_key].is_a?(Hash)
71
+ if options[:index_name]
72
+ start_key = { options[:index_name].to_s => options[:start_key] }
73
+ else
74
+ start_key = { hash_key.to_s => options[:start_key] }
75
+ end
76
+ else
77
+ start_key = options[:start_key]
78
+ end
75
79
  client.scan({
76
80
  consistent_read: options[:consistent_read],
77
- exclusive_start_key: options[:exclusive_start_key],
81
+ exclusive_start_key: start_key,
78
82
  secondary_index_name: options[:index_name],
79
83
  limit: options[:limit],
80
84
  segment: options[:segment],
@@ -90,8 +90,8 @@ module Dynamini
90
90
  sort_scanned_records!(records, args[:secondary_index_name]) if args[:secondary_index_name]
91
91
  start_index = index_of_start_key(args, records)
92
92
  items = limit_scanned_records(args[:limit], records, start_index)
93
- last_evaluated_key = get_last_evaluated_key(args[:secondary_index_name], items)
94
- OpenStruct.new(items: items, last_evaluated_key: last_evaluated_key)
93
+ last_evaluated_key = get_last_evaluated_key(args[:secondary_index_name], items, records)
94
+ OpenStruct.new({items: items, last_evaluated_key: last_evaluated_key})
95
95
  end
96
96
 
97
97
  def sort_scanned_records!(records, secondary_index_name)
@@ -106,9 +106,9 @@ module Dynamini
106
106
  sec_index = secondary_index[args[:secondary_index_name]]
107
107
  start_index = records.index do |r|
108
108
  if sec_index
109
- r[get_secondary_hash_key(sec_index)] == args[:exclusive_start_key]
109
+ r[get_secondary_hash_key(sec_index)] == args[:exclusive_start_key].values[0]
110
110
  else
111
- r[hash_key_attr] == args[:exclusive_start_key]
111
+ r[hash_key_attr] == args[:exclusive_start_key].values[0]
112
112
  end
113
113
  end
114
114
  start_index || -1
@@ -122,16 +122,15 @@ module Dynamini
122
122
  records[start_index..end_index]
123
123
  end
124
124
 
125
- def get_last_evaluated_key(secondary_index_name, items)
126
- # TODO should last evaluated key be present if the args[:limit] was reached?
127
- # if items.length > records.length
128
- index = secondary_index[secondary_index_name]
129
- if index
130
- { get_secondary_hash_key(index).to_s => items.last[get_secondary_hash_key(index)] }
131
- else
132
- { hash_key_attr.to_s => items.last[hash_key_attr] }
125
+ def get_last_evaluated_key(secondary_index_name, items, records)
126
+ if items.last != records.last
127
+ index = secondary_index[secondary_index_name]
128
+ if index
129
+ { get_secondary_hash_key(index).to_s => items.last[get_secondary_hash_key(index)] }
130
+ else
131
+ { hash_key_attr.to_s => items.last[hash_key_attr] }
132
+ end
133
133
  end
134
- # end
135
134
  end
136
135
 
137
136
  # TODO add range key support for delete, not currently implemented batch_operations.batch_delete
@@ -146,16 +146,24 @@ describe Dynamini::BatchOperations do
146
146
  context 'with an exclusive_start_key' do
147
147
  context 'with a limit' do
148
148
  it 'retrieves the correct items' do
149
- response = SecBase.scan(exclusive_start_key: '124', limit: 1)
149
+ response = SecBase.scan(start_key: '124', limit: 1)
150
150
  expect(response.items.map { |i| i.id }).to eq(['124'])
151
- expect(response.last_evaluated_key).to eq('124')
151
+ expect(response.last_evaluated_key).to eq('id' => '124')
152
152
  end
153
153
  end
154
154
  context 'without a limit' do
155
155
  it 'retrieves the correct items' do
156
- response = SecBase.scan(exclusive_start_key: '124')
156
+ response = SecBase.scan(start_key: '124')
157
157
  expect(response.items.map { |i| i.id }).to eq(%w(124 125 126))
158
- expect(response.last_evaluated_key).to eq('126')
158
+ expect(response.last_evaluated_key).to be_nil
159
+ end
160
+ end
161
+
162
+ context 'the start key is in aws sdk style' do
163
+ it 'retrieves the correct items' do
164
+ response = SecBase.scan(start_key: {'id' => '124'}, limit: 2)
165
+ expect(response.items.map { |i| i.id }).to eq(['124', '125'])
166
+ expect(response.last_evaluated_key).to eq('id' => '125')
159
167
  end
160
168
  end
161
169
  end
@@ -164,14 +172,14 @@ describe Dynamini::BatchOperations do
164
172
  it 'retrieves the correct items' do
165
173
  response = SecBase.scan(limit: 2)
166
174
  expect(response.items.map { |i| i.id }).to eq(%w(123 124))
167
- expect(response.last_evaluated_key).to eq('124')
175
+ expect(response.last_evaluated_key).to eq('id' => '124')
168
176
  end
169
177
  end
170
178
  context 'without a limit' do
171
179
  it 'retrieves the correct items' do
172
180
  response = SecBase.scan
173
181
  expect(response.items.map { |i| i.id }).to eq(%w(123 124 125 126))
174
- expect(response.last_evaluated_key).to eq('126')
182
+ expect(response.last_evaluated_key).to be_nil
175
183
  end
176
184
  end
177
185
  end
@@ -180,16 +188,16 @@ describe Dynamini::BatchOperations do
180
188
  context 'with an exclusive_start_key' do
181
189
  context 'with a limit' do
182
190
  it 'retrieves the correct items' do
183
- response = SecBase.scan(index_name: 'sec', exclusive_start_key: 'B', limit: 2)
191
+ response = SecBase.scan(index_name: 'sec', start_key: 'B', limit: 2)
184
192
  expect(response.items.map { |i| i.sec }).to eq(%w(B C))
185
- expect(response.last_evaluated_key).to eq('C')
193
+ expect(response.last_evaluated_key).to eq('sec' => 'C')
186
194
  end
187
195
  end
188
196
  context 'without a limit' do
189
197
  it 'retrieves the correct items' do
190
- response = SecBase.scan(index_name: 'sec', exclusive_start_key: 'B')
198
+ response = SecBase.scan(index_name: 'sec', start_key: 'B')
191
199
  expect(response.items.map { |i| i.sec }).to eq(%w(B C D))
192
- expect(response.last_evaluated_key).to eq('D')
200
+ expect(response.last_evaluated_key).to be_nil
193
201
  end
194
202
  end
195
203
  end
@@ -198,14 +206,14 @@ describe Dynamini::BatchOperations do
198
206
  it 'retrieves the correct items' do
199
207
  response = SecBase.scan(index_name: 'sec', limit: 3)
200
208
  expect(response.items.map { |i| i.sec }).to eq(%w(A B C))
201
- expect(response.last_evaluated_key).to eq('C')
209
+ expect(response.last_evaluated_key).to eq('sec' => 'C')
202
210
  end
203
211
  end
204
212
  context 'without a limit' do
205
213
  it 'retrieves the correct items' do
206
214
  response = SecBase.scan(index_name: 'sec')
207
215
  expect(response.items.map { |i| i.sec }).to eq(%w(A B C D))
208
- expect(response.last_evaluated_key).to eq('D')
216
+ expect(response.last_evaluated_key).to be_nil
209
217
  end
210
218
  end
211
219
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamini
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.1
4
+ version: 2.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Ward