carnivore 0.1.8 → 0.1.10
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 +6 -0
- data/README.md +2 -2
- data/carnivore.gemspec +1 -3
- data/lib/carnivore/config.rb +13 -1
- data/lib/carnivore/message.rb +8 -4
- data/lib/carnivore/runner.rb +11 -1
- data/lib/carnivore/source.rb +4 -6
- data/lib/carnivore/supervisor.rb +0 -9
- data/lib/carnivore/utils.rb +5 -0
- data/lib/carnivore/version.rb +1 -1
- metadata +3 -39
- data/carnivore-0.1.6.gem +0 -0
- data/lib/carnivore/source/http.rb +0 -44
- data/lib/carnivore/source/rabbitmq.rb +0 -37
- data/lib/carnivore/source/sqs.rb +0 -135
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
data/carnivore.gemspec
CHANGED
@@ -6,13 +6,11 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.summary = 'Message processing helper'
|
7
7
|
s.author = 'Chris Roberts'
|
8
8
|
s.email = 'chrisroberts.code@gmail.com'
|
9
|
-
s.homepage = 'https://github.com/
|
9
|
+
s.homepage = 'https://github.com/carnivore-rb/carnivore'
|
10
10
|
s.description = 'Message processing helper'
|
11
11
|
s.require_path = 'lib'
|
12
12
|
s.add_dependency 'fog'
|
13
13
|
s.add_dependency 'celluloid'
|
14
|
-
s.add_dependency 'reel'
|
15
14
|
s.add_dependency 'mixlib-config'
|
16
|
-
s.add_dependency 'bunny'
|
17
15
|
s.files = Dir['**/*']
|
18
16
|
end
|
data/lib/carnivore/config.rb
CHANGED
@@ -8,6 +8,13 @@ module Carnivore
|
|
8
8
|
|
9
9
|
class << self
|
10
10
|
|
11
|
+
def auto_symbolize(v=nil)
|
12
|
+
unless(v.nil?)
|
13
|
+
@hash_symbolizer = !!v
|
14
|
+
end
|
15
|
+
@hash_symbolizer.nil? ? false : @hash_symbolizer
|
16
|
+
end
|
17
|
+
|
11
18
|
# args:: configuration hash
|
12
19
|
# Merge provided args into configuration
|
13
20
|
def configure(args)
|
@@ -44,9 +51,14 @@ module Carnivore
|
|
44
51
|
# Config.get(:other_app, :port) => nil
|
45
52
|
# Config.get(:my_app, :mail, :server) => nil
|
46
53
|
def get(*ary)
|
47
|
-
ary.flatten.inject(self) do |memo, key|
|
54
|
+
value = ary.flatten.inject(self) do |memo, key|
|
48
55
|
memo[key.to_s] || memo[key.to_sym] || break
|
49
56
|
end
|
57
|
+
if(value.is_a?(Hash) && auto_symbolize)
|
58
|
+
Carnivore::Utils.symbolize_hash(value)
|
59
|
+
else
|
60
|
+
value
|
61
|
+
end
|
50
62
|
end
|
51
63
|
|
52
64
|
end
|
data/lib/carnivore/message.rb
CHANGED
@@ -7,17 +7,21 @@ module Carnivore
|
|
7
7
|
|
8
8
|
def initialize(args={})
|
9
9
|
unless(args[:source])
|
10
|
-
raise ArgumentError.new("A valid `Carnivore::Source` must be provided via `:source`")
|
10
|
+
raise ArgumentError.new("A valid `Carnivore::Source` name must be provided via `:source`")
|
11
11
|
end
|
12
12
|
@args = args.dup
|
13
13
|
end
|
14
14
|
|
15
15
|
def [](k)
|
16
|
-
|
16
|
+
if(k.to_sym == :source)
|
17
|
+
Celluloid::Actor[@args[:source]]
|
18
|
+
else
|
19
|
+
@args[k.to_sym] || @args[k.to_s]
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
|
-
def confirm!
|
20
|
-
self[:source].confirm(self)
|
23
|
+
def confirm!(*args)
|
24
|
+
self[:source].confirm(*([self] + args))
|
21
25
|
end
|
22
26
|
|
23
27
|
def inspect
|
data/lib/carnivore/runner.rb
CHANGED
@@ -12,10 +12,20 @@ module Carnivore
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def start!
|
15
|
+
supervisor = nil
|
15
16
|
begin
|
16
17
|
require 'carnivore/supervisor'
|
17
|
-
Supervisor.run
|
18
|
+
supervisor = Carnivore::Supervisor.run!
|
19
|
+
Source.sources.each do |source|
|
20
|
+
supervisor.supervise_as(
|
21
|
+
source.source_hash[:name],
|
22
|
+
source.klass,
|
23
|
+
source.source_hash
|
24
|
+
)
|
25
|
+
end
|
26
|
+
supervisor.wait(:kill_all_humans)
|
18
27
|
rescue Exception => e
|
28
|
+
supervisor.terminate
|
19
29
|
# Gracefully shut down
|
20
30
|
end
|
21
31
|
end
|
data/lib/carnivore/source.rb
CHANGED
@@ -91,12 +91,14 @@ module Carnivore
|
|
91
91
|
attr_reader :callbacks
|
92
92
|
attr_reader :auto_confirm
|
93
93
|
attr_reader :auto_process
|
94
|
+
attr_reader :run_process
|
94
95
|
attr_reader :callback_supervisor
|
95
96
|
|
96
97
|
def initialize(args={})
|
97
98
|
@callbacks = []
|
98
99
|
@callback_names = {}
|
99
100
|
@auto_process = args.fetch(:auto_process, true)
|
101
|
+
@run_process = @auto_process
|
100
102
|
@auto_confirm = !!args[:auto_confirm]
|
101
103
|
@callback_supervisor = Celluloid::SupervisionGroup.run!
|
102
104
|
@name = args[:name] || Celluloid.uuid
|
@@ -145,10 +147,6 @@ module Carnivore
|
|
145
147
|
debug 'No custom confirm declared'
|
146
148
|
end
|
147
149
|
|
148
|
-
def terminate
|
149
|
-
@callback_supervisor.finalize
|
150
|
-
end
|
151
|
-
|
152
150
|
def add_callback(name, block_or_class)
|
153
151
|
if(block_or_class.is_a?(Class))
|
154
152
|
size = block_or_class.workers || 1
|
@@ -189,12 +187,12 @@ module Carnivore
|
|
189
187
|
def format(msg)
|
190
188
|
Message.new(
|
191
189
|
:message => msg,
|
192
|
-
:source => self
|
190
|
+
:source => self.name
|
193
191
|
)
|
194
192
|
end
|
195
193
|
|
196
194
|
def process
|
197
|
-
|
195
|
+
while(run_process)
|
198
196
|
msgs = Array(receive).flatten.compact.map do |m|
|
199
197
|
format(m)
|
200
198
|
end
|
data/lib/carnivore/supervisor.rb
CHANGED
data/lib/carnivore/utils.rb
CHANGED
data/lib/carnivore/version.rb
CHANGED
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.1.
|
4
|
+
version: 0.1.10
|
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: 2013-10-
|
12
|
+
date: 2013-10-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -43,22 +43,6 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: reel
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
46
|
- !ruby/object:Gem::Dependency
|
63
47
|
name: mixlib-config
|
64
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,22 +59,6 @@ dependencies:
|
|
75
59
|
- - ! '>='
|
76
60
|
- !ruby/object:Gem::Version
|
77
61
|
version: '0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: bunny
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
86
|
-
type: :runtime
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
94
62
|
description: Message processing helper
|
95
63
|
email: chrisroberts.code@gmail.com
|
96
64
|
executables: []
|
@@ -99,10 +67,7 @@ extra_rdoc_files: []
|
|
99
67
|
files:
|
100
68
|
- lib/carnivore/callback.rb
|
101
69
|
- lib/carnivore/supervisor.rb
|
102
|
-
- lib/carnivore/source/http.rb
|
103
|
-
- lib/carnivore/source/sqs.rb
|
104
70
|
- lib/carnivore/source/test.rb
|
105
|
-
- lib/carnivore/source/rabbitmq.rb
|
106
71
|
- lib/carnivore/source.rb
|
107
72
|
- lib/carnivore/version.rb
|
108
73
|
- lib/carnivore/runner.rb
|
@@ -122,10 +87,9 @@ files:
|
|
122
87
|
- examples/test_block.rb
|
123
88
|
- Gemfile
|
124
89
|
- README.md
|
125
|
-
- carnivore-0.1.6.gem
|
126
90
|
- CHANGELOG.md
|
127
91
|
- carnivore.gemspec
|
128
|
-
homepage: https://github.com/
|
92
|
+
homepage: https://github.com/carnivore-rb/carnivore
|
129
93
|
licenses: []
|
130
94
|
post_install_message:
|
131
95
|
rdoc_options: []
|
data/carnivore-0.1.6.gem
DELETED
Binary file
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'reel'
|
2
|
-
require 'carnivore/source'
|
3
|
-
|
4
|
-
module Carnivore
|
5
|
-
class Source
|
6
|
-
|
7
|
-
class Http < Source
|
8
|
-
|
9
|
-
attr_reader :args
|
10
|
-
|
11
|
-
def setup(args={})
|
12
|
-
@args = default_args(args)
|
13
|
-
end
|
14
|
-
|
15
|
-
def default_args(args)
|
16
|
-
{
|
17
|
-
:bind => '0.0.0.0',
|
18
|
-
:port => '3000',
|
19
|
-
:auto_respond => true
|
20
|
-
}.merge(args)
|
21
|
-
end
|
22
|
-
|
23
|
-
def process(*process_args)
|
24
|
-
srv = Reel::Server.supervise(args[:bind], args[:port]) do |con|
|
25
|
-
while(req = con.request)
|
26
|
-
begin
|
27
|
-
msg = format(:request => req, :body => req.body, :connection => con)
|
28
|
-
callbacks.each do |name|
|
29
|
-
c_name = callback_name(name)
|
30
|
-
debug "Dispatching message<#{msg[:message].object_id}> to callback<#{name} (#{c_name})>"
|
31
|
-
Celluloid::Actor[c_name].async.call(msg)
|
32
|
-
end
|
33
|
-
con.respond(:ok, 'So long, and thanks for all the fish!') if args[:auto_respond]
|
34
|
-
rescue => e
|
35
|
-
con.respond(:bad_request, 'Failed to process request')
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'fog'
|
2
|
-
require 'carnivore/source'
|
3
|
-
|
4
|
-
module Carnivore
|
5
|
-
class Source
|
6
|
-
class RabbitMq < Source
|
7
|
-
|
8
|
-
def setup(args={})
|
9
|
-
@bunny = nil
|
10
|
-
@connection_args = args[:bunny]
|
11
|
-
@queue_name = args[:queue]
|
12
|
-
@exchange_name = args[:exchange]
|
13
|
-
debug "Creating RabbitMq source instance <#{name}>"
|
14
|
-
end
|
15
|
-
|
16
|
-
def connect
|
17
|
-
@bunny = Bunny.new(@connection_args)
|
18
|
-
@bunny.start
|
19
|
-
@channel = @bunny.create_channel
|
20
|
-
@exchange = @channel.topic(@exchange_name)
|
21
|
-
@queue = @channel.queue(@queue_name).bind(@exchange) # TODO: Add topic key
|
22
|
-
end
|
23
|
-
|
24
|
-
def process
|
25
|
-
@queue.subscribe do |info, metadata, payload|
|
26
|
-
msg = format(payload)
|
27
|
-
callbacks.each do |name|
|
28
|
-
c_name = callback_name(name)
|
29
|
-
debug "Dispatching message<#{msg[:message].object_id}> to callback<#{name} (#{c_name})>"
|
30
|
-
Celluloid::Actor[c_name].async.call(msg)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/carnivore/source/sqs.rb
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
require 'fog'
|
2
|
-
require 'carnivore/source'
|
3
|
-
|
4
|
-
module Carnivore
|
5
|
-
class Source
|
6
|
-
class Sqs < Source
|
7
|
-
|
8
|
-
OUTPUT_REPEAT_EVERY=20
|
9
|
-
|
10
|
-
attr_reader :pause_time
|
11
|
-
|
12
|
-
def setup(args={})
|
13
|
-
@fog = nil
|
14
|
-
@connection_args = args[:fog]
|
15
|
-
case args[:queues]
|
16
|
-
when Hash
|
17
|
-
@queues = args[:queues]
|
18
|
-
else
|
19
|
-
@queues = Array(args[:queues]).flatten.compact
|
20
|
-
@queues = Hash[*(
|
21
|
-
@queues.size.times.map(&:to_i).zip(@queues).flatten
|
22
|
-
)]
|
23
|
-
end
|
24
|
-
@queues.values.map do |q|
|
25
|
-
q.replace(format_queue(q))
|
26
|
-
end
|
27
|
-
if(args[:processable_queues])
|
28
|
-
@processable_queues = Array(args[:processable_queues]).flatten.compact
|
29
|
-
end
|
30
|
-
@pause_time = args[:pause] || 5
|
31
|
-
@receive_timeout = after(args[:receive_timeout] || 30){ terminate }
|
32
|
-
debug "Creating SQS source instance <#{name}>"
|
33
|
-
debug "Handled queues: #{@queues.inspect}"
|
34
|
-
end
|
35
|
-
|
36
|
-
def format_queue(q)
|
37
|
-
q.include?('.com') ? q : "/#{q.split(':')[-2,2].join('/')}"
|
38
|
-
end
|
39
|
-
|
40
|
-
def connect
|
41
|
-
@fog = Fog::AWS::SQS.new(@connection_args)
|
42
|
-
end
|
43
|
-
|
44
|
-
def receive(n=1)
|
45
|
-
count = 0
|
46
|
-
msgs = []
|
47
|
-
while(msgs.empty?)
|
48
|
-
msgs = []
|
49
|
-
@receive_timeout.reset
|
50
|
-
msgs = queues.map do |q|
|
51
|
-
m = @fog.receive_message(q, 'MaxNumberOfMessages' => n).body['Message']
|
52
|
-
m.map! do |msg|
|
53
|
-
msg.merge('SourceQueue' => q)
|
54
|
-
end
|
55
|
-
end.flatten.compact
|
56
|
-
@receive_timeout.reset
|
57
|
-
if(msgs.empty?)
|
58
|
-
if(count == 0)
|
59
|
-
debug "Source<#{name}> no message received. Sleeping for #{pause_time} seconds."
|
60
|
-
elsif(count % OUTPUT_REPEAT_EVERY == 0)
|
61
|
-
debug "Source<#{name}> last message repeated #{count} times"
|
62
|
-
end
|
63
|
-
sleep(pause_time)
|
64
|
-
else
|
65
|
-
debug "Received: #{msgs.inspect}"
|
66
|
-
end
|
67
|
-
count += 1
|
68
|
-
end
|
69
|
-
msgs.map{|m| pre_process(m) }
|
70
|
-
end
|
71
|
-
|
72
|
-
def transmit(message, original=nil)
|
73
|
-
queue = determine_queue(original)
|
74
|
-
@fog.send_message(queue, message)
|
75
|
-
end
|
76
|
-
|
77
|
-
def confirm(message)
|
78
|
-
queue = determine_queue(message)
|
79
|
-
debug "Source<#{name}> Confirming message<#{message}> on Queue<#{queue}>"
|
80
|
-
m = message.is_a?(Message) ? message[:message] : message
|
81
|
-
@fog.delete_message(queue, m['ReceiptHandle'])
|
82
|
-
end
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
|
-
def determine_queue(obj)
|
87
|
-
queue = nil
|
88
|
-
if(obj)
|
89
|
-
if(obj.is_a?(Message))
|
90
|
-
queue = obj[:message]['SourceQueue']
|
91
|
-
else
|
92
|
-
case obj
|
93
|
-
when Numeric
|
94
|
-
queue = @queues[dest]
|
95
|
-
when String, Symbol
|
96
|
-
queue = @queues[dest.to_s] || queues.detect{|q| q.end_with?(dest.to_s)}
|
97
|
-
when Hash
|
98
|
-
queue = obj['SourceQueue']
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
queue || queues.first
|
103
|
-
end
|
104
|
-
|
105
|
-
def queues
|
106
|
-
if(@processable_queues)
|
107
|
-
@queues.map do |k,v|
|
108
|
-
v if @processable_queues.include?(k)
|
109
|
-
end.compact
|
110
|
-
else
|
111
|
-
@queues.values
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def fog
|
116
|
-
unless(@fog)
|
117
|
-
connect
|
118
|
-
end
|
119
|
-
@fog
|
120
|
-
end
|
121
|
-
|
122
|
-
def pre_process(m)
|
123
|
-
if(m['Body'])
|
124
|
-
begin
|
125
|
-
m['Body'] = JSON.load(m['Body'])
|
126
|
-
rescue JSON::ParserError
|
127
|
-
# well, we did our best
|
128
|
-
end
|
129
|
-
end
|
130
|
-
m
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|