empipelines 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,7 +3,6 @@
3
3
  ## TODO
4
4
  * Make wiring easier
5
5
  * Example apps
6
- * TerminatorStage should consume message
7
6
  * Control flow for AmqpEventSource
8
7
  * Transaction ID on each message
9
8
  * Evented I/O for IOEventSource
data/Rakefile CHANGED
@@ -116,6 +116,7 @@ task :release => :ci do
116
116
  git tag -a #{gem_file} -m 'Version #{gem_file}'
117
117
  git push origin master
118
118
  git push origin --tags
119
+ gem push pkg/#{gem_file}
119
120
  END
120
121
  end
121
122
 
data/empipelines.gemspec CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
4
4
  s.rubygems_version = '1.3.5'
5
5
  ## Leave these as is they will be modified for you by the rake gemspec task.
6
6
  s.name = 'empipelines'
7
- s.version = '0.2.1'
8
- s.date = '2011-12-21'
7
+ s.version = '0.2.2'
8
+ s.date = '2011-12-23'
9
9
  s.rubyforge_project = 'empipelines'
10
10
 
11
11
  s.summary = "Simple Event Handling Pipeline Architecture for EventMachine"
@@ -37,9 +37,12 @@ Gem::Specification.new do |s|
37
37
  Rakefile
38
38
  empipelines.gemspec
39
39
  functional/consuming_events_from_file_spec.rb
40
+ functional/consuming_events_from_multiple_sources_spec.rb
41
+ functional/consuming_events_from_queue_spec.rb
40
42
  functional/events.dat
41
43
  functional/test_stages.rb
42
44
  lib/empipelines.rb
45
+ lib/empipelines/aggregated_event_source.rb
43
46
  lib/empipelines/amqp_event_source.rb
44
47
  lib/empipelines/batch_event_source.rb
45
48
  lib/empipelines/event_handlers.rb
@@ -49,6 +52,7 @@ Gem::Specification.new do |s|
49
52
  lib/empipelines/message.rb
50
53
  lib/empipelines/periodic_event_source.rb
51
54
  lib/empipelines/pipeline.rb
55
+ unit/empipelines/aggregated_event_source_spec.rb
52
56
  unit/empipelines/amqp_event_source_spec.rb
53
57
  unit/empipelines/batch_event_source_spec.rb
54
58
  unit/empipelines/empty_io_event_source.dat
@@ -10,29 +10,17 @@ module TestStages
10
10
  include EmRunner
11
11
 
12
12
  it 'consumes all events from the file' do
13
- with_em_run do
13
+ with_em_run do
14
14
  pipeline = EmPipelines::Pipeline.new(EM, {:processed => processed}, monitoring, logger)
15
15
 
16
16
  file_name = File.join(File.dirname(__FILE__), 'events.dat')
17
17
  source = EmPipelines::IOEventSource.new(EM, file_name)
18
18
 
19
- stages = [PassthroughStage, PassthroughStage, PassthroughStage, ConsumeStage]
19
+ stages = [PassthroughStage, PassthroughStage, PassthroughStage]
20
20
  event_pipeline = EmPipelines::EventPipeline.new(source, pipeline.for(stages), monitoring)
21
21
 
22
- source.on_finished do |messages|
23
- EM.stop
24
- messages.should have(10).items
25
- messages[0][:payload].should ==("event #0")
26
- messages[1][:payload].should ==("event #1")
27
- messages[2][:payload].should ==("event #2")
28
- messages[3][:payload].should ==("event #3")
29
- messages[4][:payload].should ==("event #4")
30
- messages[5][:payload].should ==("event #5")
31
- messages[6][:payload].should ==("event #6")
32
- messages[7][:payload].should ==("event #7")
33
- messages[8][:payload].should ==("event #8")
34
- messages[9][:payload].should ==("event #9")
35
- messages.each { |m| m.state.should ==(:consumed) }
22
+ source.on_finished do |s|
23
+ EM.stop
36
24
  end
37
25
 
38
26
  event_pipeline.start!
