carnivore 0.2.0 → 0.2.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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # v0.2.2
2
+ * Local loopback is optional and disabled by default
3
+ * Include Smash utility for Hash management
4
+ * Provide originating source to callback instances on initialization
5
+ * Add spec helpers
6
+ * Clean up custom supervisor implementation
7
+
1
8
  # v0.2.0
2
9
  * Remove `fog` from dependency list
3
10
  * Add common spec helper for testing
data/carnivore.gemspec CHANGED
@@ -8,9 +8,11 @@ Gem::Specification.new do |s|
8
8
  s.email = 'chrisroberts.code@gmail.com'
9
9
  s.homepage = 'https://github.com/carnivore-rb/carnivore'
10
10
  s.description = 'Message processing helper'
11
+ s.license = 'Apache 2.0'
11
12
  s.require_path = 'lib'
12
13
  s.add_dependency 'celluloid'
13
14
  s.add_dependency 'mixlib-config'
14
15
  s.add_dependency 'multi_json'
16
+ s.add_dependency 'hashie'
15
17
  s.files = Dir['lib/**/*'] + %w(carnivore.gemspec README.md CHANGELOG.md)
16
18
  end
@@ -1,6 +1,7 @@
1
1
  require 'carnivore'
2
2
 
3
3
  module Carnivore
4
+ # Payload modifier
4
5
  class Callback
5
6
 
6
7
  class << self
@@ -10,15 +11,21 @@ module Carnivore
10
11
 
11
12
  include Celluloid
12
13
  include Carnivore::Utils::Logging
14
+ # @!parse include Carnivore::Utils::Logging
13
15
 
16
+ # @return [String, Symbol] name of callback
14
17
  attr_reader :name
18
+ # @return [Carnivore::Source] source this callback is attached
19
+ attr_reader :source
15
20
 
16
- # name:: Name of the callback
17
- # block:: Optional `Proc` to define the callback behavior
18
21
  # Creates a new callback. Optional block to define callback
19
22
  # behavior must be passed as a `Proc` instance, not a block.
20
- def initialize(name, block=nil)
23
+ #
24
+ # @param name [String, Symbol] name of the callback
25
+ # @param block [Proc] optionally define the callback behavior
26
+ def initialize(name, source, block=nil)
21
27
  @name = name
28
+ @source = source
22
29
  if(block.nil? && self.class == Callback)
23
30
  raise ArgumentError.new 'Block is required for dynamic callbacks!'
24
31
  end
@@ -28,32 +35,41 @@ module Carnivore
28
35
 
29
36
  # Used by custom callback classes for setup
30
37
  def setup
38
+ debug 'No custom setup defined'
31
39
  end
32
40
 
33
41
  # Provide nice output when printed
42
+ #
43
+ # @return [String]
34
44
  def inspect
35
45
  "callback<#{self.name}:#{self.object_id}>"
36
46
  end
37
47
  alias_method :to_s, :inspect
38
48
 
39
- # message:: Carnivore::Message
40
- # Return true if message should be handled by this callback
49
+ # Message is valid for this callback
50
+ #
51
+ # @param message [Carnivore::Message]
52
+ # @return [TrueClass, FalseClass]
41
53
  def valid?(message)
42
54
  true
43
55
  end
44
56
 
45
- # message:: Carnivore::Message
46
- # Pass message to registered callbacks
57
+ # Execute callback against given message
58
+ #
59
+ # @param message [Carnivore::Message]
47
60
  def call(message)
48
- if(valid?(message))
49
- debug ">> Received message is valid for this callback (#{message})"
50
- execute(message)
51
- else
52
- debug "Invalid message for this callback #{message})"
61
+ begin
62
+ if(valid?(message))
63
+ debug ">> Received message is valid for this callback (#{message})"
64
+ execute(message)
65
+ else
66
+ debug "Invalid message for this callback #{message})"
67
+ end
68
+ rescue => e
69
+ error "[callback: #{self}, source: #{message[:source]}, message: #{message[:message].object_id}]: #{e.class} - #{e}"
70
+ debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
71
+ nil
53
72
  end
