aws-record 2.10.0 → 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 +335 -0
- data/LICENSE +202 -0
- data/VERSION +1 -0
- data/lib/aws-record/record/attribute.rb +9 -21
- data/lib/aws-record/record/attributes.rb +68 -78
- data/lib/aws-record/record/batch.rb +13 -12
- data/lib/aws-record/record/batch_read.rb +5 -2
- data/lib/aws-record/record/batch_write.rb +1 -12
- data/lib/aws-record/record/buildable_search.rb +33 -28
- data/lib/aws-record/record/client_configuration.rb +10 -21
- data/lib/aws-record/record/dirty_tracking.rb +30 -44
- data/lib/aws-record/record/errors.rb +1 -13
- data/lib/aws-record/record/item_collection.rb +5 -16
- data/lib/aws-record/record/item_data.rb +4 -18
- data/lib/aws-record/record/item_operations.rb +86 -93
- data/lib/aws-record/record/key_attributes.rb +1 -14
- data/lib/aws-record/record/marshalers/boolean_marshaler.rb +2 -16
- data/lib/aws-record/record/marshalers/date_marshaler.rb +1 -15
- data/lib/aws-record/record/marshalers/date_time_marshaler.rb +2 -14
- data/lib/aws-record/record/marshalers/epoch_time_marshaler.rb +1 -14
- data/lib/aws-record/record/marshalers/float_marshaler.rb +3 -19
- data/lib/aws-record/record/marshalers/integer_marshaler.rb +3 -19
- data/lib/aws-record/record/marshalers/list_marshaler.rb +2 -16
- data/lib/aws-record/record/marshalers/map_marshaler.rb +2 -16
- data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +3 -16
- data/lib/aws-record/record/marshalers/string_marshaler.rb +2 -16
- data/lib/aws-record/record/marshalers/string_set_marshaler.rb +3 -16
- data/lib/aws-record/record/marshalers/time_marshaler.rb +1 -14
- data/lib/aws-record/record/model_attributes.rb +14 -35
- data/lib/aws-record/record/query.rb +7 -21
- data/lib/aws-record/record/secondary_indexes.rb +23 -42
- data/lib/aws-record/record/table_config.rb +52 -74
- data/lib/aws-record/record/table_migration.rb +43 -66
- data/lib/aws-record/record/transactions.rb +67 -38
- data/lib/aws-record/record/version.rb +2 -13
- data/lib/aws-record/record.rb +30 -49
- metadata +14 -5
@@ -1,19 +1,7 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
-
# use this file except in compliance with the License. A copy of the License is
|
5
|
-
# located at
|
6
|
-
#
|
7
|
-
# http://aws.amazon.com/apache2.0/
|
8
|
-
#
|
9
|
-
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
-
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
-
# or implied. See the License for the specific language governing permissions
|
12
|
-
# and limitations under the License.
|
1
|
+
# frozen_string_literal: true
|
13
2
|
|
14
3
|
module Aws
|
15
4
|
module Record
|
16
|
-
|
17
5
|
# +Aws::Record::TableConfig+ provides a DSL for describing and modifying
|
18
6
|
# the remote configuration of your DynamoDB tables. A table configuration
|
19
7
|
# object can perform intelligent comparisons and incremental migrations
|
@@ -101,11 +89,9 @@ module Aws
|
|
101
89
|
# end
|
102
90
|
#
|
103
91
|
class TableConfig
|
104
|
-
|
105
92
|
attr_accessor :client
|
106
93
|
|
107
94
|
class << self
|
108
|
-
|
109
95
|
# Creates a new table configuration, using a DSL in the provided block.
|
110
96
|
# The DSL has the following methods:
|
111
97
|
# * +#model_class+ A class name reference to the +Aws::Record+ model
|
@@ -169,7 +155,7 @@ module Aws
|
|
169
155
|
def initialize
|
170
156
|
@client_options = {}
|
171
157
|
@global_secondary_indexes = {}
|
172
|
-
@billing_mode =
|
158
|
+
@billing_mode = 'PROVISIONED' # default
|
173
159
|
end
|
174
160
|
|
175
161
|
# @api private
|
@@ -202,6 +188,7 @@ module Aws
|
|
202
188
|
# @api private
|
203
189
|
def configure_client
|
204
190
|
@client = Aws::DynamoDB::Client.new(@client_options)
|
191
|
+
@client.config.user_agent_frameworks << 'aws-record'
|
205
192
|
end
|
206
193
|
|
207
194
|
# @api private
|
@@ -242,9 +229,9 @@ module Aws
|
|
242
229
|
unless _gsi_superset(resp)
|
243
230
|
@client.update_table(_update_index_opts(resp))
|
244
231
|
@client.wait_until(
|
245
|
-
|
246
|
-
|
247
|
-
|
232
|
+
:table_exists,
|
233
|
+
table_name: @model_class.table_name
|
234
|
+
)
|
248
235
|
end
|
249
236
|
end
|
250
237
|
rescue DynamoDB::Errors::ResourceNotFoundException
|
@@ -259,7 +246,7 @@ module Aws
|
|
259
246
|
# we will only alter TTL status if we have a TTL attribute defined. We
|
260
247
|
# may someday support explicit TTL deletion, but we do not yet do this.
|
261
248
|
if @ttl_attribute
|
262
|
-
|
249
|
+
unless _ttl_compatibility_check
|
263
250
|
client.update_time_to_live(
|
264
251
|
table_name: @model_class.table_name,
|
265
252
|
time_to_live_specification: {
|
@@ -281,12 +268,10 @@ module Aws
|
|
281
268
|
#
|
282
269
|
# @return [Boolean] true if remote is compatible, false otherwise.
|
283
270
|
def compatible?
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
false
|
289
|
-
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
|
290
275
|
end
|
291
276
|
|
292
277
|
# Checks against the remote table's configuration. If the remote table
|
@@ -296,26 +281,25 @@ module Aws
|
|
296
281
|
#
|
297
282
|
# @return [Boolean] true if remote is an exact match, false otherwise.
|
298
283
|
def exact_match?
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
false
|
308
|
-
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
|
309
292
|
end
|
310
293
|
|
311
294
|
private
|
295
|
+
|
312
296
|
def _ttl_compatibility_check
|
313
297
|
if @ttl_attribute
|
314
298
|
ttl_status = @client.describe_time_to_live(
|
315
299
|
table_name: @model_class.table_name
|
316
300
|
)
|
317
301
|
desc = ttl_status.time_to_live_description
|
318
|
-
[
|
302
|
+
%w[ENABLED ENABLING].include?(desc.time_to_live_status) &&
|
319
303
|
desc.attribute_name == @ttl_attribute
|
320
304
|
else
|
321
305
|
true
|
@@ -328,11 +312,11 @@ module Aws
|
|
328
312
|
)
|
329
313
|
desc = ttl_status.time_to_live_description
|
330
314
|
if @ttl_attribute
|
331
|
-
[
|
315
|
+
%w[ENABLED ENABLING].include?(desc.time_to_live_status) &&
|
332
316
|
desc.attribute_name == @ttl_attribute
|
333
317
|
else
|
334
|
-
|
335
|
-
desc.attribute_name
|
318
|
+
!%w[ENABLED ENABLING].include?(desc.time_to_live_status) ||
|
319
|
+
desc.attribute_name.nil?
|
336
320
|
end
|
337
321
|
end
|
338
322
|
|
@@ -347,30 +331,25 @@ module Aws
|
|
347
331
|
opts = {
|
348
332
|
table_name: @model_class.table_name
|
349
333
|
}
|
350
|
-
if @billing_mode ==
|
334
|
+
if @billing_mode == 'PROVISIONED'
|
351
335
|
opts[:provisioned_throughput] = {
|
352
336
|
read_capacity_units: @read_capacity_units,
|
353
337
|
write_capacity_units: @write_capacity_units
|
354
338
|
}
|
355
|
-
elsif @billing_mode ==
|
339
|
+
elsif @billing_mode == 'PAY_PER_REQUEST'
|
356
340
|
opts[:billing_mode] = @billing_mode
|
357
341
|
else
|
358
342
|
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
359
343
|
end
|
360
|
-
|
361
344
|
opts[:key_schema] = _key_schema
|
362
345
|
opts[:attribute_definitions] = _attribute_definitions
|
363
346
|
gsi = _global_secondary_indexes
|
364
|
-
unless gsi.empty?
|
365
|
-
opts[:global_secondary_indexes] = gsi
|
366
|
-
end
|
347
|
+
opts[:global_secondary_indexes] = gsi unless gsi.empty?
|
367
348
|
opts
|
368
349
|
end
|
369
350
|
|
370
351
|
def _add_global_secondary_index_throughput(opts, resp_gsis)
|
371
|
-
gsis = resp_gsis.map
|
372
|
-
g.index_name
|
373
|
-
end
|
352
|
+
gsis = resp_gsis.map(&:index_name)
|
374
353
|
gsi_updates = []
|
375
354
|
gsis.each do |index_name|
|
376
355
|
lgsi = @global_secondary_indexes[index_name.to_sym]
|
@@ -386,7 +365,7 @@ module Aws
|
|
386
365
|
end
|
387
366
|
|
388
367
|
def _update_throughput_opts(resp)
|
389
|
-
if @billing_mode ==
|
368
|
+
if @billing_mode == 'PROVISIONED'
|
390
369
|
opts = {
|
391
370
|
table_name: @model_class.table_name,
|
392
371
|
provisioned_throughput: {
|
@@ -397,7 +376,7 @@ module Aws
|
|
397
376
|
# special case: we have global secondary indexes existing, and they
|
398
377
|
# need provisioned capacity to be set within this call
|
399
378
|
if !resp.table.billing_mode_summary.nil? &&
|
400
|
-
|
379
|
+
resp.table.billing_mode_summary.billing_mode == 'PAY_PER_REQUEST'
|
401
380
|
opts[:billing_mode] = @billing_mode
|
402
381
|
if resp.table.global_secondary_indexes
|
403
382
|
resp_gsis = resp.table.global_secondary_indexes
|
@@ -405,10 +384,10 @@ module Aws
|
|
405
384
|
end
|
406
385
|
end # else don't include billing mode
|
407
386
|
opts
|
408
|
-
elsif @billing_mode ==
|
387
|
+
elsif @billing_mode == 'PAY_PER_REQUEST'
|
409
388
|
{
|
410
389
|
table_name: @model_class.table_name,
|
411
|
-
billing_mode:
|
390
|
+
billing_mode: 'PAY_PER_REQUEST'
|
412
391
|
}
|
413
392
|
else
|
414
393
|
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
@@ -442,7 +421,7 @@ module Aws
|
|
442
421
|
gsi[:key_schema].each do |k|
|
443
422
|
attributes_referenced.add(k[:attribute_name])
|
444
423
|
end
|
445
|
-
if @billing_mode ==
|
424
|
+
if @billing_mode == 'PROVISIONED'
|
446
425
|
lgsi = @global_secondary_indexes[index_name.to_sym]
|
447
426
|
gsi[:provisioned_throughput] = lgsi.provisioned_throughput
|
448
427
|
end
|
@@ -451,7 +430,7 @@ module Aws
|
|
451
430
|
}
|
452
431
|
end
|
453
432
|
# we don't currently update anything other than throughput
|
454
|
-
if @billing_mode ==
|
433
|
+
if @billing_mode == 'PROVISIONED'
|
455
434
|
update_candidates.each do |index_name|
|
456
435
|
lgsi = @global_secondary_indexes[index_name.to_sym]
|
457
436
|
gsi_updates << {
|
@@ -475,19 +454,19 @@ module Aws
|
|
475
454
|
_keys.map do |type, attr|
|
476
455
|
{
|
477
456
|
attribute_name: attr.database_name,
|
478
|
-
key_type: type == :hash ?
|
457
|
+
key_type: type == :hash ? 'HASH' : 'RANGE'
|
479
458
|
}
|
480
459
|
end
|
481
460
|
end
|
482
461
|
|
483
462
|
def _attribute_definitions
|
484
|
-
attribute_definitions = _keys.map do |
|
463
|
+
attribute_definitions = _keys.map do |_type, attr|
|
485
464
|
{
|
486
465
|
attribute_name: attr.database_name,
|
487
466
|
attribute_type: attr.dynamodb_type
|
488
467
|
}
|
489
468
|
end
|
490
|
-
@model_class.global_secondary_indexes.
|
469
|
+
@model_class.global_secondary_indexes.each_value do |attributes|
|
491
470
|
gsi_keys = [attributes[:hash_key]]
|
492
471
|
gsi_keys << attributes[:range_key] if attributes[:range_key]
|
493
472
|
gsi_keys.each do |name|
|
@@ -507,40 +486,40 @@ module Aws
|
|
507
486
|
end
|
508
487
|
|
509
488
|
def _keys
|
510
|
-
@model_class.keys.
|
489
|
+
@model_class.keys.each_with_object({}) do |(type, name), acc|
|
511
490
|
acc[type] = @model_class.attributes.attribute_for(name)
|
512
491
|
acc
|
513
492
|
end
|
514
493
|
end
|
515
494
|
|
516
495
|
def _throughput_equal(resp)
|
517
|
-
if @billing_mode ==
|
496
|
+
if @billing_mode == 'PAY_PER_REQUEST'
|
518
497
|
!resp.table.billing_mode_summary.nil? &&
|
519
|
-
resp.table.billing_mode_summary.billing_mode ==
|
498
|
+
resp.table.billing_mode_summary.billing_mode == 'PAY_PER_REQUEST'
|
520
499
|
else
|
521
500
|
expected = resp.table.provisioned_throughput.to_h
|
522
501
|
actual = {
|
523
502
|
read_capacity_units: @read_capacity_units,
|
524
503
|
write_capacity_units: @write_capacity_units
|
525
504
|
}
|
526
|
-
actual.all? do |k,v|
|
505
|
+
actual.all? do |k, v|
|
527
506
|
expected[k] == v
|
528
507
|
end
|
529
508
|
end
|
530
509
|
end
|
531
510
|
|
532
511
|
def _keys_equal(resp)
|
533
|
-
remote_key_schema = resp.table.key_schema.map
|
512
|
+
remote_key_schema = resp.table.key_schema.map(&:to_h)
|
534
513
|
_array_unsorted_eql(remote_key_schema, _key_schema)
|
535
514
|
end
|
536
515
|
|
537
516
|
def _ad_equal(resp)
|
538
|
-
remote_ad = resp.table.attribute_definitions.map
|
517
|
+
remote_ad = resp.table.attribute_definitions.map(&:to_h)
|
539
518
|
_array_unsorted_eql(remote_ad, _attribute_definitions)
|
540
519
|
end
|
541
520
|
|
542
521
|
def _ad_superset(resp)
|
543
|
-
remote_ad = resp.table.attribute_definitions.map
|
522
|
+
remote_ad = resp.table.attribute_definitions.map(&:to_h)
|
544
523
|
_attribute_definitions.all? do |attribute_definition|
|
545
524
|
remote_ad.include?(attribute_definition)
|
546
525
|
end
|
@@ -551,7 +530,7 @@ module Aws
|
|
551
530
|
local_gsis = _global_secondary_indexes
|
552
531
|
remote_idx, local_idx = _gsi_index_names(remote_gsis, local_gsis)
|
553
532
|
if local_idx.subset?(remote_idx)
|
554
|
-
|
533
|
+
_gsi_set_compare(remote_gsis, local_gsis)
|
555
534
|
else
|
556
535
|
# If we have any local indexes not on the remote table,
|
557
536
|
# guaranteed false.
|
@@ -576,17 +555,17 @@ module Aws
|
|
576
555
|
r.index_name == lgsi[:index_name].to_s
|
577
556
|
end
|
578
557
|
|
579
|
-
remote_key_schema = rgsi.key_schema.map
|
558
|
+
remote_key_schema = rgsi.key_schema.map(&:to_h)
|
580
559
|
ks_match = _array_unsorted_eql(remote_key_schema, lgsi[:key_schema])
|
581
560
|
|
582
561
|
# Throughput Check: Dependent on Billing Mode
|
583
562
|
rpt = rgsi.provisioned_throughput.to_h
|
584
563
|
lpt = lgsi[:provisioned_throughput]
|
585
|
-
if @billing_mode ==
|
586
|
-
pt_match = lpt.all? do |k,v|
|
564
|
+
if @billing_mode == 'PROVISIONED'
|
565
|
+
pt_match = lpt.all? do |k, v|
|
587
566
|
rpt[k] == v
|
588
567
|
end
|
589
|
-
elsif @billing_mode ==
|
568
|
+
elsif @billing_mode == 'PAY_PER_REQUEST'
|
590
569
|
pt_match = lpt.nil? ? true : false
|
591
570
|
else
|
592
571
|
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
@@ -625,7 +604,7 @@ module Aws
|
|
625
604
|
if model_gsis
|
626
605
|
model_gsis.each do |mgsi|
|
627
606
|
config = gsi_config[mgsi[:index_name]]
|
628
|
-
if @billing_mode ==
|
607
|
+
if @billing_mode == 'PROVISIONED'
|
629
608
|
gsis << mgsi.merge(
|
630
609
|
provisioned_throughput: config.provisioned_throughput
|
631
610
|
)
|
@@ -644,12 +623,12 @@ module Aws
|
|
644
623
|
def _validate_required_configuration
|
645
624
|
missing_config = []
|
646
625
|
missing_config << 'model_class' unless @model_class
|
647
|
-
if @billing_mode ==
|
626
|
+
if @billing_mode == 'PROVISIONED'
|
648
627
|
missing_config << 'read_capacity_units' unless @read_capacity_units
|
649
628
|
missing_config << 'write_capacity_units' unless @write_capacity_units
|
650
629
|
else
|
651
630
|
if @read_capacity_units || @write_capacity_units
|
652
|
-
raise ArgumentError
|
631
|
+
raise ArgumentError, "Cannot have billing mode #{@billing_mode} with provisioned capacity."
|
653
632
|
end
|
654
633
|
end
|
655
634
|
unless missing_config.empty?
|
@@ -674,7 +653,6 @@ module Aws
|
|
674
653
|
@provisioned_throughput[:write_capacity_units] = units
|
675
654
|
end
|
676
655
|
end
|
677
|
-
|
678
656
|
end
|
679
657
|
end
|
680
658
|
end
|
@@ -1,20 +1,8 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
-
# use this file except in compliance with the License. A copy of the License is
|
5
|
-
# located at
|
6
|
-
#
|
7
|
-
# http://aws.amazon.com/apache2.0/
|
8
|
-
#
|
9
|
-
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
-
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
-
# or implied. See the License for the specific language governing permissions
|
12
|
-
# and limitations under the License.
|
1
|
+
# frozen_string_literal: true
|
13
2
|
|
14
3
|
module Aws
|
15
4
|
module Record
|
16
5
|
class TableMigration
|
17
|
-
|
18
6
|
# @!attribute [rw] client
|
19
7
|
# @return [Aws::DynamoDB::Client] the
|
20
8
|
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
@@ -32,12 +20,14 @@ module Aws
|
|
32
20
|
_assert_model_valid(model)
|
33
21
|
@model = model
|
34
22
|
@client = opts[:client] || model.dynamodb_client || Aws::DynamoDB::Client.new
|
23
|
+
@client.config.user_agent_frameworks << 'aws-record'
|
35
24
|
end
|
36
25
|
|
37
26
|
# This method calls
|
38
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#create_table-instance_method
|
39
|
-
# populating the attribute definitions and
|
40
|
-
# 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.
|
41
31
|
#
|
42
32
|
# @example Creating a table with a global secondary index named +:gsi+
|
43
33
|
# migration.create!(
|
@@ -74,22 +64,20 @@ module Aws
|
|
74
64
|
gsit = opts.delete(:global_secondary_index_throughput)
|
75
65
|
_validate_billing(opts)
|
76
66
|
|
77
|
-
create_opts = opts.merge(
|
67
|
+
create_opts = opts.merge(
|
78
68
|
table_name: @model.table_name,
|
79
69
|
attribute_definitions: _attribute_definitions,
|
80
70
|
key_schema: _key_schema
|
81
|
-
|
82
|
-
if lsis = @model.local_secondary_indexes_for_migration
|
71
|
+
)
|
72
|
+
if (lsis = @model.local_secondary_indexes_for_migration)
|
83
73
|
create_opts[:local_secondary_indexes] = lsis
|
84
74
|
_append_to_attribute_definitions(lsis, create_opts)
|
85
75
|
end
|
86
|
-
if gsis = @model.global_secondary_indexes_for_migration
|
76
|
+
if (gsis = @model.global_secondary_indexes_for_migration)
|
87
77
|
unless gsit || opts[:billing_mode] == 'PAY_PER_REQUEST'
|
88
|
-
raise ArgumentError
|
89
|
-
|
90
|
-
|
91
|
-
" unless :billing_mode is set to 'PAY_PER_REQUEST'."
|
92
|
-
)
|
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'."
|
93
81
|
end
|
94
82
|
gsis_opts = if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
95
83
|
gsis
|
@@ -103,8 +91,8 @@ module Aws
|
|
103
91
|
end
|
104
92
|
|
105
93
|
# This method calls
|
106
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_table-instance_method
|
107
|
-
# 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.
|
108
96
|
#
|
109
97
|
# @param [Hash] opts options to pass on to the client call to
|
110
98
|
# +#update_table+. See the documentation above in the AWS SDK for Ruby
|
@@ -112,28 +100,24 @@ module Aws
|
|
112
100
|
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table does not
|
113
101
|
# currently exist in Amazon DynamoDB.
|
114
102
|
def update!(opts)
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
raise Errors::TableDoesNotExist.new(e)
|
122
|
-
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
|
123
109
|
end
|
124
110
|
|
125
111
|
# This method calls
|
126
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_table-instance_method
|
127
|
-
# 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.
|
128
114
|
#
|
129
115
|
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table did not
|
130
116
|
# exist in Amazon DynamoDB at the time of calling.
|
131
117
|
def delete!
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
raise Errors::TableDoesNotExist.new(e)
|
136
|
-
end
|
118
|
+
@client.delete_table(table_name: @model.table_name)
|
119
|
+
rescue DynamoDB::Errors::ResourceNotFoundException
|
120
|
+
raise Errors::TableDoesNotExist
|
137
121
|
end
|
138
122
|
|
139
123
|
# This method waits on the table specified in the model to exist and be
|
@@ -145,6 +129,7 @@ module Aws
|
|
145
129
|
end
|
146
130
|
|
147
131
|
private
|
132
|
+
|
148
133
|
def _assert_model_valid(model)
|
149
134
|
_assert_required_include(model)
|
150
135
|
model.model_valid?
|
@@ -152,7 +137,7 @@ module Aws
|
|
152
137
|
|
153
138
|
def _assert_required_include(model)
|
154
139
|
unless model.include?(::Aws::Record)
|
155
|
-
raise Errors::InvalidModel
|
140
|
+
raise Errors::InvalidModel, 'Table models must include Aws::Record'
|
156
141
|
end
|
157
142
|
end
|
158
143
|
|
@@ -160,31 +145,25 @@ module Aws
|
|
160
145
|
valid_modes = %w[PAY_PER_REQUEST PROVISIONED]
|
161
146
|
if opts.key?(:billing_mode)
|
162
147
|
unless valid_modes.include?(opts[:billing_mode])
|
163
|
-
raise ArgumentError.
|
164
|
-
|
165
|
-
" current value is: #{opts[:billing_mode]}"
|
166
|
-
)
|
148
|
+
raise ArgumentError, ":billing_mode option must be one of #{valid_modes.join(', ')}"\
|
149
|
+
" current value is: #{opts[:billing_mode]}"
|
167
150
|
end
|
168
151
|
end
|
169
152
|
if opts.key?(:provisioned_throughput)
|
170
153
|
if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
171
|
-
raise ArgumentError
|
172
|
-
|
173
|
-
" must either be unspecified or have a value of 'PROVISIONED'"
|
174
|
-
)
|
154
|
+
raise ArgumentError, 'when :provisioned_throughput option is specified, :billing_mode'\
|
155
|
+
" must either be unspecified or have a value of 'PROVISIONED'"
|
175
156
|
end
|
176
157
|
else
|
177
158
|
if opts[:billing_mode] != 'PAY_PER_REQUEST'
|
178
|
-
raise ArgumentError
|
179
|
-
|
180
|
-
" :billing_mode must be set to 'PAY_PER_REQUEST'"
|
181
|
-
)
|
159
|
+
raise ArgumentError, 'when :provisioned_throughput option is not specified,'\
|
160
|
+
" :billing_mode must be set to 'PAY_PER_REQUEST'"
|
182
161
|
end
|
183
162
|
end
|
184
163
|
end
|
185
164
|
|
186
165
|
def _attribute_definitions
|
187
|
-
_keys.map do |
|
166
|
+
_keys.map do |_type, attr|
|
188
167
|
{
|
189
168
|
attribute_name: attr.database_name,
|
190
169
|
attribute_type: attr.dynamodb_type
|
@@ -197,9 +176,9 @@ module Aws
|
|
197
176
|
attr_def = create_opts[:attribute_definitions]
|
198
177
|
secondary_indexes.each do |si|
|
199
178
|
si[:key_schema].each do |key_schema|
|
200
|
-
exists = attr_def.find
|
179
|
+
exists = attr_def.find do |a|
|
201
180
|
a[:attribute_name] == key_schema[:attribute_name]
|
202
|
-
|
181
|
+
end
|
203
182
|
unless exists
|
204
183
|
attr = attributes.attribute_for(
|
205
184
|
attributes.db_to_attribute_name(key_schema[:attribute_name])
|
@@ -223,12 +202,10 @@ module Aws
|
|
223
202
|
params.merge(provisioned_throughput: throughput)
|
224
203
|
end
|
225
204
|
unless missing_throughput.empty?
|
226
|
-
raise ArgumentError
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
" #{gsi_throughput}"
|
231
|
-
)
|
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}"
|
232
209
|
end
|
233
210
|
ret
|
234
211
|
end
|
@@ -237,13 +214,13 @@ module Aws
|
|
237
214
|
_keys.map do |type, attr|
|
238
215
|
{
|
239
216
|
attribute_name: attr.database_name,
|
240
|
-
key_type: type == :hash ?
|
217
|
+
key_type: type == :hash ? 'HASH' : 'RANGE'
|
241
218
|
}
|
242
219
|
end
|
243
220
|
end
|
244
221
|
|
245
222
|
def _keys
|
246
|
-
@model.keys.
|
223
|
+
@model.keys.each_with_object({}) do |(type, name), acc|
|
247
224
|
acc[type] = @model.attributes.attribute_for(name)
|
248
225
|
acc
|
249
226
|
end
|