aws-record 2.1.2 → 2.2.0
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 +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
|