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