dyna_model 0.0.8 → 0.0.9

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: 2739ba4513b27ea83ebe29ba3de12d9a3f96f1b0
4
- data.tar.gz: 1277e4a3d77f03f82d27a06777fa05bc1b5fb122
3
+ metadata.gz: dc459be343530c48011ba904ffd9c63471f1019d
4
+ data.tar.gz: b825c0d34229dd97637876a93aef82a607098ba4
5
5
  SHA512:
6
- metadata.gz: 4eee37ed2c9f653ed8ef651ff4c1e72625e8dbc480a75299752d0d236377ee2b69537f7e21b0a6ebfb278631c223d2e0cde07947b6bdf7b17736b3a7982a6792
7
- data.tar.gz: f3518b6a0546434f24f54fb57cad8a1ba73cbcc6fd6720ade4d25b3d529b85662261732f5f7b86f90e2d6bbd8f65f0d909286e8a0de06abe805d4af3dbe8c9e0
6
+ metadata.gz: 36075469a864e5175e3f9a5ab58115eeac91e9855fbbce69974d8c3a37ab26839f90aba0d2aad07e980f5dba4577673b6194e9984168dd4f15bc8bb8908e3192
7
+ data.tar.gz: 5595a51d3846421051df79a6b7033dbe6d82188099e4ed56f60a12bb0f5f79cc63c8a2d0a4be18f3e7faf45efd67a974c43bb3698be10cbac8d73339adf7c40f
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ .DS_Store
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
@@ -0,0 +1,20 @@
1
+ module AWS
2
+ module Record
3
+ module Attributes
4
+ class SerializedAttr < BaseAttr
5
+
6
+ # OVERRIDE
7
+ # https://github.com/aws/aws-sdk-ruby/blob/master/lib/aws/record/attributes.rb#L372
8
+ # Allow Time instead of just DateTime
9
+ def self.serialize datetime, options = {}
10
+ unless datetime.is_a?(DateTime) || datetime.is_a?(Time)
11
+ msg = "expected a DateTime value, got #{datetime.class}"
12
+ raise ArgumentError, msg
13
+ end
14
+ datetime.strftime('%Y-%m-%dT%H:%M:%S%Z')
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -11,16 +11,20 @@ module DynaModel
11
11
  extend Options
12
12
 
13
13
  # All the default options.
14
- option :logger, :default => defined?(Rails)
15
- option :read_provision, :default => 50
16
- option :write_provision, :default => 10
14
+ option :logger, default: defined?(Rails)
15
+ option :read_provision, default: 50
16
+ option :write_provision, default: 10
17
17
  # TODO - default adapter client based on config
18
18
  #option :namespace, :default => defined?(Rails) ? "#{Rails.application.class.parent_name}_#{Rails.env}" : ""
19
- option :endpoint, :default => 'dynamodb.us-west-2.amazonaws.com'
20
- option :port, :default => 443
21
- option :use_ssl, :default => true
22
- option :default_guid_delimiter, :default => ":"
23
- option :namespace, :default => ""
19
+ option :endpoint, default: 'dynamodb.us-west-2.amazonaws.com'
20
+ option :port, default: 443
21
+ option :use_ssl, default: true
22
+ option :default_guid_delimiter, default: ":"
23
+ option :namespace, default: ""
24
+
25
+ option :lock_extension_read_provision, default: 10
26
+ option :lock_extension_write_provision, default: 4
27
+ option :lock_extension_shard_name, default: "lock"
24
28
 
25
29
  # The default logger: either the Rails logger or just stdout.
26
30
  def default_logger
