observed 0.1.1 → 0.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +9 -9
- data/.travis.yml +4 -0
- data/README.md +53 -78
- data/examples/observed.rb +1 -1
- data/exe/observed-oneshot +3 -1
- data/features/explicit_routing.feature +33 -0
- data/features/oneshot.feature +4 -0
- data/features/test_in_single_ruby_source.feature +4 -0
- data/integrations/observed-clockwork/features/run_observed_inside_clockwork.feature +6 -7
- data/integrations/observed-clockwork/lib/observed/clockwork/version.rb +1 -1
- data/integrations/observed-clockwork/lib/observed/clockwork.rb +0 -1
- data/integrations/observed-clockwork/observed-clockwork.gemspec +1 -1
- data/integrations/observed-eventmachine/.gitignore +17 -0
- data/integrations/observed-eventmachine/Gemfile +8 -0
- data/integrations/observed-eventmachine/LICENSE.txt +22 -0
- data/integrations/observed-eventmachine/README.md +29 -0
- data/integrations/observed-eventmachine/Rakefile +1 -0
- data/integrations/observed-eventmachine/examples/observed.rb +30 -0
- data/integrations/observed-eventmachine/features/integration_via_single_ruby_source.feature +48 -0
- data/integrations/observed-eventmachine/features/support/env.rb +8 -0
- data/integrations/observed-eventmachine/lib/observed/eventmachine/version.rb +5 -0
- data/integrations/observed-eventmachine/lib/observed/eventmachine.rb +70 -0
- data/integrations/observed-eventmachine/observed-eventmachine.gemspec +28 -0
- data/lib/observed/application/oneshot.rb +14 -37
- data/lib/observed/builtin_plugins/file.rb +5 -14
- data/lib/observed/builtin_plugins/stdout.rb +7 -14
- data/lib/observed/config.rb +4 -4
- data/lib/observed/config_builder.rb +154 -87
- data/lib/observed/config_dsl.rb +2 -8
- data/lib/observed/configurable.rb +61 -3
- data/lib/observed/context.rb +90 -0
- data/lib/observed/default/observer.rb +2 -5
- data/lib/observed/default.rb +0 -1
- data/lib/observed/event_bus.rb +31 -0
- data/lib/observed/execution_job_factory.rb +95 -0
- data/lib/observed/job.rb +163 -0
- data/lib/observed/jobbed_event_bus.rb +33 -0
- data/lib/observed/logging.rb +40 -0
- data/lib/observed/observer.rb +1 -0
- data/lib/observed/observer_helpers/timer.rb +13 -5
- data/lib/observed/pluggable.rb +11 -0
- data/lib/observed/reporter/regexp_matching.rb +2 -1
- data/lib/observed/reporter/report_formatting.rb +57 -0
- data/lib/observed/reporter.rb +0 -2
- data/lib/observed/system.rb +11 -78
- data/lib/observed/translator.rb +22 -0
- data/lib/observed/version.rb +1 -1
- data/lib/observed.rb +10 -12
- data/omnibus-observed/.gitignore +9 -0
- data/omnibus-observed/Berksfile +3 -0
- data/omnibus-observed/Berksfile.lock +52 -0
- data/omnibus-observed/Gemfile +4 -0
- data/omnibus-observed/README.md +102 -0
- data/omnibus-observed/Vagrantfile +93 -0
- data/omnibus-observed/config/projects/observed.rb +20 -0
- data/omnibus-observed/config/software/observed.rb +19 -0
- data/omnibus-observed/package-scripts/observed/makeselfinst +27 -0
- data/omnibus-observed/package-scripts/observed/postinst +17 -0
- data/omnibus-observed/package-scripts/observed/postrm +9 -0
- data/plugins/observed-fluentd/lib/observed/fluentd/version.rb +1 -1
- data/plugins/observed-gauge/README.md +5 -0
- data/plugins/observed-gauge/lib/observed/gauge/version.rb +1 -1
- data/plugins/observed-gauge/lib/observed/gauge.rb +11 -13
- data/plugins/observed-gauge/observed-gauge.gemspec +1 -1
- data/plugins/observed-gauge/spec/gauge_spec.rb +7 -7
- data/plugins/observed-growl/Gemfile +6 -0
- data/plugins/observed-growl/lib/observed/growl.rb +80 -0
- data/plugins/observed-http/lib/observed/http/version.rb +1 -1
- data/plugins/observed-http/lib/observed/http.rb +10 -8
- data/plugins/observed-http/observed-http.gemspec +1 -1
- data/plugins/observed-http/spec/http_spec.rb +62 -7
- data/plugins/observed-http/spec/integration_spec.rb +14 -0
- data/plugins/observed-shell/Gemfile +5 -0
- data/plugins/observed-shell/lib/observed/shell.rb +54 -0
- data/run-integration-tests +81 -0
- data/spec/builtin_plugins/stdout_spec.rb +7 -3
- data/spec/config_builder_spec.rb +42 -59
- data/spec/config_dsl_spec.rb +4 -0
- data/spec/configurable_spec.rb +141 -31
- data/spec/event_bus_spec.rb +16 -0
- data/spec/execution_job_factory_spec.rb +35 -0
- data/spec/job_factory_spec.rb +16 -0
- data/spec/job_spec.rb +228 -0
- data/spec/jobbed_event_bus_spec.rb +38 -0
- data/spec/observed_spec.rb +203 -0
- data/spec/observer_helpers/timer_spec.rb +187 -0
- data/spec/oneshot_spec.rb +7 -2
- data/spec/system_spec.rb +5 -39
- metadata +55 -12
- data/lib/observed/default/reporter.rb +0 -17
- data/lib/observed/reader.rb +0 -14
- data/lib/observed/writer.rb +0 -14
- data/spec/reader_spec.rb +0 -15
- data/spec/writer_spec.rb +0 -16
data/spec/configurable_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'observed/configurable'
|
3
|
+
require 'observed/pluggable'
|
3
4
|
|
4
5
|
module ConfigurableSpec
|
5
6
|
class Foo
|
@@ -11,55 +12,164 @@ module ConfigurableSpec
|
|
11
12
|
|
12
13
|
default :bar => 345
|
13
14
|
end
|
15
|
+
|
16
|
+
module ConfigurableModule
|
17
|
+
include Observed::Configurable
|
18
|
+
|
19
|
+
attribute :baz
|
20
|
+
end
|
21
|
+
|
22
|
+
module IntermediateModule
|
23
|
+
include Observed::Configurable
|
24
|
+
include ConfigurableModule
|
25
|
+
|
26
|
+
attribute :bar, default: 234
|
27
|
+
end
|
28
|
+
|
29
|
+
class ConfigurableModuleIncluder
|
30
|
+
include Observed::Configurable
|
31
|
+
include ConfigurableModule
|
32
|
+
|
33
|
+
attribute :bar, default: 234
|
34
|
+
default :bar => 345
|
35
|
+
attribute :foo, default: 123
|
36
|
+
end
|
37
|
+
|
38
|
+
class IntermediateModuleIncluder
|
39
|
+
include Observed::Configurable
|
40
|
+
include IntermediateModule
|
41
|
+
|
42
|
+
default :bar => 345
|
43
|
+
attribute :foo, default: 123
|
44
|
+
end
|
45
|
+
|
46
|
+
class SpecialCMI < ConfigurableModuleIncluder
|
47
|
+
include Observed::Configurable
|
48
|
+
end
|
49
|
+
|
50
|
+
class SpecialIMI < IntermediateModuleIncluder
|
51
|
+
include Observed::Configurable
|
52
|
+
end
|
53
|
+
|
54
|
+
class Plugin
|
55
|
+
include Observed::Configurable
|
56
|
+
include Observed::Pluggable
|
57
|
+
include ConfigurableModule
|
58
|
+
attribute :bar, default: 234
|
59
|
+
default :bar => 345
|
60
|
+
end
|
61
|
+
|
62
|
+
class PluginImpl < Plugin
|
63
|
+
include Observed::Configurable
|
64
|
+
attribute :foo, default: 123
|
65
|
+
end
|
66
|
+
|
67
|
+
class Overriding
|
68
|
+
include Observed::Configurable
|
69
|
+
include IntermediateModule
|
70
|
+
|
71
|
+
def foo
|
72
|
+
@attributes[:foo] || 123
|
73
|
+
end
|
74
|
+
|
75
|
+
default :bar => 345
|
76
|
+
attribute :foo, default: 1234
|
77
|
+
end
|
14
78
|
end
|
15
79
|
|
16
80
|
describe Observed::Configurable do
|
17
81
|
|
18
|
-
|
19
|
-
subject {
|
20
|
-
ConfigurableSpec::Foo.new
|
21
|
-
}
|
82
|
+
shared_examples_for 'a configurable object' do
|
22
83
|
it 'uses default values for attributes' do
|
23
|
-
expect(subject.foo).to eq(123)
|
84
|
+
expect(subject.new.foo).to eq(123)
|
24
85
|
end
|
86
|
+
|
25
87
|
it 'overrides default values on `attribute name, :default => default_value`' do
|
26
|
-
expect(subject.bar).to eq(345)
|
88
|
+
expect(subject.new.bar).to eq(345)
|
27
89
|
end
|
90
|
+
|
28
91
|
it 'raises errors when attributes without values are read' do
|
29
|
-
expect { subject.baz }.to raise_error
|
92
|
+
expect { subject.new.baz }.to raise_error
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when configured via the `configure` method' do
|
96
|
+
it 'prefers arguments of the method over defaults' do
|
97
|
+
instance = subject.new
|
98
|
+
|
99
|
+
instance.configure foo: 1, bar: 2
|
100
|
+
|
101
|
+
expect(instance.foo).to eq(1)
|
102
|
+
expect(instance.bar).to eq(2)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'when configured via constructor parameters' do
|
107
|
+
context 'when the keys are symbols' do
|
108
|
+
it 'prefers values from constructor parameters over defaults' do
|
109
|
+
instance = subject.new({foo: 1, bar: 2, baz: 3})
|
110
|
+
expect(instance.foo).to eq(1)
|
111
|
+
expect(instance.bar).to eq(2)
|
112
|
+
expect(instance.baz).to eq(3)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
context 'when the keys are strings' do
|
116
|
+
it 'does not prefer constructor parameters' do
|
117
|
+
instance = subject.new({'foo' => 1, 'bar' => 2, 'baz' => 3})
|
118
|
+
expect(instance.foo).to eq(123)
|
119
|
+
expect(instance.bar).to eq(345)
|
120
|
+
expect { instance.baz }.to raise_error
|
121
|
+
end
|
122
|
+
end
|
30
123
|
end
|
31
124
|
end
|
32
125
|
|
33
|
-
context '
|
126
|
+
context 'when included in a class' do
|
34
127
|
subject {
|
35
|
-
ConfigurableSpec::Foo
|
128
|
+
ConfigurableSpec::Foo
|
36
129
|
}
|
37
|
-
|
38
|
-
expect(subject.foo).to eq(1)
|
39
|
-
expect(subject.bar).to eq(2)
|
40
|
-
expect(subject.baz).to eq(3)
|
41
|
-
end
|
130
|
+
it_behaves_like 'a configurable object'
|
42
131
|
end
|
43
132
|
|
44
|
-
context '
|
133
|
+
context 'when included in a module' do
|
45
134
|
subject {
|
46
|
-
|
47
|
-
foo.configure(args)
|
48
|
-
foo
|
135
|
+
ConfigurableSpec::ConfigurableModuleIncluder
|
49
136
|
}
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
137
|
+
it_behaves_like 'a configurable object'
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'when included via a intermediate module' do
|
141
|
+
subject {
|
142
|
+
ConfigurableSpec::IntermediateModuleIncluder
|
143
|
+
}
|
144
|
+
it_behaves_like 'a configurable object'
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'when extended from a class which is a Plugin' do
|
148
|
+
subject {
|
149
|
+
ConfigurableSpec::PluginImpl
|
150
|
+
}
|
151
|
+
it_behaves_like 'a configurable object'
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'when inherited from a class included the intermediate module' do
|
155
|
+
subject {
|
156
|
+
ConfigurableSpec::SpecialIMI
|
157
|
+
}
|
158
|
+
it_behaves_like 'a configurable object'
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'when inherited from a class included the module includes it' do
|
162
|
+
subject {
|
163
|
+
ConfigurableSpec::SpecialCMI
|
164
|
+
}
|
165
|
+
it_behaves_like 'a configurable object'
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'when there is a method named exactly same as the attribute' do
|
169
|
+
subject {
|
170
|
+
ConfigurableSpec::Overriding
|
171
|
+
}
|
172
|
+
it_behaves_like 'a configurable object'
|
63
173
|
end
|
64
174
|
|
65
175
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'observed/event_bus'
|
3
|
+
|
4
|
+
describe Observed::EventBus do
|
5
|
+
it 'calls the handler for the emitted event' do
|
6
|
+
handler_one_called = false
|
7
|
+
handler_two_called = false
|
8
|
+
bus = Observed::EventBus.new
|
9
|
+
expect { bus.emit('foo') }.to_not raise_error
|
10
|
+
expect { bus.on_receive(/^bar$/) { handler_one_called = true } }.to_not raise_error
|
11
|
+
expect { bus.on_receive(/^baz$/) { handler_two_called = true } }.to_not raise_error
|
12
|
+
expect { bus.emit('bar') }.to_not raise_error
|
13
|
+
expect(handler_one_called).to be_true
|
14
|
+
expect(handler_two_called).to be_false
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'observed/execution_job_factory'
|
3
|
+
|
4
|
+
describe Observed::ExecutionJobFactory do
|
5
|
+
subject {
|
6
|
+
Observed::ExecutionJobFactory.new
|
7
|
+
}
|
8
|
+
it 'should convert observers, translators, reporters to jobs' do
|
9
|
+
output = mock('output')
|
10
|
+
|
11
|
+
the_observer = Class.new(Observed::Observer) do
|
12
|
+
def observe(data)
|
13
|
+
data.merge(b:2)
|
14
|
+
end
|
15
|
+
end.new
|
16
|
+
the_reporter = Class.new(Observed::Reporter) do
|
17
|
+
attribute :output
|
18
|
+
def report(tag, time, data)
|
19
|
+
output.write(tag: tag, time: time, data: data)
|
20
|
+
end
|
21
|
+
end.new(output: output)
|
22
|
+
the_translator = Class.new(Observed::Translator) do
|
23
|
+
def translate(tag, time, data)
|
24
|
+
data.merge(c:3)
|
25
|
+
end
|
26
|
+
end.new
|
27
|
+
job = subject.convert_to_job(the_observer)
|
28
|
+
.then(subject.convert_to_job(the_translator))
|
29
|
+
.then(subject.convert_to_job(the_reporter))
|
30
|
+
tag = 'the_tag'
|
31
|
+
time = Time.now
|
32
|
+
output.expects(:write).with(tag: tag, time: time, data: {a:1,b:2,c:3})
|
33
|
+
job.now({a:1}, {tag: tag, time: time})
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'observed/job'
|
3
|
+
|
4
|
+
describe Observed::JobFactory do
|
5
|
+
context 'when the executor not given' do
|
6
|
+
it 'fails to initialize' do
|
7
|
+
expect { Observed::JobFactory.new() }.to raise_error
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'when a logger given' do
|
12
|
+
it 'may prefer the given logger over the default one' do
|
13
|
+
Observed::JobFactory.new(executor: mock('executor'), logger: ::Logger.new(STDERR))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/job_spec.rb
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'observed/job'
|
3
|
+
|
4
|
+
describe Observed::MutableJob do
|
5
|
+
let(:factory) {
|
6
|
+
Observed::JobFactory.new(:executor => Observed::BlockingJobExecutor.new)
|
7
|
+
}
|
8
|
+
|
9
|
+
it 'yields the given block' do
|
10
|
+
yielded = nil
|
11
|
+
job = factory.mutable_job { |data|
|
12
|
+
data
|
13
|
+
}
|
14
|
+
job.now({a:1}, {b:2}) do |data, options|
|
15
|
+
yielded = [data, options]
|
16
|
+
end
|
17
|
+
expect(yielded).to eq([{a:1}, {b:2}])
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'executes the job regardless of whether or not a block is given' do
|
21
|
+
executed = nil
|
22
|
+
job = factory.mutable_job { |data, options|
|
23
|
+
executed = [data, options]
|
24
|
+
data
|
25
|
+
}
|
26
|
+
job.now({a:1}, {b:2})
|
27
|
+
expect(executed).to eq([{a:1}, {b:2}])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Observed::ParallelJob do
|
32
|
+
let(:factory) {
|
33
|
+
Observed::JobFactory.new(:executor => Observed::BlockingJobExecutor.new)
|
34
|
+
}
|
35
|
+
|
36
|
+
it 'yields the given block' do
|
37
|
+
job1 = factory.job { |data, |
|
38
|
+
data.merge(c:3)
|
39
|
+
}
|
40
|
+
job2 = factory.job { |data|
|
41
|
+
data.merge(d:4)
|
42
|
+
}
|
43
|
+
par = Observed::ParallelJob.new([job1, job2])
|
44
|
+
yielded = []
|
45
|
+
par.now({a:1}, {b:2}) do |data, options|
|
46
|
+
yielded.push([data, options])
|
47
|
+
end
|
48
|
+
expect(yielded).to eq([[{a:1,c:3},{b:2}], [{a:1,d:4},{b:2}]])
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'executes the job regardless of whether or not a block is given' do
|
52
|
+
executed = []
|
53
|
+
job1 = factory.job { |data, options|
|
54
|
+
r = data.merge(c:3)
|
55
|
+
executed.push([r, options])
|
56
|
+
r
|
57
|
+
}
|
58
|
+
job2 = factory.job { |data, options|
|
59
|
+
r = data.merge(d:4)
|
60
|
+
executed.push([r, options])
|
61
|
+
r
|
62
|
+
}
|
63
|
+
par = Observed::ParallelJob.new([job1, job2])
|
64
|
+
par.now({a:1}, {b:2})
|
65
|
+
expect(executed).to eq([[{a:1,c:3},{b:2}], [{a:1,d:4},{b:2}]])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe Observed::SequenceJob do
|
70
|
+
let(:factory) {
|
71
|
+
Observed::JobFactory.new(:executor => Observed::BlockingJobExecutor.new)
|
72
|
+
}
|
73
|
+
|
74
|
+
it 'yields the given block' do
|
75
|
+
job1 = factory.job { |data|
|
76
|
+
data.merge(c:3)
|
77
|
+
}
|
78
|
+
job2 = factory.job { |data|
|
79
|
+
data.merge(d:4)
|
80
|
+
}
|
81
|
+
seq = Observed::SequenceJob.new(job1, job2)
|
82
|
+
yielded = []
|
83
|
+
seq.now({a:1}, {b:2}) do |data, options|
|
84
|
+
yielded.push([data, options])
|
85
|
+
end
|
86
|
+
expect(yielded).to eq([[{a:1,c:3,d:4},{b:2}]])
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'executes the job regardless of whether or not a block is given' do
|
90
|
+
executed = []
|
91
|
+
job1 = factory.job { |data, options|
|
92
|
+
r = data.merge(c:3)
|
93
|
+
executed.push([r, options])
|
94
|
+
r
|
95
|
+
}
|
96
|
+
job2 = factory.job { |data, options|
|
97
|
+
r = data.merge(d:4)
|
98
|
+
executed.push([r, options])
|
99
|
+
r
|
100
|
+
}
|
101
|
+
seq = Observed::SequenceJob.new(job1, job2)
|
102
|
+
seq.now({a:1}, {b:2})
|
103
|
+
expect(executed).to eq([[{a:1,c:3},{b:2}], [{a:1,c:3,d:4},{b:2}]])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe Observed::Job do
|
108
|
+
context 'in simple use cases' do
|
109
|
+
let(:factory) {
|
110
|
+
Observed::JobFactory.new(:executor => Observed::BlockingJobExecutor.new)
|
111
|
+
}
|
112
|
+
context 'when the options as input are given' do
|
113
|
+
it 'propagates the options from the input' do
|
114
|
+
job1 = factory.job { |data, options|
|
115
|
+
expect(options).to eq({b:2})
|
116
|
+
data
|
117
|
+
}
|
118
|
+
job2 = factory.job { |_, options|
|
119
|
+
expect(options).to eq({b:2})
|
120
|
+
}
|
121
|
+
seq = job1.then(job2)
|
122
|
+
seq.now({a:1}, {b:2})
|
123
|
+
end
|
124
|
+
it 'allows to override the options from the input in subsequent jobs' do
|
125
|
+
job1 = factory.job { |data, options|
|
126
|
+
expect(options).to eq({b:2})
|
127
|
+
[data, {b:3}]
|
128
|
+
}
|
129
|
+
job2 = factory.job { |_, options|
|
130
|
+
expect(options).to eq({b:3})
|
131
|
+
}
|
132
|
+
seq = job1.then(job2)
|
133
|
+
seq.now({a:1}, {b:2})
|
134
|
+
end
|
135
|
+
end
|
136
|
+
context 'when the options as input are not given' do
|
137
|
+
it 'provides nil in the block parameter and allows to override it in subsequent jobs' do
|
138
|
+
job1 = factory.job { |data, options|
|
139
|
+
expect(options).to be_nil
|
140
|
+
[data, {b:3}]
|
141
|
+
}
|
142
|
+
job2 = factory.job { |_, options|
|
143
|
+
expect(options).to eq({b:3})
|
144
|
+
}
|
145
|
+
seq = job1.then(job2)
|
146
|
+
seq.now({a:1})
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
context 'when used in an immutable way' do
|
151
|
+
it 'propagates the resulting data to next jobs' do
|
152
|
+
factory = Observed::JobFactory.new(:executor => Observed::BlockingJobExecutor.new)
|
153
|
+
output = mock('output')
|
154
|
+
input_data = { input: 1 }
|
155
|
+
a = factory.job { |data|
|
156
|
+
data.merge(a: 2)
|
157
|
+
}
|
158
|
+
b = factory.job { |data, options|
|
159
|
+
data.merge(b: 3)
|
160
|
+
}
|
161
|
+
c = factory.job { |data, options|
|
162
|
+
output.write data.merge(c: 4)
|
163
|
+
}
|
164
|
+
d = factory.job { |data|
|
165
|
+
output.write data.merge(d: 5)
|
166
|
+
}
|
167
|
+
foo = a.then(b).then(c, d)
|
168
|
+
output.expects(:write).with({input:1,a:2,b:3,c:4})
|
169
|
+
output.expects(:write).with({input:1,a:2,b:3,d:5})
|
170
|
+
foo.now(input_data)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'when used in a mutable way' do
|
175
|
+
it 'propagates the resulting data to next jobs' do
|
176
|
+
factory = Observed::JobFactory.new(:executor => Observed::BlockingJobExecutor.new)
|
177
|
+
output = mock('output')
|
178
|
+
input_data = { input: 1 }
|
179
|
+
a = factory.mutable_job { |data|
|
180
|
+
data.merge(a: 2)
|
181
|
+
}
|
182
|
+
b = factory.job { |data, options|
|
183
|
+
data.merge(b: 3)
|
184
|
+
}
|
185
|
+
c = factory.job { |data, options|
|
186
|
+
output.write data.merge(c: 4)
|
187
|
+
}
|
188
|
+
d = factory.job { |data|
|
189
|
+
output.write data.merge(d: 5)
|
190
|
+
}
|
191
|
+
a.then(b).then(c, d)
|
192
|
+
output.expects(:write).with({input:1,a:2,b:3,c:4})
|
193
|
+
output.expects(:write).with({input:1,a:2,b:3,d:5})
|
194
|
+
a.now(input_data)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'when listeners given' do
|
199
|
+
it 'notifies listeners with resulting data' do
|
200
|
+
|
201
|
+
listener = mock('listener')
|
202
|
+
factory = Observed::JobFactory.new(
|
203
|
+
:executor => Observed::BlockingJobExecutor.new,
|
204
|
+
:listener => listener
|
205
|
+
)
|
206
|
+
output = mock('output')
|
207
|
+
input_data = { input: 1 }
|
208
|
+
a = factory.job { |data|
|
209
|
+
data.merge(a: 2)
|
210
|
+
}
|
211
|
+
b = factory.job { |data, options|
|
212
|
+
data.merge(b: 3)
|
213
|
+
}
|
214
|
+
c = factory.job { |data, options|
|
215
|
+
output.write data.merge(c: 4)
|
216
|
+
}
|
217
|
+
d = factory.job { |data|
|
218
|
+
output.write data.merge(d: 5)
|
219
|
+
}
|
220
|
+
foo = a.then(b).then(c, d)
|
221
|
+
output.expects(:write).with({input:1,a:2,b:3,c:4})
|
222
|
+
output.expects(:write).with({input:1,a:2,b:3,d:5})
|
223
|
+
listener.expects(:on_result).with({input:1,a:2}, {opt:1})
|
224
|
+
listener.expects(:on_result).with({input:1,a:2,b:3}, {opt:1})
|
225
|
+
foo.now(input_data, {opt:1})
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'observed/job'
|
4
|
+
require 'observed/jobbed_event_bus'
|
5
|
+
|
6
|
+
describe Observed::JobbedEventBus do
|
7
|
+
let(:out) {
|
8
|
+
mock('out')
|
9
|
+
}
|
10
|
+
let(:factory) {
|
11
|
+
executor = Observed::BlockingJobExecutor.new
|
12
|
+
Observed::JobFactory.new(executor: executor)
|
13
|
+
}
|
14
|
+
let(:the_job) {
|
15
|
+
factory.job { |data, options|
|
16
|
+
out.write data, options
|
17
|
+
}
|
18
|
+
}
|
19
|
+
let(:bus) {
|
20
|
+
Observed::JobbedEventBus.new(job_factory: factory)
|
21
|
+
}
|
22
|
+
it 'should invoke jobs when the corresponding events are emitted' do
|
23
|
+
bus.emit('foo')
|
24
|
+
bus.receive(/^bar$/).then(the_job)
|
25
|
+
bus.emit('baz')
|
26
|
+
out.expects(:write).with({a:1}, {b:2})
|
27
|
+
bus.emit('bar', {a:1}, {b:2})
|
28
|
+
bus.emit('blah')
|
29
|
+
end
|
30
|
+
it 'should return the job to emit events' do
|
31
|
+
bus.pipe_to_emit('foo').now
|
32
|
+
bus.receive(/^bar$/).then(the_job)
|
33
|
+
bus.pipe_to_emit('baz').now
|
34
|
+
out.expects(:write).with({a:1}, {b:2})
|
35
|
+
bus.pipe_to_emit('bar').now({a:1}, {b:2})
|
36
|
+
bus.pipe_to_emit('blah').now
|
37
|
+
end
|
38
|
+
end
|