@@ -0,0 +1,31 @@
1
+ require 'eventmachine'
2
+ require 'empipelines'
3
+ require File.join(File.dirname(__FILE__), 'test_stages')
4
+
5
+ module TestStages
6
+ describe 'Consumption of events from multiple sources' do
7
+ let(:monitoring) { stub() }
8
+ let(:logger) { stub(:info => nil, :debug => nil) }
9
+ let (:processed) { {} }
10
+ include EmRunner
11
+
12
+ it 'consumes all events from all sources' do
13
+ pipeline = EmPipelines::Pipeline.new(EM, {:processed => processed}, monitoring, logger)
14
+
15
+ file_name = File.join(File.dirname(__FILE__), 'events.dat')
16
+ num_events_on_file = IO.readlines(file_name).size
17
+ io_source = EmPipelines::IOEventSource.new(EM, file_name)
18
+
19
+ batch = (1...1000).to_a
20
+ batch_name = "my batch!"
21
+ batch_source = EmPipelines::BatchEventSource.new(EM, batch_name, batch)
22
+
23
+ composed_event_source = EmPipelines::AggregatedEventSource.new(EM, batch_source, io_source)
24
+
25
+ composed_event_source.on_finished do |s|
26
+ EM.stop
27
+ s.should ==(composed_event_source)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ require 'eventmachine'
2
+ require 'empipelines'
3
+ require File.join(File.dirname(__FILE__), 'test_stages')
4
+
5
+ module TestStages
6
+ describe 'Consumption of events from a queue' do
7
+ let(:monitoring) { stub() }
8
+ let(:logger) { stub(:info => nil, :debug => nil) }
9
+ let (:processed) { {} }
10
+ include EmRunner
11
+
12
+ it 'consumes all events from the a queue' do
13
+ with_em_run do
14
+ pipeline = EmPipelines::Pipeline.new(EM, {:processed => processed}, monitoring, logger)
15
+
16
+ batch = (1...1000).to_a
17
+ batch_name = "my batch!"
18
+ source = EmPipelines::BatchEventSource.new(EM, batch_name, batch)
19
+
20
+ stages = [PassthroughStage, PassthroughStage, PassthroughStage]
21
+ event_pipeline = EmPipelines::EventPipeline.new(source, pipeline.for(stages), monitoring)
22
+
23
+ source.on_finished do |s|
24
+ EM.stop
25
+ s.should ==(source)
26
+ end
27
+
28
+ event_pipeline.start!
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,10 +1,3 @@
1
- event #0
2
- event #1
3
- event #2
4
- event #3
5
- event #4
6
- event #5
7
- event #6
8
- event #7
9
- event #8
10
- event #9
1
+ 1baa575127c661dfa754a43238b51bdb6adbc0ead0a3b1abec0d45e394ee19f1
2
+ c9730aa998cda290da19a311d19bb91a6aefa3552795dfbd8a2083bf833ba645
3
+ 3fc87b82e170d9e01889537f1dee465e829461178b6eb0ea49b0429e4c75d798
@@ -29,7 +29,7 @@ module TestStages
29
29
  include SomeStage
30
30
 
31
31
  def process(message, callback)
32
- callback.call(message)
32
+ callback.call(message.merge!({}))
33
33
  end
34
34
  end
35
35
 
@@ -0,0 +1,24 @@
1
+ require 'empipelines/event_handlers'
2
+
3
+ module EmPipelines
4
+ class AggregatedEventSource
5
+ include EventHandlers
6
+
7
+ def initialize(em, *event_sources)
8
+ @em, @sources = em, event_sources.flatten
9
+ end
10
+
11
+ def start!
12
+ finished = 0
13
+ @sources.each do |s|
14
+ s.on_event(event_handler)
15
+
16
+ s.on_finished do |*ignored|
17
+ finished += 1
18
+ finished_handler.call(self) if finished == @sources.size
19
+ end
20
+ @em.next_tick { s.start! }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,6 +1,7 @@
1
1
  require 'json'
