observed 0.1.1 → 0.2.0.rc1
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.
- 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
|