rjr 0.12.2 → 0.15.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.
Files changed (65) hide show
  1. data/README.md +49 -36
  2. data/Rakefile +2 -0
  3. data/bin/rjr-client +11 -9
  4. data/bin/rjr-server +12 -10
  5. data/examples/amqp.rb +29 -0
  6. data/examples/client.rb +32 -0
  7. data/examples/complete.rb +36 -0
  8. data/examples/local.rb +29 -0
  9. data/examples/server.rb +26 -0
  10. data/examples/tcp.rb +29 -0
  11. data/examples/web.rb +22 -0
  12. data/examples/ws.rb +29 -0
  13. data/lib/rjr/common.rb +7 -12
  14. data/lib/rjr/dispatcher.rb +171 -239
  15. data/lib/rjr/em_adapter.rb +33 -66
  16. data/lib/rjr/message.rb +43 -12
  17. data/lib/rjr/node.rb +197 -103
  18. data/lib/rjr/nodes/amqp.rb +216 -0
  19. data/lib/rjr/nodes/easy.rb +159 -0
  20. data/lib/rjr/nodes/local.rb +118 -0
  21. data/lib/rjr/{missing_node.rb → nodes/missing.rb} +4 -2
  22. data/lib/rjr/nodes/multi.rb +79 -0
  23. data/lib/rjr/nodes/tcp.rb +211 -0
  24. data/lib/rjr/nodes/web.rb +197 -0
  25. data/lib/rjr/nodes/ws.rb +187 -0
  26. data/lib/rjr/stats.rb +70 -0
  27. data/lib/rjr/thread_pool.rb +178 -123
  28. data/site/index.html +45 -0
  29. data/site/jquery-latest.js +9404 -0
  30. data/site/jrw.js +297 -0
  31. data/site/json.js +199 -0
  32. data/specs/dispatcher_spec.rb +244 -198
  33. data/specs/em_adapter_spec.rb +52 -80
  34. data/specs/message_spec.rb +223 -197
  35. data/specs/node_spec.rb +67 -163
  36. data/specs/nodes/amqp_spec.rb +82 -0
  37. data/specs/nodes/easy_spec.rb +13 -0
  38. data/specs/nodes/local_spec.rb +72 -0
  39. data/specs/nodes/multi_spec.rb +65 -0
  40. data/specs/nodes/tcp_spec.rb +75 -0
  41. data/specs/nodes/web_spec.rb +77 -0
  42. data/specs/nodes/ws_spec.rb +78 -0
  43. data/specs/stats_spec.rb +59 -0
  44. data/specs/thread_pool_spec.rb +44 -35
  45. metadata +40 -30
  46. data/lib/rjr/amqp_node.rb +0 -330
  47. data/lib/rjr/inspect.rb +0 -65
  48. data/lib/rjr/local_node.rb +0 -150
  49. data/lib/rjr/multi_node.rb +0 -65
  50. data/lib/rjr/tcp_node.rb +0 -323
  51. data/lib/rjr/thread_pool2.rb +0 -272
  52. data/lib/rjr/util.rb +0 -104
  53. data/lib/rjr/web_node.rb +0 -266
  54. data/lib/rjr/ws_node.rb +0 -289
  55. data/lib/rjr.rb +0 -16
  56. data/specs/amqp_node_spec.rb +0 -31
  57. data/specs/inspect_spec.rb +0 -60
  58. data/specs/local_node_spec.rb +0 -43
  59. data/specs/multi_node_spec.rb +0 -45
  60. data/specs/tcp_node_spec.rb +0 -33
  61. data/specs/util_spec.rb +0 -46
  62. data/specs/web_node_spec.rb +0 -32
  63. data/specs/ws_node_spec.rb +0 -32
  64. /data/lib/rjr/{tcp_node2.rb → nodes/tcp2.rb} +0 -0
  65. /data/lib/rjr/{udp_node.rb → nodes/udp.rb} +0 -0
@@ -1,225 +1,271 @@
1
1
  require 'rjr/dispatcher'
2
2
 
