ocean-dynamo 0.2.2 → 0.2.3

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: 38c9f3db161b07ef4486141afad09f05af00b752
4
- data.tar.gz: 92a73810cedf7aceb64e31fde8582afd2e56fe18
3
+ metadata.gz: 8eaf6828f75761ed94d2acbfa5a28383b892c2d3
4
+ data.tar.gz: 9cc793dae4769417a4b87949f6c8a183679f6bc8
5
5
  SHA512:
6
- metadata.gz: 0116191369abb7f9124034727ea50dc32995cfbebd55a4c030ded15a963c3f5fd7a1ed244ce85971606af4e329cf78f942b84a2d81e270af94bc4eddd135c3b1
7
- data.tar.gz: 95861f8c29cd86c2018633549c21ce45b61adf65e8c2742496da04321ef6e2dd40447b8438c7d70ce36c40b35bcc87874bb65a50279ae835ef0f9a4d84b7cd5b
6
+ metadata.gz: ff59c0d44b7c45cdd07702f199b6816f1daedfa9998d0ffe8c6e75f8bff094c46ab55a144e81a57932d8775e758d0af0e378b922815959144294c715e53c3a40
7
+ data.tar.gz: ea2b09b9afa20d4a0cf0e6e6d0a7e51b739e0674dd06f9fbbf877a903c31a96e3311e00dad45578948b5a0c5601312f65ceb15539de33c73310a1c09f054a49c
@@ -72,7 +72,22 @@ Sets are represented as arrays and may not contain duplicates and may not be emp
72
72
  All attributes except the :string type can take the value nil. Storing nil for a string
73
73
  value will return the empty string, "".
74
74
 
75
- Also, dynamo_schema takes args and many options. Detailed documentation is forthcoming.
75
+ Also, dynamo_schema takes args and many options. Here's the full syntax:
76
+
77
+ dynamo_schema(
78
+ table_hash_key = :uuid,
79
+ table_range_key = nil,
80
+ table_name: compute_table_name,
81
+ table_name_prefix: nil,
82
+ table_name_suffix: nil,
83
+ read_capacity_units: 10,
84
+ write_capacity_units: 5,
85
+ connect: :late,
86
+ create: false,
87
+ locking: :lock_version,
88
+ timestamps: [:created_at, :updated_at],
89
+ &block
90
+ )
76
91
 
77
92
  At the moment, OceanDynamo is fully usable as an ActiveModel and can be used by Rails
78
93
  controllers. Furthermore, OceanDynamo implements much of the infrastructure of ActiveRecord;
@@ -15,10 +15,4 @@ require "ocean-dynamo/persistence"
15
15
 
16
16
  module OceanDynamo
17
17
 
18
- DEFAULT_ATTRIBUTES = [
19
- [:created_at, :datetime],
20
- [:updated_at, :datetime],
21
- [:lock_version, :integer, default: 0]
22
- ]
23
-
24
18
  end
@@ -16,9 +16,7 @@ module OceanDynamo
16
16
  write_attribute(name, evaluate_default(md[:default], md[:type]))
17
17
  self.class.class_eval "def #{name}; read_attribute('#{name.to_s}'); end"
18
18
  self.class.class_eval "def #{name}=(value); write_attribute('#{name.to_s}', value); end"
19
- if fields[name][:type] == :boolean
20
- self.class.class_eval "def #{name}?; read_attribute('#{name.to_s}'); end"
21
- end
19
+ self.class.class_eval "def #{name}?; read_attribute('#{name.to_s}').present?; end"
22
20
  end
23
21
  @dynamo_item = nil
24
22
  @destroyed = false
@@ -91,9 +89,7 @@ module OceanDynamo
91
89
  # raise ActiveModel::ForbiddenAttributesError
92
90
  # end
93
91
  # end
94
- values.each do |k, v|
95
- _assign_attribute(k, v)
96
- end
92
+ values.each { |k, v| _assign_attribute(k, v) }
97
93
  end
98
94
 
99
95
 
@@ -197,11 +193,11 @@ module OceanDynamo
197
193
 
198
194
  def _assign_attribute(k, v) # :nodoc:
199
195
  public_send("#{k}=", v)
200
- rescue ActiveModel::NoMethodError
196
+ rescue NoMethodError
201
197
  if respond_to?("#{k}=")
202
198
  raise
203
199
  else
204
- raise ActiveModel::UnknownAttributeError, "unknown attribute: #{k}"
200
+ raise UnknownAttributeError, "unknown attribute: #{k}"
205
201
  end
206
202
  end
207
203
 
@@ -4,5 +4,35 @@ module OceanDynamo
4
4
  include ActiveModel::Model
5
5
  include ActiveModel::Validations::Callbacks
