hoodie 0.4.1 → 0.4.2
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/lib/hoodie/identity_map.rb +59 -57
- data/lib/hoodie/utils.rb +163 -161
- data/lib/hoodie/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f049115fb6e28197cf8fc99f90a93b47dfc6d36
|
4
|
+
data.tar.gz: 11356e662f4b076be57c3b42f5e0f0f37ceba367
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7655a46f873e0a0bcaa29b190086e05782816696cbf8d59d013547c32a98d99486fc85d3a773da46655315a26e4cab78a2f4eb22a570f3cb6897d9f8a2bab65
|
7
|
+
data.tar.gz: f4d66b616e2e3f5a73adb2f1dd22b201be54f49c9d8bc43126bb9498333e018f4a75795c6cb25fe739c15bdc853deb5b1757610b9340594eaaa832ebec485c1e
|
data/lib/hoodie/identity_map.rb
CHANGED
@@ -17,78 +17,80 @@
|
|
17
17
|
# permissions and limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
module Hoodie
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def self.enabled
|
26
|
-
Thread.current[:identity_map_enabled]
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.enabled?
|
30
|
-
enabled == true
|
31
|
-
end
|
20
|
+
module Hoodie
|
21
|
+
module IdentityMap
|
22
|
+
def self.enabled=(flag)
|
23
|
+
Thread.current[:identity_map_enabled] = flag
|
24
|
+
end
|
32
25
|
|
33
|
-
|
34
|
-
|
35
|
-
|
26
|
+
def self.enabled
|
27
|
+
Thread.current[:identity_map_enabled]
|
28
|
+
end
|
36
29
|
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
def self.enabled?
|
31
|
+
enabled == true
|
32
|
+
end
|
40
33
|
|
41
|
-
|
42
|
-
|
43
|
-
|
34
|
+
def self.repository
|
35
|
+
Thread.current[:identity_map] ||= {}
|
36
|
+
end
|
44
37
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
ensure
|
49
|
-
self.enabled = old
|
50
|
-
clear
|
51
|
-
end
|
38
|
+
def self.clear
|
39
|
+
repository.clear
|
40
|
+
end
|
52
41
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
ensure
|
57
|
-
self.enabled = old
|
58
|
-
end
|
42
|
+
def self.include?(object)
|
43
|
+
repository.keys.include?(object.id)
|
44
|
+
end
|
59
45
|
|
60
|
-
|
61
|
-
|
62
|
-
|
46
|
+
def self.use
|
47
|
+
old, self.enabled = enabled, true
|
48
|
+
yield if block_given?
|
49
|
+
ensure
|
50
|
+
self.enabled = old
|
51
|
+
clear
|
63
52
|
end
|
64
53
|
|
65
|
-
def
|
66
|
-
|
54
|
+
def self.without
|
55
|
+
old, self.enabled = enabled, false
|
56
|
+
yield if block_given?
|
57
|
+
ensure
|
58
|
+
self.enabled = old
|
67
59
|
end
|
68
|
-
private :get_from_identity_map
|
69
60
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
61
|
+
module ClassMethods
|
62
|
+
def get(id, options = nil)
|
63
|
+
get_from_identity_map(id) || super
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_from_identity_map(id)
|
67
|
+
IdentityMap.repository[id] if IdentityMap.enabled?
|
68
|
+
end
|
69
|
+
private :get_from_identity_map
|
70
|
+
|
71
|
+
def load(id, attrs)
|
72
|
+
if IdentityMap.enabled? && instance = IdentityMap.repository[id]
|
73
|
+
instance
|
74
|
+
else
|
75
|
+
super.tap { |doc| doc.add_to_identity_map }
|
76
|
+
end
|
75
77
|
end
|
76
78
|
end
|
77
|
-
end
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
def save(options={})
|
81
|
+
super.tap { |result| add_to_identity_map if result }
|
82
|
+
end
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
84
|
+
def delete
|
85
|
+
super.tap { remove_from_identity_map }
|
86
|
+
end
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
88
|
+
def add_to_identity_map
|
89
|
+
IdentityMap.repository[id] = self if IdentityMap.enabled?
|
90
|
+
end
|
90
91
|
|
91
|
-
|
92
|
-
|
92
|
+
def remove_from_identity_map
|
93
|
+
IdentityMap.repository.delete(id) if IdentityMap.enabled?
|
94
|
+
end
|
93
95
|
end
|
94
96
|
end
|
data/lib/hoodie/utils.rb
CHANGED
@@ -21,13 +21,84 @@
|
|
21
21
|
require 'securerandom'
|
22
22
|
require 'time'
|
23
23
|
|
24
|
-
module Hoodie
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
module Hoodie
|
25
|
+
module Utils
|
26
|
+
def self.included(base)
|
27
|
+
base.extend(ClassMethods)
|
28
|
+
end
|
29
|
+
private_class_method :included
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def callable(call_her)
|
33
|
+
call_her.respond_to?(:call) ? call_her : lambda { call_her }
|
34
|
+
end
|
35
|
+
|
36
|
+
def camelize(underscored_word)
|
37
|
+
underscored_word.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
|
38
|
+
end
|
39
|
+
|
40
|
+
def classify(table_name)
|
41
|
+
camelize singularize(table_name.to_s.sub(/.*\./, ''))
|
42
|
+
end
|
43
|
+
|
44
|
+
def class_name
|
45
|
+
demodulize(self.class)
|
46
|
+
end
|
47
|
+
|
48
|
+
def caller_name
|
49
|
+
caller_locations(2, 1).first.label
|
50
|
+
end
|
51
|
+
|
52
|
+
def demodulize(class_name_in_module)
|
53
|
+
class_name_in_module.to_s.sub(/^.*::/, '')
|
54
|
+
end
|
55
|
+
|
56
|
+
def pluralize(word)
|
57
|
+
word.to_s.sub(/([^s])$/, '\1s')
|
58
|
+
end
|
59
|
+
|
60
|
+
def singularize(word)
|
61
|
+
word.to_s.sub(/s$/, '').sub(/ie$/, 'y')
|
62
|
+
end
|
63
|
+
|
64
|
+
def underscore(camel_cased_word)
|
65
|
+
word = camel_cased_word.to_s.dup
|
66
|
+
word.gsub!(/::/, '/')
|
67
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
68
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
69
|
+
word.tr! '-', '_'
|
70
|
+
word.downcase!
|
71
|
+
word
|
72
|
+
end
|
73
|
+
|
74
|
+
# Return the date and time in "HTTP-date" format as defined by RFC 7231.
|
75
|
+
#
|
76
|
+
# @return [Date,Time] in "HTTP-date" format
|
77
|
+
def utc_httpdate
|
78
|
+
Time.now.utc.httpdate
|
79
|
+
end
|
80
|
+
|
81
|
+
def request_id
|
82
|
+
SecureRandom.uuid
|
83
|
+
end
|
84
|
+
|
85
|
+
def twenty_four_hours_ago
|
86
|
+
Time.now - ( 60 * 60 * 24)
|
87
|
+
end
|
88
|
+
|
89
|
+
def verify_options(accepted, actual) # @private
|
90
|
+
return unless debug || $DEBUG
|
91
|
+
unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
|
92
|
+
raise Croesus::Errors::UnknownOption,
|
93
|
+
"\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" <<
|
94
|
+
"Accepted options are: #{accepted.inspect}"
|
95
|
+
end
|
96
|
+
yield if block_given?
|
97
|
+
end
|
98
|
+
end # module ClassMethods
|
99
|
+
|
100
|
+
# ============================================================================
|
29
101
|
|
30
|
-
module ClassMethods
|
31
102
|
def callable(call_her)
|
32
103
|
call_her.respond_to?(:call) ? call_her : lambda { call_her }
|
33
104
|
end
|
@@ -94,172 +165,103 @@ module Hoodie::Utils
|
|
94
165
|
end
|
95
166
|
yield if block_given?
|
96
167
|
end
|
97
|
-
end # module ClassMethods
|
98
|
-
|
99
|
-
# ============================================================================
|
100
|
-
|
101
|
-
def callable(call_her)
|
102
|
-
call_her.respond_to?(:call) ? call_her : lambda { call_her }
|
103
|
-
end
|
104
|
-
|
105
|
-
def camelize(underscored_word)
|
106
|
-
underscored_word.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
|
107
|
-
end
|
108
|
-
|
109
|
-
def classify(table_name)
|
110
|
-
camelize singularize(table_name.to_s.sub(/.*\./, ''))
|
111
|
-
end
|
112
168
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
word.gsub!(/::/, '/')
|
136
|
-
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
137
|
-
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
138
|
-
word.tr! '-', '_'
|
139
|
-
word.downcase!
|
140
|
-
word
|
141
|
-
end
|
142
|
-
|
143
|
-
# Return the date and time in "HTTP-date" format as defined by RFC 7231.
|
144
|
-
#
|
145
|
-
# @return [Date,Time] in "HTTP-date" format
|
146
|
-
def utc_httpdate
|
147
|
-
Time.now.utc.httpdate
|
148
|
-
end
|
169
|
+
# Returns the columns and lines of the current tty.
|
170
|
+
#
|
171
|
+
# @return [Integer]
|
172
|
+
# number of columns and lines of tty, returns [0, 0] if no tty is present.
|
173
|
+
#
|
174
|
+
# @api public
|
175
|
+
def terminal_dimensions
|
176
|
+
[0, 0] unless STDOUT.tty?
|
177
|
+
[80, 40] if OS.windows?
|
178
|
+
|
179
|
+
if ENV['COLUMNS'] && ENV['LINES']
|
180
|
+
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
181
|
+
elsif ENV['TERM'] && command_in_path?('tput')
|
182
|
+
[`tput cols`.to_i, `tput lines`.to_i]
|
183
|
+
elsif command_in_path?('stty')
|
184
|
+
`stty size`.scan(/\d+/).map {|s| s.to_i }
|
185
|
+
else
|
186
|
+
[0, 0]
|
187
|
+
end
|
188
|
+
rescue
|
189
|
+
[0, 0]
|
190
|
+
end
|
149
191
|
|
150
|
-
|
151
|
-
|
152
|
-
|
192
|
+
# Checks in PATH returns true if the command is found
|
193
|
+
def command_in_path?(command)
|
194
|
+
found = ENV['PATH'].split(File::PATH_SEPARATOR).map do |p|
|
195
|
+
File.exist?(File.join(p, command))
|
196
|
+
end
|
197
|
+
found.include?(true)
|
198
|
+
end
|
153
199
|
|
154
|
-
|
155
|
-
|
156
|
-
|
200
|
+
# Runs a code block, and retries it when an exception occurs. Should the
|
201
|
+
# number of retries be reached without success, the last exception will be
|
202
|
+
# raised.
|
203
|
+
#
|
204
|
+
# @param opts [Hash{Symbol => Value}]
|
205
|
+
# @option opts [Fixnum] :tries
|
206
|
+
# number of attempts to retry before raising the last exception
|
207
|
+
# @option opts [Fixnum] :sleep
|
208
|
+
# number of seconds to wait between retries, use lambda to exponentially
|
209
|
+
# increasing delay between retries
|
210
|
+
# @option opts [Array(Exception)] :on
|
211
|
+
# the type of exception(s) to catch and retry on
|
212
|
+
# @option opts [Regex] :matching
|
213
|
+
# match based on the exception message
|
214
|
+
# @option opts [Block] :ensure
|
215
|
+
# ensure a block of code is executed, regardless of whether an exception
|
216
|
+
# is raised
|
217
|
+
#
|
218
|
+
# @return [Block]
|
219
|
+
#
|
220
|
+
def retrier(opts = {}, &block)
|
221
|
+
defaults = {
|
222
|
+
tries: 2,
|
223
|
+
sleep: 1,
|
224
|
+
on: StandardError,
|
225
|
+
matching: /.*/,
|
226
|
+
:ensure => Proc.new {}
|
227
|
+
}
|
157
228
|
|
158
|
-
|
159
|
-
|
160
|
-
unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
|
161
|
-
raise Croesus::Errors::UnknownOption,
|
162
|
-
"\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" <<
|
163
|
-
"Accepted options are: #{accepted.inspect}"
|
164
|
-
end
|
165
|
-
yield if block_given?
|
166
|
-
end
|
229
|
+
check_for_invalid_options(opts, defaults)
|
230
|
+
defaults.merge!(opts)
|
167
231
|
|
168
|
-
|
169
|
-
#
|
170
|
-
# @return [Integer]
|
171
|
-
# number of columns and lines of tty, returns [0, 0] if no tty is present.
|
172
|
-
#
|
173
|
-
# @api public
|
174
|
-
def terminal_dimensions
|
175
|
-
[0, 0] unless STDOUT.tty?
|
176
|
-
[80, 40] if OS.windows?
|
177
|
-
|
178
|
-
if ENV['COLUMNS'] && ENV['LINES']
|
179
|
-
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
180
|
-
elsif ENV['TERM'] && command_in_path?('tput')
|
181
|
-
[`tput cols`.to_i, `tput lines`.to_i]
|
182
|
-
elsif command_in_path?('stty')
|
183
|
-
`stty size`.scan(/\d+/).map {|s| s.to_i }
|
184
|
-
else
|
185
|
-
[0, 0]
|
186
|
-
end
|
187
|
-
rescue
|
188
|
-
[0, 0]
|
189
|
-
end
|
232
|
+
return if defaults[:tries] == 0
|
190
233
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
File.exist?(File.join(p, command))
|
195
|
-
end
|
196
|
-
found.include?(true)
|
197
|
-
end
|
234
|
+
on_exception, tries = [defaults[:on]].flatten, defaults[:tries]
|
235
|
+
retries = 0
|
236
|
+
retry_exception = nil
|
198
237
|
|
199
|
-
# Runs a code block, and retries it when an exception occurs. Should the
|
200
|
-
# number of retries be reached without success, the last exception will be
|
201
|
-
# raised.
|
202
|
-
#
|
203
|
-
# @param opts [Hash{Symbol => Value}]
|
204
|
-
# @option opts [Fixnum] :tries
|
205
|
-
# number of attempts to retry before raising the last exception
|
206
|
-
# @option opts [Fixnum] :sleep
|
207
|
-
# number of seconds to wait between retries, use lambda to exponentially
|
208
|
-
# increasing delay between retries
|
209
|
-
# @option opts [Array(Exception)] :on
|
210
|
-
# the type of exception(s) to catch and retry on
|
211
|
-
# @option opts [Regex] :matching
|
212
|
-
# match based on the exception message
|
213
|
-
# @option opts [Block] :ensure
|
214
|
-
# ensure a block of code is executed, regardless of whether an exception
|
215
|
-
# is raised
|
216
|
-
#
|
217
|
-
# @return [Block]
|
218
|
-
#
|
219
|
-
def retrier(opts = {}, &block)
|
220
|
-
defaults = {
|
221
|
-
tries: 2,
|
222
|
-
sleep: 1,
|
223
|
-
on: StandardError,
|
224
|
-
matching: /.*/,
|
225
|
-
:ensure => Proc.new {}
|
226
|
-
}
|
227
|
-
|
228
|
-
check_for_invalid_options(opts, defaults)
|
229
|
-
defaults.merge!(opts)
|
230
|
-
|
231
|
-
return if defaults[:tries] == 0
|
232
|
-
|
233
|
-
on_exception, tries = [defaults[:on]].flatten, defaults[:tries]
|
234
|
-
retries = 0
|
235
|
-
retry_exception = nil
|
236
|
-
|
237
|
-
begin
|
238
|
-
yield retries, retry_exception
|
239
|
-
rescue *on_exception => exception
|
240
|
-
raise unless exception.message =~ defaults[:matching]
|
241
|
-
raise if retries+1 >= defaults[:tries]
|
242
|
-
|
243
|
-
# Interrupt Exception could be raised while sleeping
|
244
238
|
begin
|
245
|
-
|
246
|
-
|
247
|
-
|
239
|
+
yield retries, retry_exception
|
240
|
+
rescue *on_exception => exception
|
241
|
+
raise unless exception.message =~ defaults[:matching]
|
242
|
+
raise if retries+1 >= defaults[:tries]
|
243
|
+
|
244
|
+
# Interrupt Exception could be raised while sleeping
|
245
|
+
begin
|
246
|
+
sleep defaults[:sleep].respond_to?(:call) ?
|
247
|
+
defaults[:sleep].call(retries) : defaults[:sleep]
|
248
|
+
rescue *on_exception
|
249
|
+
end
|
250
|
+
|
251
|
+
retries += 1
|
252
|
+
retry_exception = exception
|
253
|
+
retry
|
254
|
+
ensure
|
255
|
+
defaults[:ensure].call(retries)
|
248
256
|
end
|
249
|
-
|
250
|
-
retries += 1
|
251
|
-
retry_exception = exception
|
252
|
-
retry
|
253
|
-
ensure
|
254
|
-
defaults[:ensure].call(retries)
|
255
257
|
end
|
256
|
-
end
|
257
258
|
|
258
|
-
|
259
|
+
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
259
260
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
261
|
+
def check_for_invalid_options(custom_options, defaults)
|
262
|
+
invalid_options = defaults.merge(custom_options).keys - defaults.keys
|
263
|
+
raise ArgumentError.new('[Retrier] Invalid options: ' \
|
264
|
+
"#{invalid_options.join(", ")}") unless invalid_options.empty?
|
265
|
+
end
|
264
266
|
end
|
265
267
|
end
|
data/lib/hoodie/version.rb
CHANGED