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 +7 -0
- data/carnivore.gemspec +2 -0
- data/lib/carnivore/callback.rb +31 -15
- data/lib/carnivore/config.rb +22 -12
- data/lib/carnivore/container.rb +8 -0
- data/lib/carnivore/errors.rb +2 -0
- data/lib/carnivore/message.rb +15 -8
- data/lib/carnivore/runner.rb +8 -4
- data/lib/carnivore/source/test.rb +11 -3
- data/lib/carnivore/source.rb +181 -79
- data/lib/carnivore/source_container.rb +14 -4
- data/lib/carnivore/spec_helper.rb +65 -3
- data/lib/carnivore/supervisor.rb +40 -22
- data/lib/carnivore/utils/logging.rb +4 -0
- data/lib/carnivore/utils/message_registry.rb +16 -7
- data/lib/carnivore/utils/params.rb +9 -5
- data/lib/carnivore/utils/smash.rb +90 -0
- data/lib/carnivore/utils.rb +2 -0
- data/lib/carnivore/version.rb +3 -3
- data/lib/carnivore.rb +16 -2
- metadata +21 -4
- data/lib/carnivore/autoloader.rb +0 -13
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
|
data/lib/carnivore/callback.rb
CHANGED
@@ -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
|
-
|
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
|
-
#
|
40
|
-
#
|
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
|
46
|
-
#
|
57
|
+
# Execute callback against given message
|
58
|
+
#
|
59
|
+
# @param message [Carnivore::Message]
|
47
60
|
def call(message)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
data/lib/carnivore/config.rb
CHANGED
@@ -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
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
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
|
-
|
69
|
+
Smash.new(value)
|
60
70
|
else
|
61
71
|
value
|
62
72
|
end
|
data/lib/carnivore/container.rb
CHANGED
@@ -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
|
data/lib/carnivore/errors.rb
CHANGED
data/lib/carnivore/message.rb
CHANGED
@@ -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
|
17
|
+
@args = args
|
13
18
|
end
|
14
19
|
|
15
|
-
#
|
20
|
+
# @return [Array<String>] keys available in message hash
|
16
21
|
def keys
|
17
22
|
args.keys
|
18
23
|
end
|
19
24
|
|
20
|
-
#
|
21
|
-
#
|
25
|
+
# Message accessor
|
26
|
+
#
|
27
|
+
# @param k [String, Symbol]
|
22
28
|
def [](k)
|
23
|
-
args[k
|
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
|
-
#
|
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
|
data/lib/carnivore/runner.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
-
require 'carnivore
|
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
|
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
|
-
|
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
|
-
|
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
|