aws-record 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1183f72d5c4a9eb76cce79e3dc780651d33840a8
4
- data.tar.gz: 9b003057c87a84aca97b35e1bbeb2c92f873cb53
3
+ metadata.gz: 3d5eae4de88bc967f473b49bf9294047a6ee6821
4
+ data.tar.gz: 5c2e4404ad3b47f909d572b546f3cd70a8e0e93d
5
5
  SHA512:
6
- metadata.gz: 641f8d63bd27d4c77725cf09c67260e7ea46d11b1502778c180fdb356fd987ae4ded2267428f4466bcf8412aefcf57135a3ea56383fe017af076e67573af6daa
7
- data.tar.gz: 6cd6d4756195610a012767c3f7a9b5a7818ab931a5c0b78ab47b8a895963a7378d90e38ee829f45399826e1648a7b78391b61d9be0fe70155933635625c3f0e6
6
+ metadata.gz: c261673f84aa256222fdd9c17f715ab9161c1a1a1fd23978b494c62627312d12dd314d824321ef43296f87fe92be35ab135de104b6094bb753b746fe3e7235f6
7
+ data.tar.gz: 7742ea625d83be44c72602f0d55b05f7614f87971cd69bcb402f02de0e7c55057b9870a77b43b0d2adfe02f428565b7be7e770317ba9220bc8b2386528306750
data/lib/aws-record.rb CHANGED
@@ -34,6 +34,7 @@ require_relative 'aws-record/record/marshalers/float_marshaler'
34
34
  require_relative 'aws-record/record/marshalers/date_marshaler'
35
35
  require_relative 'aws-record/record/marshalers/date_time_marshaler'
36
36
  require_relative 'aws-record/record/marshalers/time_marshaler'
37
+ require_relative 'aws-record/record/marshalers/epoch_time_marshaler'
37
38
  require_relative 'aws-record/record/marshalers/list_marshaler'
38
39
  require_relative 'aws-record/record/marshalers/map_marshaler'
39
40
  require_relative 'aws-record/record/marshalers/string_set_marshaler'
@@ -240,6 +240,28 @@ module Aws
240
240
  attr(name, Marshalers::TimeMarshaler.new(opts), opts)
241
241
  end
242
242
 
243
+ # Define a time-type attribute for your model which persists as
244
+ # epoch-seconds.
245
+ #
246
+ # @param [Symbol] name Name of this attribute. It should be a name
247
+ # that is safe to use as a method.
248
+ # @param [Hash] opts
249
+ # @option opts [Boolean] :hash_key Set to true if this attribute is
250
+ # the hash key for the table.
251
+ # @option opts [Boolean] :range_key Set to true if this attribute is
252
+ # the range key for the table.
253
+ # @option opts [Boolean] :persist_nil Optional attribute used to
254
+ # indicate whether nil values should be persisted. If true, explicitly
255
+ # set nil values will be saved to DynamoDB as a "null" type. If false,
256
+ # nil values will be ignored and not persisted. By default, is false.
257
+ # @option opts [Object] :default_value Optional attribute used to
258
+ # define a "default value" to be used if the attribute's value on an
259
+ # item is nil or not set at persistence time.
260
+ def epoch_time_attr(name, opts = {})
261
+ opts[:dynamodb_type] = "N"
262
+ attr(name, Marshalers::EpochTimeMarshaler.new(opts), opts)
263
+ end
264
+
243
265
  # Define a list-type attribute for your model.
244
266
  #
245
267
  # Lists do not have to be homogeneous, but they do have to be types that
@@ -0,0 +1,66 @@
1
+ # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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.
13
+
14
+ require 'time'
15
+
16
+ module Aws
17
+ module Record
18
+ module Marshalers
19
+
20
+ class EpochTimeMarshaler
21
+ def initialize(opts = {})
22
+ @use_local_time = opts[:use_local_time] ? true : false
23
+ end
24
+
25
+ def type_cast(raw_value)
26
+ value = _format(raw_value)
27
+ if !@use_local_time && value.is_a?(::Time)
28
+ value.utc
29
+ else
30
+ value
31
+ end
32
+ end
33
+
34
+ def serialize(raw_value)
35
+ time = type_cast(raw_value)
36
+ if time.nil?
37
+ nil
38
+ elsif time.is_a?(::Time)
39
+ time.to_i
40
+ else
41
+ msg = "expected a Time value or nil, got #{time.class}"
42
+ raise ArgumentError, msg
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def _format(raw_value)
49
+ case raw_value
50
+ when nil
51
+ nil
52
+ when ''
53
+ nil
54
+ when ::Time
55
+ raw_value
56
+ when Integer # timestamp
57
+ ::Time.at(raw_value)
58
+ else # Date, DateTime, or String
59
+ ::Time.parse(raw_value.to_s)
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -74,6 +74,19 @@ module Aws
74
74
  # end
75
75
  # end
76
76
  #
77
+ # @example A model with a Time to Live attribute
78
+ # class ExpiringTokens
79
+ # string_attr :token_uuid, hash_key: true
80
+ # epoch_time_attr :ttl
81
+ # end
82
+ #
83
+ # table_config = Aws::Record::TableConfig.define do |t|
84
+ # t.model_class ExpiringTokens
85
+ # t.read_capacity_units 10
86
+ # t.write_capacity_units 1
87
+ # t.ttl_attribute :ttl
88
+ # end
89
+ #
77
90
  class TableConfig
