larva 1.0.0 → 1.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 56edc62f830f8beaa3862dcb8ff381f1cd4b35d2
4
- data.tar.gz: 7a77450848d9d87cb6b50f9ac95486cce0fdd8c5
3
+ metadata.gz: 803859c8d275ec839b7b26e3701e2b2f304d78d3
4
+ data.tar.gz: 783918f6ee9a3a4c7e7c42b58380275ef9cbcaf1
5
5
  SHA512:
6
- metadata.gz: 330518dec7552c9150b65fa6ae78c7f12283da832344be782f4db5a48c3795aee8463cdb2f3809f78dc3d260269467fb43604fe06b204d64421c5009697ec923
7
- data.tar.gz: b928a17b94ce057fd544c39824dfe9be8fcdabbdd72c97b070210ce30339de611cb0d271fe64f2544eff418c9e915109b45ee8a9e2d291b12ac5d08a0827fb71
6
+ metadata.gz: b53f60b7190c3ddddbe9de31304ccb261e408c0cbd389b9f34c9ca7338511a50d92e76ad8c9493fb6d1ecfa20d6481ee9f0c27eda572d813314baf8db37a414f
7
+ data.tar.gz: 2b48aa486cbe746af30ffd777febc4f932d9159884cc5363514ccc8611de3f588ad22d1561a9935e148066545a11763b308d82d0afaf89cfff6866d39ea51014
@@ -1,3 +1,7 @@
1
+ # 1.0.1 / 2014-07-12
2
+ * [BUGFIX] Don't require that the logger is Filum.
3
+ * [BUGFIX] Fix bug with message keys not being detected properly.
4
+
1
5
  # 1.0.0 / 2014-07-12
2
6
  * [FEATURE] Remove Meducation specific code and bump to 1.0.0
3
7
 
@@ -2,6 +2,8 @@ require 'active_support/core_ext'
2
2
  require 'filum'
3
3
  require 'propono'
4
4
 
5
+ require_relative 'larva/hash_with_indifferent_access' unless defined?(HashWithIndifferentAccess)
6
+
5
7
  require_relative 'larva/configuration'
6
8
  require_relative 'larva/configurator'
7
9
  require_relative 'larva/mocker'
@@ -0,0 +1,411 @@
1
+ class Hash
2
+ # Returns a new hash with all keys converted using the block operation.
3
+ #
4
+ # hash = { name: 'Rob', age: '28' }
5
+ #
6
+ # hash.transform_keys{ |key| key.to_s.upcase }
7
+ # # => {"NAME"=>"Rob", "AGE"=>"28"}
8
+ def transform_keys
9
+ result = {}
10
+ each_key do |key|
11
+ result[yield(key)] = self[key]
12
+ end
13
+ result
14
+ end
15
+
16
+ # Destructively convert all keys using the block operations.
17
+ # Same as transform_keys but modifies +self+.
18
+ def transform_keys!
19
+ keys.each do |key|
20
+ self[yield(key)] = delete(key)
21
+ end
22
+ self
23
+ end
24
+
25
+ # Returns a new hash with all keys converted to strings.
26
+ #
27
+ # hash = { name: 'Rob', age: '28' }
28
+ #
29
+ # hash.stringify_keys
30
+ # # => { "name" => "Rob", "age" => "28" }
31
+ def stringify_keys
32
+ transform_keys{ |key| key.to_s }
33
+ end
34
+
35
+ # Destructively convert all keys to strings. Same as
36
+ # +stringify_keys+, but modifies +self+.
37
+ def stringify_keys!
38
+ transform_keys!{ |key| key.to_s }
39
+ end
40
+
41
+ # Returns a new hash with all keys converted to symbols, as long as
42
+ # they respond to +to_sym+.
43
+ #
44
+ # hash = { 'name' => 'Rob', 'age' => '28' }
45
+ #
46
+ # hash.symbolize_keys
47
+ # # => { name: "Rob", age: "28" }
48
+ def symbolize_keys
49
+ transform_keys{ |key| key.to_sym rescue key }
50
+ end
51
+ alias_method :to_options, :symbolize_keys
52
+
53
+ # Destructively convert all keys to symbols, as long as they respond
54
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
55
+ def symbolize_keys!
56
+ transform_keys!{ |key| key.to_sym rescue key }
57
+ end
58
+ alias_method :to_options!, :symbolize_keys!
59
+
60
+ # Validate all keys in a hash match <tt>*valid_keys</tt>, raising ArgumentError
61
+ # on a mismatch. Note that keys are NOT treated indifferently, meaning if you
62
+ # use strings for keys but assert symbols as keys, this will fail.
63
+ #
64
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
65
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
66
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
67
+ def assert_valid_keys(*valid_keys)
68
+ valid_keys.flatten!
69
+ each_key do |k|
70
+ unless valid_keys.include?(k)
71
+ raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
72
+ end
73
+ end
74
+ end
75
+
76
+ # Returns a new hash with all keys converted by the block operation.
77
+ # This includes the keys from the root hash and from all
78
+ # nested hashes.
79
+ #
80
+ # hash = { person: { name: 'Rob', age: '28' } }
81
+ #
82
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
83
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
84
+ def deep_transform_keys(&block)
85
+ result = {}
86
+ each do |key, value|
87
+ result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
88
+ end
89
+ result
90
+ end
91
+
92
+ # Destructively convert all keys by using the block operation.
93
+ # This includes the keys from the root hash and from all
94
+ # nested hashes.
95
+ def deep_transform_keys!(&block)
96
+ keys.each do |key|
97
+ value = delete(key)
98
+ self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
99
+ end
100
+ self
101
+ end
102
+
103
+ # Returns a new hash with all keys converted to strings.
104
+ # This includes the keys from the root hash and from all
105
+ # nested hashes.
106
+ #
107
+ # hash = { person: { name: 'Rob', age: '28' } }
108
+ #
109
+ # hash.deep_stringify_keys
110
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
111
+ def deep_stringify_keys
112
+ deep_transform_keys{ |key| key.to_s }
113
+ end
114
+
115
+ # Destructively convert all keys to strings.
116
+ # This includes the keys from the root hash and from all
117
+ # nested hashes.
118
+ def deep_stringify_keys!
119
+ deep_transform_keys!{ |key| key.to_s }
120
+ end
121
+
122
+ # Returns a new hash with all keys converted to symbols, as long as
123
+ # they respond to +to_sym+. This includes the keys from the root hash
124
+ # and from all nested hashes.
125
+ #
126
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
127
+ #
128
+ # hash.deep_symbolize_keys
129
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
130
+ def deep_symbolize_keys
131
+ deep_transform_keys{ |key| key.to_sym rescue key }
132
+ end
133
+
134
+ # Destructively convert all keys to symbols, as long as they respond
135
+ # to +to_sym+. This includes the keys from the root hash and from all
136
+ # nested hashes.
137
+ def deep_symbolize_keys!
138
+ deep_transform_keys!{ |key| key.to_sym rescue key }
139
+ end
140
+ end
141
+
142
+ module ActiveSupport
143
+ # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
144
+ # to be the same.
145
+ #
146
+ # rgb = ActiveSupport::HashWithIndifferentAccess.new
147
+ #
148
+ # rgb[:black] = '#000000'
149
+ # rgb[:black] # => '#000000'
150
+ # rgb['black'] # => '#000000'
151
+ #
152
+ # rgb['white'] = '#FFFFFF'
153
+ # rgb[:white] # => '#FFFFFF'
154
+ # rgb['white'] # => '#FFFFFF'
155
+ #
156
+ # Internally symbols are mapped to strings when used as keys in the entire
157
+ # writing interface (calling <tt>[]=</tt>, <tt>merge</tt>, etc). This
158
+ # mapping belongs to the public interface. For example, given:
159
+ #
160
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
161
+ #
162
+ # You are guaranteed that the key is returned as a string:
163
+ #
164
+ # hash.keys # => ["a"]
165
+ #
166
+ # Technically other types of keys are accepted:
167
+ #
168
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
169
+ # hash[0] = 0
170
+ # hash # => {"a"=>1, 0=>0}
171
+ #
172
+ # but this class is intended for use cases where strings or symbols are the
173
+ # expected keys and it is convenient to understand both as the same. For
174
+ # example the +params+ hash in Ruby on Rails.
175
+ #
176
+ # Note that core extensions define <tt>Hash#with_indifferent_access</tt>:
177
+ #
178
+ # rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
179
+ #
180
+ # which may be handy.
181
+ class HashWithIndifferentAccess < Hash
182
+ # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
183
+ # this class.
184
+ def extractable_options?
185
+ true
186
+ end
187
+
188
+ def with_indifferent_access
189
+ dup
190
+ end
191
+
192
+ def nested_under_indifferent_access
193
+ self
194
+ end
195
+
196
+ def initialize(constructor = {})
197
+ if constructor.is_a?(Hash)
198
+ super()
199
+ update(constructor)
200
+ else
201
+ super(constructor)
202
+ end
203
+ end
204
+
205
+ def default(key = nil)
206
+ if key.is_a?(Symbol) && include?(key = key.to_s)
207
+ self[key]
208
+ else
209
+ super
210
+ end
211
+ end
212
+
213
+ def self.new_from_hash_copying_default(hash)
214
+ hash = hash.to_hash
215
+ new(hash).tap do |new_hash|
216
+ new_hash.default = hash.default
217
+ end
218
+ end
219
+
220
+ def self.[](*args)
221
+ new.merge!(Hash[*args])
222
+ end
223
+
224
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
225
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
226
+
227
+ # Assigns a new value to the hash:
228
+ #
229
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
230
+ # hash[:key] = 'value'
231
+ #
232
+ # This value can be later fetched using either +:key+ or +'key'+.
233
+ def []=(key, value)
234
+ regular_writer(convert_key(key), convert_value(value, for: :assignment))
235
+ end
236
+
237
+ alias_method :store, :[]=
238
+
239
+ # Updates the receiver in-place, merging in the hash passed as argument:
240
+ #
241
+ # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
242
+ # hash_1[:key] = 'value'
243
+ #
244
+ # hash_2 = ActiveSupport::HashWithIndifferentAccess.new
245
+ # hash_2[:key] = 'New Value!'
246
+ #
247
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
248
+ #
249
+ # The argument can be either an
250
+ # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
251
+ # In either case the merge respects the semantics of indifferent access.
252
+ #
253
+ # If the argument is a regular hash with keys +:key+ and +"key"+ only one
254
+ # of the values end up in the receiver, but which one is unspecified.
255
+ #
256
+ # When given a block, the value for duplicated keys will be determined
257
+ # by the result of invoking the block with the duplicated key, the value
258
+ # in the receiver, and the value in +other_hash+. The rules for duplicated
259
+ # keys follow the semantics of indifferent access:
260
+ #
261
+ # hash_1[:key] = 10
262
+ # hash_2['key'] = 12
263
+ # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
264
+ def update(other_hash)
265
+ if other_hash.is_a? HashWithIndifferentAccess
266
+ super(other_hash)
267
+ else
268
+ other_hash.to_hash.each_pair do |key, value|
269
+ if block_given? && key?(key)
270
+ value = yield(convert_key(key), self[key], value)
271
+ end
272
+ regular_writer(convert_key(key), convert_value(value))
273
+ end
274
+ self
275
+ end
276
+ end
277
+
278
+ alias_method :merge!, :update
279
+
280
+ # Checks the hash for a key matching the argument passed in:
281
+ #
282
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
283
+ # hash['key'] = 'value'
284
+ # hash.key?(:key) # => true
285
+ # hash.key?('key') # => true
286
+ def key?(key)
287
+ super(convert_key(key))
288
+ end
289
+
290
+ alias_method :include?, :key?
291
+ alias_method :has_key?, :key?
292
+ alias_method :member?, :key?
293
+
294
+ # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
295
+ # either a string or a symbol:
296
+ #
297
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
298
+ # counters[:foo] = 1
299
+ #
300
+ # counters.fetch('foo') # => 1
301
+ # counters.fetch(:bar, 0) # => 0
302
+ # counters.fetch(:bar) { |key| 0 } # => 0
303
+ # counters.fetch(:zoo) # => KeyError: key not found: "zoo"
304
+ def fetch(key, *extras)
305
+ super(convert_key(key), *extras)
306
+ end
307
+
308
+ # Returns an array of the values at the specified indices:
309
+ #
310
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
311
+ # hash[:a] = 'x'
312
+ # hash[:b] = 'y'
313
+ # hash.values_at('a', 'b') # => ["x", "y"]
314
+ def values_at(*indices)
315
+ indices.collect { |key| self[convert_key(key)] }
316
+ end
317
+
318
+ # Returns an exact copy of the hash.
319
+ def dup
320
+ self.class.new(self).tap do |new_hash|
321
+ new_hash.default = default
322
+ end
323
+ end
324
+
325
+ # This method has the same semantics of +update+, except it does not
326
+ # modify the receiver but rather returns a new hash with indifferent
327
+ # access with the result of the merge.
328
+ def merge(hash, &block)
329
+ self.dup.update(hash, &block)
330
+ end
331
+
332
+ # Like +merge+ but the other way around: Merges the receiver into the
333
+ # argument and returns a new hash with indifferent access as result:
334
+ #
335
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
336
+ # hash['a'] = nil
337
+ # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
338
+ def reverse_merge(other_hash)
339
+ super(self.class.new_from_hash_copying_default(other_hash))
340
+ end
341
+
342
+ # Same semantics as +reverse_merge+ but modifies the receiver in-place.
343
+ def reverse_merge!(other_hash)
344
+ replace(reverse_merge( other_hash ))
345
+ end
346
+
347
+ # Replaces the contents of this hash with other_hash.
348
+ #
349
+ # h = { "a" => 100, "b" => 200 }
350
+ # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
351
+ def replace(other_hash)
352
+ super(self.class.new_from_hash_copying_default(other_hash))
353
+ end
354
+
355
+ # Removes the specified key from the hash.
356
+ def delete(key)
357
+ super(convert_key(key))
358
+ end
359
+
360
+ def stringify_keys!; self end
361
+ def deep_stringify_keys!; self end
362
+ def stringify_keys; dup end
363
+ def deep_stringify_keys; dup end
364
+ undef :symbolize_keys!
365
+ undef :deep_symbolize_keys!
366
+ def symbolize_keys; to_hash.symbolize_keys! end
367
+ def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
368
+ def to_options!; self end
369
+
370
+ def select(*args, &block)
371
+ dup.tap { |hash| hash.select!(*args, &block) }
372
+ end
373
+
374
+ def reject(*args, &block)
375
+ dup.tap { |hash| hash.reject!(*args, &block) }
376
+ end
377
+
378
+ # Convert to a regular hash with string keys.
379
+ def to_hash
380
+ _new_hash= {}
381
+ each do |key, value|
382
+ _new_hash[convert_key(key)] = convert_value(value, for: :to_hash)
383
+ end
384
+ Hash.new(default).merge!(_new_hash)
385
+ end
386
+
387
+ protected
388
+ def convert_key(key)
389
+ key.kind_of?(Symbol) ? key.to_s : key
390
+ end
391
+
392
+ def convert_value(value, options = {})
393
+ if value.is_a? Hash
394
+ if options[:for] == :to_hash
395
+ value.to_hash
396
+ else
397
+ value.nested_under_indifferent_access
398
+ end
399
+ elsif value.is_a?(Array)
400
+ unless options[:for] == :assignment
401
+ value = value.dup
402
+ end
403
+ value.map! { |e| convert_value(e, options) }
404
+ else
405
+ value
406
+ end
407
+ end
408
+ end
409
+ end
410
+
411
+ HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
@@ -15,7 +15,7 @@ module Larva
15
15
  queue_name = "#{topic_name}"
16
16
  Propono.config.logger.info "Starting to listen to queue #{queue_name}"
17
17
  Propono.listen_to_queue("#{queue_name}") do |message, context|
18
- Propono.config.logger.context_id = context[:id]
18
+ Propono.config.logger.context_id = context[:id] if Propono.config.logger.respond_to?(:context_id=)
19
19
  Propono.config.logger.info "Received message: #{message}"
20
20
  processor.process(message)
21
21
  end
@@ -5,8 +5,8 @@ module Larva
5
5
  end
6
6
 
7
7
  attr_accessor :message, :action, :entity, :id
8
- def initialize(message)
9
- @message = message
8
+ def initialize(raw_message)
9
+ @message = HashWithIndifferentAccess.new(raw_message)
10
10
  @action = message[:action]
11
11
  @entity = message[:entity]
12
12
  @id = message[:id]
@@ -1,3 +1,3 @@
1
1
  module Larva
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
@@ -20,9 +20,20 @@ module Larva
20
20
  assert_equal action, processor.action
21
21
  end
22
22
 
23
+ def test_initialize_should_extract_action_and_entity_when_strings
24
+ entity = "media_file"
25
+ action = "processed"
26
+ id = "8"
27
+ message = {'entity' => entity, 'action' => action, 'id' => "8"}
28
+ processor = Processor.new(message)
29
+ assert_equal entity, processor.entity
30
+ assert_equal action, processor.action
31
+ assert_equal id, processor.message[:id]
32
+ end
33
+
23
34
  def test_process_logs_message
24
35
  message = {entity: "media_file", action: "processed", media_file_id: "8"}
25
- output = "Processing message: #{message}"
36
+ output = "Processing message: #{message.stringify_keys}"
26
37
  Propono.config.logger.stubs(:info)
27
38
  Propono.config.logger.expects(:info).with(output)
28
39
  NormalProcessor.process(message)
@@ -42,7 +53,7 @@ module Larva
42
53
 
43
54
  def test_process_logs_success
44
55
  message = {entity: "media_file", action: "processed", media_file_id: "8"}
45
- output = "Message Processed: #{message}"
56
+ output = "Message Processed: #{message.stringify_keys}"
46
57
  Propono.config.logger.stubs(:info)
47
58
  Propono.config.logger.expects(:info).with(output)
48
59
  NormalProcessor.any_instance.expects(:process).returns(true)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: larva
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - iHiD
@@ -131,6 +131,7 @@ files:
131
131
  - lib/larva/configurator.rb
132
132
  - lib/larva/daemon.rb
133
133
  - lib/larva/daemon_creator.rb
134
+ - lib/larva/hash_with_indifferent_access.rb
134
135
  - lib/larva/listener.rb
135
136
  - lib/larva/message_replayer.rb
136
137
  - lib/larva/mocker.rb