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 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