3
- describe RJR::Request do
4
- it "invokes registered handler in request context" do
5
- invoked = false
6
- rjr_callback = Object.new
7
- request = RJR::Request.new :method => 'foobar',
8
- :method_args => ['a', 123],
9
- :headers => {'qqq' => 'www'},
10
- :rjr_callback => rjr_callback,
11
- :rjr_node_id => 'test',
12
- :rjr_node_type => 'test_type',
13
- :handler => lambda { |p1, p2|
14
- invoked = true
15
- @method.should == 'foobar'
16
- p1.should == 'a'
17
- p2.should == 123
18
- @headers['qqq'].should == 'www'
19
- @rjr_callback.should == rjr_callback
20
- @rjr_node_id.should == 'test'
21
- @rjr_node_type.should == 'test_type'
22
- }
23
- request.handle
24
- invoked.should == true
25
- end
26
- end
3
+ module RJR
4
+ describe Result do
5
+ describe "#initialize" do
6
+ it "initializes default attributes" do
7
+ result = Result.new
8
+ result.result.should be_nil
9
+ result.error_code.should be_nil
10
+ result.error_msg.should be_nil
11
+ result.error_class.should be_nil
12
+ end
27
13
 
28
- describe RJR::Result do
29
- it "should handle successful results" do
30
- result = RJR::Result.new :result => 'foobar'
31
- result.success.should == true
32
- result.failed.should == false
33
- result.result.should == 'foobar'
34
- result.error_code.should == nil
35
- result.error_msg.should == nil
36
- result.error_class.should == nil
37
- end
14
+ it "stores result" do
15
+ result = Result.new :result => 'foobar'
16
+ result.result.should == 'foobar'
17
+ end
38
18
 
39
- it "should handle errors" do
40
- result = RJR::Result.new :error_code => 123, :error_msg => 'abc', :error_class => ArgumentError
41
- result.success.should == false
42
- result.failed.should == true
43
- result.result.should == nil
44
- result.error_code.should == 123
45
- result.error_msg.should == 'abc'
46
- result.error_class.should == ArgumentError
47
- end
48
- end
19
+ it "stores error" do
20
+ result = Result.new :error_code => 123, :error_msg => 'abc',
21
+ :error_class => ArgumentError
22
+ result.error_code.should == 123
23
+ result.error_msg.should == 'abc'
24
+ result.error_class.should == ArgumentError
25
+ end
49
26
 
27
+ context "when an error code is not specified" do
28
+ it "should be marked as successful" do
29
+ result = Result.new
30
+ result.success.should == true
31
+ result.failed.should == false
32
+ end
33
+ end
50
34
 
51
- describe RJR::Handler do
52
- before(:each) do
53
- RJR::DispatcherStat.reset
54
- end
35
+ context "when an error code is specified" do
36
+ it "should be marked as failed" do
37
+ result = Result.new :error_code => 123
38
+ result.success.should == false
39
+ result.failed.should == true
40
+ end
41
+ end
55
42
 
56
- it "should return method not found result if method name is not specified" do
57
- handler = RJR::Handler.new :method => nil
58
- result = handler.handle
59
- result.should == RJR::Result.method_not_found(nil)
60
- end
43
+ end # describe #initialize
61
44
 
62
- it "should invoke registered handler for request" do
63
- invoked = false
64
- handler = RJR::Handler.new :method => 'foobar',
65
- :handler => lambda {
66
- invoked = true
67
- }
68
- handler.handle({:method_args => [] })
69
- invoked.should == true
70
- end
45
+ describe "#==" do
46
+ it "return true for equal results"
47
+ it "return false for inequal results"
48
+ end # descirbe #==
71
49
 
72
- it "should create dispatcher stat when invoking handler" do
73
- handler = RJR::Handler.new :method => 'foobar',
74
- :handler => lambda { 42 }
75
- handler.handle({:method_args => [] })
76
- RJR::DispatcherStat.stats.size.should == 1
77
- RJR::DispatcherStat.stats.first.request.method.should == 'foobar'
78
- RJR::DispatcherStat.stats.first.result.result.should == 42
79
- end
50
+ end # describe Result
51
+ end # module RJR
80
52
 
81
- it "should return handler's return value in successful result" do
82
- retval = Object.new
83
- handler = RJR::Handler.new :method => 'foobar',
84
- :handler => lambda {
85
- retval
86
- }
87
- res = handler.handle({:method_args => [] })
88
- res.success.should == true
89
- res.result.should == retval
90
- end
53
+ module RJR
54
+ describe Request do
55
+ it "should be convertable to json" do
56
+ req = Request.new :rjr_method => 'foobar',
57
+ :rjr_method_args => [:a, :b],
58
+ :rjr_headers => { :header1 => :val1 },
59
+ :rjr_node_type => :local,
60
+ :rjr_node_id => :loc1
91
61
 