2
2
 
3
3
  module EmPipelines
4
+ #this must have a on_finished!
4
5
  class AmqpEventSource
5
6
  def initialize(em, queue, event_name)
6
7
  @em, @queue, @event_name = em, queue, event_name
@@ -5,6 +5,7 @@ module EmPipelines
5
5
  include EventHandlers
6
6
 
7
7
  def initialize(em, list_name, events)
8
+ @num_finalised = 0
8
9
  @em, @list_name, @events = em, list_name,events
9
10
  end
10
11
 
@@ -13,7 +14,7 @@ module EmPipelines
13
14
  check_if_finished
14
15
 
15
16
  message_finished = lambda do |m|
16
- @finalised << m
17
+ @num_finalised += 1
17
18
  check_if_finished
18
19
  end
19
20
 
@@ -33,10 +34,13 @@ module EmPipelines
33
34
 
34
35
  private
35
36
  def check_if_finished
36
- finished = (@finalised.size == @events.size)
37
+ #TODO: can we make this not be based on size?
38
+ #it makes it harder to have streams as event sources (i.e. ranges).
39
+ #this class should only rely on Enumerable methods.
40
+ finished = (@num_finalised == @events.size)
37
41
 
38
42
  if finished and finished_handler
39
- @em.next_tick { finished_handler.call(@finalised) }
43
+ @em.next_tick { finished_handler.call(self) }
40
44
  end
41
45
  end
42
46
  end
@@ -15,7 +15,7 @@ module EmPipelines
15
15
 
16
16
  wrapped_handler = BatchEventSource.new(@em, @file_path, events)
17
17
  wrapped_handler.on_event(event_handler)
18
- wrapped_handler.on_finished(finished_handler)
18
+ wrapped_handler.on_finished { |*ignored| finished_handler.call(self) }
19
19
  wrapped_handler.start!
20
20
  end
21
21
  end
@@ -3,27 +3,28 @@ module EmPipelines
3
3
  attr_reader :state
4
4
 
5
5
  def initialize(base_hash={})
6
- hash!(base_hash)
6
+ backing_hash!(base_hash)
7
7
  created!
8
8
  end
9
9
 
10
10
  def [](key)
11
- hash[key]
11
+ as_hash[key]
12
12
  end
13
13
 
14
14
  def []=(key, value)
15
15
  check_if_mutation_allowed
16
- hash[key] = value
16
+ as_hash[key] = value
17
17
  end
18
18
 
19
19
  def delete(key)
20
20
  check_if_mutation_allowed
21
- hash.delete key
21
+ as_hash.delete key
22
22
  end
23
23
 
24
- def merge(other_hash)
24
+ def merge!(other_hash)
25
25
  check_if_mutation_allowed
26
- Message.new(hash.merge(other_hash))
26
+ backing_hash!(as_hash.merge(other_hash))
27
+ self
27
28
  end
28
29
 
29
30
  def on_consumed(callback=nil, &callback_block)
@@ -56,17 +57,21 @@ module EmPipelines
56
57
  invoke(@rejected_broken_callback)
57
58
  end
58
59
 
59
- def hash
60
+ def as_hash
60
61
  @backing_hash
61
62
  end
63
+
64
+ def payload
65
+ as_hash[:payload]
66
+ end
62
67
 
63
68
  def to_s
64
- "#{self.class.name} state:#{@state} hash:#{hash}"
69
+ "#{self.class.name} state:#{@state} backing_hash:#{as_hash}"
65
70
  end
66
71
 
67
72
  private
68
73
 
69
- def hash!(other)
74
+ def backing_hash!(other)
70
75
  @backing_hash = symbolised(other)
71
76
  end
72
77
 
@@ -1,5 +1,6 @@
1
1
  module EmPipelines
2
2
  class PeriodicEventSource
3
+ #on finish!!!!
3
4
  def initialize(em, name, interval_in_secs, &event_sourcing_code)
4
5
  @em = em
5
6
  @name = name