@@ -0,0 +1,125 @@
1
+ module DynaModel
2
+ module Extensions
3
+ class Lock
4
+
5
+ class LockNotAcquired < StandardError
6
+ end
7
+
8
+ HOST = `hostname`.strip
9
+
10
+ include DynaModel::Document
11
+
12
+ string_attr :lock_name
13
+ datetime_attr :locked_at
14
+ datetime_attr :expires_at
15
+ string_attr :locked_by
16
+
17
+ hash_key :lock_name
18
+
19
+ set_shard_name DynaModel::Config.lock_extension_shard_name
20
+
21
+ read_provision DynaModel::Config.lock_extension_read_provision
22
+ write_provision DynaModel::Config.lock_extension_write_provision
23
+
24
+ def self.locked_by
25
+ "#{HOST}:#{Process.pid}"
26
+ end
27
+
28
+ def self.lock(lock_name, options={}, &block)
29
+ lock_acquired = false
30
+ if lock_obj_acquired = self.acquire(lock_name, options)
31
+ lock_acquired = true
32
+ if block
33
+ begin
34
+ result = (block.arity == 1) ? block.call(lock_obj_acquired) : block.call
35
+ ensure
36
+ release(lock_name) if lock_acquired
37
+ end
38
+ end
39
+ result
40
+ end
41
+ end
42
+
43
+ def self.acquire(lock_name, options={})
44
+ options[:acquisition_timeout] ||= 15
45
+ options[:expires_in] ||= 10
46
+
47
+ retries = 0
48
+ begin
49
+ Timeout::timeout(options[:acquisition_timeout]) do
50
+ begin
51
+ locked_at = DateTime.now
52
+ expires_at = locked_at + options[:expires_in].seconds
53
+ lock_obj = self.new(
54
+ lock_name: lock_name,
55
+ locked_at: locked_at,
56
+ expires_at: expires_at,
57
+ locked_by: self.locked_by
58
+ )
59
+ if lock_obj.save(expected: {
60
+ :locked_by.null => "",
61
+ :expires_at.le => locked_at
62
+ }, conditional_operator: :or)
63
+ DynaModel::Config.logger.info "Acquired lock '#{lock_name}'"
64
+ lock_obj
65
+ else
66
+ raise "Error acquiring lock: #{lock_obj.errors.full_messages.to_sentence}"
67
+ end
68
+ rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
69
+ DynaModel::Config.logger.info "Lock condition failed for '#{lock_name}'. Retrying..."
70
+ sleep((2 ** retries) * 0.05)
71
+ retries += 1
72
+ retry
73
+ end
74
+ end
75
+ rescue Timeout::Error
76
+ raise LockNotAcquired, "Could not acquire lock after #{options[:acquisition_timeout]} seconds"
77
+ end
78
+ end
79
+
80
+ def self.release(lock_name, options={})
81
+ lock_obj = self.new(
82
+ lock_name: lock_name,
83
+ locked_at: nil,
84
+ expires_at: nil,
85
+ locked_by: nil
86
+ )
87
+
88
+ if lock_obj.save(expected: {
89
+ :locked_by.eq => self.locked_by
90
+ })
91
+ DynaModel::Config.logger.info "Released lock '#{lock_name}'"
92
+ true
93
+ else
94
+ raise "Error releasing lock: #{lock_obj.errors.full_messages.to_sentence}"
95
+ end
96
+ rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException => e
97
+ DynaModel::Config.logger.info "Condition failed to release lock '#{lock_name}'"
98
+ end
99
+
100
+ def self.extend(lock_name, extension_time=5.seconds)
101
+ locked_at = DateTime.now
102
+ expires_at = locked_at + extension_time
103
+
104
+ lock_obj = self.new(
105
+ lock_name: lock_name,
106
+ locked_at: locked_at,
107
+ expires_at: expires_at,
108
+ locked_by: self.locked_by
109
+ )
110
+
111
+ if lock_obj.save(expected: {
112
+ :locked_by.eq => self.locked_by
113
+ })
114
+ DynaModel::Config.logger.info "Extended lock '#{lock_name}' for #{extension_time} seconds"
115
+ true
116
+ else
117
+ raise "Error extending lock: #{lock_obj.errors.full_messages.to_sentence}"
118
+ end
119
+ rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException => e
120
+ DynaModel::Config.logger.info "Condition failed to extend lock '#{lock_name}'"
121
+ end
122
+
123
+ end
124
+ end
125
+ end
@@ -155,11 +155,11 @@ module DynaModel
155
155
  end
156
156
 
157
157
  if @schema_loaded_from_dynamo[:table][:provisioned_throughput][:read_capacity_units] != @table_schema[:provisioned_throughput][:read_capacity_units]
158
- Toy::Dynamo::Config.logger.error "read_capacity_units mismatch. Need to update table?"
158
+ DynaModel::Config.logger.error "read_capacity_units mismatch. Need to update table?"
159
159
  end