92
- it "should catch handler errors and return error result" do
93
- handler = RJR::Handler.new :method => 'foobar',
94
- :method_args => [],
95
- :handler => lambda {
96
- raise ArgumentError, "uh oh!"
97
- }
98
- res = handler.handle({:method_args => [] })
99
- res.failed.should == true
100
- res.error_code.should == -32000
101
- res.error_msg.should == "uh oh!"
102
- res.error_class.should == ArgumentError
103
- end
104
- end
62
+ res = RJR::Result.new :result => 42,
63
+ :error_code => 123,
64
+ :error_msg => 'error occurred',
65
+ :error_class => 'ArgumentError'
66
+ req.result = res
105
67
 
106
- describe RJR::DispatcherStat do
107
- before(:each) do
108
- RJR::DispatcherStat.reset
109
- end
68
+ j = req.to_json()
69
+ j.should include('"json_class":"RJR::Request"')
70
+ j.should include('"rjr_method":"foobar"')
71
+ j.should include('"rjr_method_args":["a","b"]')
72
+ j.should include('"rjr_headers":{"header1":"val1"}')
73
+ j.should include('"rjr_node_type":"local"')
74
+ j.should include('"rjr_node_id":"loc1"')
75
+ j.should include('"result":42')
76
+ j.should include('"error_code":123')
77
+ j.should include('"error_msg":"error occurred"')
78
+ j.should include('"error_class":"ArgumentError"')
79
+ end
110
80
 
111
- it "should store request and result" do
112
- req = RJR::Request.new
113
- res = RJR::Result.new
114
- stat = RJR::DispatcherStat.new req, res
115
- (stat.request == req).should be_true
116
- stat.result.should == res
117
- end
81
+ it "should be convertable from json" do
82
+ j = '{"json_class":"RJR::Request","data":{"request":{"rjr_method":"foobar","rjr_method_args":["a","b"],"rjr_headers":{"foo":"bar"},"rjr_node_type":"local","rjr_node_id":"loc1"},"result":{"result":42,"error_code":null,"error_msg":null,"error_class":null}}}'
83
+ r = JSON.parse(j)
118
84
 
119
- it "should track global stats" do
120
- req = RJR::Request.new
121
- res = RJR::Result.new
122
- stat = RJR::DispatcherStat.new req, res
85
+ r.class.should == RJR::Request
86
+ r.rjr_method.should == 'foobar'
87
+ r.rjr_method_args.should == ['a', 'b']
88
+ r.rjr_headers.should == { 'foo' => 'bar' }
89
+ r.rjr_node_type.should == 'local'
90
+ r.rjr_node_id.should == 'loc1'
91
+ r.result.result.should == 42
92
+ end
123
93
 
124
- RJR::DispatcherStat << stat
125
- RJR::DispatcherStat.stats.should include(stat)
126
- end
94
+ context "handling" do
95
+ it "should invoke handler in request context" do
96
+ method = 'foobar'
97
+ params = ['a', 1]
98
+ ni = 'test'
99
+ nt = 'test_type'
100
+ cb = Object.new
101
+ headers = {'header1' => 'val1'}
127
102
 
128
- it "should be convertable to json" do
129
- req = RJR::Request.new :method => 'foobar', :method_args => [:a, :b],
130
- :headers => { :foo => :bar }, :rjr_node_type => :local,
131
- :rjr_node_id => :loc1
132
- res = RJR::Result.new :result => 42
133
-
134
- stat = RJR::DispatcherStat.new req, res
135
- j = stat.to_json()
136
- j.should include('"json_class":"RJR::DispatcherStat"')
137
- j.should include('"method":"foobar"')
138
- j.should include('"method_args":["a","b"]')
139
- j.should include('"headers":{"foo":"bar"}')
140
- j.should include('"rjr_node_type":"local"')
141
- j.should include('"rjr_node_id":"loc1"')
142
- j.should include('"result":42')
143
- end
103
+ invoked = ip1 = ip2 =
104
+ icb = im = ini = int = ih = nil
105
+ handler = proc { |p1, p2|
106
+ invoked = true
107
+ ip1 = p1
108
+ ip2 = p2
109
+ im = @rjr_method
110
+ ini = @rjr_node_id
111
+ int = @rjr_node_type
112
+ icb = @rjr_callback
113
+ ih = @rjr_headers
114
+ }
115
+
116
+ request = Request.new :rjr_method => method,
117
+ :rjr_method_args => params,
118
+ :rjr_headers => headers,
119
+ :rjr_callback => cb,
120
+ :rjr_node_id => ni,
121
+ :rjr_node_type => nt,
122
+ :rjr_handler => handler
144
123
 