@@ -1,8 +1,8 @@
1
1
  module EmPipelines
2
2
  class Pipeline
3
3
  class TerminatorStage
4
- def self.notify(ignored, also_ignored = {})
5
- #noop
4
+ def self.notify(message, ignored = {})
5
+ message.consumed!
6
6
  end
7
7
  end
8
8
 
data/lib/empipelines.rb CHANGED
@@ -1,13 +1,16 @@
1
1
  module EmPipelines
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
4
4
 
5
+ require 'empipelines/message'
6
+
5
7
  require 'empipelines/event_handlers'
6
8
  require 'empipelines/amqp_event_source'
7
9
  require 'empipelines/batch_event_source'
8
10
  require 'empipelines/io_event_source'
9
- require 'empipelines/event_pipeline'
10
11
  require 'empipelines/list_event_source'
11
- require 'empipelines/message'
12
12
  require 'empipelines/periodic_event_source'
13
+ require 'empipelines/aggregated_event_source'
14
+
15
+ require 'empipelines/event_pipeline'
13
16
  require 'empipelines/pipeline'
@@ -0,0 +1,85 @@
1
+ require 'empipelines/aggregated_event_source'
2
+
3
+ module EmPipelines
4
+ class EventSourceStub
5
+ include EventHandlers
6
+
7
+ def event!(contents)
8
+ raise 'not started' unless @started
9
+ event_handler.call(contents) if event_handler
10
+ end
11
+
12
+ def finish!
13
+ raise 'not started' unless @started
14
+ finished_handler.call([:this, :should, :not, :be, :used])
15
+ end
16
+
17
+ def start!
18
+ @started = true
19
+ end
20
+ end
21
+
22
+ describe AggregatedEventSource do
23
+
24
+ let (:em) do
25
+ em = mock('eventmachine')
26
+ em.stub(:next_tick).and_yield
27
+ em
28
+ end
29
+
30
+ let (:list_name) { "list of stuff" }
31
+
32
+ it 'sends each sends messages from all sources, as they happen, to listeners' do
33
+ source1, source2, source3 = EventSourceStub.new, EventSourceStub.new, EventSourceStub.new
34
+
35
+ aggregated = AggregatedEventSource.new(em, source1, source2, source3)
36
+
37
+ expected = (0..4).map{ |i| stub("Message #{i}") }
38
+ received = []
39
+ aggregated.on_event { |m| received << m}
40
+
41
+ aggregated.start!
42
+
43
+ source1.event! expected[0]
44
+ source2.event! expected[1]
45
+ source2.event! expected[2]
46
+ source3.event! expected[3]
47
+ source1.event! expected[4]
48
+
49
+ received.should ==(expected)
50
+ end
51
+
52
+ it 'calls the finished handler when all sources finished' do
53
+ sources = [EventSourceStub.new, EventSourceStub.new, EventSourceStub.new]
54
+
55
+ aggregated = AggregatedEventSource.new(em, sources)
56
+
57
+ has_finished = [false]
58
+ aggregated.on_finished do |s|
59
+ s.should ==(aggregated)
60
+ has_finished[0] = true
61
+ end
62
+
63
+ aggregated.start!
64
+ sources[2].finish!
65
+ sources[1].finish!
66
+ sources[0].finish!
67
+
68
+ has_finished.first.should be_true
69
+ end
70
+
71
+ it 'does not call the finished handler if a source is still going' do
72
+ sources = [EventSourceStub.new, EventSourceStub.new, EventSourceStub.new]
73
+
74
+ aggregated = AggregatedEventSource.new(em, sources)
75
+
76
+ aggregated.on_finished do |s|
77
+ raise 'should never happen'
78
+ end
79
+
80
+ aggregated.start!
81
+ sources[2].finish!
82
+ sources[0].finish!
83
+ end
84
+ end
85
+ end
@@ -1,6 +1,7 @@
1
1
  require 'empipelines/batch_event_source'
2
2
 
3
3
  module EmPipelines
4
+ ShouldNotBeCalled = lambda { raise 'should not be called' }
4
5
  describe BatchEventSource do
5
6
 
6
7
  let (:em) do
@@ -9,9 +10,9 @@ module EmPipelines
9
10
  em
10
11
  end
11
12
 
12
- let (:list_name) { "list of stuff" }
13
+ let (:list_name) { 'list of stuff' }
13
14
 
14
- it "sends each element on the list as a payload to the listener" do
15
+ it 'sends each element on the list as a payload to the listener' do
15
16
  events = [1,2,3,4,5,6,7,8,9,10]
16
17
  source = BatchEventSource.new(em, list_name, events)
17
18
 
@@ -26,14 +27,15 @@ module EmPipelines
26
27
  received.each{ |i| i[:origin].should == list_name }
27
28
  end
28
29
 
29
- it "calls the batch finished callback when all items were processed" do
30
+ it 'calls the batch finished callback when all items were processed' do
30
31
  events = [1,2,3,4,5,6,7,8,9,10]
31
32
  source = BatchEventSource.new(em, list_name, events)
32
33
 
33
- has_finished = []
34
+ has_finished = [false]
34
35
 
35
- source.on_finished do |messages|
36
- has_finished << messages
36
+ source.on_finished do |s|
37
+ s.should ==(source)
38
+ has_finished[0] = true
37
39
  end
38
40
 
39
41
  source.on_event do |e|
@@ -42,33 +44,30 @@ module EmPipelines
42
44
 
43
45
  source.start!
44
46
 
45
- has_finished.first.map{ |i| i[:payload] }.should ==(events)
47
+ has_finished.first.should be_true
46
48
  end
47
49
 
48
- it "finishes immediately if there are no events to process" do
50
+ it 'finishes immediately if there are no events to process' do
49
51
  source = BatchEventSource.new(em, list_name, [])
50
52
 
51
53
  has_finished = []
52
- source.on_finished do |messages|
54
+ source.on_finished do |s|
55
+ s.should ==(source)
53
56
  has_finished << true
54
57
  end
55
58
 
56
- source.on_event do |e|
57
- raise 'should not be called!'
58
- end
59
+ source.on_event(&ShouldNotBeCalled)
59
60
 
60
61
  source.start!
61
62
 
62
63
  has_finished.first.should be_true
63
64
  end
64
65
 
65
- it "only calls the finished handler if all events were processed" do
66
+ it 'only calls the finished handler if all events were processed' do
66
67
  events = [1,2,3,4,5,6,7,8,9,10]
67
68
  source = BatchEventSource.new(em, list_name, events)
68
69
 
69
- source.on_finished do |messages|
70
- raise "should not be called"
71
- end
70
+ source.on_event(&ShouldNotBeCalled)
72
71
 
73
72
  count = 0
74
73
  source.on_event do |e|
@@ -33,10 +33,11 @@ module EmPipelines
33
33
  it 'calls the finished callback when all messages were processed' do
34
34
  source = IOEventSource.new(em, events_file)
35
35
 
36
- has_finished = []
36
+ has_finished = [false]
37
37
 
38
- source.on_finished do |messages|
39
- has_finished << messages
38
+ source.on_finished do |s|
39
+ s.should ==(source)
40
+ has_finished[0] = true
40
41
  end
41
42
 
42
43
  source.on_event do |e|
@@ -45,15 +46,16 @@ module EmPipelines
45
46
 
46
47
  source.start!
47
48
 
48
- has_finished.first.map{ |i| i[:payload].to_i }.should ==([1,2,3])
49
+ has_finished.first.should be_true
49
50
  end
50
51
 
51
52
  it 'finishes immediately if there are no events to process' do
52
53
  source = IOEventSource.new(em, empty_file)
53
54
 
54
- has_finished = []
55
- source.on_finished do |messages|
56
- has_finished << true
55
+ has_finished = [false]
56
+ source.on_finished do |s|
57
+ s.should ==(source)
58
+ has_finished[0] = true
57
59
  end
58
60
 
