dyna_model 0.0.8 → 0.0.9
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/.gitignore +1 -0
- data/lib/dyna_model/aws/record/attributes/date_time_attr.rb +20 -0
- data/lib/dyna_model/config.rb +12 -8
- data/lib/dyna_model/extensions/lock.rb +125 -0
- data/lib/dyna_model/table.rb +12 -5
- data/lib/dyna_model/version.rb +1 -1
- data/lib/dyna_model.rb +2 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc459be343530c48011ba904ffd9c63471f1019d
|
4
|
+
data.tar.gz: b825c0d34229dd97637876a93aef82a607098ba4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36075469a864e5175e3f9a5ab58115eeac91e9855fbbce69974d8c3a37ab26839f90aba0d2aad07e980f5dba4577673b6194e9984168dd4f15bc8bb8908e3192
|
7
|
+
data.tar.gz: 5595a51d3846421051df79a6b7033dbe6d82188099e4ed56f60a12bb0f5f79cc63c8a2d0a4be18f3e7faf45efd67a974c43bb3698be10cbac8d73339adf7c40f
|
data/.gitignore
CHANGED
@@ -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
|
data/lib/dyna_model/config.rb
CHANGED
@@ -11,16 +11,20 @@ module DynaModel
|
|
11
11
|
extend Options
|
12
12
|
|
13
13
|
# All the default options.
|
14
|
-
option :logger, :
|
15
|
-
option :read_provision, :
|
16
|
-
option :write_provision, :
|
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, :
|
20
|
-
option :port, :
|
21
|
-
option :use_ssl, :
|
22
|
-
option :default_guid_delimiter, :
|
23
|
-
option :namespace, :
|
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
|
data/lib/dyna_model/table.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/dyna_model/version.rb
CHANGED
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/
|
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.
|
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-
|
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
|