145
- it "should be convertable from json" do
146
- j = '{"json_class":"RJR::DispatcherStat","data":{"request":{"method":"foobar","method_args":["a","b"],"headers":{"foo":"bar"},"rjr_node_type":"local","rjr_node_id":"loc1"},"result":{"result":42,"error_code":null,"error_msg":null,"error_class":null}}}'
147
- s = JSON.parse(j)
148
-
149
- s.class.should == RJR::DispatcherStat
150
- s.request.method.should == 'foobar'
151
- s.request.method_args.should == ['a', 'b']
152
- s.request.headers.should == { 'foo' => 'bar' }
153
- s.request.rjr_node_type.should == 'local'
154
- s.request.rjr_node_id.should == 'loc1'
155
- s.result.result.should == 42
124
+ request.handle
125
+ invoked.should be_true
126
+ ip1.should == params[0]
127
+ ip2.should == params[1]
128
+ im.should == method
129
+ ini.should == ni
130
+ int.should == nt
131
+ icb.should == cb
132
+ ih.should == headers
133
+ end
134
+ end
156
135
  end
157
136
  end
158
137
 
159
- describe RJR::Dispatcher do
160
- it "should dispatch request to registered handler" do
161
- invoked_foobar = false
162
- invoked_barfoo = false
163
- RJR::Dispatcher.init_handlers
164
- RJR::Dispatcher.add_handler('foobar') { |param1, param2|
165
- invoked_foobar = true
166
- param1.should == "param1"
167
- param2.should == "param2"
168
- "retval"
169
- }
170
- RJR::Dispatcher.add_handler('barfoo') { |param1, param2|
171
- invoked_barfoo = true
172
- }
173
- res = RJR::Dispatcher.dispatch_request('foobar', :method_args => ['param1', 'param2'])
174
- res.success.should == true
175
- res.result.should == "retval"
176
- invoked_foobar.should == true
177
- invoked_barfoo.should == false
178
- end
138
+ module RJR
139
+ describe Dispatcher do
140
+ context "registering handlers" do
141
+ it "should load module"
179
142
 
180
- it "should allow user to determine registered handlers" do
181
- foobar = lambda {}
182
- barfoo = lambda {}
183
- RJR::Dispatcher.add_handler('foobar', &foobar)
184
- RJR::Dispatcher.add_handler('barfoo', &barfoo)
143
+ it "should register handler for method" do
144
+ d = Dispatcher.new
145
+ h = proc {}
146
+ d.handle('foobar', h)
147
+ d.handlers['foobar'].should == h
148
+ end
185
149
 
186
- RJR::Dispatcher.has_handler_for?('foobar').should be_true
187
- RJR::Dispatcher.has_handler_for?('barfoo').should be_true
188
- RJR::Dispatcher.has_handler_for?('money').should be_false
150
+ it "should set handler from block param" do
151
+ d = Dispatcher.new
152
+ h = proc {}
153
+ d.handle('foobar', &h)
154
+ d.handlers['foobar'].should == h
155
+ end
189
156
 
190
- RJR::Dispatcher.handler_for('foobar').handler_proc.should == foobar
191
- RJR::Dispatcher.handler_for('barfoo').handler_proc.should == barfoo
192
- RJR::Dispatcher.handler_for('money').should be_nil
193
- end
157
+ it "should register handler for multiple methods" do
158
+ d = Dispatcher.new
159
+ h = proc {}
160
+ d.handle(['foobar', 'barfoo'], &h)
161
+ d.handlers['foobar'].should == h
162
+ d.handlers['barfoo'].should == h
163
+ end
164
+ end
194
165
 
