gilmour 0.4.4 → 0.4.5
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 +4 -4
- data/.gitignore +1 -0
- data/README.md +1 -0
- data/examples/composition.rb +10 -3
- data/gilmour.gemspec +0 -1
- data/lib/gilmour/backends/redis.rb +5 -1
- data/lib/gilmour/composers.rb +54 -9
- data/lib/gilmour/responder.rb +1 -0
- data/test/spec/test_pipelines.rb +28 -6
- data/test/spec/test_subscriber_redis_reply_slot.rb +0 -1
- data/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f60416d0af8de59564c01a5580ee0a40df3772d
|
4
|
+
data.tar.gz: 2055fa3c380a7524d528c5e079c671e70f4acbfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6225255b7c13937b8c0cf83def803eb8827908a8b1580a838d3617b2d3845b743b008294736fb3890af2c090300748d30e4797c8f69de5ee86dfc0ccdf61224f
|
7
|
+
data.tar.gz: c6b4e8128620579b15939d0fe6ca3be4d377acc513495bc2c692e1e2650a6c7c83f7d9942eb9bd90f0dcd36ed74a54e7bbf50a868f4a1dbd79b4f6eec2a8939b
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -30,6 +30,7 @@ Microservices increase the granularity of our services oriented architectures. B
|
|
30
30
|
* Composition: `cmd1 | cmd2 | cmd2`
|
31
31
|
* AndAnd: `cmd1 && cmd2 && cmd3`
|
32
32
|
* Batch: `cmd1; cmd2; cmd3 > out` or `(cmd1; cmd2; cmd3) > out`
|
33
|
+
* Parallel: This runs stages in parallel call the callback when all are done. The data passed to the callback is an array of {:data, :code} hashes in no particular order. The code is the highest error code from the array.
|
33
34
|
|
34
35
|
Also, you should be able to use these methods of composition in any combination and also in a nexted manner - `(cmd1 | cmd2) && cmd3`. Gilmour enables you to do just that. See `examples/composition.rb`.
|
35
36
|
|
data/examples/composition.rb
CHANGED
@@ -76,9 +76,9 @@ batch.execute do |data, code|
|
|
76
76
|
end
|
77
77
|
batch_waiter.wait
|
78
78
|
|
79
|
-
batch_record =
|
80
|
-
|
81
|
-
|
79
|
+
batch_record = gilmour.batch([{topic: 'one'}, {topic: 'badtwo'},
|
80
|
+
{topic: 'three', message: {'anotherthree' => 'anotherthree'}}
|
81
|
+
]).with_recorder # with_recorder will record all responses in an array
|
82
82
|
batch_record_waiter = Gilmour::Waiter.new
|
83
83
|
batch_record.execute do |data, code|
|
84
84
|
puts "\nbatch with record:"
|
@@ -87,6 +87,13 @@ batch_record.execute do |data, code|
|
|
87
87
|
end
|
88
88
|
batch_record_waiter.wait
|
89
89
|
|
90
|
+
parallel = gilmour.parallel([{topic: 'one'}, {topic: 'badtwo'}])
|
91
|
+
parallel.execute do |data, code|
|
92
|
+
puts "\nparallel:"
|
93
|
+
puts code
|
94
|
+
data.each { |d| puts d }
|
95
|
+
end
|
96
|
+
|
90
97
|
t_andand = gilmour.andand([{topic: 'one'}, {topic: 'two'}])
|
91
98
|
# Use the above composition inside another
|
92
99
|
compose = gilmour.compose([t_andand, {topic: 'three'}])
|
data/gilmour.gemspec
CHANGED
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.add_dependency "mash"
|
18
18
|
s.add_dependency "redis"
|
19
19
|
s.add_dependency "gilmour-em-hiredis"
|
20
|
-
s.add_dependency "amqp"
|
21
20
|
|
22
21
|
s.files = `git ls-files`.split("\n")
|
23
22
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -145,7 +145,11 @@ module Gilmour
|
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
|
-
def response_handler(sender, payload)
|
148
|
+
def response_handler(sender, payload)
|
149
|
+
EM.defer { _response_handler(sender, payload) }
|
150
|
+
end
|
151
|
+
|
152
|
+
def _response_handler(sender, payload) #:nodoc:
|
149
153
|
data, code, _ = Gilmour::Protocol.parse_response(payload)
|
150
154
|
handler = @response_handlers.delete(sender)
|
151
155
|
@subscriber.unsubscribe(sender)
|
data/lib/gilmour/composers.rb
CHANGED
@@ -25,7 +25,11 @@ module Gilmour
|
|
25
25
|
|
26
26
|
def execute(data = {}, &blk)
|
27
27
|
if @spec.kind_of?(Proc)
|
28
|
-
|
28
|
+
begin
|
29
|
+
res = @spec.call(data)
|
30
|
+
rescue => e
|
31
|
+
code = 500
|
32
|
+
end
|
29
33
|
code = res ? 200 : 500
|
30
34
|
blk.call(res, code)
|
31
35
|
else
|
@@ -114,8 +118,8 @@ module Gilmour
|
|
114
118
|
# any kind of composition itself, allowing the creation of
|
115
119
|
# nested compositions. See examples in the source code.
|
116
120
|
#
|
117
|
-
def compose(spec)
|
118
|
-
Compose.new(self, spec)
|
121
|
+
def compose(*spec)
|
122
|
+
Compose.new(self, spec.flatten)
|
119
123
|
end
|
120
124
|
|
121
125
|
class AndAnd < Pipeline
|
@@ -142,16 +146,20 @@ module Gilmour
|
|
142
146
|
# It is roughly equivalent to the unix construct
|
143
147
|
# cmd1 && cmd2 && cmd3
|
144
148
|
|
145
|
-
def andand(spec)
|
146
|
-
AndAnd.new(self, spec)
|
149
|
+
def andand(*spec)
|
150
|
+
AndAnd.new(self, spec.flatten)
|
147
151
|
end
|
148
152
|
|
149
153
|
class Batch < Pipeline
|
150
|
-
def initialize(backend, spec
|
154
|
+
def initialize(backend, spec) #:nodoc:
|
151
155
|
super(backend, spec)
|
152
|
-
@record =
|
156
|
+
@record = false
|
153
157
|
end
|
154
158
|
|
159
|
+
def with_recorder(record=true)
|
160
|
+
@record = record
|
161
|
+
self
|
162
|
+
end
|
155
163
|
# Execute the batch pipeline. This pipeline ignores all errors
|
156
164
|
# step is passed to block.
|
157
165
|
# See the documentation of the #batch method for more details
|
@@ -183,8 +191,45 @@ module Gilmour
|
|
183
191
|
# +record+:: If this is false, only the output of the last step
|
184
192
|
# is passed to the block passed to execute. If true, all outputs
|
185
193
|
# are collected in an array and passed to the block
|
186
|
-
def batch(spec
|
187
|
-
Batch.new(self, spec
|
194
|
+
def batch(*spec)
|
195
|
+
Batch.new(self, spec.flatten)
|
196
|
+
end
|
197
|
+
|
198
|
+
class Parallel < Pipeline
|
199
|
+
def initialize(backend, spec) #:nodoc:
|
200
|
+
super(backend, spec)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Execute the batch pipeline. This pipeline ignores all errors
|
204
|
+
# step is passed to block.
|
205
|
+
# See the documentation of the #batch method for more details
|
206
|
+
def execute(data=nil, &blk)
|
207
|
+
results = []
|
208
|
+
blk.call(nil, nil) if pipeline.empty?
|
209
|
+
waiters = []
|
210
|
+
pipeline.each do |p|
|
211
|
+
waiter = Gilmour::Waiter.new
|
212
|
+
waiters << waiter
|
213
|
+
p.execute do |d, c|
|
214
|
+
results << {data: d, code: c}
|
215
|
+
waiter.signal
|
216
|
+
end
|
217
|
+
end
|
218
|
+
waiters.each(&:wait)
|
219
|
+
code = results.map { |r| r[:code] }.max
|
220
|
+
blk.call(results, code)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def parallel(*spec)
|
225
|
+
Parallel.new(self, spec.flatten)
|
226
|
+
end
|
227
|
+
|
228
|
+
def sync(*spec, &blk)
|
229
|
+
Parallel.new(self, spec.flatten).execute do |_res, code|
|
230
|
+
res = _res.size == 1 ? _res.first[:data] : _res
|
231
|
+
blk.call(res, code)
|
232
|
+
end
|
188
233
|
end
|
189
234
|
end
|
190
235
|
end
|
data/lib/gilmour/responder.rb
CHANGED
data/test/spec/test_pipelines.rb
CHANGED
@@ -131,6 +131,23 @@ describe 'Pipelines' do
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
+
context 'Parallel' do
|
135
|
+
Given(:parallel) {
|
136
|
+
gilmour.parallel([{topic: 'one'}, {topic: 'badtwo'},
|
137
|
+
{topic: 'three', message: {'anotherthree' => 'anotherthree'}}])
|
138
|
+
}
|
139
|
+
Then {
|
140
|
+
done = false
|
141
|
+
parallel.execute do |data, code|
|
142
|
+
expect(data).to be_kind_of(Array)
|
143
|
+
expect(data.size).to eq(3)
|
144
|
+
expect(code).to eq(500)
|
145
|
+
done = true
|
146
|
+
end
|
147
|
+
expect(done).to eq(true)
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
134
151
|
context 'Batch' do
|
135
152
|
context 'Without record' do
|
136
153
|
Given(:batch) {
|
@@ -158,8 +175,8 @@ describe 'Pipelines' do
|
|
158
175
|
context 'With record' do
|
159
176
|
Given(:batchrecord) {
|
160
177
|
gilmour.batch([{topic: 'one'}, {topic: 'badtwo'},
|
161
|
-
|
162
|
-
|
178
|
+
{topic: 'three', message: {'anotherthree' => 'anotherthree'}}
|
179
|
+
]).with_recorder
|
163
180
|
}
|
164
181
|
Then {
|
165
182
|
waiter = Waiter.new
|
@@ -183,8 +200,13 @@ describe 'Pipelines' do
|
|
183
200
|
Given(:andand) {
|
184
201
|
gilmour.andand([{topic: 'one'}, {topic: 'two'}])
|
185
202
|
}
|
203
|
+
Given(:parallel) {
|
204
|
+
gilmour.compose([gilmour.parallel([{topic: 'one'}, {topic: 'two'}]),
|
205
|
+
->(d) { d.reduce({}) { |m, r| m.merge(r[:data]) } }]
|
206
|
+
)
|
207
|
+
}
|
186
208
|
Given(:compose) {
|
187
|
-
gilmour.compose([andand, {topic: 'three'}])
|
209
|
+
gilmour.compose([andand, parallel, {topic: 'three'}])
|
188
210
|
}
|
189
211
|
Then {
|
190
212
|
waiter = Waiter.new
|
@@ -195,11 +217,11 @@ describe 'Pipelines' do
|
|
195
217
|
waiter.signal
|
196
218
|
end
|
197
219
|
waiter.wait
|
198
|
-
expect(
|
199
|
-
|
220
|
+
expect(code).to eq(200)
|
221
|
+
expect(data.keys.size).to eq(3)
|
222
|
+
['one', 'two', 'three'].each do |k|
|
200
223
|
expect(data.has_key?(k)).to be_truthy
|
201
224
|
end
|
202
|
-
expect(code).to eq(200)
|
203
225
|
}
|
204
226
|
end
|
205
227
|
end
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gilmour
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aditya Godbole
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-08-
|
12
|
+
date: 2015-08-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -81,20 +81,6 @@ dependencies:
|
|
81
81
|
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
|
-
- !ruby/object:Gem::Dependency
|
85
|
-
name: amqp
|
86
|
-
requirement: !ruby/object:Gem::Requirement
|
87
|
-
requirements:
|
88
|
-
- - ">="
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: '0'
|
91
|
-
type: :runtime
|
92
|
-
prerelease: false
|
93
|
-
version_requirements: !ruby/object:Gem::Requirement
|
94
|
-
requirements:
|
95
|
-
- - ">="
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
version: '0'
|
98
84
|
description: This gem provides a Sinatra like DSL and a simple protocol to enable
|
99
85
|
writing services that communicate over AMQP
|
100
86
|
email:
|