54
- rescue => e
55
- error "[callback: #{self}, source: #{message[:source]}, message: #{message[:message].object_id}]: #{e.class} - #{e}"
56
- debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
57
73
  end
58
74
 
59
75
  end
@@ -3,14 +3,18 @@ require 'mixlib/config'
3
3
  require 'carnivore'
4
4
 
5
5
  module Carnivore
6
+ # Configuration helper
6
7
  class Config
7
8
 
8
9
  extend Mixlib::Config
9
10
 
10
11
  class << self
11
12
 
12
- # v:: Boolean value
13
13
  # Set/get automatic symbolization of hash keys
14
+ #
15
+ # @param v [Object] truthy or falsey value
16
+ # @return [TrueClass, FalseClass]
17
+ # v:: Boolean value
14
18
  def auto_symbolize(v=nil)
15
19
  unless(v.nil?)
16
20
  @hash_symbolizer = !!v
@@ -18,16 +22,20 @@ module Carnivore
18
22
  @hash_symbolizer.nil? ? false : @hash_symbolizer
19
23
  end
20
24
 
21
- # args:: configuration hash
22
25
  # Merge provided args into configuration
26
+ #
27
+ # @param args [Hash]
28
+ # @return [self]
23
29
  def configure(args)
24
30
  build(args[:config_path]) if args[:config_path]
25
31
  self.merge!(args)
26
32
  self
27
33
  end
28
34
 
29
- # path_or_hash:: Path to JSON file or configuration Hash
30
35
  # Populates the configuration
36
+ #
37
+ # @param path_or_hash [String, Hash] Path to JSON file or configuration hash
38
+ # @return [self]
31
39
  def build(path_or_hash)
32
40
  if(path_or_hash.is_a?(Hash))
33
41
  conf = path_or_hash
@@ -45,18 +53,20 @@ module Carnivore
45
53
  self
46
54
  end
47
55
 
48
- # ary: keys into a hash
49
- # Returns value if exists or nil
50
- # Example:
51
- # Config.build(:my_app => {:port => 30})
52
- # Config.get(:my_app, :port) => 30
53
- # Config.get(:my_app, :host) => nil
54
- # Config.get(:other_app, :port) => nil
55
- # Config.get(:my_app, :mail, :server) => nil
56
+ # Fetch value from configuration
57
+ #
58
+ # @param ary [String, Symbol] list of strings or symbols as hash path
59
+ # @return [Object] return value or nil
60
+ # @example
61
+ # Config.build(:my_app => {:port => 30})
62
+ # Config.get(:my_app, :port) => 30
63
+ # Config.get(:my_app, :host) => nil
64
+ # Config.get(:other_app, :port) => nil
65
+ # Config.get(:my_app, :mail, :server) => nil
56
66
  def get(*ary)
57
67
  value = Carnivore::Utils.retrieve(self, *ary)
58
68
  if(value.is_a?(Hash) && auto_symbolize)
59
- Carnivore::Utils.symbolize_hash(value)
69
+ Smash.new(value)
60
70
  else
61
71
  value
62
72
  end
@@ -2,17 +2,25 @@ require 'carnivore'
2
2
  require 'celluloid/logger'
3
3
 
4
4
  module Carnivore
5
+ # Module used for building isolation
5
6
  class Container < Module
6
7
 
7
8
  include Carnivore::Utils::Logging
9
+ # @!parse include Carnivore::Utils::Logging
8
10
 
9
11
  class << self
12
+
13
+ # @return [Celluloid::Logger]
10
14
  def log
11
15
  Celluloid::Logger
12
16
  end
17
+
13
18
  end
19
+
20
+ # @return [Celluloid::Logger]
14
21
  def log
15
22
  Celluloid::Logger
16
23
  end
24
+
17
25
  end
18
26
  end
@@ -1,7 +1,9 @@
1
1
  require 'carnivore'
2
2
 
3
3
  module Carnivore
4
+ # Default Carnivore error class
4
5
  class Error < StandardError
6
+ # Supervisor has died
5
7
  class DeadSupervisor < Error; end
6
8
  end
7
9
  end
@@ -1,40 +1,47 @@
1
1
  require 'carnivore'
2
2
 
3
3
  module Carnivore