78
91
 
79
92
  attr_accessor :client
@@ -92,6 +105,8 @@ module Aws
92
105
  # index.
93
106
  # * +#write_capacity_units+ Sets the write capacity units for the
94
107
  # index.
108
+ # * +#ttl_attribute+ Sets the attribute ID to be used as the TTL
109
+ # attribute, and if present, TTL will be enabled for the table.
95
110
  #
96
111
  # @example Defining a migration with a GSI.
97
112
  # class Forum
@@ -170,6 +185,16 @@ module Aws
170
185
  @client = Aws::DynamoDB::Client.new(@client_options)
171
186
  end
172
187
 
188
+ # @api private
189
+ def ttl_attribute(attribute_symbol)
190
+ attribute = @model_class.attributes.attribute_for(attribute_symbol)
191
+ if attribute
192
+ @ttl_attribute = attribute.database_name
193
+ else
194
+ raise ArgumentError, "Invalid attribute #{attribute_symbol} for #{@model_class}"
195
+ end
196
+ end
197
+
173
198
  # Performs a migration, if needed, against the remote table. If
174
199
  # +#compatible?+ would return true, the remote table already has the same
175
200
  # throughput, key schema, attribute definitions, and global secondary
@@ -210,6 +235,22 @@ module Aws
210
235
  @client.create_table(_create_table_opts)
211
236
  @client.wait_until(:table_exists, table_name: @model_class.table_name)
212
237
  end
238
+ # At this stage, we have a table and need to check for after-effects to
239
+ # apply.
240
+ # First up is TTL attribute. Since this migration is not exact match,
241
+ # we will only alter TTL status if we have a TTL attribute defined. We
242
+ # may someday support explicit TTL deletion, but we do not yet do this.
243
+ if @ttl_attribute
244
+ if !_ttl_compatibility_check
245
+ client.update_time_to_live(
246
+ table_name: @model_class.table_name,
247
+ time_to_live_specification: {
248
+ enabled: true,
249
+ attribute_name: @ttl_attribute
250
+ }
251
+ )
252
+ end # Else TTL is compatible and we are done.
253
+ end # Else our work is done.
213
254
  end
214
255
 
215
256
  # Checks the remote table for compatibility. Similar to +#exact_match?+,
@@ -224,7 +265,7 @@ module Aws
224
265
  def compatible?
225
266
  begin
226
267
  resp = @client.describe_table(table_name: @model_class.table_name)
227
- _compatible_check(resp)
268
+ _compatible_check(resp) && _ttl_compatibility_check
228
269
  rescue DynamoDB::Errors::ResourceNotFoundException
229
270
  false
230
271
  end
@@ -242,13 +283,41 @@ module Aws
242
283
  _throughput_equal(resp) &&
243
284
  _keys_equal(resp) &&
244
285
  _ad_equal(resp) &&
245
- _gsi_equal(resp)
286
+ _gsi_equal(resp) &&
287
+ _ttl_match_check
246
288
  rescue DynamoDB::Errors::ResourceNotFoundException
247
289
  false
248
290
  end
249
291
  end
250
292
 
251
293
  private
294
+ def _ttl_compatibility_check
295
+ if @ttl_attribute
296
+ ttl_status = @client.describe_time_to_live(
297
+ table_name: @model_class.table_name
298
+ )
299
+ desc = ttl_status.time_to_live_description
300
+ ["ENABLED", "ENABLING"].include?(desc.time_to_live_status) &&
301
+ desc.attribute_name == @ttl_attribute
302
+ else
303
+ true
304
+ end
305
+ end
306
+
307
+ def _ttl_match_check
308
+ ttl_status = @client.describe_time_to_live(
309
+ table_name: @model_class.table_name
310
+ )
311
+ desc = ttl_status.time_to_live_description
312
+ if @ttl_attribute
313
+ ["ENABLED", "ENABLING"].include?(desc.time_to_live_status) &&
314
+ desc.attribute_name == @ttl_attribute
315
+ else
316
+ !["ENABLED", "ENABLING"].include?(desc.time_to_live_status) ||
317
+ desc.attribute_name == nil
318
+ end
319
+ end
320
+
252
321
  def _compatible_check(resp)
253
322
  _throughput_equal(resp) &&
254
323
  _keys_equal(resp) &&
@@ -13,6 +13,6 @@
13
13
 
14
14
  module Aws
15
15
  module Record
16
- VERSION = '2.1.0'
16
+ VERSION = '2.1.1'
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.0
4
+ version: 2.1.1
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-06-25 00:00:00.000000000 Z
11
+ date: 2018-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -44,6 +44,7 @@ files:
44
44
  - lib/aws-record/record/marshalers/boolean_marshaler.rb
45
45
  - lib/aws-record/record/marshalers/date_marshaler.rb
46
46
  - lib/aws-record/record/marshalers/date_time_marshaler.rb
47
+ - lib/aws-record/record/marshalers/epoch_time_marshaler.rb
47
48
  - lib/aws-record/record/marshalers/float_marshaler.rb
48
49
  - lib/aws-record/record/marshalers/integer_marshaler.rb
49
50
  - lib/aws-record/record/marshalers/list_marshaler.rb