carnivore 0.1.0 → 0.1.1

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