carnivore 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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