59
61
  source.on_event do |e|
@@ -46,12 +46,10 @@ module EmPipelines
46
46
 
47
47
  it "can be merged with a map, symbolising keys" do
48
48
  original = Message.new({'a' => 1})
49
- merged = original.merge({'b' => 2})
49
+ original.merge!({'b' => 2})
50
50
 
51
- original[:b].should be_nil
52
-
53
- merged[:a].should ==(original[:a])
54
- merged[:b].should_not be_nil
51
+ original[:a].should ==(1)
52
+ original[:b].should ==(2)
55
53
  end
56
54
  end
57
55
 
@@ -1,21 +1,45 @@
1
- require "empipelines/pipeline"
1
+ require 'empipelines/pipeline'
2
+
3
+ def msg(some_map)
4
+ EmPipelines:: MessageMock.new(some_map)
5
+ end
2
6
 
3
7
  module EmPipelines
8
+ class MessageMock < EmPipelines::Message
9
+ def consumed!
10
+ raise 'unexpected call'
11
+ end
12
+
13
+ def rejected!
14
+ raise 'unexpected call'
15
+ end
16
+
17
+ def broken!
18
+ raise 'unexpected call'
19
+ end
20
+ end
21
+
4
22
  class AddOne
5
23
  def call(input, &next_stage)
6
- next_stage.call({:data => (input[:data] + 1)})
24
+ next_stage.call(input.merge!({:data => (input[:data] + 1)}))
25
+ end
26
+ end
27
+
28
+ class Passthrough
29
+ def call(input, &next_stage)
30
+ next_stage.call(input)
7
31
  end
8
32
  end
9
33
 
10
34
  class SquareIt
11
35
  def call(input, &next_stage)
12
- next_stage.call({:data => (input[:data] * input[:data])})
36
+ next_stage.call(input.merge!({:data => (input[:data] * input[:data])}))
13
37
  end
14
38
  end
15
39
 
16
40
  class BrokenStage
17
41
  def call(ignore, &ignored_too)
18
- raise "Boo!"
42
+ raise 'Boo!'
19
43
  end
20
44
  end
21
45
 
@@ -27,13 +51,13 @@ module EmPipelines
27
51
 
28
52
  class NeedsAnApple
29
53
  def call(input, &next_stage)
30
- next_stage.call(input.merge({:apple => apple}))
54
+ next_stage.call(input.merge!({:apple => apple}))
31
55
  end
32
56
  end
33
57
 
34
58
  class NeedsAnOrange
35
59
  def call(input, &next_stage)
36
- next_stage.call(input.merge({:orange => orange}))
60
+ next_stage.call(input.merge!({:orange => orange}))
37
61
  end
38
62
  end
39
63
 
@@ -49,7 +73,7 @@ module EmPipelines
49
73
 
50
74
  def call(input, &next_step)
51
75
  @@value = input
52
- next_step.call(self.class)
76
+ next_step.call(input)
53
77
  end
54
78
  end
55
79
 
@@ -72,35 +96,55 @@ module EmPipelines
72
96
 
73
97
  describe Pipeline do
74
98
  let(:logger) {stub(:info => true, :debug => true)}
75
- it "chains the actions using processes" do
99
+
100
+ it 'chains the actions using processes' do
76
101
  event_chain = [AddOne, SquareIt, GlobalHolder]
102
+ a_msg = msg({:data =>1})
103
+ a_msg.should_receive(:consumed!)
104
+
77
105
  pipelines = Pipeline.new(StubSpawner.new, {}, stub('monitoring'), logger)
78
106
  pipeline = pipelines.for(event_chain)
79
- pipeline.notify({:data =>1})
80
- GlobalHolder.held.should eql({:data => 4})
107
+ pipeline.notify(a_msg)
108
+
109
+ GlobalHolder.held[:data].should ==(4)
81
110
  end
82
111
 
83
- it "does not send to the next if last returned nil" do
112
+ it 'does not send to the next if last returned nil' do
84
113
  event_chain = [AddOne, SquareIt, DeadEnd, GlobalHolder]
