aws-record 2.1.2 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aws-record/record/table_config.rb +135 -38
- data/lib/aws-record/record/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76f3f70bc226f5e34e377328a8829db296bffa304238da8d7542a947ba0b7a9e
|
4
|
+
data.tar.gz: f22f14e087edf96717fbaffd03bc7b3917001fb5238597994143b50bc5e16894
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 745aff26cc027c53552b456066b56900f1489c1aa4433b8e539d1ac6f093d0cbaa62dec5054b433d2f8f2f42220471cca55dcdb6fa0d6ae1d23f542318ccd296
|
7
|
+
data.tar.gz: 2e20c004f7ca252dfdff66eb4005137c74da60a964ce4862bb2390fceaf6ce2fe0f1c63bcdc00a1671f13c69dc6165b0488afc1ba4779b524ba1740c1d7f2591
|
@@ -33,6 +33,17 @@ module Aws
|
|
33
33
|
# t.write_capacity_units 5
|
34
34
|
# end
|
35
35
|
#
|
36
|
+
# @example A basic model with pay per request billing.
|
37
|
+
# class Model
|
38
|
+
# include Aws::Record
|
39
|
+
# string_attr :uuid, hash_key: true
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# table_config = Aws::Record::TableConfig.define do |t|
|
43
|
+
# t.model_class Model
|
44
|
+
# t.billing_mode "PAY_PER_REQUEST"
|
45
|
+
# end
|
46
|
+
#
|
36
47
|
# @example Running a conditional migration on a basic model.
|
37
48
|
# table_config = Aws::Record::TableConfig.define do |t|
|
38
49
|
# t.model_class Model
|
@@ -59,7 +70,9 @@ module Aws
|
|
59
70
|
# :title,
|
60
71
|
# hash_key: :forum_uuid,
|
61
72
|
# range_key: :post_title,
|
62
|
-
#
|
73
|
+
# projection: {
|
74
|
+
# projection_type: "ALL"
|
75
|
+
# }
|
63
76
|
# )
|
64
77
|
# end
|
65
78
|
#
|
@@ -106,7 +119,12 @@ module Aws
|
|
106
119
|
# * +#write_capacity_units+ Sets the write capacity units for the
|
107
120
|
# index.
|
108
121
|
# * +#ttl_attribute+ Sets the attribute ID to be used as the TTL
|
109
|
-
#
|
122
|
+
# attribute, and if present, TTL will be enabled for the table.
|
123
|
+
# * +#billing_mode+ Sets the billing mode, with the current supported
|
124
|
+
# options being "PROVISIONED" and "PAY_PER_REQUEST". If using
|
125
|
+
# "PAY_PER_REQUEST" you must not set provisioned throughput values,
|
126
|
+
# and if using "PROVISIONED" you must set provisioned throughput
|
127
|
+
# values. Default assumption is "PROVISIONED".
|
110
128
|
#
|
111
129
|
# @example Defining a migration with a GSI.
|
112
130
|
# class Forum
|
@@ -151,6 +169,7 @@ module Aws
|
|
151
169
|
def initialize
|
152
170
|
@client_options = {}
|
153
171
|
@global_secondary_indexes = {}
|
172
|
+
@billing_mode = "PROVISIONED" # default
|
154
173
|
end
|
155
174
|
|
156
175
|
# @api private
|
@@ -195,6 +214,11 @@ module Aws
|
|
195
214
|
end
|
196
215
|
end
|
197
216
|
|
217
|
+
# @api private
|
218
|
+
def billing_mode(mode)
|
219
|
+
@billing_mode = mode
|
220
|
+
end
|
221
|
+
|
198
222
|
# Performs a migration, if needed, against the remote table. If
|
199
223
|
# +#compatible?+ would return true, the remote table already has the same
|
200
224
|
# throughput, key schema, attribute definitions, and global secondary
|
@@ -209,13 +233,7 @@ module Aws
|
|
209
233
|
else
|
210
234
|
# Gotcha: You need separate migrations for indexes and throughput
|
211
235
|
unless _throughput_equal(resp)
|
212
|
-
@client.update_table(
|
213
|
-
table_name: @model_class.table_name,
|
214
|
-
provisioned_throughput: {
|
215
|
-
read_capacity_units: @read_capacity_units,
|
216
|
-
write_capacity_units: @write_capacity_units
|
217
|
-
}
|
218
|
-
)
|
236
|
+
@client.update_table(_update_throughput_opts(resp))
|
219
237
|
@client.wait_until(
|
220
238
|
:table_exists,
|
221
239
|
table_name: @model_class.table_name
|
@@ -327,12 +345,19 @@ module Aws
|
|
327
345
|
|
328
346
|
def _create_table_opts
|
329
347
|
opts = {
|
330
|
-
table_name: @model_class.table_name
|
331
|
-
|
348
|
+
table_name: @model_class.table_name
|
349
|
+
}
|
350
|
+
if @billing_mode == "PROVISIONED"
|
351
|
+
opts[:provisioned_throughput] = {
|
332
352
|
read_capacity_units: @read_capacity_units,
|
333
353
|
write_capacity_units: @write_capacity_units
|
334
354
|
}
|
335
|
-
|
355
|
+
elsif @billing_mode == "PAY_PER_REQUEST"
|
356
|
+
opts[:billing_mode] = @billing_mode
|
357
|
+
else
|
358
|
+
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
359
|
+
end
|
360
|
+
|
336
361
|
opts[:key_schema] = _key_schema
|
337
362
|
opts[:attribute_definitions] = _attribute_definitions
|
338
363
|
gsi = _global_secondary_indexes
|
@@ -342,6 +367,54 @@ module Aws
|
|
342
367
|
opts
|
343
368
|
end
|
344
369
|
|
370
|
+
def _add_global_secondary_index_throughput(opts, resp_gsis)
|
371
|
+
gsis = resp_gsis.map do |g|
|
372
|
+
g.index_name
|
373
|
+
end
|
374
|
+
gsi_updates = []
|
375
|
+
gsis.each do |index_name|
|
376
|
+
lgsi = @global_secondary_indexes[index_name.to_sym]
|
377
|
+
gsi_updates << {
|
378
|
+
update: {
|
379
|
+
index_name: index_name,
|
380
|
+
provisioned_throughput: lgsi.provisioned_throughput
|
381
|
+
}
|
382
|
+
}
|
383
|
+
end
|
384
|
+
opts[:global_secondary_index_updates] = gsi_updates
|
385
|
+
true
|
386
|
+
end
|
387
|
+
|
388
|
+
def _update_throughput_opts(resp)
|
389
|
+
if @billing_mode == "PROVISIONED"
|
390
|
+
opts = {
|
391
|
+
table_name: @model_class.table_name,
|
392
|
+
provisioned_throughput: {
|
393
|
+
read_capacity_units: @read_capacity_units,
|
394
|
+
write_capacity_units: @write_capacity_units
|
395
|
+
}
|
396
|
+
}
|
397
|
+
# special case: we have global secondary indexes existing, and they
|
398
|
+
# need provisioned capacity to be set within this call
|
399
|
+
if !resp.table.billing_mode_summary.nil? &&
|
400
|
+
resp.table.billing_mode_summary.billing_mode == "PAY_PER_REQUEST"
|
401
|
+
opts[:billing_mode] = @billing_mode
|
402
|
+
if resp.table.global_secondary_indexes
|
403
|
+
resp_gsis = resp.table.global_secondary_indexes
|
404
|
+
_add_global_secondary_index_throughput(opts, resp_gsis)
|
405
|
+
end
|
406
|
+
end # else don't include billing mode
|
407
|
+
opts
|
408
|
+
elsif @billing_mode == "PAY_PER_REQUEST"
|
409
|
+
{
|
410
|
+
table_name: @model_class.table_name,
|
411
|
+
billing_mode: "PAY_PER_REQUEST"
|
412
|
+
}
|
413
|
+
else
|
414
|
+
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
345
418
|
def _update_index_opts(resp)
|
346
419
|
gsi_updates, attribute_definitions = _gsi_updates(resp)
|
347
420
|
opts = {
|
@@ -369,22 +442,25 @@ module Aws
|
|
369
442
|
gsi[:key_schema].each do |k|
|
370
443
|
attributes_referenced.add(k[:attribute_name])
|
371
444
|
end
|
372
|
-
|
373
|
-
|
374
|
-
|
445
|
+
if @billing_mode == "PROVISIONED"
|
446
|
+
lgsi = @global_secondary_indexes[index_name.to_sym]
|
447
|
+
gsi[:provisioned_throughput] = lgsi.provisioned_throughput
|
448
|
+
end
|
375
449
|
gsi_updates << {
|
376
450
|
create: gsi
|
377
451
|
}
|
378
452
|
end
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
453
|
+
# we don't currently update anything other than throughput
|
454
|
+
if @billing_mode == "PROVISIONED"
|
455
|
+
update_candidates.each do |index_name|
|
456
|
+
lgsi = @global_secondary_indexes[index_name.to_sym]
|
457
|
+
gsi_updates << {
|
458
|
+
update: {
|
459
|
+
index_name: index_name,
|
460
|
+
provisioned_throughput: lgsi.provisioned_throughput
|
461
|
+
}
|
386
462
|
}
|
387
|
-
|
463
|
+
end
|
388
464
|
end
|
389
465
|
attribute_definitions = _attribute_definitions
|
390
466
|
incremental_attributes = attributes_referenced.map do |attr_name|
|
@@ -438,13 +514,18 @@ module Aws
|
|
438
514
|
end
|
439
515
|
|
440
516
|
def _throughput_equal(resp)
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
517
|
+
if @billing_mode == "PAY_PER_REQUEST"
|
518
|
+
!resp.table.billing_mode_summary.nil? &&
|
519
|
+
resp.table.billing_mode_summary.billing_mode == "PAY_PER_REQUEST"
|
520
|
+
else
|
521
|
+
expected = resp.table.provisioned_throughput.to_h
|
522
|
+
actual = {
|
523
|
+
read_capacity_units: @read_capacity_units,
|
524
|
+
write_capacity_units: @write_capacity_units
|
525
|
+
}
|
526
|
+
actual.all? do |k,v|
|
527
|
+
expected[k] == v
|
528
|
+
end
|
448
529
|
end
|
449
530
|
end
|
450
531
|
|
@@ -498,10 +579,17 @@ module Aws
|
|
498
579
|
remote_key_schema = rgsi.key_schema.map { |i| i.to_h }
|
499
580
|
ks_match = _array_unsorted_eql(remote_key_schema, lgsi[:key_schema])
|
500
581
|
|
582
|
+
# Throughput Check: Dependent on Billing Mode
|
501
583
|
rpt = rgsi.provisioned_throughput.to_h
|
502
584
|
lpt = lgsi[:provisioned_throughput]
|
503
|
-
|
504
|
-
|
585
|
+
if @billing_mode == "PROVISIONED"
|
586
|
+
pt_match = lpt.all? do |k,v|
|
587
|
+
rpt[k] == v
|
588
|
+
end
|
589
|
+
elsif @billing_mode == "PAY_PER_REQUEST"
|
590
|
+
pt_match = lpt.nil? ? true : false
|
591
|
+
else
|
592
|
+
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
505
593
|
end
|
506
594
|
|
507
595
|
rp = rgsi.projection.to_h
|
@@ -537,10 +625,13 @@ module Aws
|
|
537
625
|
if model_gsis
|
538
626
|
model_gsis.each do |mgsi|
|
539
627
|
config = gsi_config[mgsi[:index_name]]
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
628
|
+
if @billing_mode == "PROVISIONED"
|
629
|
+
gsis << mgsi.merge(
|
630
|
+
provisioned_throughput: config.provisioned_throughput
|
631
|
+
)
|
632
|
+
else
|
633
|
+
gsis << mgsi
|
634
|
+
end
|
544
635
|
end
|
545
636
|
end
|
546
637
|
gsis
|
@@ -553,8 +644,14 @@ module Aws
|
|
553
644
|
def _validate_required_configuration
|
554
645
|
missing_config = []
|
555
646
|
missing_config << 'model_class' unless @model_class
|
556
|
-
|
557
|
-
|
647
|
+
if @billing_mode == "PROVISIONED"
|
648
|
+
missing_config << 'read_capacity_units' unless @read_capacity_units
|
649
|
+
missing_config << 'write_capacity_units' unless @write_capacity_units
|
650
|
+
else
|
651
|
+
if @read_capacity_units || @write_capacity_units
|
652
|
+
raise ArgumentError.new("Cannot have billing mode #{@billing_mode} with provisioned capacity.")
|
653
|
+
end
|
654
|
+
end
|
558
655
|
unless missing_config.empty?
|
559
656
|
msg = missing_config.join(', ')
|
560
657
|
raise Errors::MissingRequiredConfiguration, 'Missing: ' + msg
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amazon Web Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-dynamodb
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.18'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.18'
|
27
27
|
description: Provides an object mapping abstraction for Amazon DynamoDB.
|
28
28
|
email:
|
29
29
|
- alexwood@amazon.com
|