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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b1ff4831b48174ce4404f6f24108ee85b11a104da96aa5176a218fdfeb8dcb8
4
- data.tar.gz: 0610b848e4705bbbb013e8833b8b54f701f100a617714ae9f5bc7891f2d63a99
3
+ metadata.gz: 76f3f70bc226f5e34e377328a8829db296bffa304238da8d7542a947ba0b7a9e
4
+ data.tar.gz: f22f14e087edf96717fbaffd03bc7b3917001fb5238597994143b50bc5e16894
5
5
  SHA512:
6
- metadata.gz: fa1408a44611715ae071ce35b937f40d2c8eae43d1dff2c4d4848a000b34e6944591f56478175ca5b5c3fb0e08e0711cb23ef171def537983d250854ff52a31d
7
- data.tar.gz: 73a5ae3dc603b55e2827cd8126219bddc066a61674ff328a6beed41fca855b3c2e3c8161be3fe57fdec6c7d095b0c482495200b87e5a9f5f10672b7e0b0e4a6e
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
- # projection_type: "ALL"
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
- # attribute, and if present, TTL will be enabled for the table.
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
- provisioned_throughput: {
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
- # This may be a problem, check if I can maintain symbols.
373
- lgsi = @global_secondary_indexes[index_name.to_sym]
374
- gsi[:provisioned_throughput] = lgsi.provisioned_throughput
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
- update_candidates.each do |index_name|
380
- # This may be a problem, check if I can maintain symbols.
381
- lgsi = @global_secondary_indexes[index_name.to_sym]
382
- gsi_updates << {
383
- update: {
384
- index_name: index_name,
385
- provisioned_throughput: lgsi.provisioned_throughput
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
- expected = resp.table.provisioned_throughput.to_h
442
- actual = {
443
- read_capacity_units: @read_capacity_units,
444
- write_capacity_units: @write_capacity_units
445
- }
446
- actual.all? do |k,v|
447
- expected[k] == v
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
- pt_match = lpt.all? do |k,v|
504
- rpt[k] == v
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
- # Validate throughput exists? Validate each throughput is in model?
541
- gsis << mgsi.merge(
542
- provisioned_throughput: config.provisioned_throughput
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
- missing_config << 'read_capacity_units' unless @read_capacity_units
557
- missing_config << 'write_capacity_units' unless @write_capacity_units
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
@@ -13,6 +13,6 @@
13
13
 
14
14
  module Aws
15
15
  module Record
16
- VERSION = '2.1.2'
16
+ VERSION = '2.2.0'
17
17
  end
18
18
  end
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.1.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-15 00:00:00.000000000 Z
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.0'
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.0'
26
+ version: '1.18'
27
27
  description: Provides an object mapping abstraction for Amazon DynamoDB.
28
28
  email:
29
29
  - alexwood@amazon.com