carnivore 0.2.2 → 0.2.4

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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # v0.2.4
2
+ * Move receive starts out of processing loop
3
+ * Extract source name from arguments on setup
4
+ * Deep force smash type on conversion
5
+ * Add optional disablement of multiple callback matches
6
+
1
7
  # v0.2.2
2
8
  * Local loopback is optional and disabled by default
3
9
  * Include Smash utility for Hash management
@@ -1,4 +1,5 @@
1
1
  require 'carnivore'
2
+ require 'celluloid/autostart'
2
3
 
3
4
  module Carnivore
4
5
  # Payload modifier
@@ -122,6 +122,10 @@ module Carnivore
122
122
  attr_reader :message_remote
123
123
  # @return [TrueClass, FalseClass] currently processing a message
124
124
  attr_reader :processing
125
+ # @return [TrueClass, FalseClass] allow multiple callback matches
126
+ attr_reader :allow_multiple_matches
127
+ # @return [Hash] original options hash
128
+ attr_reader :arguments
125
129
 
126
130
  # Create new Source
127
131
  #
@@ -130,9 +134,13 @@ module Carnivore
130
134
  # @option args [TrueClass, FalseClass] :auto_process start processing on initialization
131
135
  # @option args [TrueClass, FalseClass] :auto_confirm confirm messages automatically on receive
132
136
  # @option args [Proc] :orphan_callback execute block when no callbacks are valid for message
137
+ # @option args [Proc] :multiple_callback execute block when multiple callbacks are valid and multiple support is disabled
133
138
  # @option args [TrueClass, FalseClass] :prevent_duplicates setup and use message registry
139
+ # @option args [TrueClass, FalseClass] :allow_multiple_matches allow multiple callback matches (defaults true)
134
140
  # @option args [Array<Callback>] :callbacks callbacks to register on this source
135
141
  def initialize(args={})
142
+ @arguments = args.dup
143
+ @name = args[:name]
136
144
  @args = Smash.new(args)
137
145
  @callbacks = []
138
146
  @message_loop = Queue.new
@@ -142,11 +150,14 @@ module Carnivore
142
150
  @run_process = true
143
151
  @auto_confirm = !!args[:auto_confirm]
144
152
  @callback_supervisor = Carnivore::Supervisor.create!.last
145
- if(args[:orphan_callback])
146
- unless(args[:orphan_callback].is_a?(Proc))
147
- raise TypeError.new("Expected `Proc` type for `orphan_callback` but received `#{args[:orphan_callback].class}`")
153
+ @allow_multiple_matches = !!args.fetch(:allow_multiple_matches, true)
154
+ [:orphan_callback, :multiple_callback].each do |key|
155
+ if(args[key])
156
+ unless(args[key].is_a?(Proc))
157
+ raise TypeError.new("Expected `Proc` type for `#{key}` but received `#{args[key].class}`")
158
+ end
159
+ define_singleton_method(key, &args[key])
148
160
  end
149
- define_singleton_method(:orphan_callback, &args[:orphan_callback])
150
161
  end
151
162
  if(args[:prevent_duplicates])
152
163
  init_registry
@@ -162,7 +173,10 @@ module Carnivore
162
173
  connect
163
174
  if(auto_process && !callbacks.empty?)
164
175
  async.process
176
+ else
177
+ warn 'Processing is disabled'
165
178
  end
179
+ info 'Source initialization is complete'
166
180
  rescue => e
167
181
  debug "Failed to initialize: #{self} - #{e.class}: #{e}\n#{e.backtrace.join("\n")}"
168
182
  raise
@@ -320,9 +334,9 @@ module Carnivore
320
334
  # @return [TrueClass]
321
335
  def process(*args)
322
336
  begin
337
+ async.receive_messages
338
+ @processing = true
323
339
  while(run_process && !callbacks.empty?)
324
- @processing = true
325
- async.receive_messages
326
340
  if(message_loop.empty? && message_remote.empty?)
327
341
  wait(:messages_available)
328
342
  end
@@ -335,20 +349,24 @@ module Carnivore
335
349
  end
336
350
  end.compact
337
351
  msgs.each do |msg|
338
- if(respond_to?(:orphan_callback))
352
+ if(multiple_callbacks? || respond_to?(:orphan_callback))
339
353
  valid_callbacks = callbacks.find_all do |name|
340
354
  callback_supervisor[callback_name(name)].valid?(msg)
341
355
  end
342
356
  else
343
357
  valid_callbacks = callbacks