6
6
 
7
+
8
+ def ==(comparison_object)
9
+ super ||
10
+ comparison_object.instance_of?(self.class) &&
11
+ id.present? &&
12
+ comparison_object.id == id
13
+ end
14
+ alias :eql? :==
15
+
16
+
17
+ # Clone and freeze the attributes hash such that associations are still
18
+ # accessible, even on destroyed records, but cloned models will not be
19
+ # frozen.
20
+ def freeze
21
+ @attributes = @attributes.clone.freeze
22
+ self
23
+ end
24
+
25
+ # Returns +true+ if the attributes hash has been frozen.
26
+ def frozen?
27
+ @attributes.frozen?
28
+ end
29
+
30
+ # Allows sort on objects
31
+ def <=>(other_object)
32
+ if other_object.is_a?(self.class)
33
+ self.to_key <=> other_object.to_key
34
+ end
35
+ end
36
+
7
37
  end
8
38
  end
@@ -43,5 +43,11 @@ module OceanDynamo
43
43
  class_attribute :table_create_policy, instance_writer: false
44
44
  self.table_create_policy = false
45
45
 
46
+ class_attribute :lock_attribute, instance_writer: false
47
+ self.lock_attribute = :lock_version
48
+
49
+ class_attribute :timestamp_attributes, instance_writer: false
50
+ self.timestamp_attributes = [:created_at, :updated_at]
51
+
46
52
  end
47
53
  end
@@ -108,9 +108,7 @@ module OceanDynamo
108
108
  run_callbacks :create do
109
109
  k = read_attribute(table_hash_key)
110
110
  write_attribute(table_hash_key, SecureRandom.uuid) if k == "" || k == nil
111
- t = Time.zone.now
112
- self.created_at ||= t
113
- self.updated_at ||= t
111
+ set_timestamps
114
112
  dynamo_persist
115
113
  true
116
114
  end
@@ -124,8 +122,8 @@ module OceanDynamo
124
122
  run_callbacks :commit do
125
123
  run_callbacks :save do
126
124
  run_callbacks :update do
127
- self.updated_at = Time.zone.now
128
- dynamo_persist
125
+ set_timestamps
126
+ dynamo_persist(lock: lock_attribute)
129
127
  true
130
128
  end
131
129
  end
@@ -148,12 +146,11 @@ module OceanDynamo
148
146
 
149
147
 
150
148
  def delete
151
- _connect_late?
152
149
  if persisted?
153
- @dynamo_item.delete
150
+ dynamo_delete(lock: lock_attribute)
154
151
  end
152
+ freeze
155
153
  @destroyed = true
156
- #freeze
157
154
  end
158
155
 
159
156
 
@@ -167,17 +164,16 @@ module OceanDynamo
167
164
 
168
165
  def touch(name=nil)
169
166
  raise DynamoError, "can not touch on a new record object" unless persisted?
170
- _connect_late?
167
+ _late_connect?
171
168
  run_callbacks :touch do
172
- attrs = ['updated_at']
173
- attrs << name if name
174
- t = Time.zone.now
175
- attrs.each { |k| write_attribute k, t }
176
- # TODO: handle lock_version
177
- dynamo_item.attributes.update do |u|
178
- attrs.each do |k|
179
- u.set(k => serialize_attribute(k, t))
169
+ begin
170
+ dynamo_item.attributes.update(_handle_locking) do |u|
171
+ set_timestamps(name).each do |k|
172
+ u.set(k => serialize_attribute(k, read_attribute(k)))
173
+ end
180
174
  end
175
+ rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
176
+ raise OceanDynamo::StaleObjectError
181
177
  end
182
178
  self
183
179
  end
@@ -187,7 +183,7 @@ module OceanDynamo
187
183
 
188
184
  protected
189
185
 
190
- def self._connect_late?
186
+ def self._late_connect?
191
187
  return false if table_connected
192
188
  return false unless table_connect_policy
193
189
  establish_db_connection
@@ -195,8 +191,8 @@ module OceanDynamo
195
191
  end
196
192
 
197
193
 
198
- def _connect_late?
199
- self.class._connect_late?
194
+ def _late_connect?
195
+ self.class._late_connect?
200
196
  end
201
197
 
202
198
 
@@ -205,16 +201,33 @@ module OceanDynamo
205
201
  end
206
202
 
207
203
 
208
- def dynamo_persist # :nodoc:
209
- _connect_late?
210
- @dynamo_item = dynamo_items.put(serialized_attributes)
204
+ def dynamo_persist(lock: nil) # :nodoc:
205
+ _late_connect?
206
+ begin
207
+ options = _handle_locking(lock)
208
+ @dynamo_item = dynamo_items.put(serialized_attributes, options)
209
+ rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
210
+ raise OceanDynamo::StaleObjectError
211
+ end
212
+
211
213
  @new_record = false