195
- it "should allow a single handler to be subscribed to multiple methods" do
196
- invoked_handler = 0
197
- RJR::Dispatcher.init_handlers
198
- RJR::Dispatcher.add_handler(['foobar', 'barfoo']) { |param1, param2|
199
- invoked_handler += 1
200
- }
201
- RJR::Dispatcher.dispatch_request('foobar', :method_args => ['param1', 'param2'])
202
- RJR::Dispatcher.dispatch_request('barfoo', :method_args => ['param1', 'param2'])
203
- invoked_handler.should == 2
204
- end
166
+ context "dispatching requests" do
167
+ context "handler does not exist" do
168
+ it "should return method not found" do
169
+ d = Dispatcher.new
170
+ r = d.dispatch :rjr_method => 'foobar'
171
+ r.should == Result.method_not_found('foobar')
172
+ end
173
+ end
205
174
 
206
- it "should return method not found result if handler for specified message is missing" do
207
- RJR::Dispatcher.init_handlers
208
- res = RJR::Dispatcher.dispatch_request('foobar')
209
- res.should == RJR::Result.method_not_found('foobar')
210
- end
175
+ context "handler is registered" do
176
+ it "should invoke handler" do
177
+ invoked = false
178
+ d = Dispatcher.new
179
+ h = proc { invoked = true }
180
+ d.handle('foobar', &h)
211
181
 
212
- it "should handle success response" do
213
- res = RJR::Result.new :result => 'woot'
214
- processed = RJR::Dispatcher.handle_response(res)
215
- processed.should == "woot"
216
- end
182
+ d.dispatch :rjr_method => 'foobar'
183
+ invoked.should be_true
184
+ end
217
185
 
218
- it "should handle error response" do
219
- lambda{
220
- res = RJR::Result.new :error_code => 123, :error_msg => "bah", :error_class => ArgumentError
221
- RJR::Dispatcher.handle_response(res)
222
- }.should raise_error(Exception, "bah")
223
- #}.should raise_error(ArgumentError, "bah")
224
- end
225
- end
186
+ it "should pass params to handler" do
187
+ param = nil
188
+ d = Dispatcher.new
189
+ h = proc { |p| param = p}
190
+ d.handle('foobar', &h)
191
+
192
+ d.dispatch(:rjr_method => 'foobar', :rjr_method_args => [42])
193
+ param.should == 42
194
+ end
195
+
196
+ it "should return request result" do
197
+ d = Dispatcher.new
198
+ h = proc { 42 }
199
+ d.handle('foobar', &h)
200
+
201
+ r = d.dispatch :rjr_method => 'foobar'
202
+ r.result.should == 42
203
+ end
204
+
205
+ it "should return request error" do
206
+ d = Dispatcher.new
207
+ h = proc { raise ArgumentError, "bah" }
208
+ d.handle('foobar', &h)
209
+
210
+ r = d.dispatch :rjr_method => 'foobar'
211
+ r.error_code.should == -32000
212
+ r.error_msg.should == "bah"
213
+ r.error_class.should == ArgumentError
214
+ end
215
+
216
+ it "should register request" do
217
+ d = Dispatcher.new
218
+ h = proc {}
219
+ d.handle('foobar', &h)
220
+
221
+ d.requests.size.should == 0
222
+ d.dispatch :rjr_method => 'foobar'
223
+ d.requests.size.should == 1
224
+ d.requests.first.rjr_method.should == 'foobar'
225
+ end
226
+
227
+ it "should set params on request" do
228
+ d = Dispatcher.new
229
+ h = proc { |p| }
230
+ d.handle('foobar', &h)
231
+
232
+ d.dispatch(:rjr_method => 'foobar', :rjr_method_args => [42])
233
+ d.requests.first.rjr_method_args.should == [42]
234
+ end
235
+
236
+ it "should set result on request" do
237
+ d = Dispatcher.new
238
+ h = proc { 42 }
239
+ d.handle('foobar', &h)
240
+
241
+ d.dispatch :rjr_method => 'foobar'
242
+ d.requests.first.result.result.should == 42
243
+ end
244
+ end
245
+ end
246
+
247
+ context "processing responses" do
248
+ context "successful response" do
249
+ it "should return result" do
250
+ r = Result.new :result => 'woot'
251
+ d = Dispatcher.new
252
+ p = d.handle_response(r)
253
+ p.should == "woot"
254
+ end
255
+ end
256
+
257
+ context "failed response" do
258
+ it "should raise error" do
259
+ r = Result.new :error_code => 123, :error_msg => "bah",
260
+ :error_class => ArgumentError
261
+ d = Dispatcher.new
262
+ lambda{
263
+ d.handle_response(r)
264
+ }.should raise_error(Exception, "bah")
265
+ #}.should raise_error(ArgumentError, "bah")
266
+ end
267
+ end
268
+ end
269
+
270
+ end # describe Dispatcher
271
+ end # module RJR
@@ -1,85 +1,57 @@
1
- require 'rjr/dispatcher'
1
+ require 'thread'
2
2
  require 'rjr/em_adapter'