4
+ # Wraps a message (Hash) with Carnivore specific helpers
4
5
  class Message
5
6
 
7
+ # @return [Hash] underlying message hash
6
8
  attr_reader :args
7
9
 
10
+ # @param args [Hash]
11
+ # @option args [Carnivore::Source] :source origin source of message
8
12
  def initialize(args={})
13
+ args = args.to_smash
9
14
  unless(args[:source])
10
15
  raise ArgumentError.new("A valid `Carnivore::Source` name must be provided via `:source`")
11
16
  end
12
- @args = args.dup
17
+ @args = args
13
18
  end
14
19
 
15
- # Helper method to return keys available from `args`
20
+ # @return [Array<String>] keys available in message hash
16
21
  def keys
17
22
  args.keys
18
23
  end
19
24
 
20
- # k:: key
21
- # Accessor into message
25
+ # Message accessor
26
+ #
27
+ # @param k [String, Symbol]
22
28
  def [](k)
23
- args[k.to_sym] || args[k.to_s]
29
+ args[k]
24
30
  end
25
31
 
26
- # args:: Arguments
27
32
  # Confirm message was received on source
33
+ #
34
+ # @param args [Object] list passed to Carnivore::Source#confirm
28
35
  def confirm!(*args)
29
36
  self[:source].confirm(*([self] + args).flatten(1).compact)
30
37
  end
31
38
 
32
- # Formatted inspection string
39
+ # @return [String] formatted inspection string
33
40
  def inspect
34
41
  "<Carnivore::Message[#{self.object_id}] @args=#{args.inspect}>"
35
42
  end
36
43
 
37
- # String representation
44
+ # @return [String] string representation
38
45
  def to_s
39
46
  "<Carnivore::Message:#{self.object_id}>"
40
47
  end
@@ -1,17 +1,19 @@
1
- require 'carnivore/autoloader'
1
+ require 'carnivore'
2
2
 
3
3
  module Carnivore
4
4
  class << self
5
5
 
6
- # block:: Block of configuration
7
6
  # Add configuration to Carnivore
7
+ #
8
+ # @yield block of configuration
9
+ # @return [self]
8
10
  def configure(&block)
9
11
  mod = Container.new
10
12
  mod.instance_exec(mod, &block)
11
13
  self
12
14
  end
13
15
 
14
- # Start carnivore
16
+ # Start the Carnivore subsystem
15
17
  def start!
16
18
  supervisor = nil
17
19
  begin
@@ -44,7 +46,9 @@ module Carnivore
44
46
  sleep 10
45
47
  retry
46
48
  rescue Exception => e
47
- supervisor.terminate
49
+ Celluloid::Logger.warn "Exception type encountered forcing shutdown - #{e.class}: #{e}"
50
+ Celluloid::Logger.debug "Shutdown exception info: #{e.class}: #{e}\n#{e.backtrace.join("\n")}"
51
+ supervisor.terminate if supervisor
48
52
  # Gracefully shut down
49
53
  end
50
54
  end
@@ -1,18 +1,23 @@
1
1
  module Carnivore
2
2
  class Source
3
+ # Test source
3
4
  class Test < Source
4
5
 
6
+ # Maximum rand value
5
7
  RAND_MAX = 99999
8
+ # Default rand divisor
6
9
  RAND_DIV = 3
10
+ # Sleep length when valid
7
11
  RAND_SLEEP = 10
8
12
 
9
- def setup(args={})
10
- end
11
-
13
+ # Note that we are connected
12
14
  def connect(*args)
13
15
  info 'Test connect called'
14
16
  end
15
17
 
18
+ # Receive randomly generated message
19
+ #
20
+ # @return [Array<String>]
16
21
  def receive(*args)
17
22
  if(rand(RAND_MAX) % RAND_DIV == 0)
18
23
  sleep_for = rand(RAND_SLEEP)
@@ -22,6 +27,9 @@ module Carnivore
22
27
  20.times.map{('a'..'z').to_a.shuffle.first}.join
23
28
  end
24
29
 
30
+ # Dummy transmit message
31
+ #
32
+ # @param message [Carnivore::Message]
25
33
  def transmit(message)
26
34
  info "Transmit requested: #{message}"
27
35
  end