gilmour 0.3.4 → 0.4.1
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/.travis.yml +1 -0
- data/README.md +59 -4
- data/examples/composition.rb +98 -0
- data/examples/container.rb +19 -0
- data/examples/echoclient.rb +12 -8
- data/examples/fibonacci.rb +32 -0
- data/examples/forkechoclient.rb +23 -0
- data/examples/signal_slot.rb +35 -0
- data/examples/subscribers/echo.rb +22 -0
- data/lib/gilmour/backends/backend.rb +154 -29
- data/lib/gilmour/backends/redis.rb +45 -31
- data/lib/gilmour/base.rb +61 -30
- data/lib/gilmour/composers.rb +190 -0
- data/lib/gilmour/responder.rb +184 -138
- data/lib/gilmour/waiter.rb +6 -25
- data/test/spec/helpers/common.rb +2 -22
- data/test/spec/helpers/connection.rb +2 -3
- data/test/spec/test_pipelines.rb +207 -0
- data/test/spec/test_subscriber_redis.rb +1 -1
- data/test/spec/test_subscriber_redis_forked.rb +1 -2
- data/test/spec/test_subscriber_redis_reply_slot.rb +303 -0
- data/test/spec/test_subscriber_redis_reply_slot_fork.rb +274 -0
- data/test/spec/test_waiter.rb +114 -0
- data/test/testservice/subscribers/test_reply.rb +69 -0
- data/test/testservice/subscribers/test_subscriber.rb +1 -0
- data/version.rb +1 -1
- metadata +19 -5
- data/examples/fork_log_server.rb +0 -97
- data/examples/server.rb +0 -47
- data/examples/thread_example.rb +0 -40
@@ -0,0 +1,274 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rspec/given'
|
3
|
+
require 'securerandom'
|
4
|
+
require './testservice/test_service_base'
|
5
|
+
|
6
|
+
require_relative 'helpers/common'
|
7
|
+
require_relative 'helpers/connection'
|
8
|
+
|
9
|
+
def install_test_subscriber
|
10
|
+
waiter = Waiter.new
|
11
|
+
TestReplier.callback do |topic, data|
|
12
|
+
@topic = topic
|
13
|
+
@data = data
|
14
|
+
waiter.signal
|
15
|
+
end
|
16
|
+
waiter
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'TestReplier' do
|
20
|
+
opts = redis_connection_options
|
21
|
+
opts[:broadcast_errors] = true
|
22
|
+
|
23
|
+
test_subscriber_path = './testservice/subscribers/test_reply'
|
24
|
+
after(:all) do
|
25
|
+
EM.stop
|
26
|
+
end
|
27
|
+
Given(:subscriber) { TestServiceBase }
|
28
|
+
Given do
|
29
|
+
subscriber.load_subscriber(test_subscriber_path)
|
30
|
+
subscriber.subscribers.each do |topic, arr|
|
31
|
+
arr.each do |s|
|
32
|
+
s[:fork] = true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
Then do
|
37
|
+
handlers = subscriber.subscribers(TestReplier::Topic)
|
38
|
+
module_present = handlers.find { |h| h[:subscriber] == TestReplier }
|
39
|
+
module_present.should be_truthy
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'Running Service' do
|
43
|
+
before(:all) do
|
44
|
+
@service = TestServiceBase.new(opts, 'redis')
|
45
|
+
end
|
46
|
+
Given(:connection_opts) { opts }
|
47
|
+
before(:all) do
|
48
|
+
@service.registered_subscribers.each do |s|
|
49
|
+
s.backend = 'redis'
|
50
|
+
end
|
51
|
+
@service.start
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'Handler Register' do
|
55
|
+
When { install_test_subscriber }
|
56
|
+
context 'Check registered handlers' do
|
57
|
+
When(:handlers) do
|
58
|
+
subscriber.subscribers(TestReplier::Simulation)
|
59
|
+
.map { |h| h[:handler] }
|
60
|
+
end
|
61
|
+
Then { handlers.each { |h| h.should be_kind_of Proc } }
|
62
|
+
Then do
|
63
|
+
arg1 = TestReplier::Simulation
|
64
|
+
handlers.each do |h|
|
65
|
+
arg2 = SecureRandom.hex
|
66
|
+
# simualate a handler call
|
67
|
+
h.call(arg1, arg2)
|
68
|
+
@topic.should be == arg1
|
69
|
+
@data.should be == arg2
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'Publisher side timeout' do
|
76
|
+
Given(:ping_opts) do
|
77
|
+
redis_ping_options
|
78
|
+
end
|
79
|
+
|
80
|
+
When(:sub) do
|
81
|
+
Gilmour::RedisBackend.new({})
|
82
|
+
end
|
83
|
+
When(:code) do
|
84
|
+
code = nil
|
85
|
+
waiter_code = Waiter.new
|
86
|
+
|
87
|
+
sub.request!(3, TestReplier::TimeoutTopic, {:timeout => 1}) do |d, c|
|
88
|
+
code = c
|
89
|
+
waiter_code.signal
|
90
|
+
end
|
91
|
+
|
92
|
+
waiter_code.wait(5)
|
93
|
+
code
|
94
|
+
end
|
95
|
+
Then do
|
96
|
+
code.should be == 499
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'Handler sleeps longer than the Timeout' do
|
101
|
+
Given(:ping_opts) do
|
102
|
+
redis_ping_options
|
103
|
+
end
|
104
|
+
|
105
|
+
When(:sub) do
|
106
|
+
Gilmour::RedisBackend.new({})
|
107
|
+
end
|
108
|
+
When(:code) do
|
109
|
+
waiter_error = Waiter.new
|
110
|
+
waiter_code = Waiter.new
|
111
|
+
code = nil
|
112
|
+
|
113
|
+
backend = @service.get_backend("redis")
|
114
|
+
backend.broadcast_errors = true
|
115
|
+
sub.slot Gilmour::ErrorChannel do
|
116
|
+
waiter_error.signal
|
117
|
+
end
|
118
|
+
|
119
|
+
sub.request!(3, TestReplier::TimeoutTopic) do |d, c|
|
120
|
+
code = c
|
121
|
+
waiter_code.signal
|
122
|
+
end
|
123
|
+
|
124
|
+
waiter_code.wait(5)
|
125
|
+
waiter_error.wait(5)
|
126
|
+
|
127
|
+
backend.broadcast_errors = false
|
128
|
+
code
|
129
|
+
end
|
130
|
+
Then do
|
131
|
+
code.should be == 504
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'Handler sleeps just enough to survive the timeout' do
|
136
|
+
Given(:ping_opts) do
|
137
|
+
redis_ping_options
|
138
|
+
end
|
139
|
+
|
140
|
+
When(:sub) do
|
141
|
+
Gilmour::RedisBackend.new({})
|
142
|
+
end
|
143
|
+
When(:code) do
|
144
|
+
waiter = Waiter.new
|
145
|
+
code = nil
|
146
|
+
|
147
|
+
sub.request!(1, TestReplier::TimeoutTopic) do |d, c|
|
148
|
+
code = c
|
149
|
+
waiter.signal
|
150
|
+
end
|
151
|
+
|
152
|
+
waiter.wait(5)
|
153
|
+
code
|
154
|
+
end
|
155
|
+
Then do
|
156
|
+
code.should be == 200
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
context 'Request! sans subscriber error' do
|
162
|
+
Given(:ping_opts) do
|
163
|
+
redis_ping_options
|
164
|
+
end
|
165
|
+
|
166
|
+
When(:sub) do
|
167
|
+
Gilmour::RedisBackend.new({})
|
168
|
+
end
|
169
|
+
When(:response) do
|
170
|
+
waiter = Waiter.new
|
171
|
+
data = code = nil
|
172
|
+
sub.request!(ping_opts[:message], "hello.world") do |d, c|
|
173
|
+
data = d
|
174
|
+
code = c
|
175
|
+
waiter.signal
|
176
|
+
end
|
177
|
+
waiter.wait(5)
|
178
|
+
[data, code]
|
179
|
+
end
|
180
|
+
Then do
|
181
|
+
data, code = response
|
182
|
+
data.should be == nil
|
183
|
+
code.should be == 404
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'Send and receive a message' do
|
189
|
+
Given(:ping_opts) { redis_ping_options }
|
190
|
+
When(:sub) do
|
191
|
+
Gilmour::RedisBackend.new({})
|
192
|
+
end
|
193
|
+
When(:response) do
|
194
|
+
waiter = Waiter.new
|
195
|
+
data = code = nil
|
196
|
+
sub.request!(ping_opts[:message], TestReplier::Topic) do |d, c|
|
197
|
+
data = d
|
198
|
+
code = c
|
199
|
+
waiter.signal
|
200
|
+
end
|
201
|
+
waiter.wait(5)
|
202
|
+
[data, code]
|
203
|
+
end
|
204
|
+
Then do
|
205
|
+
data, code = response
|
206
|
+
data.should be == ping_opts[:response]
|
207
|
+
code.should be == 200
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'Send once, Receive twice' do
|
212
|
+
Given(:ping_opts) { redis_ping_options }
|
213
|
+
When(:sub) do
|
214
|
+
Gilmour::RedisBackend.new({})
|
215
|
+
end
|
216
|
+
When (:response) do
|
217
|
+
waiter = Waiter.new
|
218
|
+
|
219
|
+
actual_ret = []
|
220
|
+
|
221
|
+
group_proc = sub.slot TestReplier::GroupReturn do
|
222
|
+
actual_ret.push(request.body)
|
223
|
+
waiter.signal if actual_ret.length == 4
|
224
|
+
end
|
225
|
+
|
226
|
+
sub.signal!(ping_opts[:message], TestReplier::GroupTopic)
|
227
|
+
waiter.wait(5)
|
228
|
+
|
229
|
+
sub.remove_slot TestReplier::GroupReturn, group_proc
|
230
|
+
actual_ret
|
231
|
+
end
|
232
|
+
Then do
|
233
|
+
response.select { |e| e == ping_opts[:message] }.size.should == 2
|
234
|
+
response.select { |e| e == "2" }.size.should == 2
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
context 'Handler to Test exits' do
|
239
|
+
Given(:ping_opts) do
|
240
|
+
redis_ping_options
|
241
|
+
end
|
242
|
+
|
243
|
+
When(:sub) do
|
244
|
+
Gilmour::RedisBackend.new({})
|
245
|
+
end
|
246
|
+
When(:code) do
|
247
|
+
waiter_error = Waiter.new
|
248
|
+
waiter_code = Waiter.new
|
249
|
+
code = nil
|
250
|
+
|
251
|
+
#backend = @service.get_backend("redis")
|
252
|
+
#backend.broadcast_errors = true
|
253
|
+
error_listener_proc = sub.slot Gilmour::ErrorChannel do |d, c|
|
254
|
+
waiter_error.signal
|
255
|
+
end
|
256
|
+
|
257
|
+
sub.request!(1, TestReplier::ExitTopic) do |d, c|
|
258
|
+
code = c
|
259
|
+
waiter_code.signal
|
260
|
+
end
|
261
|
+
|
262
|
+
waiter_code.wait(5)
|
263
|
+
waiter_error.wait(5)
|
264
|
+
|
265
|
+
sub.remove_listener Gilmour::ErrorChannel, error_listener_proc
|
266
|
+
#backend.broadcast_errors = false
|
267
|
+
code
|
268
|
+
end
|
269
|
+
Then do
|
270
|
+
code.should be == 500
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rspec/given'
|
3
|
+
|
4
|
+
require '../lib/gilmour/waiter'
|
5
|
+
|
6
|
+
describe 'TestAddGroup' do
|
7
|
+
context "Wait Group" do
|
8
|
+
it "Wait should return instantly" do
|
9
|
+
wg = Gilmour::Waiter.new
|
10
|
+
|
11
|
+
num = 2
|
12
|
+
arr = []
|
13
|
+
|
14
|
+
num.times do
|
15
|
+
wg.add 1
|
16
|
+
Thread.new {
|
17
|
+
arr << "done"
|
18
|
+
wg.done
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
wg.wait
|
23
|
+
expect(arr.length).to eq num
|
24
|
+
end
|
25
|
+
|
26
|
+
it "Wait should return after sleep" do
|
27
|
+
wg = Gilmour::Waiter.new
|
28
|
+
|
29
|
+
num = 2
|
30
|
+
arr = []
|
31
|
+
|
32
|
+
num.times do
|
33
|
+
wg.add 1
|
34
|
+
Thread.new {
|
35
|
+
sleep(1)
|
36
|
+
arr << true
|
37
|
+
wg.done
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
wg.wait
|
42
|
+
expect(arr.length).to eq num
|
43
|
+
end
|
44
|
+
|
45
|
+
it "Wait should perform a yield" do
|
46
|
+
wg = Gilmour::Waiter.new
|
47
|
+
|
48
|
+
num = 2
|
49
|
+
arr = []
|
50
|
+
|
51
|
+
num.times do
|
52
|
+
wg.add 1
|
53
|
+
Thread.new {
|
54
|
+
sleep(1)
|
55
|
+
arr << true
|
56
|
+
wg.done
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
wg.wait do
|
61
|
+
arr << true
|
62
|
+
end
|
63
|
+
|
64
|
+
expect(arr.length).to eq num+1
|
65
|
+
end
|
66
|
+
|
67
|
+
it "Wait should timeout" do
|
68
|
+
wg = Gilmour::Waiter.new
|
69
|
+
|
70
|
+
num = 2
|
71
|
+
arr = []
|
72
|
+
|
73
|
+
num.times do
|
74
|
+
wg.add 1
|
75
|
+
Thread.new {
|
76
|
+
sleep(2)
|
77
|
+
arr << true
|
78
|
+
wg.done
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
wg.wait(1) do
|
83
|
+
arr << true
|
84
|
+
end
|
85
|
+
|
86
|
+
expect(arr.length).to eq 1
|
87
|
+
end
|
88
|
+
|
89
|
+
it "Done and Wait only" do
|
90
|
+
wg = Gilmour::Waiter.new
|
91
|
+
|
92
|
+
arr = []
|
93
|
+
|
94
|
+
Thread.new {
|
95
|
+
sleep(2)
|
96
|
+
arr << true
|
97
|
+
wg.done
|
98
|
+
}
|
99
|
+
|
100
|
+
wg.wait do
|
101
|
+
arr << true
|
102
|
+
end
|
103
|
+
|
104
|
+
expect(arr.length).to eq 2
|
105
|
+
end
|
106
|
+
|
107
|
+
it "Signal should raise when using add" do
|
108
|
+
wg = Gilmour::Waiter.new
|
109
|
+
wg.add 1
|
110
|
+
expect{wg.signal}.to raise_error(RuntimeError)
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class TestReplier < TestServiceBase
|
2
|
+
TimeoutTopic = "test.reply.timeout"
|
3
|
+
Topic = 'test.reply.topic'
|
4
|
+
WildcardTopic = 'test.reply.wildcard.*'
|
5
|
+
Simulation = 'simulate.reply.topic'
|
6
|
+
Republish = 'test.reply.republish'
|
7
|
+
GroupReturn = "test.slot.group_return"
|
8
|
+
GroupTopic = "test.slot.group"
|
9
|
+
ExclusiveTopic = "test.reply.exclusive"
|
10
|
+
ExitTopic = "topic.reply.exit"
|
11
|
+
ReListenTopic = "topic.reply.relisten"
|
12
|
+
|
13
|
+
|
14
|
+
def self.get_callback
|
15
|
+
@callback
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.callback
|
19
|
+
@callback = Proc.new
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
2.times do
|
24
|
+
slot GroupTopic do
|
25
|
+
signal!(request.body, TestReplier::GroupReturn)
|
26
|
+
signal!("2", TestReplier::GroupReturn)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
reply_to TimeoutTopic, {timeout: 2} do
|
31
|
+
data, _, _ = Gilmour::Protocol.parse_response(request.body)
|
32
|
+
logger.info "Will sleep for #{data} seconds now. But allowed timeout is 2."
|
33
|
+
sleep data
|
34
|
+
respond 'Pong!'
|
35
|
+
logger.info "Done with sleep"
|
36
|
+
end
|
37
|
+
|
38
|
+
reply_to ExitTopic do
|
39
|
+
logger.info "Sleeping for 2 seconds, and then will exit"
|
40
|
+
exit!
|
41
|
+
end
|
42
|
+
|
43
|
+
reply_to ReListenTopic do
|
44
|
+
# In forked environment this should not work.
|
45
|
+
reply_to "test.world", excl_group: 'relisten' do
|
46
|
+
respond "Pong!"
|
47
|
+
end
|
48
|
+
respond "Pong"
|
49
|
+
end
|
50
|
+
|
51
|
+
reply_to Topic do
|
52
|
+
if TestReplier.get_callback
|
53
|
+
TestReplier.get_callback.call(request.topic, request.body)
|
54
|
+
end
|
55
|
+
respond 'Pong!' if request.body == 'Ping!'
|
56
|
+
end
|
57
|
+
|
58
|
+
reply_to Simulation do |topic, data|
|
59
|
+
@callback.call(topic, data)
|
60
|
+
end
|
61
|
+
|
62
|
+
reply_to Republish do
|
63
|
+
resp = self
|
64
|
+
request!(request.body, Topic) do |data, code|
|
65
|
+
resp.respond data, 200, now: true
|
66
|
+
end
|
67
|
+
delay_response
|
68
|
+
end
|
69
|
+
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
|
+
version: 0.4.1
|
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-
|
12
|
+
date: 2015-08-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -109,24 +109,33 @@ files:
|
|
109
109
|
- Gemfile
|
110
110
|
- LICENSE
|
111
111
|
- README.md
|
112
|
+
- examples/composition.rb
|
113
|
+
- examples/container.rb
|
112
114
|
- examples/echoclient.rb
|
113
|
-
- examples/
|
114
|
-
- examples/
|
115
|
-
- examples/
|
115
|
+
- examples/fibonacci.rb
|
116
|
+
- examples/forkechoclient.rb
|
117
|
+
- examples/signal_slot.rb
|
118
|
+
- examples/subscribers/echo.rb
|
116
119
|
- gilmour.gemspec
|
117
120
|
- lib/gilmour.rb
|
118
121
|
- lib/gilmour/backends/backend.rb
|
119
122
|
- lib/gilmour/backends/redis.rb
|
120
123
|
- lib/gilmour/base.rb
|
124
|
+
- lib/gilmour/composers.rb
|
121
125
|
- lib/gilmour/protocol.rb
|
122
126
|
- lib/gilmour/responder.rb
|
123
127
|
- lib/gilmour/waiter.rb
|
124
128
|
- test/spec/helpers/common.rb
|
125
129
|
- test/spec/helpers/connection.rb
|
126
130
|
- test/spec/helpers/data.yml
|
131
|
+
- test/spec/test_pipelines.rb
|
127
132
|
- test/spec/test_service_base.rb
|
128
133
|
- test/spec/test_subscriber_redis.rb
|
129
134
|
- test/spec/test_subscriber_redis_forked.rb
|
135
|
+
- test/spec/test_subscriber_redis_reply_slot.rb
|
136
|
+
- test/spec/test_subscriber_redis_reply_slot_fork.rb
|
137
|
+
- test/spec/test_waiter.rb
|
138
|
+
- test/testservice/subscribers/test_reply.rb
|
130
139
|
- test/testservice/subscribers/test_subscriber.rb
|
131
140
|
- test/testservice/test_service_base.rb
|
132
141
|
- version.rb
|
@@ -157,8 +166,13 @@ test_files:
|
|
157
166
|
- test/spec/helpers/common.rb
|
158
167
|
- test/spec/helpers/connection.rb
|
159
168
|
- test/spec/helpers/data.yml
|
169
|
+
- test/spec/test_pipelines.rb
|
160
170
|
- test/spec/test_service_base.rb
|
161
171
|
- test/spec/test_subscriber_redis.rb
|
162
172
|
- test/spec/test_subscriber_redis_forked.rb
|
173
|
+
- test/spec/test_subscriber_redis_reply_slot.rb
|
174
|
+
- test/spec/test_subscriber_redis_reply_slot_fork.rb
|
175
|
+
- test/spec/test_waiter.rb
|
176
|
+
- test/testservice/subscribers/test_reply.rb
|
163
177
|
- test/testservice/subscribers/test_subscriber.rb
|
164
178
|
- test/testservice/test_service_base.rb
|
data/examples/fork_log_server.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require_relative '../lib/gilmour'
|
3
|
-
|
4
|
-
class EventServer
|
5
|
-
include Gilmour::Base
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
backend = 'redis'
|
9
|
-
enable_backend(backend, { })
|
10
|
-
registered_subscribers.each do |sub|
|
11
|
-
sub.backend = backend
|
12
|
-
end
|
13
|
-
$stderr.puts "Starting server. To see messaging in action run clients."
|
14
|
-
start(true)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class EchoSubscriber < EventServer
|
19
|
-
class << self
|
20
|
-
def capture_output(pipe)
|
21
|
-
streams = [$stdout, $stderr]
|
22
|
-
|
23
|
-
# Save the streams to be reassigned later.
|
24
|
-
# Actually it doesn't matter because the child process would be killed
|
25
|
-
# anyway after the work is done.
|
26
|
-
saved = streams.collect { |stream| stream.dup }
|
27
|
-
|
28
|
-
begin
|
29
|
-
streams.each_with_index do |stream, ix|
|
30
|
-
# Probably I should not use IX, otherwise stdout and stderr can arrive
|
31
|
-
# out of order, which they should?
|
32
|
-
# If I reopen both of them on the same PIPE, they are guaranteed to
|
33
|
-
# arrive in order.
|
34
|
-
stream.reopen(pipe)
|
35
|
-
#stream.sync = true
|
36
|
-
end
|
37
|
-
yield
|
38
|
-
ensure
|
39
|
-
# This is sort of meaningless, just makes sense aesthetically.
|
40
|
-
# To return what was borrowed.
|
41
|
-
streams.each_with_index do |stream, i|
|
42
|
-
stream.reopen(saved[i])
|
43
|
-
end
|
44
|
-
pipe.close unless pipe.closed?
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def ds_respond(topic, opts={}, &blk)
|
49
|
-
options = { exclusive: true, fork: true }.merge(opts)
|
50
|
-
listen_to topic, options do
|
51
|
-
logger.error "Captuting output before execution"
|
52
|
-
|
53
|
-
waiter = Gilmour::Waiter.new
|
54
|
-
waiter.add 1
|
55
|
-
read_pipe, write_pipe = IO.pipe
|
56
|
-
|
57
|
-
th = Thread.new {
|
58
|
-
loop {
|
59
|
-
begin
|
60
|
-
result = read_pipe.readline.chomp
|
61
|
-
logger.debug result
|
62
|
-
rescue EOFError
|
63
|
-
waiter.done
|
64
|
-
rescue Exception => e
|
65
|
-
logger.error "Error: #{e.message}"
|
66
|
-
logger.error "Traceback: #{e.backtrace}"
|
67
|
-
end
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
EchoSubscriber::capture_output(write_pipe) do
|
72
|
-
instance_eval(&blk)
|
73
|
-
end
|
74
|
-
|
75
|
-
waiter.wait do
|
76
|
-
th.kill
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Passing second parameter as true makes only one instance of this handler handle a request
|
84
|
-
EchoSubscriber::ds_respond 'echo.*' do
|
85
|
-
if request.body == 'Palmolive'
|
86
|
-
respond nil
|
87
|
-
else
|
88
|
-
logger.error "logger: #{request.body}"
|
89
|
-
$stderr.puts "stderr.puts: #{request.body}"
|
90
|
-
puts "stdout.puts #{request.body}"
|
91
|
-
respond "#{request.topic}"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
EventServer.new
|
data/examples/server.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'gilmour'
|
3
|
-
|
4
|
-
class EventServer
|
5
|
-
include Gilmour::Base
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
backend = 'redis'
|
9
|
-
enable_backend(backend, { })
|
10
|
-
registered_subscribers.each do |sub|
|
11
|
-
sub.backend = backend
|
12
|
-
end
|
13
|
-
$stderr.puts "Starting server. To see messaging in action run clients."
|
14
|
-
start(true)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class EchoSubscriber < EventServer
|
19
|
-
# Passing second parameter as true makes only one instance of this handler handle a request
|
20
|
-
listen_to 'echo.*', {"exclusive" => true} do
|
21
|
-
if request.body == 'Palmolive'
|
22
|
-
respond nil
|
23
|
-
else
|
24
|
-
$stderr.puts request.body
|
25
|
-
respond "#{request.topic}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class FibonacciSubscriber < EventServer
|
31
|
-
class << self
|
32
|
-
attr_accessor :last
|
33
|
-
end
|
34
|
-
|
35
|
-
listen_to 'fib.next' do
|
36
|
-
old = FibonacciSubscriber.last
|
37
|
-
FibonacciSubscriber.last = new = request.body
|
38
|
-
respond(old + new)
|
39
|
-
end
|
40
|
-
|
41
|
-
listen_to 'fib.init' do
|
42
|
-
FibonacciSubscriber.last = request.body
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
EventServer.new
|