85
114
  pipelines = Pipeline.new(StubSpawner.new, {}, stub('monitoring'), logger)
86
115
  pipeline = pipelines.for(event_chain)
87
- pipeline.notify({:data => 1})
116
+ pipeline.notify(msg({:data => 1}))
88
117
  GlobalHolder.held.should be_nil
89
118
  end
90
119
 
91
- it "makes all objects in the context object available to stages" do
120
+ it 'makes all objects in the context object available to stages' do
92
121
  event_chain = [NeedsAnApple, NeedsAnOrange, GlobalHolder]
93
122
  pipelines = Pipeline.new(StubSpawner.new, {:apple => :some_apple, :orange => :some_orange}, stub('monitoring'), logger)
123
+ a_msg = msg({})
124
+ a_msg.should_receive(:consumed!)
125
+
94
126
  pipeline = pipelines.for(event_chain)
95
- pipeline.notify({})
96
- GlobalHolder.held.should eql({:apple => :some_apple, :orange => :some_orange})
127
+ pipeline.notify(a_msg)
128
+
129
+ GlobalHolder.held[:apple].should ==(:some_apple)
130
+ GlobalHolder.held[:orange].should ==(:some_orange)
97
131
  end
98
132
 
99
- it "sends exception to the proper handler" do
133
+ it 'sends exception to the proper handler' do
100
134
  monitoring = mock()
101
135
  monitoring.should_receive(:inform_exception!)
102
136
  pipeline = Pipeline.new(StubSpawner.new, {}, monitoring, logger)
103
- pipeline.for([BrokenStage]).notify({})
137
+ pipeline.for([BrokenStage]).notify(msg({}))
138
+ end
139
+
140
+ it 'flags the message as consumed if goest through all stages' do
141
+ event_chain = [Passthrough, Passthrough]
142
+ pipelines = Pipeline.new(StubSpawner.new, {}, stub('monitoring'), logger)
143
+ pipeline = pipelines.for(event_chain)
144
+ a_msg = msg({:data => :whatevah})
145
+ a_msg.should_receive(:consumed!)
146
+
147
+ pipeline.notify(a_msg)
104
148
  end
105
149
  end
106
150
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: empipelines
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-12-21 00:00:00.000000000Z
13
+ date: 2011-12-23 00:00:00.000000000Z
14
14
  dependencies: []
15
15
  description: Simple Event Handling Pipeline Architecture for EventMachine
16
16
  email: pcalcado+empipelines@gmail.com
@@ -25,9 +25,12 @@ files:
25
25
  - Rakefile
26
26
  - empipelines.gemspec
27
27
  - functional/consuming_events_from_file_spec.rb
28
+ - functional/consuming_events_from_multiple_sources_spec.rb
29
+ - functional/consuming_events_from_queue_spec.rb
28
30
  - functional/events.dat
29
31
  - functional/test_stages.rb
30
32
  - lib/empipelines.rb
33
+ - lib/empipelines/aggregated_event_source.rb
31
34
  - lib/empipelines/amqp_event_source.rb
32
35
  - lib/empipelines/batch_event_source.rb
33
36
  - lib/empipelines/event_handlers.rb
@@ -37,6 +40,7 @@ files:
37
40
  - lib/empipelines/message.rb
38
41
  - lib/empipelines/periodic_event_source.rb
39
42
  - lib/empipelines/pipeline.rb
43
+ - unit/empipelines/aggregated_event_source_spec.rb
40
44
  - unit/empipelines/amqp_event_source_spec.rb
41
45
  - unit/empipelines/batch_event_source_spec.rb
42
46
  - unit/empipelines/empty_io_event_source.dat
@@ -64,7 +68,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
64
68
  version: '0'
65
69
  segments:
66
70
  - 0
67
- hash: -3827854829014823938
71
+ hash: -530546752871247334
68
72
  required_rubygems_version: !ruby/object:Gem::Requirement
69
73
  none: false
70
74
  requirements: