aws-record 2.10.1 → 2.11.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/CHANGELOG.md +5 -0
- data/VERSION +1 -1
- data/lib/aws-record/record/attribute.rb +4 -6
- data/lib/aws-record/record/attributes.rb +36 -49
- data/lib/aws-record/record/batch.rb +13 -12
- data/lib/aws-record/record/batch_read.rb +5 -2
- data/lib/aws-record/record/buildable_search.rb +29 -26
- data/lib/aws-record/record/client_configuration.rb +9 -9
- data/lib/aws-record/record/dirty_tracking.rb +29 -32
- data/lib/aws-record/record/errors.rb +0 -1
- data/lib/aws-record/record/item_collection.rb +4 -4
- data/lib/aws-record/record/item_data.rb +3 -6
- data/lib/aws-record/record/item_operations.rb +77 -93
- data/lib/aws-record/record/key_attributes.rb +0 -2
- data/lib/aws-record/record/marshalers/boolean_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/date_marshaler.rb +0 -3
- data/lib/aws-record/record/marshalers/date_time_marshaler.rb +1 -2
- data/lib/aws-record/record/marshalers/epoch_time_marshaler.rb +0 -2
- data/lib/aws-record/record/marshalers/float_marshaler.rb +2 -7
- data/lib/aws-record/record/marshalers/integer_marshaler.rb +2 -7
- data/lib/aws-record/record/marshalers/list_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/map_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +2 -4
- data/lib/aws-record/record/marshalers/string_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/string_set_marshaler.rb +2 -4
- data/lib/aws-record/record/marshalers/time_marshaler.rb +0 -2
- data/lib/aws-record/record/model_attributes.rb +13 -23
- data/lib/aws-record/record/query.rb +6 -9
- data/lib/aws-record/record/secondary_indexes.rb +22 -30
- data/lib/aws-record/record/table_config.rb +51 -62
- data/lib/aws-record/record/table_migration.rb +42 -54
- data/lib/aws-record/record/transactions.rb +32 -35
- data/lib/aws-record/record.rb +29 -37
- metadata +11 -5
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
|
-
|
6
5
|
# +Aws::Record::TableConfig+ provides a DSL for describing and modifying
|
7
6
|
# the remote configuration of your DynamoDB tables. A table configuration
|
8
7
|
# object can perform intelligent comparisons and incremental migrations
|
@@ -90,11 +89,9 @@ module Aws
|
|
90
89
|
# end
|
91
90
|
#
|
92
91
|
class TableConfig
|
93
|
-
|
94
92
|
attr_accessor :client
|
95
93
|
|
96
94
|
class << self
|
97
|
-
|
98
95
|
# Creates a new table configuration, using a DSL in the provided block.
|
99
96
|
# The DSL has the following methods:
|
100
97
|
# * +#model_class+ A class name reference to the +Aws::Record+ model
|
@@ -158,7 +155,7 @@ module Aws
|
|
158
155
|
def initialize
|
159
156
|
@client_options = {}
|
160
157
|
@global_secondary_indexes = {}
|
161
|
-
@billing_mode =
|
158
|
+
@billing_mode = 'PROVISIONED' # default
|
162
159
|
end
|
163
160
|
|
164
161
|
# @api private
|
@@ -191,6 +188,7 @@ module Aws
|
|
191
188
|
# @api private
|
192
189
|
def configure_client
|
193
190
|
@client = Aws::DynamoDB::Client.new(@client_options)
|
191
|
+
@client.config.user_agent_frameworks << 'aws-record'
|
194
192
|
end
|
195
193
|
|
196
194
|
# @api private
|
@@ -231,9 +229,9 @@ module Aws
|
|
231
229
|
unless _gsi_superset(resp)
|
232
230
|
@client.update_table(_update_index_opts(resp))
|
233
231
|
@client.wait_until(
|
234
|
-
|
235
|
-
|
236
|
-
|
232
|
+
:table_exists,
|
233
|
+
table_name: @model_class.table_name
|
234
|
+
)
|
237
235
|
end
|
238
236
|
end
|
239
237
|
rescue DynamoDB::Errors::ResourceNotFoundException
|
@@ -248,7 +246,7 @@ module Aws
|
|
248
246
|
# we will only alter TTL status if we have a TTL attribute defined. We
|
249
247
|
# may someday support explicit TTL deletion, but we do not yet do this.
|
250
248
|
if @ttl_attribute
|
251
|
-
|
249
|
+
unless _ttl_compatibility_check
|
252
250
|
client.update_time_to_live(
|
253
251
|
table_name: @model_class.table_name,
|
254
252
|
time_to_live_specification: {
|
@@ -270,12 +268,10 @@ module Aws
|
|
270
268
|
#
|
271
269
|
# @return [Boolean] true if remote is compatible, false otherwise.
|
272
270
|
def compatible?
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
false
|
278
|
-
end
|
271
|
+
resp = @client.describe_table(table_name: @model_class.table_name)
|
272
|
+
_compatible_check(resp) && _ttl_compatibility_check
|
273
|
+
rescue DynamoDB::Errors::ResourceNotFoundException
|
274
|
+
false
|
279
275
|
end
|
280
276
|
|
281
277
|
# Checks against the remote table's configuration. If the remote table
|
@@ -285,26 +281,25 @@ module Aws
|
|
285
281
|
#
|
286
282
|
# @return [Boolean] true if remote is an exact match, false otherwise.
|
287
283
|
def exact_match?
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
false
|
297
|
-
end
|
284
|
+
resp = @client.describe_table(table_name: @model_class.table_name)
|
285
|
+
_throughput_equal(resp) &&
|
286
|
+
_keys_equal(resp) &&
|
287
|
+
_ad_equal(resp) &&
|
288
|
+
_gsi_equal(resp) &&
|
289
|
+
_ttl_match_check
|
290
|
+
rescue DynamoDB::Errors::ResourceNotFoundException
|
291
|
+
false
|
298
292
|
end
|
299
293
|
|
300
294
|
private
|
295
|
+
|
301
296
|
def _ttl_compatibility_check
|
302
297
|
if @ttl_attribute
|
303
298
|
ttl_status = @client.describe_time_to_live(
|
304
299
|
table_name: @model_class.table_name
|
305
300
|
)
|
306
301
|
desc = ttl_status.time_to_live_description
|
307
|
-
[
|
302
|
+
%w[ENABLED ENABLING].include?(desc.time_to_live_status) &&
|
308
303
|
desc.attribute_name == @ttl_attribute
|
309
304
|
else
|
310
305
|
true
|
@@ -317,11 +312,11 @@ module Aws
|
|
317
312
|
)
|
318
313
|
desc = ttl_status.time_to_live_description
|
319
314
|
if @ttl_attribute
|
320
|
-
[
|
315
|
+
%w[ENABLED ENABLING].include?(desc.time_to_live_status) &&
|
321
316
|
desc.attribute_name == @ttl_attribute
|
322
317
|
else
|
323
|
-
|
324
|
-
desc.attribute_name
|
318
|
+
!%w[ENABLED ENABLING].include?(desc.time_to_live_status) ||
|
319
|
+
desc.attribute_name.nil?
|
325
320
|
end
|
326
321
|
end
|
327
322
|
|
@@ -336,30 +331,25 @@ module Aws
|
|
336
331
|
opts = {
|
337
332
|
table_name: @model_class.table_name
|
338
333
|
}
|
339
|
-
if @billing_mode ==
|
334
|
+
if @billing_mode == 'PROVISIONED'
|
340
335
|
opts[:provisioned_throughput] = {
|
341
336
|
read_capacity_units: @read_capacity_units,
|
342
337
|
write_capacity_units: @write_capacity_units
|
343
338
|
}
|
344
|
-
elsif @billing_mode ==
|
339
|
+
elsif @billing_mode == 'PAY_PER_REQUEST'
|
345
340
|
opts[:billing_mode] = @billing_mode
|
346
341
|
else
|
347
342
|
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
348
343
|
end
|
349
|
-
|
350
344
|
opts[:key_schema] = _key_schema
|
351
345
|
opts[:attribute_definitions] = _attribute_definitions
|
352
346
|
gsi = _global_secondary_indexes
|
353
|
-
unless gsi.empty?
|
354
|
-
opts[:global_secondary_indexes] = gsi
|
355
|
-
end
|
347
|
+
opts[:global_secondary_indexes] = gsi unless gsi.empty?
|
356
348
|
opts
|
357
349
|
end
|
358
350
|
|
359
351
|
def _add_global_secondary_index_throughput(opts, resp_gsis)
|
360
|
-
gsis = resp_gsis.map
|
361
|
-
g.index_name
|
362
|
-
end
|
352
|
+
gsis = resp_gsis.map(&:index_name)
|
363
353
|
gsi_updates = []
|
364
354
|
gsis.each do |index_name|
|
365
355
|
lgsi = @global_secondary_indexes[index_name.to_sym]
|
@@ -375,7 +365,7 @@ module Aws
|
|
375
365
|
end
|
376
366
|
|
377
367
|
def _update_throughput_opts(resp)
|
378
|
-
if @billing_mode ==
|
368
|
+
if @billing_mode == 'PROVISIONED'
|
379
369
|
opts = {
|
380
370
|
table_name: @model_class.table_name,
|
381
371
|
provisioned_throughput: {
|
@@ -386,7 +376,7 @@ module Aws
|
|
386
376
|
# special case: we have global secondary indexes existing, and they
|
387
377
|
# need provisioned capacity to be set within this call
|
388
378
|
if !resp.table.billing_mode_summary.nil? &&
|
389
|
-
|
379
|
+
resp.table.billing_mode_summary.billing_mode == 'PAY_PER_REQUEST'
|
390
380
|
opts[:billing_mode] = @billing_mode
|
391
381
|
if resp.table.global_secondary_indexes
|
392
382
|
resp_gsis = resp.table.global_secondary_indexes
|
@@ -394,10 +384,10 @@ module Aws
|
|
394
384
|
end
|
395
385
|
end # else don't include billing mode
|
396
386
|
opts
|
397
|
-
elsif @billing_mode ==
|
387
|
+
elsif @billing_mode == 'PAY_PER_REQUEST'
|
398
388
|
{
|
399
389
|
table_name: @model_class.table_name,
|
400
|
-
billing_mode:
|
390
|
+
billing_mode: 'PAY_PER_REQUEST'
|
401
391
|
}
|
402
392
|
else
|
403
393
|
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
@@ -431,7 +421,7 @@ module Aws
|
|
431
421
|
gsi[:key_schema].each do |k|
|
432
422
|
attributes_referenced.add(k[:attribute_name])
|
433
423
|
end
|
434
|
-
if @billing_mode ==
|
424
|
+
if @billing_mode == 'PROVISIONED'
|
435
425
|
lgsi = @global_secondary_indexes[index_name.to_sym]
|
436
426
|
gsi[:provisioned_throughput] = lgsi.provisioned_throughput
|
437
427
|
end
|
@@ -440,7 +430,7 @@ module Aws
|
|
440
430
|
}
|
441
431
|
end
|
442
432
|
# we don't currently update anything other than throughput
|
443
|
-
if @billing_mode ==
|
433
|
+
if @billing_mode == 'PROVISIONED'
|
444
434
|
update_candidates.each do |index_name|
|
445
435
|
lgsi = @global_secondary_indexes[index_name.to_sym]
|
446
436
|
gsi_updates << {
|
@@ -464,19 +454,19 @@ module Aws
|
|
464
454
|
_keys.map do |type, attr|
|
465
455
|
{
|
466
456
|
attribute_name: attr.database_name,
|
467
|
-
key_type: type == :hash ?
|
457
|
+
key_type: type == :hash ? 'HASH' : 'RANGE'
|
468
458
|
}
|
469
459
|
end
|
470
460
|
end
|
471
461
|
|
472
462
|
def _attribute_definitions
|
473
|
-
attribute_definitions = _keys.map do |
|
463
|
+
attribute_definitions = _keys.map do |_type, attr|
|
474
464
|
{
|
475
465
|
attribute_name: attr.database_name,
|
476
466
|
attribute_type: attr.dynamodb_type
|
477
467
|
}
|
478
468
|
end
|
479
|
-
@model_class.global_secondary_indexes.
|
469
|
+
@model_class.global_secondary_indexes.each_value do |attributes|
|
480
470
|
gsi_keys = [attributes[:hash_key]]
|
481
471
|
gsi_keys << attributes[:range_key] if attributes[:range_key]
|
482
472
|
gsi_keys.each do |name|
|
@@ -496,40 +486,40 @@ module Aws
|
|
496
486
|
end
|
497
487
|
|
498
488
|
def _keys
|
499
|
-
@model_class.keys.
|
489
|
+
@model_class.keys.each_with_object({}) do |(type, name), acc|
|
500
490
|
acc[type] = @model_class.attributes.attribute_for(name)
|
501
491
|
acc
|
502
492
|
end
|
503
493
|
end
|
504
494
|
|
505
495
|
def _throughput_equal(resp)
|
506
|
-
if @billing_mode ==
|
496
|
+
if @billing_mode == 'PAY_PER_REQUEST'
|
507
497
|
!resp.table.billing_mode_summary.nil? &&
|
508
|
-
resp.table.billing_mode_summary.billing_mode ==
|
498
|
+
resp.table.billing_mode_summary.billing_mode == 'PAY_PER_REQUEST'
|
509
499
|
else
|
510
500
|
expected = resp.table.provisioned_throughput.to_h
|
511
501
|
actual = {
|
512
502
|
read_capacity_units: @read_capacity_units,
|
513
503
|
write_capacity_units: @write_capacity_units
|
514
504
|
}
|
515
|
-
actual.all? do |k,v|
|
505
|
+
actual.all? do |k, v|
|
516
506
|
expected[k] == v
|
517
507
|
end
|
518
508
|
end
|
519
509
|
end
|
520
510
|
|
521
511
|
def _keys_equal(resp)
|
522
|
-
remote_key_schema = resp.table.key_schema.map
|
512
|
+
remote_key_schema = resp.table.key_schema.map(&:to_h)
|
523
513
|
_array_unsorted_eql(remote_key_schema, _key_schema)
|
524
514
|
end
|
525
515
|
|
526
516
|
def _ad_equal(resp)
|
527
|
-
remote_ad = resp.table.attribute_definitions.map
|
517
|
+
remote_ad = resp.table.attribute_definitions.map(&:to_h)
|
528
518
|
_array_unsorted_eql(remote_ad, _attribute_definitions)
|
529
519
|
end
|
530
520
|
|
531
521
|
def _ad_superset(resp)
|
532
|
-
remote_ad = resp.table.attribute_definitions.map
|
522
|
+
remote_ad = resp.table.attribute_definitions.map(&:to_h)
|
533
523
|
_attribute_definitions.all? do |attribute_definition|
|
534
524
|
remote_ad.include?(attribute_definition)
|
535
525
|
end
|
@@ -540,7 +530,7 @@ module Aws
|
|
540
530
|
local_gsis = _global_secondary_indexes
|
541
531
|
remote_idx, local_idx = _gsi_index_names(remote_gsis, local_gsis)
|
542
532
|
if local_idx.subset?(remote_idx)
|
543
|
-
|
533
|
+
_gsi_set_compare(remote_gsis, local_gsis)
|
544
534
|
else
|
545
535
|
# If we have any local indexes not on the remote table,
|
546
536
|
# guaranteed false.
|
@@ -565,17 +555,17 @@ module Aws
|
|
565
555
|
r.index_name == lgsi[:index_name].to_s
|
566
556
|
end
|
567
557
|
|
568
|
-
remote_key_schema = rgsi.key_schema.map
|
558
|
+
remote_key_schema = rgsi.key_schema.map(&:to_h)
|
569
559
|
ks_match = _array_unsorted_eql(remote_key_schema, lgsi[:key_schema])
|
570
560
|
|
571
561
|
# Throughput Check: Dependent on Billing Mode
|
572
562
|
rpt = rgsi.provisioned_throughput.to_h
|
573
563
|
lpt = lgsi[:provisioned_throughput]
|
574
|
-
if @billing_mode ==
|
575
|
-
pt_match = lpt.all? do |k,v|
|
564
|
+
if @billing_mode == 'PROVISIONED'
|
565
|
+
pt_match = lpt.all? do |k, v|
|
576
566
|
rpt[k] == v
|
577
567
|
end
|
578
|
-
elsif @billing_mode ==
|
568
|
+
elsif @billing_mode == 'PAY_PER_REQUEST'
|
579
569
|
pt_match = lpt.nil? ? true : false
|
580
570
|
else
|
581
571
|
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
@@ -614,7 +604,7 @@ module Aws
|
|
614
604
|
if model_gsis
|
615
605
|
model_gsis.each do |mgsi|
|
616
606
|
config = gsi_config[mgsi[:index_name]]
|
617
|
-
if @billing_mode ==
|
607
|
+
if @billing_mode == 'PROVISIONED'
|
618
608
|
gsis << mgsi.merge(
|
619
609
|
provisioned_throughput: config.provisioned_throughput
|
620
610
|
)
|
@@ -633,12 +623,12 @@ module Aws
|
|
633
623
|
def _validate_required_configuration
|
634
624
|
missing_config = []
|
635
625
|
missing_config << 'model_class' unless @model_class
|
636
|
-
if @billing_mode ==
|
626
|
+
if @billing_mode == 'PROVISIONED'
|
637
627
|
missing_config << 'read_capacity_units' unless @read_capacity_units
|
638
628
|
missing_config << 'write_capacity_units' unless @write_capacity_units
|
639
629
|
else
|
640
630
|
if @read_capacity_units || @write_capacity_units
|
641
|
-
raise ArgumentError
|
631
|
+
raise ArgumentError, "Cannot have billing mode #{@billing_mode} with provisioned capacity."
|
642
632
|
end
|
643
633
|
end
|
644
634
|
unless missing_config.empty?
|
@@ -663,7 +653,6 @@ module Aws
|
|
663
653
|
@provisioned_throughput[:write_capacity_units] = units
|
664
654
|
end
|
665
655
|
end
|
666
|
-
|
667
656
|
end
|
668
657
|
end
|
669
658
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
class TableMigration
|
6
|
-
|
7
6
|
# @!attribute [rw] client
|
8
7
|
# @return [Aws::DynamoDB::Client] the
|
9
8
|
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
@@ -21,12 +20,14 @@ module Aws
|
|
21
20
|
_assert_model_valid(model)
|
22
21
|
@model = model
|
23
22
|
@client = opts[:client] || model.dynamodb_client || Aws::DynamoDB::Client.new
|
23
|
+
@client.config.user_agent_frameworks << 'aws-record'
|
24
24
|
end
|
25
25
|
|
26
26
|
# This method calls
|
27
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#create_table-instance_method
|
28
|
-
# populating the attribute definitions and
|
29
|
-
# class, as well as passing through other
|
27
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#create_table-instance_method
|
28
|
+
# Aws::DynamoDB::Client#create_table}, populating the attribute definitions and
|
29
|
+
# key schema based on your model class, as well as passing through other
|
30
|
+
# parameters as provided by you.
|
30
31
|
#
|
31
32
|
# @example Creating a table with a global secondary index named +:gsi+
|
32
33
|
# migration.create!(
|
@@ -63,22 +64,20 @@ module Aws
|
|
63
64
|
gsit = opts.delete(:global_secondary_index_throughput)
|
64
65
|
_validate_billing(opts)
|
65
66
|
|
66
|
-
create_opts = opts.merge(
|
67
|
+
create_opts = opts.merge(
|
67
68
|
table_name: @model.table_name,
|
68
69
|
attribute_definitions: _attribute_definitions,
|
69
70
|
key_schema: _key_schema
|
70
|
-
|
71
|
-
if lsis = @model.local_secondary_indexes_for_migration
|
71
|
+
)
|
72
|
+
if (lsis = @model.local_secondary_indexes_for_migration)
|
72
73
|
create_opts[:local_secondary_indexes] = lsis
|
73
74
|
_append_to_attribute_definitions(lsis, create_opts)
|
74
75
|
end
|
75
|
-
if gsis = @model.global_secondary_indexes_for_migration
|
76
|
+
if (gsis = @model.global_secondary_indexes_for_migration)
|
76
77
|
unless gsit || opts[:billing_mode] == 'PAY_PER_REQUEST'
|
77
|
-
raise ArgumentError
|
78
|
-
|
79
|
-
|
80
|
-
" unless :billing_mode is set to 'PAY_PER_REQUEST'."
|
81
|
-
)
|
78
|
+
raise ArgumentError, 'If you define global secondary indexes, you must also define'\
|
79
|
+
' :global_secondary_index_throughput on table creation,'\
|
80
|
+
" unless :billing_mode is set to 'PAY_PER_REQUEST'."
|
82
81
|
end
|
83
82
|
gsis_opts = if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
84
83
|
gsis
|
@@ -92,8 +91,8 @@ module Aws
|
|
92
91
|
end
|
93
92
|
|
94
93
|
# This method calls
|
95
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_table-instance_method
|
96
|
-
# using the parameters that you provide.
|
94
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_table-instance_method
|
95
|
+
# Aws::DynamoDB::Client#update_table} using the parameters that you provide.
|
97
96
|
#
|
98
97
|
# @param [Hash] opts options to pass on to the client call to
|
99
98
|
# +#update_table+. See the documentation above in the AWS SDK for Ruby
|
@@ -101,28 +100,24 @@ module Aws
|
|
101
100
|
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table does not
|
102
101
|
# currently exist in Amazon DynamoDB.
|
103
102
|
def update!(opts)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
raise Errors::TableDoesNotExist.new(e)
|
111
|
-
end
|
103
|
+
update_opts = opts.merge(
|
104
|
+
table_name: @model.table_name
|
105
|
+
)
|
106
|
+
@client.update_table(update_opts)
|
107
|
+
rescue DynamoDB::Errors::ResourceNotFoundException
|
108
|
+
raise Errors::TableDoesNotExist
|
112
109
|
end
|
113
110
|
|
114
111
|
# This method calls
|
115
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_table-instance_method
|
116
|
-
# using the table name of your model.
|
112
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_table-instance_method
|
113
|
+
# Aws::DynamoDB::Client#delete_table} using the table name of your model.
|
117
114
|
#
|
118
115
|
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table did not
|
119
116
|
# exist in Amazon DynamoDB at the time of calling.
|
120
117
|
def delete!
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
raise Errors::TableDoesNotExist.new(e)
|
125
|
-
end
|
118
|
+
@client.delete_table(table_name: @model.table_name)
|
119
|
+
rescue DynamoDB::Errors::ResourceNotFoundException
|
120
|
+
raise Errors::TableDoesNotExist
|
126
121
|
end
|
127
122
|
|
128
123
|
# This method waits on the table specified in the model to exist and be
|
@@ -134,6 +129,7 @@ module Aws
|
|
134
129
|
end
|
135
130
|
|
136
131
|
private
|
132
|
+
|
137
133
|
def _assert_model_valid(model)
|
138
134
|
_assert_required_include(model)
|
139
135
|
model.model_valid?
|
@@ -141,7 +137,7 @@ module Aws
|
|
141
137
|
|
142
138
|
def _assert_required_include(model)
|
143
139
|
unless model.include?(::Aws::Record)
|
144
|
-
raise Errors::InvalidModel
|
140
|
+
raise Errors::InvalidModel, 'Table models must include Aws::Record'
|
145
141
|
end
|
146
142
|
end
|
147
143
|
|
@@ -149,31 +145,25 @@ module Aws
|
|
149
145
|
valid_modes = %w[PAY_PER_REQUEST PROVISIONED]
|
150
146
|
if opts.key?(:billing_mode)
|
151
147
|
unless valid_modes.include?(opts[:billing_mode])
|
152
|
-
raise ArgumentError.
|
153
|
-
|
154
|
-
" current value is: #{opts[:billing_mode]}"
|
155
|
-
)
|
148
|
+
raise ArgumentError, ":billing_mode option must be one of #{valid_modes.join(', ')}"\
|
149
|
+
" current value is: #{opts[:billing_mode]}"
|
156
150
|
end
|
157
151
|
end
|
158
152
|
if opts.key?(:provisioned_throughput)
|
159
153
|
if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
160
|
-
raise ArgumentError
|
161
|
-
|
162
|
-
" must either be unspecified or have a value of 'PROVISIONED'"
|
163
|
-
)
|
154
|
+
raise ArgumentError, 'when :provisioned_throughput option is specified, :billing_mode'\
|
155
|
+
" must either be unspecified or have a value of 'PROVISIONED'"
|
164
156
|
end
|
165
157
|
else
|
166
158
|
if opts[:billing_mode] != 'PAY_PER_REQUEST'
|
167
|
-
raise ArgumentError
|
168
|
-
|
169
|
-
" :billing_mode must be set to 'PAY_PER_REQUEST'"
|
170
|
-
)
|
159
|
+
raise ArgumentError, 'when :provisioned_throughput option is not specified,'\
|
160
|
+
" :billing_mode must be set to 'PAY_PER_REQUEST'"
|
171
161
|
end
|
172
162
|
end
|
173
163
|
end
|
174
164
|
|
175
165
|
def _attribute_definitions
|
176
|
-
_keys.map do |
|
166
|
+
_keys.map do |_type, attr|
|
177
167
|
{
|
178
168
|
attribute_name: attr.database_name,
|
179
169
|
attribute_type: attr.dynamodb_type
|
@@ -186,9 +176,9 @@ module Aws
|
|
186
176
|
attr_def = create_opts[:attribute_definitions]
|
187
177
|
secondary_indexes.each do |si|
|
188
178
|
si[:key_schema].each do |key_schema|
|
189
|
-
exists = attr_def.find
|
179
|
+
exists = attr_def.find do |a|
|
190
180
|
a[:attribute_name] == key_schema[:attribute_name]
|
191
|
-
|
181
|
+
end
|
192
182
|
unless exists
|
193
183
|
attr = attributes.attribute_for(
|
194
184
|
attributes.db_to_attribute_name(key_schema[:attribute_name])
|
@@ -212,12 +202,10 @@ module Aws
|
|
212
202
|
params.merge(provisioned_throughput: throughput)
|
213
203
|
end
|
214
204
|
unless missing_throughput.empty?
|
215
|
-
raise ArgumentError
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
" #{gsi_throughput}"
|
220
|
-
)
|
205
|
+
raise ArgumentError, 'Missing provisioned throughput for the following global secondary'\
|
206
|
+
" indexes: #{missing_throughput.join(', ')}. GSIs:"\
|
207
|
+
" #{global_secondary_indexes} and defined throughput:"\
|
208
|
+
" #{gsi_throughput}"
|
221
209
|
end
|
222
210
|
ret
|
223
211
|
end
|
@@ -226,13 +214,13 @@ module Aws
|
|
226
214
|
_keys.map do |type, attr|
|
227
215
|
{
|
228
216
|
attribute_name: attr.database_name,
|
229
|
-
key_type: type == :hash ?
|
217
|
+
key_type: type == :hash ? 'HASH' : 'RANGE'
|
230
218
|
}
|
231
219
|
end
|
232
220
|
end
|
233
221
|
|
234
222
|
def _keys
|
235
|
-
@model.keys.
|
223
|
+
@model.keys.each_with_object({}) do |(type, name), acc|
|
236
224
|
acc[type] = @model.attributes.attribute_for(name)
|
237
225
|
acc
|
238
226
|
end
|