212
214
  true
213
215
  end
214
216
 
215
217
 
218
+ def dynamo_delete(lock: nil)
219
+ _late_connect?
220
+ begin
221
+ options = _handle_locking(lock)
222
+ @dynamo_item.delete(options)
223
+ rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
224
+ raise OceanDynamo::StaleObjectError
225
+ end
226
+ end
227
+
228
+
216
229
  def dynamo_unpersist(item, consistent) # :nodoc:
217
- _connect_late?
230
+ _late_connect?
218
231
  @dynamo_item = item
219
232
  @new_record = false
220
233
  assign_attributes(_dynamo_read_attributes(consistent_read: consistent))
@@ -237,5 +250,34 @@ module OceanDynamo
237
250
  end
238
251
 
239
252
 
253
+ def set_timestamps(name=nil)
254
+ attrs = []
255
+ attrs << timestamp_attributes[0] if timestamp_attributes && new_record?
256
+ attrs << timestamp_attributes[1] if timestamp_attributes
257
+ attrs << name if name
258
+ _set_timestamp_attributes(attrs)
259
+ attrs
260
+ end
261
+
262
+
263
+ def _set_timestamp_attributes(attrs)
264
+ return if attrs.blank?
265
+ t = Time.zone.now
266
+ attrs.each { |a| write_attribute a, t }
267
+ t
268
+ end
269
+
270
+
271
+ def _handle_locking(lock=lock_attribute)
272
+ _late_connect?
273
+ if lock
274
+ current_v = read_attribute(lock)
275
+ write_attribute(lock, current_v+1) unless frozen?
276
+ {if: {lock => current_v}}
277
+ else
278
+ {}
279
+ end
280
+ end
281
+
240
282
  end
241
283
  end
@@ -2,15 +2,22 @@ module OceanDynamo
2
2
  class Base
3
3
 
4
4
  def self.find(hash, range=nil, consistent: false)
5
- _connect_late?
5
+ _late_connect?
6
6
  item = dynamo_items[hash, range]
7
7
  raise RecordNotFound unless item.exists?
8
8
  new.send(:dynamo_unpersist, item, consistent)
9
9
  end
10
10
 
11
11
 
12
+ def self.find_by_key(*args)
13
+ find(*args)
14
+ rescue RecordNotFound
15
+ nil
16
+ end
17
+
18
+
12
19
  def self.count
13
- _connect_late?
20
+ _late_connect?
14
21
  dynamo_table.item_count || -1 # The || -1 is for fake_dynamo specs.
15
22
  end
16
23
 
@@ -2,7 +2,8 @@ module OceanDynamo
2
2
  class Base
3
3
 
4
4
 
5
- def self.dynamo_schema(table_hash_key=:uuid, table_range_key=nil,
5
+ def self.dynamo_schema(table_hash_key=:uuid,
6
+ table_range_key=nil,
6
7
  table_name: compute_table_name,
7
8
  table_name_prefix: nil,
8
9
  table_name_suffix: nil,
@@ -10,6 +11,8 @@ module OceanDynamo
10
11
  write_capacity_units: 5,
11
12
  connect: :late,
12
13
  create: false,
14
+ locking: :lock_version,
15
+ timestamps: [:created_at, :updated_at],
13
16
  &block)
14
17
  # Set class vars
15
18
  self.dynamo_client = nil
@@ -25,10 +28,13 @@ module OceanDynamo
25
28
  self.table_name_suffix = table_name_suffix
26
29
  self.table_read_capacity_units = read_capacity_units
27
30
  self.table_write_capacity_units = write_capacity_units
31
+ self.lock_attribute = locking
32
+ self.timestamp_attributes = timestamps
28
33
  # Init
29
34
  self.fields = HashWithIndifferentAccess.new
30
35
  attribute table_hash_key, :string, default: ''
31
- DEFAULT_ATTRIBUTES.each { |name, type, **pairs| attribute name, type, **pairs }
36
+ timestamp_attributes.each { |name| attribute name, :datetime } if timestamp_attributes
37
+ attribute lock_attribute, :integer, default: 0
32
38
  block.call
33
39
  # Connect to AWS
34
40
  establish_db_connection if connect == true
@@ -38,7 +38,6 @@ module OceanDynamo
38
38
  else
39
39
  raise UnknownTableStatus.new("Unknown DynamoDB table status '#{dynamo_table.status}'")
40
40
  end
41
- sleep 1
42
41
  end
43
42
  end
44
43
 
@@ -1,3 +1,3 @@
1
1
  module OceanDynamo
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ocean-dynamo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Bengtson