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 CHANGED
@@ -1,3 +1,9 @@
1
+ # v0.1.10
2
+ * Remove builtin sources
3
+ * Allow optional auto-symbolize
4
+ * Let `confirm!` accept extra parameters
5
+ * Add custom supervisor for future expansion
6
+
1
7
  # v0.1.8
2
8
  * Clean up requires
3
9
  * Register sources by name for easy lookup
data/README.md CHANGED
@@ -110,5 +110,5 @@ end.start!
110
110
 
111
111
  ## Info
112
112
 
113
- * Repository: https://github.com/heavywater/carnivore
114
- * IRC: Freenode @ #heavywater
113
+ * Repository: https://github.com/carnivore-rb/carnivore
114
+ * IRC: Freenode @ #carnivore
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/heavywater/carnivore'
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
@@ -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
@@ -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
- @args[k.to_sym] || @args[k.to_s]
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
@@ -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
@@ -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
- loop do
195
+ while(run_process)
198
196
  msgs = Array(receive).flatten.compact.map do |m|
199
197
  format(m)
200
198
  end
@@ -1,13 +1,4 @@
1
1
  module Carnivore
2
2
  class Supervisor < Celluloid::SupervisionGroup
3
-
4
- Source.sources.each do |source|
5
- supervise(
6
- source.klass,
7
- as: source.source_hash[:name],
8
- args: [source.source_hash]
9
- )
10
- end
11
-
12
3
  end
13
4
  end
@@ -21,6 +21,8 @@ module Carnivore
21
21
  end
22
22
  end
23
23
 
24
+ extend Params
25
+
24
26
  module Logging
25
27
 
26
28
  %w(debug info warn error).each do |key|
@@ -39,5 +41,8 @@ module Carnivore
39
41
  end
40
42
 
41
43
  end
44
+
45
+ extend Logging
46
+
42
47
  end
43
48
  end
@@ -1,5 +1,5 @@
1
1
  module Carnivore
2
2
  class Version < Gem::Version
3
3
  end
4
- VERSION = Version.new('0.1.8')
4
+ VERSION = Version.new('0.1.10')
5
5
  end
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.8
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-18 00:00:00.000000000 Z
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/heavywater/carnivore
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
@@ -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