160
160
 
161
161
  if @schema_loaded_from_dynamo[:table][:provisioned_throughput][:write_capacity_units] != @table_schema[:provisioned_throughput][:write_capacity_units]
162
- Toy::Dynamo::Config.logger.error "write_capacity_units mismatch. Need to update table?"
162
+ DynaModel::Config.logger.error "write_capacity_units mismatch. Need to update table?"
163
163
  end
164
164
  end
165
165
 
@@ -513,6 +513,7 @@ module DynaModel
513
513
  attr_name, comparison_operator = attr_conditional.keys.first.split(".")
514
514
  raise ArgumentError, "Comparison operator must be one of (#{(COMPARISON_OPERATOR.keys - COMPARISON_OPERATOR_SCAN_ONLY).join(", ")})" unless COMPARISON_OPERATOR.keys.include?(comparison_operator.to_sym)
515
515
  attr_key = @model.attributes[attr_name]
516
+ attr_class = attr_key.class
516
517
  raise ArgumentError, "#{attr_name} not a valid attribute" unless attr_key
517
518
  attr_type = @model.attribute_type_indicator(attr_key)
518
519
  raise ArgumentError, "#{attr_name} key must be a Range if using the operator BETWEEN" if comparison_operator == "between" && !attr_conditional.values.first.is_a?(Range)
@@ -522,14 +523,14 @@ module DynaModel
522
523
 
523
524
  attribute_value_list = []
524
525
  if comparison_operator == "in"
525
- attr_conditional.values.first.each do |in_v|
526
- attribute_value_list << { attr_type => in_v.to_s }
526
+ attr_value.each do |in_v|
527
+ attribute_value_list << { attr_type => casted_attr_value(attr_class, in_v).to_s }
527
528
  end
528
529
  elsif comparison_operator == "between"
529
530
  attribute_value_list << { attr_type => attr_value.min.to_s }
530
531
  attribute_value_list << { attr_type => attr_value.max.to_s }
531
532
  else
532
- attribute_value_list = [{ attr_type => attr_value.to_s }]
533
+ attribute_value_list = [{ attr_type => casted_attr_value(attr_class, attr_value).to_s }]
533
534
  end
534
535
 
535
536
  attribute_comparison_hash = {
@@ -540,5 +541,11 @@ module DynaModel
540
541
  { attr_name => attribute_comparison_hash }
541
542
  end
542
543
 
544
+ def casted_attr_value(attr_class, val)
545
+ casted = attr_class.type_cast(val)
546
+ return nil if casted.nil?
547
+ attr_class.serialize(casted)
548
+ end
549
+
543
550
  end
544
551
  end
@@ -1,3 +1,3 @@
1
1
  module DynaModel
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
data/lib/dyna_model.rb CHANGED
@@ -14,9 +14,10 @@ require "dyna_model/table"
14
14
  require "dyna_model/query"
15
15
  require "dyna_model/response"
16
16
  require "dyna_model/validations"
17
+ require "dyna_model/document"
17
18
  require "dyna_model/extensions/symbol"
18
19
  require "dyna_model/extensions/s3_backup"
19
- require "dyna_model/document"
20
+ require "dyna_model/extensions/lock"
20
21
 
21
22
  module DynaModel
22
23
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dyna_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cary Dunn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-28 00:00:00.000000000 Z
11
+ date: 2014-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -139,10 +139,12 @@ files:
139
139
  - lib/dyna_model/adapters/carrierwave/dyna_model.rb
140
140
  - lib/dyna_model/adapters/elasticsearch/dyna_model_adapter.rb
141
141
  - lib/dyna_model/attributes.rb
142
+ - lib/dyna_model/aws/record/attributes/date_time_attr.rb
142
143
  - lib/dyna_model/aws/record/attributes/serialized_attr.rb
143
144
  - lib/dyna_model/config.rb
144
145
  - lib/dyna_model/config/options.rb
145
146
  - lib/dyna_model/document.rb
147
+ - lib/dyna_model/extensions/lock.rb
146
148
  - lib/dyna_model/extensions/s3_backup.rb
147
149
  - lib/dyna_model/extensions/symbol.rb
148
150
  - lib/dyna_model/persistence.rb