batsir 0.1.0 → 0.3.7
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/.travis.yml +9 -1
- data/CHANGES.md +54 -0
- data/Gemfile +7 -10
- data/README.md +49 -5
- data/Rakefile +23 -16
- data/batsir.gemspec +43 -15
- data/lib/batsir/acceptors/acceptor.rb +31 -5
- data/lib/batsir/acceptors/amqp_acceptor.rb +36 -8
- data/lib/batsir/amqp.rb +35 -7
- data/lib/batsir/amqp_consumer.rb +8 -0
- data/lib/batsir/compiler/stage_worker_compiler.rb +86 -0
- data/lib/batsir/config.rb +208 -24
- data/lib/batsir/dsl/conditional_notifier_declaration.rb +31 -0
- data/lib/batsir/dsl/dsl_mappings.rb +27 -2
- data/lib/batsir/errors.rb +18 -0
- data/lib/batsir/filter.rb +5 -0
- data/lib/batsir/log.rb +7 -0
- data/lib/batsir/logger.rb +37 -0
- data/lib/batsir/logo.rb +3 -8
- data/lib/batsir/notifiers/amqp_notifier.rb +14 -4
- data/lib/batsir/notifiers/conditional_notifier.rb +29 -0
- data/lib/batsir/notifiers/notifier.rb +6 -5
- data/lib/batsir/registry.rb +6 -2
- data/lib/batsir/stage.rb +9 -4
- data/lib/batsir/stage_worker.rb +3 -56
- data/lib/batsir/strategies/retry_strategy.rb +35 -0
- data/lib/batsir/strategies/strategy.rb +20 -0
- data/lib/batsir/transformers/field_transformer.rb +2 -3
- data/lib/batsir/transformers/json_input_transformer.rb +6 -2
- data/lib/batsir/transformers/json_output_transformer.rb +6 -2
- data/lib/batsir/transformers/transformer.rb +5 -1
- data/lib/batsir/version.rb +10 -0
- data/lib/batsir.rb +31 -13
- data/spec/batsir/acceptors/acceptor_spec.rb +7 -78
- data/spec/batsir/acceptors/amqp_acceptor_spec.rb +55 -66
- data/spec/batsir/acceptors/shared_examples.rb +102 -0
- data/spec/batsir/amqp_spec.rb +58 -0
- data/spec/batsir/chain_spec.rb +4 -4
- data/spec/batsir/config_spec.rb +97 -0
- data/spec/batsir/dsl/chain_mapping_spec.rb +5 -6
- data/spec/batsir/dsl/conditional_notifier_mapping_spec.rb +80 -0
- data/spec/batsir/dsl/stage_mapping_spec.rb +38 -20
- data/spec/batsir/filter_queue_spec.rb +9 -15
- data/spec/batsir/filter_spec.rb +4 -5
- data/spec/batsir/log_spec.rb +10 -0
- data/spec/batsir/logger_spec.rb +46 -0
- data/spec/batsir/notifiers/amqp_notifier_spec.rb +43 -22
- data/spec/batsir/notifiers/conditional_notifier_spec.rb +62 -0
- data/spec/batsir/notifiers/notifier_spec.rb +4 -66
- data/spec/batsir/notifiers/shared_examples.rb +100 -0
- data/spec/batsir/registry_spec.rb +48 -0
- data/spec/batsir/stage_spec.rb +91 -85
- data/spec/batsir/stage_worker_spec.rb +13 -13
- data/spec/batsir/strategies/retry_strategy_spec.rb +58 -0
- data/spec/batsir/strategies/strategy_spec.rb +28 -0
- data/spec/batsir/support/bunny_mocks.rb +78 -5
- data/spec/batsir/transformers/field_transformer_spec.rb +22 -22
- data/spec/batsir/transformers/json_input_transformer_spec.rb +8 -3
- data/spec/batsir/transformers/json_output_transformer_spec.rb +2 -2
- data/spec/batsir/transformers/transformer_spec.rb +18 -4
- data/spec/spec_helper.rb +6 -2
- metadata +78 -23
- data/VERSION +0 -1
@@ -1,51 +1,58 @@
|
|
1
1
|
require File.join( File.dirname(__FILE__), "..", "..", "spec_helper" )
|
2
|
+
require File.join( File.dirname(__FILE__), 'shared_examples')
|
2
3
|
|
3
4
|
describe Batsir::Notifiers::AMQPNotifier do
|
4
5
|
let(:notifier_class){
|
5
6
|
Batsir::Notifiers::AMQPNotifier
|
6
|
-
}
|
7
|
+
}
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def new_notifier(options = {})
|
10
|
+
notifier_class.new(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
it_should_behave_like "a notifier", Batsir::Notifiers::AMQPNotifier
|
14
|
+
|
15
|
+
context "with respect to setting options" do
|
16
|
+
it "is a Batsir::Notifiers::Notifier" do
|
10
17
|
notifier_class.ancestors.should include Batsir::Notifiers::Notifier
|
11
18
|
end
|
12
19
|
|
13
|
-
it "
|
20
|
+
it "can set the queue on which to listen" do
|
14
21
|
notifier = notifier_class.new(:queue => :queue)
|
15
22
|
notifier.queue.should == :queue
|
16
23
|
end
|
17
24
|
|
18
|
-
it "
|
25
|
+
it "can set the host of the amqp broker" do
|
19
26
|
notifier = notifier_class.new(:host => 'localhost')
|
20
27
|
notifier.host.should == 'localhost'
|
21
28
|
end
|
22
29
|
|
23
|
-
it "
|
30
|
+
it "can set the port of the amqp broker" do
|
24
31
|
notifier = notifier_class.new(:port => 1234)
|
25
32
|
notifier.port.should == 1234
|
26
33
|
end
|
27
34
|
|
28
|
-
it "
|
35
|
+
it "can set the username with which to connect to the broker" do
|
29
36
|
notifier = notifier_class.new(:username => 'some_user')
|
30
37
|
notifier.username.should == 'some_user'
|
31
38
|
end
|
32
39
|
|
33
|
-
it "
|
40
|
+
it "can set the password with which to connect to the broker" do
|
34
41
|
notifier = notifier_class.new(:password => 'password')
|
35
42
|
notifier.password.should == 'password'
|
36
43
|
end
|
37
44
|
|
38
|
-
it "
|
45
|
+
it "can set the vhost to use on the broker" do
|
39
46
|
notifier = notifier_class.new(:vhost => '/blah')
|
40
47
|
notifier.vhost.should == '/blah'
|
41
48
|
end
|
42
49
|
|
43
|
-
it "
|
50
|
+
it "can set the exchange to use on the broker" do
|
44
51
|
notifier = notifier_class.new(:exchange => 'amq.direct')
|
45
52
|
notifier.exchange.should == 'amq.direct'
|
46
53
|
end
|
47
54
|
|
48
|
-
it "
|
55
|
+
it "defaults to amqp://guest:guest@localhost:5672/ with direct exchange on vhost ''" do
|
49
56
|
notifier = notifier_class.new(:queue => :somequeue)
|
50
57
|
notifier.queue.should == :somequeue
|
51
58
|
notifier.host.should == 'localhost'
|
@@ -57,54 +64,62 @@ describe Batsir::Notifiers::AMQPNotifier do
|
|
57
64
|
end
|
58
65
|
end
|
59
66
|
|
60
|
-
context "
|
61
|
-
|
62
|
-
|
67
|
+
context "with respect to notifying" do
|
68
|
+
before :each do
|
69
|
+
Batsir::Registry.reset
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'has an #execute method' do
|
73
|
+
notifier_class.instance_methods.map{|m| m.to_s}.should include "execute"
|
63
74
|
end
|
64
75
|
|
65
|
-
it
|
76
|
+
it 'has a #handle_error method' do
|
77
|
+
notifier_class.instance_methods.map{|m| m.to_s}.should include "handle_error"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "connects to the configured host" do
|
66
81
|
notifier = new_notifier(:host => 'somehost')
|
67
82
|
notifier.execute({})
|
68
83
|
instance = Bunny.instance
|
69
84
|
instance.options[:host].should == 'somehost'
|
70
85
|
end
|
71
86
|
|
72
|
-
it "
|
87
|
+
it "connects to the configured port" do
|
73
88
|
notifier = new_notifier(:port => 1234)
|
74
89
|
notifier.execute({})
|
75
90
|
instance = Bunny.instance
|
76
91
|
instance.options[:port].should == 1234
|
77
92
|
end
|
78
93
|
|
79
|
-
it "
|
94
|
+
it "connects with the configured username" do
|
80
95
|
notifier = new_notifier(:username => 'user')
|
81
96
|
notifier.execute({})
|
82
97
|
instance = Bunny.instance
|
83
|
-
instance.
|
98
|
+
instance.user.should == 'user'
|
84
99
|
end
|
85
100
|
|
86
|
-
it "
|
101
|
+
it "connects with the configured password" do
|
87
102
|
notifier = new_notifier(:password => 'pass')
|
88
103
|
notifier.execute({})
|
89
104
|
instance = Bunny.instance
|
90
105
|
instance.options[:pass].should == 'pass'
|
91
106
|
end
|
92
107
|
|
93
|
-
it "
|
108
|
+
it "connects to the configured vhost" do
|
94
109
|
notifier = new_notifier(:vhost => '/vhost')
|
95
110
|
notifier.execute({})
|
96
111
|
instance = Bunny.instance
|
97
112
|
instance.options[:vhost].should == '/vhost'
|
98
113
|
end
|
99
114
|
|
100
|
-
it "
|
115
|
+
it "declares the configured exchange" do
|
101
116
|
notifier = new_notifier(:exchange => 'some_exchange')
|
102
117
|
notifier.execute({})
|
103
118
|
instance = Bunny.instance
|
104
119
|
instance.exchange.name.should == 'some_exchange'
|
105
120
|
end
|
106
121
|
|
107
|
-
it "
|
122
|
+
it "binds the configured exchange to the queue and publish the message with the queue set as routing key" do
|
108
123
|
notifier = new_notifier(:exchange => 'some_exchange', :queue => :queue)
|
109
124
|
notifier.execute({})
|
110
125
|
instance = Bunny.instance
|
@@ -112,6 +127,12 @@ describe Batsir::Notifiers::AMQPNotifier do
|
|
112
127
|
instance.exchange.message.should == {}
|
113
128
|
instance.exchange.key.should == :queue
|
114
129
|
end
|
130
|
+
end
|
115
131
|
|
132
|
+
context "with respect to error handling" do
|
133
|
+
it 'uses a strategy object to resolve notification errors' do
|
134
|
+
notifier = new_notifier(:exchange => 'some_exchange', :queue => :queue)
|
135
|
+
notifier.error_strategy.should be_a Batsir::Strategies::RetryStrategy
|
136
|
+
end
|
116
137
|
end
|
117
138
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", "..", "spec_helper" )
|
2
|
+
require File.join( File.dirname(__FILE__), 'shared_examples')
|
3
|
+
|
4
|
+
describe Batsir::Notifiers::ConditionalNotifier do
|
5
|
+
|
6
|
+
it_should_behave_like "a notifier", Batsir::Notifiers::ConditionalNotifier
|
7
|
+
|
8
|
+
true_block = ::Proc.new { |message| true }
|
9
|
+
|
10
|
+
let(:notifier){ Batsir::Notifiers::Notifier }
|
11
|
+
|
12
|
+
it "can add notifiers" do
|
13
|
+
subject.notifiers.size.should == 0
|
14
|
+
subject.add_notifier( true_block, notifier)
|
15
|
+
subject.notifiers.size.should == 1
|
16
|
+
end
|
17
|
+
|
18
|
+
it "stores notifier conditions" do
|
19
|
+
subject.add_notifier(true_block, notifier)
|
20
|
+
|
21
|
+
notifier_condition = subject.notifiers.first
|
22
|
+
notifier_condition.should be_a Batsir::Notifiers::ConditionalNotifier::NotifierCondition
|
23
|
+
notifier_condition.condition.should == true_block
|
24
|
+
notifier_condition.notifier.should == notifier
|
25
|
+
end
|
26
|
+
|
27
|
+
it "stores optional options for the notifier" do
|
28
|
+
subject.add_notifier( true_block, notifier, :some => :extra, :options => :foryou)
|
29
|
+
|
30
|
+
notifier_condition = subject.notifiers.first
|
31
|
+
notifier_condition.options.size.should == 2
|
32
|
+
notifier_condition.options.should have_key :some
|
33
|
+
notifier_condition.options.should have_key :options
|
34
|
+
end
|
35
|
+
|
36
|
+
context "sending messages" do
|
37
|
+
class FakeNotifier < Batsir::Notifiers::Notifier; end
|
38
|
+
|
39
|
+
it "executes notifiers if condition is true" do
|
40
|
+
|
41
|
+
notifier_class = FakeNotifier
|
42
|
+
notifier_class.any_instance.stub(:execute)
|
43
|
+
notifier_class.any_instance.should_receive(:execute)
|
44
|
+
|
45
|
+
conditional = Batsir::Notifiers::ConditionalNotifier.new
|
46
|
+
conditional.add_notifier( true_block, notifier_class.new({}) )
|
47
|
+
conditional.execute("some message")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not execute when condition is false" do
|
51
|
+
false_block = lambda {|message| false}
|
52
|
+
|
53
|
+
notifier_class = FakeNotifier
|
54
|
+
notifier_class.any_instance.stub(:execute)
|
55
|
+
notifier_class.any_instance.should_not_receive(:execute)
|
56
|
+
|
57
|
+
conditional = Batsir::Notifiers::ConditionalNotifier.new
|
58
|
+
conditional.add_notifier( false_block, notifier_class.new({}) )
|
59
|
+
conditional.execute("some message")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,73 +1,11 @@
|
|
1
1
|
require File.join( File.dirname(__FILE__), "..", "..", "spec_helper" )
|
2
|
+
require File.join( File.dirname(__FILE__), 'shared_examples')
|
2
3
|
|
3
4
|
describe Batsir::Notifiers::Notifier do
|
4
|
-
let( :notifier_class ) do
|
5
|
-
Batsir::Notifiers::Notifier
|
6
|
-
end
|
7
|
-
|
8
|
-
it "should have a transformer_queue" do
|
9
|
-
notifier = notifier_class.new
|
10
|
-
notifier.transformer_queue.should_not be_nil
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should initially have an empty transformer_queue" do
|
14
|
-
notifier = notifier_class.new
|
15
|
-
notifier.transformer_queue.should_not be_nil
|
16
|
-
notifier.transformer_queue.should be_empty
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should be possible to add a transformer to the transformer_queue" do
|
20
|
-
transformer = :transformer
|
21
|
-
|
22
|
-
notifier = notifier_class.new
|
23
|
-
notifier.add_transformer transformer
|
24
|
-
|
25
|
-
notifier.transformer_queue.should_not be_empty
|
26
|
-
notifier.transformer_queue.size.should == 1
|
27
|
-
notifier.transformer_queue.first.should == :transformer
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should be possible to add a transformer multiple times" do
|
31
|
-
transformer = :transformer
|
32
5
|
|
33
|
-
|
34
|
-
notifier.add_transformer transformer
|
35
|
-
notifier.add_transformer transformer
|
36
|
-
|
37
|
-
notifier.transformer_queue.should_not be_empty
|
38
|
-
notifier.transformer_queue.size.should == 2
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should create a FieldTransformer when the 'fields' option is given during initialization" do
|
42
|
-
fields = {:foo => :bar}
|
43
|
-
notifier = notifier_class.new(:fields => fields)
|
44
|
-
notifier.transformer_queue.should_not be_empty
|
45
|
-
notifier.transformer_queue.first.class.should == Batsir::Transformers::FieldTransformer
|
46
|
-
notifier.transformer_queue.first.fields.should == fields
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should call #transform when #notify is called" do
|
50
|
-
notifier = notifier_class.new
|
51
|
-
notifier.should_receive(:transform).with({})
|
52
|
-
notifier.notify({})
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should call #transform on all transformers when #transform is called" do
|
56
|
-
class MockTransformer < Batsir::Transformers::Transformer
|
57
|
-
end
|
58
|
-
|
59
|
-
notifier = notifier_class.new
|
60
|
-
transformer = MockTransformer.new
|
61
|
-
notifier.add_transformer transformer
|
62
|
-
notifier.transformer_queue.size.should == 1
|
63
|
-
|
64
|
-
transformer.should_receive(:transform).with({})
|
65
|
-
notifier.notify({})
|
66
|
-
end
|
6
|
+
it_should_behave_like "a notifier", Batsir::Notifiers::Notifier
|
67
7
|
|
68
|
-
it
|
69
|
-
|
70
|
-
notifier.should_receive(:execute)
|
71
|
-
notifier.notify({})
|
8
|
+
it 'raises an error when the #execute method is not implemented' do
|
9
|
+
lambda{ subject.notify({})}.should raise_error NotImplementedError
|
72
10
|
end
|
73
11
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
shared_examples_for "a notifier" do |notifier_class|
|
2
|
+
before :each do
|
3
|
+
subject{notifier_class.new}
|
4
|
+
end
|
5
|
+
|
6
|
+
context 'transformers' do
|
7
|
+
it "has a transformer_queue" do
|
8
|
+
subject.transformer_queue.should_not be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "initially has an empty transformer_queue" do
|
12
|
+
subject.transformer_queue.should_not be_nil
|
13
|
+
subject.transformer_queue.should be_empty
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can add a transformer to the transformer_queue" do
|
17
|
+
transformer = :transformer
|
18
|
+
|
19
|
+
subject.add_transformer transformer
|
20
|
+
|
21
|
+
subject.transformer_queue.should_not be_empty
|
22
|
+
subject.transformer_queue.size.should == 1
|
23
|
+
subject.transformer_queue.first.should == :transformer
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can add a transformer multiple times" do
|
27
|
+
transformer = :transformer
|
28
|
+
|
29
|
+
subject.add_transformer transformer
|
30
|
+
subject.add_transformer transformer
|
31
|
+
|
32
|
+
subject.transformer_queue.should_not be_empty
|
33
|
+
subject.transformer_queue.size.should == 2
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates a FieldTransformer when the 'fields' option is given during initialization" do
|
37
|
+
fields = {:foo => :bar}
|
38
|
+
subject = notifier_class.new(:fields => fields)
|
39
|
+
subject.transformer_queue.should_not be_empty
|
40
|
+
subject.transformer_queue.first.class.should == Batsir::Transformers::FieldTransformer
|
41
|
+
subject.transformer_queue.first.fields.should == fields
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'methods calls' do
|
46
|
+
it "has an #execute method" do
|
47
|
+
notifier_class.instance_methods.map{|m| m.to_s}.should include "execute"
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
it "calls #transform when #notify is called" do
|
52
|
+
subject.stub(:execute)
|
53
|
+
subject.should_receive(:transform).with({})
|
54
|
+
subject.notify({})
|
55
|
+
end
|
56
|
+
|
57
|
+
it "calls #transform on all transformers when #transform is called" do
|
58
|
+
class MockTransformer < Batsir::Transformers::Transformer
|
59
|
+
end
|
60
|
+
|
61
|
+
subject.stub(:execute)
|
62
|
+
transformer = MockTransformer.new
|
63
|
+
subject.add_transformer transformer
|
64
|
+
subject.transformer_queue.size.should == 1
|
65
|
+
|
66
|
+
transformer.should_receive(:transform).with({})
|
67
|
+
subject.notify({})
|
68
|
+
end
|
69
|
+
|
70
|
+
it "calls #execute when #notify is called" do
|
71
|
+
subject.stub(:execute)
|
72
|
+
subject.should_receive(:execute)
|
73
|
+
subject.notify({})
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'message unmodified' do
|
78
|
+
it 'has no transformers' do
|
79
|
+
message = {'test_id' => 123}
|
80
|
+
subject.add_transformer(Batsir::Transformers::JSONOutputTransformer.new)
|
81
|
+
begin
|
82
|
+
subject.notify(message).should == {'test_id' => 123}
|
83
|
+
rescue NotImplementedError => e
|
84
|
+
end
|
85
|
+
message.should == {'test_id' => 123}
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'has a FieldTransformer' do
|
89
|
+
fields = {:foo => 'bar', 'test_id' => 'test'}
|
90
|
+
message = {'test_id' => 123}
|
91
|
+
subject = notifier_class.new(:fields => fields)
|
92
|
+
subject.add_transformer(Batsir::Transformers::JSONOutputTransformer.new)
|
93
|
+
begin
|
94
|
+
subject.notify(message).should == {'test_id' => 123}
|
95
|
+
rescue NotImplementedError => e
|
96
|
+
end
|
97
|
+
message.should == {'test_id' => 123}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", "spec_helper" )
|
2
|
+
|
3
|
+
describe Batsir::Registry do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
@class = Batsir::Registry
|
7
|
+
end
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
@class.reset
|
11
|
+
end
|
12
|
+
|
13
|
+
it "outputs the whole registry" do
|
14
|
+
@class.registry.should == {}
|
15
|
+
end
|
16
|
+
|
17
|
+
it "registers a value" do
|
18
|
+
@class.register(:foo, :bar)
|
19
|
+
@class.registry.keys.size.should == 1
|
20
|
+
@class.registry.keys.should include :foo
|
21
|
+
@class.registry.values.size.should == 1
|
22
|
+
@class.registry.values.should include :bar
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is able to retrieve a registered variable" do
|
26
|
+
@class.register('test', 'value')
|
27
|
+
@class.get('test').should == 'value'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns nil when the requested key is not found" do
|
31
|
+
@class.get('foobar').should be_nil
|
32
|
+
end
|
33
|
+
|
34
|
+
context "resetting" do
|
35
|
+
it "is possible" do
|
36
|
+
@class.register('foo', 'bar')
|
37
|
+
@class.registry.should == {'foo' => 'bar'}
|
38
|
+
@class.reset
|
39
|
+
@class.registry.should == {}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns its new state" do
|
43
|
+
@class.register('foo', 'bar')
|
44
|
+
result = @class.reset
|
45
|
+
result.should == {}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|