344
358
  end
345
- valid_callbacks.each do |name|
346
- debug "Dispatching message<#{msg[:message].object_id}> to callback<#{name} (#{callback_name(name)})>"
347
- callback_supervisor[callback_name(name)].async.call(msg)
348
- end
349
359
  if(valid_callbacks.empty?)
350
360
  warn "Received message was not processed through any callbacks on this source: #{msg}"
351
- orphan_callback(current_actor, msg) if respond_to?(:orphan_callback)
361
+ orphan_callback(msg) if respond_to?(:orphan_callback)
362
+ elsif(valid_callbacks.size > 1 && !multiple_callbacks?)
363
+ error "Received message is valid for multiple callbacks but multiple callbacks are disabled: #{msg}"
364
+ multiple_callback(msg) if respond_to?(:multiple_callback)
365
+ else
366
+ valid_callbacks.each do |name|
367
+ debug "Dispatching message<#{msg[:message].object_id}> to callback<#{name} (#{callback_name(name)})>"
368
+ callback_supervisor[callback_name(name)].async.call(msg)
369
+ end
352
370
  end
353
371
  end
354
372
  end
@@ -409,6 +427,15 @@ module Carnivore
409
427
  false
410
428
  end
411
429
 
430
+ # Allow sending payload to multiple matching callbacks. Custom
431
+ # sources should override this method to disable multiple
432
+ # callback matches if desired.
433
+ #
434
+ # @return [TrueClass, FalseClass]
435
+ def multiple_callbacks?
436
+ allow_multiple_matches
437
+ end
438
+
412
439
  # Load and initialize the message registry
413
440
  #
414
441
  # @return [MessageRegistry] new registry
@@ -58,6 +58,13 @@ module Carnivore
58
58
  true
59
59
  end
60
60
 
61
+ # Check if default supervisor is alive
62
+ #
63
+ # @return [TrueClass, FalseClass]
64
+ def alive?
65
+ supervisor && supervisor.alive?
66
+ end
67
+
61
68
  end
62
69
 
63
70
  # @return [Celluloid::Registry]
@@ -26,6 +26,14 @@ module Carnivore
26
26
  end
27
27
  end
28
28
 
29
+ # Log exception
30
+ #
31
+ # @param e [Exception]
32
+ def exception_log(e)
33
+ error "#{e.class}: #{e}"
34
+ debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
35
+ end
36
+
29
37
  end
30
38
 
31
39
  end
@@ -6,6 +6,7 @@ module Carnivore
6
6
  # Customized Hash
7
7
  class Smash < Hash
8
8
  include Hashie::Extensions::IndifferentAccess
9
+ include Hashie::Extensions::MergeInitializer
9
10
  include Hashie::Extensions::DeepMerge
10
11
  include Hashie::Extensions::Coercion
11
12
 
@@ -21,10 +22,15 @@ module Carnivore
21
22
  end
22
23
  super *args
23
24
  if(base)
24
- self.replace(base)
25
+ self.replace(base.to_smash)
25
26
  end
26
27
  end
27
28
 
29
+ def merge!(hash)
30
+ hash = hash.to_smash unless hash.is_a?(::Smash)
31
+ super(hash)
32
+ end
33
+
28
34
  # Get value at given path
29
35
  #
30
36
  # @param args [String, Symbol] key path to walk
@@ -81,7 +87,11 @@ class Hash
81
87
  #
82
88
  # @return [Smash]
83
89
  def to_smash
84
- ::Smash.new.replace(self)
90
+ ::Smash.new.tap do |smash|
91
+ self.each do |k,v|
92
+ smash[k.is_a?(Symbol) ? k.to_s : k] = v.is_a?(::Hash) && !v.is_a?(::Smash) ? v.to_smash : v
93
+ end
94
+ end
85
95
  end
86
96
  alias_method :hulk_smash, :to_smash
87
97
 
@@ -3,5 +3,5 @@ module Carnivore
3
3
  class Version < Gem::Version
4
4
  end
5
5
  # Current version of library
6
- VERSION = Version.new('0.2.2')
6
+ VERSION = Version.new('0.2.4')
7
7
  end
data/lib/carnivore.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  require 'carnivore/runner'
2
2
  require 'carnivore/version'
3
- # Load in celluloid as required
4
- require 'celluloid/autostart'
5
3
 
6
4
  # Message consumer and processor
7
5
  module Carnivore
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carnivore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-13 00:00:00.000000000 Z
12
+ date: 2014-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: celluloid