3
3
 
4
- describe EMManager do
5
- it "should start and halt the reactor thread" do
6
- manager = EMManager.new
7
- manager.start
8
- EventMachine.reactor_running?.should be_true
9
- manager.running?.should be_true
10
- manager.instance_variable_get(:@reactor_thread).should_not be_nil
11
- rt = manager.instance_variable_get(:@reactor_thread)
12
- ['sleep', 'run'].should include(manager.instance_variable_get(:@reactor_thread).status)
4
+ module RJR
5
+ describe EMAdapter do
6
+ after(:each) do
7
+ EMAdapter.instance.halt
8
+ EMAdapter.instance.join
9
+ end
10
+
11
+ it "should be a singleton" do
12
+ em = EMAdapter.instance
13
+ EMAdapter.instance.should == em
14
+ end
15
+
16
+ it "should start the reactor" do
17
+ em = EMAdapter.instance
18
+ em.start
19
+ em.reactor_running?.should be_true
20
+ ['sleep', 'run'].should include(em.reactor_thread.status)
21
+ end
22
+
23
+ it "should only start the reactor once" do
24
+ em = EMAdapter.instance
25
+ em.start
26
+
27
+ ot = em.reactor_thread
28
+ em.start
29
+ em.reactor_thread.should == ot
30
+ end
31
+
32
+ it "should halt the reactor" do
33
+ em = EMAdapter.instance
34
+ em.start
35
+
36
+ em.halt
37
+ em.join
38
+ em.reactor_running?.should be_false
39
+ em.reactor_thread.should be_nil
40
+ end
41
+
42
+ it "should dispatch all requests to eventmachine" do
43
+ em = EMAdapter.instance
44
+ em.start
45
+
46
+ invoked = false
47
+ m,c = Mutex.new, ConditionVariable.new
48
+ em.schedule {
49
+ invoked = true
50
+ m.synchronize { c.signal }
51
+ }
52
+ m.synchronize { c.wait m, 0.5 } if !invoked
53
+ invoked.should be_true
54
+ end
13
55
 
14
- manager.start
15
- rt2 = manager.instance_variable_get(:@reactor_thread)
16
- rt.should == rt2
17
-
18
- manager.halt
19
- manager.join
20
- EventMachine.reactor_running?.should be_false
21
- manager.running?.should be_false
22
- manager.instance_variable_get(:@reactor_thread).should be_nil
23
- end
24
-
25
- it "should allow the user to schedule jobs" do
26
- manager = EMManager.new
27
- manager.start
28
- manager.running?.should be_true
29
- block_ran = false
30
- manager.schedule {
31
- block_ran = true
32
- }
33
- sleep 0.5
34
- block_ran.should == true
35
-
36
- manager.halt
37
- manager.join
38
- manager.running?.should be_false
39
- end
40
-
41
- it "should allow the user to keep the reactor alive until forcibly stopped" do
42
- manager = EMManager.new
43
- manager.start
44
- manager.running?.should be_true
45
- manager.schedule { "foo" }
46
-
47
- manager.running?.should be_true
48
-
49
- # forcibly stop the reactor
50
- manager.halt
51
- manager.join
52
- manager.running?.should be_false
53
- end
54
-
55
- it "should allow the user to schedule at job after a specified interval" do
56
- manager = EMManager.new
57
- manager.start
58
- manager.running?.should be_true
59
- block_called = false
60
- manager.add_timer(1) { block_called = true }
61
- sleep 0.5
62
- block_called.should == false
63
- sleep 1
64
- block_called.should == true
65
- manager.halt
66
- manager.join
67
- end
68
-
69
- it "should allow the user to schedule at job repeatidly with a specified interval" do
70
- manager = EMManager.new
71
- manager.start
72
- manager.running?.should be_true
73
- times_block_called = 0
74
- manager.add_periodic_timer(1) { times_block_called += 1 }
75
- sleep 0.6
76
- times_block_called.should == 0
77
- sleep 0.6
78
- times_block_called.should == 1
79
- sleep 1.2
80
- times_block_called.should == 2
81
-
82
- manager.halt
83
- manager.join
84
56
  end
85
57
  end