carnivore 0.1.0 → 0.1.1

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,2 +1,7 @@
1
+ # v0.1.1
2
+ * Update block implementation within callback
3
+ * Allow multiple queues on single SQS source
4
+ * Custom logging to provide instance source information
5
+
1
6
  # v0.1.0
2
7
  * Initial release
data/README.md CHANGED
@@ -54,6 +54,61 @@ Carnivore.configure do
54
54
  end.start!
55
55
  ```
56
56
 
57
+ ### Block execution
58
+
59
+ It is important to note that when providing blocks, they will
60
+ lose all reference to the scope in which they are defined. This
61
+ is due to how `Callback` is implemented and is by design. Simply
62
+ ensure that blocks are fully autonomous and everything will be
63
+ great.
64
+
65
+ #### Example (bad):
66
+
67
+ ```ruby
68
+ Carnivore.configure do
69
+ my_inst = AwesomeSauce.new
70
+ src = Source.build(:type => :test, :args => {})
71
+ src.add_callback(:print_message) do |msg|
72
+ my_inst.be_awesome!
73
+ puts "Received message: #{message}"
74
+ end
75
+ end.start!
76
+ ```
77
+
78
+ #### Example (good):
79
+
80
+ ```ruby
81
+ Carnivore.configure do
82
+ src = Source.build(:type => :test, :args => {})
83
+ src.add_callback(:print_message) do |msg|
84
+ my_inst = AwesomeSauce.new
85
+ my_inst.be_awesome!
86
+ puts "Received message: #{message}"
87
+ end
88
+ end.start!
89
+ ```
90
+
91
+ So, does that mean a new `AwesomeSauce` instance will be
92
+ created on every message processed? Yes, yes it does. However,
93
+ the block at runtime is no longer really a block, so lets
94
+ keep that instance around so it can be reused:
95
+
96
+ #### Example (more gooder):
97
+
98
+ ```ruby
99
+ Carnivore.configure do
100
+ src = Source.build(:type => :test, :args => {})
101
+ src.add_callback(:print_message) do |msg|
102
+ unless(@my_inst)
103
+ @my_inst = AwesomeSauce.new
104
+ end
105
+ @my_inst.be_awesome!
106
+ puts "Received message: #{message}"
107
+ end
108
+ end.start!
109
+ ```
110
+
57
111
  ## Info
58
112
 
59
- * Repository: https://github.com/heavywater/carnivore
113
+ * Repository: https://github.com/heavywater/carnivore
114
+ * IRC: Freenode @ #heavywater
@@ -6,18 +6,15 @@ module Carnivore
6
6
  end
7
7
 
8
8
  include Celluloid
9
- include Celluloid::Logger
10
-
11
- execute_block_on_receiver :execute
12
9
 
13
10
  attr_reader :name
14
11
 
15
12
  def initialize(name, block=nil)
16
13
  @name = name
17
- @block = block
18
- if(@block.nil? && self.class == Callback)
14
+ if(block.nil? && self.class == Callback)
19
15
  raise ArgumentError.new 'Block is required for dynamic callbacks!'
20
16
  end
17
+ define_singleton_method(:execute, &block) if block
21
18
  setup
22
19
  end
23
20
 
@@ -25,7 +22,7 @@ module Carnivore
25
22
  end
26
23
 
27
24
  def inspect
28
- "callback<#{self.object_id}>"
25
+ "callback<#{self.name}:#{self.object_id}>"
29
26
  end
30
27
 
31
28
  def valid?(message)
@@ -33,16 +30,31 @@ module Carnivore
33
30
  end
34
31
 
35
32
  def call(message)
36
- raise TypeError.new('Invalid message for this callback!') unless valid?(message)
37
- @block ? execute(message, &@block) : execute(message)
33
+ if(valid?(message))
34
+ @block ? execute(message, &@block) : execute(message)
35
+ else
36
+ debug 'Received message not valid for this callback'
37
+ end
38
38
  rescue => e
39
39
  error "[callback: #{self}, source: #{message[:source]}, message: #{message[:message].object_id}]: #{e.class} - #{e}"
40
40
  debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
41
41
  end
42
42
 
43
- def execute(message)
44
- yield message
43
+ # Custom logger helpers
44
+
45
+ %w(debug info warn error).each do |key|
46
+ define_method(key) do |string|
47
+ log(key, string)
48
+ end
45
49
  end
46
50
 
51
+ def log(*args)
52
+ if(args.empty?)
53
+ Celluloid::Logger
54
+ else
55
+ severity, string = args
56
+ Celluloid::Logger.send(severity.to_sym, "#{self}: #{string}")
57
+ end
58
+ end
47
59
  end
48
60
  end
@@ -5,14 +5,14 @@ module Carnivore
5
5
  class Source
6
6
  class Sqs < Source
7
7
 
8
- OUTPUT_REPEAT_EVERY=5
8
+ OUTPUT_REPEAT_EVERY=20
9
9
 
10
10
  attr_reader :pause_time
11
11
 
12
12
  def setup(args={})
13
13
  @fog = nil
14
14
  @connection_args = args[:fog]
15
- @queue = args[:queue_url]
15
+ @queues = Array(args[:queues]).compact.flatten
16
16
  @pause_time = args[:pause] || 5
17
17
  @receive_timeout = after(args[:receive_timeout] || 30){ terminate }
18
18
  debug "Creating SQS source instance <#{name}>"
@@ -24,13 +24,15 @@ module Carnivore
24
24
 
25
25
  def receive(n=1)
26
26
  count = 0
27
- m = nil
28
- until(m)
29
- m = nil
27
+ msgs = []
28
+ while(msgs.empty?)
29
+ msgs = []
30
30
  @receive_timeout.reset
31
- m = @fog.receive_message(@queue, 'MaxNumberOfMessages' => n).body['Message'].first
31
+ msgs = @queues.map do |q|
32
+ @fog.receive_message(q, 'MaxNumberOfMessages' => n).body['Message']
33
+ end.flatten.compact
32
34
  @receive_timeout.reset
33
- unless(m)
35
+ if(msgs.empty?)
34
36
  if(count == 0)
35
37
  debug "Source<#{name}> no message received. Sleeping for #{pause_time} seconds."
36
38
  elsif(count % OUTPUT_REPEAT_EVERY == 0)
@@ -40,7 +42,7 @@ module Carnivore
40
42
  end
41
43
  count += 1
42
44
  end
43
- pre_process(m)
45
+ msgs.map{|m| pre_process(m) }
44
46
  end
45
47
 
46
48
  def send(message)
@@ -139,10 +139,14 @@ module Carnivore
139
139
 
140
140
  def process
141
141
  loop do
142
- msg = format(receive)
143
- @callbacks.each do |name|
144
- debug "Dispatching message<#{msg[:message].object_id}> to callback<#{name} (#{callback_name(name)})>"
145
- Celluloid::Actor[callback_name(name)].async.call(msg)
142
+ msgs = Array(receive).flatten.compact.map do |m|
143
+ format(m)
144
+ end
145
+ msgs.each do |msg|
146
+ @callbacks.each do |name|
147
+ debug "Dispatching message<#{msg[:message].object_id}> to callback<#{name} (#{callback_name(name)})>"
148
+ Celluloid::Actor[callback_name(name)].async.call(msg)
149
+ end
146
150
  end
147
151
  end
148
152
  end
@@ -1,5 +1,5 @@
1
1
  module Carnivore
2
2
  class Version < Gem::Version
3
3
  end
4
- VERSION = Version.new('0.1.0')
4
+ VERSION = Version.new('0.1.1')
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.0
4
+ version: 0.1.1
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-09-11 00:00:00.000000000 Z
12
+ date: 2013-09-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog