dynamini 2.9.1 → 2.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +17 -20
- data/README.md +18 -9
- data/dynamini.gemspec +1 -1
- data/lib/dynamini/batch_operations.rb +12 -8
- data/lib/dynamini/test_client.rb +12 -13
- data/spec/dynamini/batch_operations_spec.rb +20 -12
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4da5852711d8ecb8a226a9ae7c987f2ea0324927
|
4
|
+
data.tar.gz: eec0aaae89719060294b9ae055f8effabf79dd9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6eaf764f422c931ae8e5d669f2b26349cfaffedfcabb6c13654f06ac40b758ea371b0328149d1f3c0914de67972fa7971d7a01d89bef94b6ab825b3bd1527c3
|
7
|
+
data.tar.gz: d97dab7690b1c371052bff3c1c1a7b8d39107281b2ed71c90e6eb05b3dc18998d9f51c8ad81307ebb249de1d4924f56245ef8f4e85100d42d4fd71b870f5081c
|
data/Gemfile.lock
CHANGED
@@ -1,30 +1,29 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dynamini (2.9.
|
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.
|
12
|
-
activesupport (= 4.2.
|
11
|
+
activemodel (4.2.5.1)
|
12
|
+
activesupport (= 4.2.5.1)
|
13
13
|
builder (~> 3.1)
|
14
|
-
activesupport (4.2.
|
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.
|
20
|
-
aws-sdk-resources (= 2.
|
21
|
-
aws-sdk-core (2.
|
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.
|
25
|
-
aws-sdk-core (= 2.
|
26
|
-
|
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.
|
53
|
-
jmespath (1.3
|
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.
|
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.
|
89
|
-
tzinfo (1.2.
|
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 (
|
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
|
-
|
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
|
|
data/dynamini.gemspec
CHANGED
@@ -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
|
-
|
46
|
-
|
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:
|
81
|
+
exclusive_start_key: start_key,
|
78
82
|
secondary_index_name: options[:index_name],
|
79
83
|
limit: options[:limit],
|
80
84
|
segment: options[:segment],
|
data/lib/dynamini/test_client.rb
CHANGED
@@ -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
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
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(
|
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(
|
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
|
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
|
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',
|
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',
|
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
|
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
|
216
|
+
expect(response.last_evaluated_key).to be_nil
|
209
217
|
end
|
210
218
|
end
|
211
219
|
end
|