pigeon 0.8.0 → 0.9.0
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.
- data/Rakefile +0 -10
- data/VERSION +1 -1
- data/lib/pigeon/engine.rb +115 -32
- data/lib/pigeon/launcher.rb +15 -11
- data/lib/pigeon.rb +1 -0
- data/pigeon.gemspec +3 -3
- data/test/helper.rb +21 -28
- data/test/unit/pigeon_backlog_test.rb +17 -6
- data/test/unit/pigeon_engine_test.rb +55 -0
- data/test/unit/pigeon_launcher_test.rb +6 -0
- data/test/unit/pigeon_processor_test.rb +27 -15
- data/test/unit/pigeon_scheduler_test.rb +3 -4
- data/test/unit/pigeon_task_test.rb +79 -81
- metadata +10 -5
data/Rakefile
CHANGED
@@ -28,13 +28,3 @@ end
|
|
28
28
|
task :test => :check_dependencies
|
29
29
|
|
30
30
|
task :default => :test
|
31
|
-
|
32
|
-
require 'rake/rdoctask'
|
33
|
-
Rake::RDocTask.new do |rdoc|
|
34
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
35
|
-
|
36
|
-
rdoc.rdoc_dir = 'rdoc'
|
37
|
-
rdoc.title = "pigeon #{version}"
|
38
|
-
rdoc.rdoc_files.include('README*')
|
39
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
40
|
-
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.0
|
data/lib/pigeon/engine.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
require 'socket'
|
3
|
+
require 'fiber'
|
3
4
|
|
4
5
|
class Pigeon::Engine
|
5
6
|
# == Submodules ===========================================================
|
@@ -23,6 +24,7 @@ class Pigeon::Engine
|
|
23
24
|
:boolean => true
|
24
25
|
option_accessor :debug,
|
25
26
|
:boolean => true
|
27
|
+
option_accessor :log_rotation
|
26
28
|
option_accessor :engine_log_name,
|
27
29
|
:default => 'engine.log'
|
28
30
|
option_accessor :engine_logger
|
@@ -44,6 +46,7 @@ class Pigeon::Engine
|
|
44
46
|
:default => false
|
45
47
|
|
46
48
|
attr_reader :id
|
49
|
+
attr_reader :state
|
47
50
|
|
48
51
|
# == Constants ============================================================
|
49
52
|
|
@@ -53,6 +56,12 @@ class Pigeon::Engine
|
|
53
56
|
after_start
|
54
57
|
before_stop
|
55
58
|
after_stop
|
59
|
+
before_resume
|
60
|
+
after_resume
|
61
|
+
before_standby
|
62
|
+
after_standby
|
63
|
+
before_shutdown
|
64
|
+
after_shutdown
|
56
65
|
].collect(&:to_sym).freeze
|
57
66
|
|
58
67
|
# == Class Methods ========================================================
|
@@ -166,6 +175,14 @@ class Pigeon::Engine
|
|
166
175
|
# No such process exception
|
167
176
|
pid = nil
|
168
177
|
end
|
178
|
+
|
179
|
+
begin
|
180
|
+
while (Process.kill(0, pid))
|
181
|
+
sleep(1)
|
182
|
+
end
|
183
|
+
rescue Errno::ESRCH
|
184
|
+
# No such process, already terminated
|
185
|
+
end
|
169
186
|
|
170
187
|
pid_file.remove!
|
171
188
|
end
|
@@ -200,7 +217,7 @@ class Pigeon::Engine
|
|
200
217
|
f = File.open(File.expand_path(self.engine_log_name, self.log_dir), 'a')
|
201
218
|
f.sync = true
|
202
219
|
|
203
|
-
Pigeon::Logger.new(f)
|
220
|
+
Pigeon::Logger.new(f, self.log_rotation)
|
204
221
|
end
|
205
222
|
end
|
206
223
|
|
@@ -210,7 +227,7 @@ class Pigeon::Engine
|
|
210
227
|
f = File.open(File.expand_path(self.query_log_name, self.log_dir), 'a')
|
211
228
|
f.sync = true
|
212
229
|
|
213
|
-
Pigeon::Logger.new(f)
|
230
|
+
Pigeon::Logger.new(f, self.log_rotation)
|
214
231
|
end
|
215
232
|
end
|
216
233
|
|
@@ -243,20 +260,22 @@ class Pigeon::Engine
|
|
243
260
|
def initialize(options = nil)
|
244
261
|
@id = Pigeon::Support.unique_id
|
245
262
|
|
246
|
-
|
263
|
+
wrap_chain(:initialize) do
|
264
|
+
@options = options || { }
|
247
265
|
|
248
|
-
|
249
|
-
|
266
|
+
@task_lock = Mutex.new
|
267
|
+
@task_locks = { }
|
250
268
|
|
251
|
-
|
252
|
-
|
269
|
+
@task_register_lock = Mutex.new
|
270
|
+
@registered_tasks = { }
|
253
271
|
|
254
|
-
|
255
|
-
|
272
|
+
self.logger ||= self.engine_logger
|
273
|
+
self.logger.level = Pigeon::Logger::DEBUG if (self.debug?)
|
256
274
|
|
257
|
-
|
275
|
+
@dispatcher = { }
|
258
276
|
|
259
|
-
|
277
|
+
@state = :initialized
|
278
|
+
end
|
260
279
|
end
|
261
280
|
|
262
281
|
# Returns the hostname of the system this engine is running on.
|
@@ -269,15 +288,15 @@ class Pigeon::Engine
|
|
269
288
|
def run
|
270
289
|
assign_process_name!
|
271
290
|
|
272
|
-
|
273
|
-
|
274
|
-
STDOUT.sync = true
|
291
|
+
wrap_chain(:start) do
|
292
|
+
STDOUT.sync = true
|
275
293
|
|
276
|
-
|
277
|
-
|
278
|
-
run_chain(:after_start)
|
294
|
+
logger.info("Engine \##{id} Running")
|
279
295
|
|
280
|
-
|
296
|
+
switch_to_effective_user! if (self.class.user)
|
297
|
+
|
298
|
+
@state = :running
|
299
|
+
end
|
281
300
|
end
|
282
301
|
|
283
302
|
# Used to periodically execute a task or block. When giving a task name,
|
@@ -339,11 +358,10 @@ class Pigeon::Engine
|
|
339
358
|
# Shuts down the engine. Will also trigger the before_stop and after_stop
|
340
359
|
# events.
|
341
360
|
def terminate
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
run_chain(:after_stop)
|
361
|
+
wrap_chain(:stop) do
|
362
|
+
EventMachine.stop_event_loop
|
363
|
+
@state = :terminated
|
364
|
+
end
|
347
365
|
end
|
348
366
|
|
349
367
|
# Used to dispatch a block for immediate processing on a background thread.
|
@@ -359,6 +377,43 @@ class Pigeon::Engine
|
|
359
377
|
EventMachine.next_tick(&block)
|
360
378
|
end
|
361
379
|
end
|
380
|
+
|
381
|
+
def resume!
|
382
|
+
case (@state)
|
383
|
+
when :running
|
384
|
+
# Ignored since already running.
|
385
|
+
when :terminated
|
386
|
+
# Invalid operation, should produce error.
|
387
|
+
else
|
388
|
+
wrap_chain(:resume) do
|
389
|
+
@state = :running
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def standby!
|
395
|
+
case (@state)
|
396
|
+
when :standby
|
397
|
+
# Already in standby state, ignored.
|
398
|
+
when :terminated
|
399
|
+
# Invalid operation, should produce error.
|
400
|
+
else
|
401
|
+
wrap_chain(:standby) do
|
402
|
+
@state = :standby
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def shutdown!
|
408
|
+
case (@state)
|
409
|
+
when :terminated
|
410
|
+
# Already terminated, ignored.
|
411
|
+
else
|
412
|
+
wrap_chain(:shutdown) do
|
413
|
+
self.terminate
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
362
417
|
|
363
418
|
class << self
|
364
419
|
CHAINS.each do |chain_name|
|
@@ -377,14 +432,8 @@ class Pigeon::Engine
|
|
377
432
|
end
|
378
433
|
end
|
379
434
|
|
380
|
-
def
|
381
|
-
|
382
|
-
|
383
|
-
return unless (chain)
|
384
|
-
|
385
|
-
chain.each do |proc|
|
386
|
-
instance.instance_eval(&proc)
|
387
|
-
end
|
435
|
+
def chain_procs(chain_name)
|
436
|
+
instance_variable_get(:"@_#{chain_name}_chain")
|
388
437
|
end
|
389
438
|
end
|
390
439
|
|
@@ -421,8 +470,42 @@ class Pigeon::Engine
|
|
421
470
|
end
|
422
471
|
|
423
472
|
protected
|
473
|
+
def wrap_chain(chain_name)
|
474
|
+
Fiber.new do
|
475
|
+
run_chain(:"before_#{chain_name}")
|
476
|
+
yield if (block_given?)
|
477
|
+
run_chain(:"after_#{chain_name}")
|
478
|
+
end.resume
|
479
|
+
end
|
480
|
+
|
424
481
|
def run_chain(chain_name)
|
425
|
-
|
482
|
+
callbacks = { }
|
483
|
+
fiber = Fiber.current
|
484
|
+
|
485
|
+
if (procs = self.class.chain_procs(chain_name))
|
486
|
+
procs.each do |proc|
|
487
|
+
case (proc.arity)
|
488
|
+
when 1
|
489
|
+
callback = lambda {
|
490
|
+
callbacks.delete(callback)
|
491
|
+
|
492
|
+
if (callbacks.empty?)
|
493
|
+
fiber.resume
|
494
|
+
end
|
495
|
+
}
|
496
|
+
|
497
|
+
callbacks[callback] = true
|
498
|
+
|
499
|
+
instance_exec(callback, &proc)
|
500
|
+
else
|
501
|
+
instance_eval(&proc)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
if (callbacks.any?)
|
506
|
+
Fiber.yield
|
507
|
+
end
|
508
|
+
end
|
426
509
|
end
|
427
510
|
|
428
511
|
def switch_to_effective_user!
|
data/lib/pigeon/launcher.rb
CHANGED
@@ -46,43 +46,47 @@ class Pigeon::Launcher
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def run(pid)
|
49
|
-
|
50
|
-
|
49
|
+
log "#{@engine.name} now running. [%d]" % pid
|
50
|
+
log "Use ^C to terminate."
|
51
51
|
end
|
52
52
|
|
53
53
|
def start(pid)
|
54
|
-
|
54
|
+
log "#{@engine.name} now running. [%d]" % pid
|
55
55
|
end
|
56
56
|
|
57
57
|
def stop(pid)
|
58
58
|
if (pid)
|
59
|
-
|
59
|
+
log "#{@engine.name} shut down. [%d]" % pid
|
60
60
|
else
|
61
|
-
|
61
|
+
log "#{@engine.name} was not running."
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
def status(pid)
|
66
66
|
if (pid)
|
67
|
-
|
67
|
+
log "#{@engine.name} running. [%d]" % pid
|
68
68
|
else
|
69
|
-
|
69
|
+
log "#{@engine.name} is not running."
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
73
|
def restart(pid, old_pid)
|
74
74
|
if (old_pid)
|
75
|
-
|
75
|
+
log "#{@engine.name} terminated. [%d]" % old_pid
|
76
76
|
end
|
77
77
|
|
78
|
-
|
78
|
+
log "#{@engine.name} now running. [%d]" % pid
|
79
79
|
end
|
80
80
|
|
81
81
|
def shutdown(pid)
|
82
|
-
|
82
|
+
log "Shutting down."
|
83
83
|
end
|
84
84
|
|
85
85
|
def usage
|
86
|
-
|
86
|
+
log "Usage: #{File.basename($0)} [start|stop|restart|status|run]"
|
87
|
+
end
|
88
|
+
|
89
|
+
def log(message)
|
90
|
+
puts message
|
87
91
|
end
|
88
92
|
end
|
data/lib/pigeon.rb
CHANGED
data/pigeon.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "pigeon"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.9.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["tadman"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-10-15"
|
13
13
|
s.description = "Pigeon is a simple way to get started building an EventMachine engine that's intended to run as a background job."
|
14
14
|
s.email = "github@tadman.ca"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -52,7 +52,7 @@ Gem::Specification.new do |s|
|
|
52
52
|
]
|
53
53
|
s.homepage = "http://github.com/twg/pigeon"
|
54
54
|
s.require_paths = ["lib"]
|
55
|
-
s.rubygems_version = "1.8.
|
55
|
+
s.rubygems_version = "1.8.24"
|
56
56
|
s.summary = "Simple daemonized EventMachine engine framework with plug-in support"
|
57
57
|
|
58
58
|
if s.respond_to? :specification_version then
|
data/test/helper.rb
CHANGED
@@ -8,10 +8,10 @@ require 'timeout'
|
|
8
8
|
|
9
9
|
require 'rubygems'
|
10
10
|
|
11
|
-
|
11
|
+
begin
|
12
12
|
gem 'eventmachine'
|
13
|
-
|
14
|
-
raise "EventMachine gem is not installed."
|
13
|
+
rescue => e
|
14
|
+
raise "EventMachine gem is not installed or could not be loaded: [#{e.class}] #{e}"
|
15
15
|
end
|
16
16
|
|
17
17
|
require 'pigeon'
|
@@ -37,37 +37,30 @@ class Test::Unit::TestCase
|
|
37
37
|
|
38
38
|
def engine
|
39
39
|
exception = nil
|
40
|
+
|
41
|
+
Pigeon::Engine.launch do |new_engine|
|
42
|
+
@engine = new_engine
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
begin
|
57
|
-
@engine.terminate
|
58
|
-
rescue Object
|
59
|
-
# Shutting down may trigger an exception from time to time
|
60
|
-
# if the engine itself has failed.
|
61
|
-
end
|
62
|
-
end
|
44
|
+
# Execute the test code in a separate thread to avoid blocking
|
45
|
+
# the EventMachine loop.
|
46
|
+
Thread.new do
|
47
|
+
begin
|
48
|
+
Thread.abort_on_exception = true
|
49
|
+
yield
|
50
|
+
rescue Object => exception
|
51
|
+
ensure
|
52
|
+
begin
|
53
|
+
# Regardless what happened, always terminate the engine.
|
54
|
+
@engine.terminate
|
55
|
+
rescue Object => e
|
56
|
+
# Shutting down may trigger an exception from time to time
|
57
|
+
# if the engine itself has failed.
|
58
|
+
STDERR.puts("Exception: [#{e.class}] #{e}")
|
63
59
|
end
|
64
60
|
end
|
65
|
-
rescue Object => exception
|
66
61
|
end
|
67
62
|
end
|
68
63
|
|
69
|
-
@engine_thread.join
|
70
|
-
|
71
64
|
if (exception)
|
72
65
|
raise exception
|
73
66
|
end
|
@@ -11,15 +11,26 @@ class PigeonQueueTest < Test::Unit::TestCase
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_queue_cycling
|
14
|
-
|
14
|
+
engine do
|
15
|
+
queue = Pigeon::Queue.new
|
16
|
+
|
17
|
+
task = Pigeon::Task.new
|
18
|
+
|
19
|
+
queue << task
|
20
|
+
|
21
|
+
assert_eventually(1) do
|
22
|
+
!queue.empty?
|
23
|
+
end
|
15
24
|
|
16
|
-
|
25
|
+
assert_equal 1, queue.length
|
26
|
+
assert !queue.empty?
|
17
27
|
|
18
|
-
|
28
|
+
found_task = queue.pop
|
19
29
|
|
20
|
-
|
21
|
-
assert !queue.empty?
|
30
|
+
assert_equal task, found_task
|
22
31
|
|
23
|
-
|
32
|
+
assert_equal 0, queue.length
|
33
|
+
assert queue.empty?
|
34
|
+
end
|
24
35
|
end
|
25
36
|
end
|
@@ -55,6 +55,22 @@ class CallbackTestEngine < Pigeon::Engine
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
class ShutdownCallbackTestEngine < Pigeon::Engine
|
59
|
+
attr_accessor :callbacks
|
60
|
+
|
61
|
+
after_start do
|
62
|
+
@callbacks = [ ]
|
63
|
+
end
|
64
|
+
|
65
|
+
before_shutdown do |callback|
|
66
|
+
@callbacks << callback
|
67
|
+
end
|
68
|
+
|
69
|
+
before_shutdown do |callback|
|
70
|
+
@callbacks << callback
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
58
74
|
class TestPigeonEngine < Test::Unit::TestCase
|
59
75
|
def test_default_options
|
60
76
|
assert TestEngine.engine_logger
|
@@ -173,4 +189,43 @@ class TestPigeonEngine < Test::Unit::TestCase
|
|
173
189
|
|
174
190
|
assert_equal nil, running_pid
|
175
191
|
end
|
192
|
+
|
193
|
+
def test_shutdown_engine_with_blocking_callback
|
194
|
+
e = nil
|
195
|
+
|
196
|
+
Thread.new do
|
197
|
+
Thread.abort_on_exception = true
|
198
|
+
|
199
|
+
ShutdownCallbackTestEngine.launch do |_e|
|
200
|
+
e = _e
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
assert_eventually(5) do
|
205
|
+
e
|
206
|
+
end
|
207
|
+
|
208
|
+
assert e, "Engine variable was not bound"
|
209
|
+
assert_equal [ ], e.callbacks
|
210
|
+
|
211
|
+
assert_eventually(5) do
|
212
|
+
e.state == :running
|
213
|
+
end
|
214
|
+
|
215
|
+
e.shutdown!
|
216
|
+
|
217
|
+
assert e.callbacks
|
218
|
+
assert !e.callbacks.empty?
|
219
|
+
assert_equal :running, e.state
|
220
|
+
|
221
|
+
assert_equal 2, e.callbacks.length
|
222
|
+
|
223
|
+
e.callbacks[0].call
|
224
|
+
|
225
|
+
assert_equal :running, e.state
|
226
|
+
|
227
|
+
e.callbacks[1].call
|
228
|
+
|
229
|
+
assert_equal :terminated, e.state
|
230
|
+
end
|
176
231
|
end
|
@@ -1,5 +1,11 @@
|
|
1
1
|
require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
2
2
|
|
3
|
+
class Pigeon::Launcher
|
4
|
+
def log(*args)
|
5
|
+
# Disabled for testing.
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
3
9
|
class PigeonLauncherTest < Test::Unit::TestCase
|
4
10
|
def test_default_launcher
|
5
11
|
pid = Pigeon::Launcher.launch
|
@@ -3,6 +3,7 @@ require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
|
3
3
|
class PigeonProcessorTest < Test::Unit::TestCase
|
4
4
|
class TaggedTask < Pigeon::Task
|
5
5
|
attr_accessor :tag
|
6
|
+
attr_reader :last_task
|
6
7
|
|
7
8
|
def initialize(tag, options = nil)
|
8
9
|
super(options)
|
@@ -37,29 +38,36 @@ class PigeonProcessorTest < Test::Unit::TestCase
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def test_simple_filter
|
40
|
-
|
41
|
+
engine do
|
42
|
+
queue = Pigeon::Queue.new
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
processor = Pigeon::Processor.new(queue) do |task|
|
45
|
+
(task.tag % 2) == 1
|
46
|
+
end
|
45
47
|
|
46
|
-
|
48
|
+
assert_equal false, processor.task?
|
47
49
|
|
48
|
-
|
50
|
+
queue << TaggedTask.new(0)
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
+
assert_eventually(1) do
|
53
|
+
queue.length == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
assert_equal false, processor.task?
|
57
|
+
assert_equal 1, queue.length
|
52
58
|
|
53
|
-
|
59
|
+
queue << TaggedTask.new(1)
|
54
60
|
|
55
|
-
|
56
|
-
|
61
|
+
assert_eventually(1) do
|
62
|
+
queue.length == 1
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_equal 1, queue.length
|
57
66
|
|
58
|
-
|
59
|
-
|
67
|
+
assert_eventually(5) do
|
68
|
+
!processor.task?
|
69
|
+
end
|
60
70
|
end
|
61
|
-
|
62
|
-
assert_equal 1, queue.length
|
63
71
|
end
|
64
72
|
|
65
73
|
def test_on_backlog
|
@@ -137,6 +145,10 @@ class PigeonProcessorTest < Test::Unit::TestCase
|
|
137
145
|
queue << TaggedTask.new(n)
|
138
146
|
end
|
139
147
|
|
148
|
+
assert_eventually(2) do
|
149
|
+
queue.length == count
|
150
|
+
end
|
151
|
+
|
140
152
|
assert_equal count, queue.length
|
141
153
|
|
142
154
|
processors = (0..9).to_a.collect do
|
@@ -53,12 +53,13 @@ class PigeonSchedulerTest < Test::Unit::TestCase
|
|
53
53
|
|
54
54
|
def test_add
|
55
55
|
queue = Pigeon::Queue.new
|
56
|
-
|
57
56
|
scheduler = Pigeon::Scheduler.new(queue)
|
57
|
+
|
58
|
+
assert scheduler.processors.length > 0
|
58
59
|
|
59
60
|
count = 1000
|
60
|
-
|
61
61
|
backlog = [ ]
|
62
|
+
|
62
63
|
count.times do |n|
|
63
64
|
scheduler.add(TaggedTask.new(n * 2 + 1))
|
64
65
|
backlog << TaggedTask.new(n * 2)
|
@@ -66,8 +67,6 @@ class PigeonSchedulerTest < Test::Unit::TestCase
|
|
66
67
|
|
67
68
|
scheduler.add(backlog)
|
68
69
|
|
69
|
-
assert !queue.empty?
|
70
|
-
|
71
70
|
assert_eventually(5) do
|
72
71
|
queue.empty?
|
73
72
|
end
|
@@ -44,35 +44,27 @@ class FailingTask < Pigeon::Task
|
|
44
44
|
end
|
45
45
|
|
46
46
|
class PigeonTaskTest < Test::Unit::TestCase
|
47
|
-
def setup
|
48
|
-
@engine = Pigeon::Engine.new
|
49
|
-
|
50
|
-
Pigeon::Engine.register_engine(@engine)
|
51
|
-
end
|
52
|
-
|
53
|
-
def teardown
|
54
|
-
Pigeon::Engine.unregister_engine(@engine)
|
55
|
-
end
|
56
|
-
|
57
47
|
def test_empty_task
|
58
|
-
|
48
|
+
engine do
|
49
|
+
task = Pigeon::Task.new
|
59
50
|
|
60
|
-
|
51
|
+
reported = 0
|
61
52
|
|
62
|
-
|
63
|
-
|
64
|
-
|
53
|
+
task.run! do
|
54
|
+
reported = 1
|
55
|
+
end
|
65
56
|
|
66
|
-
|
67
|
-
|
68
|
-
|
57
|
+
assert_eventually(5) do
|
58
|
+
task.finished? and reported > 0
|
59
|
+
end
|
69
60
|
|
70
|
-
|
71
|
-
|
61
|
+
assert_equal 1, reported
|
62
|
+
assert_equal :finished, task.state
|
72
63
|
|
73
|
-
|
64
|
+
assert_equal nil, task.exception
|
74
65
|
|
75
|
-
|
66
|
+
assert_equal @engine.object_id, task.engine.object_id
|
67
|
+
end
|
76
68
|
end
|
77
69
|
|
78
70
|
def test_alternate_engine
|
@@ -83,61 +75,65 @@ class PigeonTaskTest < Test::Unit::TestCase
|
|
83
75
|
end
|
84
76
|
|
85
77
|
def test_example_task
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
78
|
+
engine do
|
79
|
+
task = ExampleTask.new
|
80
|
+
|
81
|
+
callbacks = [ ]
|
82
|
+
|
83
|
+
task.run! do |state|
|
84
|
+
callbacks << state
|
85
|
+
end
|
86
|
+
|
87
|
+
assert_eventually(5) do
|
88
|
+
task.finished?
|
89
|
+
end
|
90
|
+
|
91
|
+
assert_equal nil, task.exception
|
92
|
+
|
93
|
+
assert_equal :finished, task.state
|
94
|
+
|
95
|
+
expected_triggers = [
|
96
|
+
:after_initialized,
|
97
|
+
:initialized,
|
98
|
+
:state1,
|
99
|
+
:state2,
|
100
|
+
:state3,
|
101
|
+
:state4,
|
102
|
+
:finished,
|
103
|
+
:after_finished
|
104
|
+
]
|
105
|
+
|
106
|
+
assert_equal expected_triggers, task.triggers
|
107
|
+
|
108
|
+
expected_callbacks = [
|
109
|
+
:initialized,
|
110
|
+
:state1,
|
111
|
+
:state2,
|
112
|
+
:state3,
|
113
|
+
:state4,
|
114
|
+
:finished
|
115
|
+
]
|
116
|
+
|
117
|
+
assert_equal expected_callbacks, callbacks
|
92
118
|
end
|
93
|
-
|
94
|
-
assert_eventually(5) do
|
95
|
-
task.finished?
|
96
|
-
end
|
97
|
-
|
98
|
-
assert_equal nil, task.exception
|
99
|
-
|
100
|
-
assert_equal :finished, task.state
|
101
|
-
|
102
|
-
expected_triggers = [
|
103
|
-
:after_initialized,
|
104
|
-
:initialized,
|
105
|
-
:state1,
|
106
|
-
:state2,
|
107
|
-
:state3,
|
108
|
-
:state4,
|
109
|
-
:finished,
|
110
|
-
:after_finished
|
111
|
-
]
|
112
|
-
|
113
|
-
assert_equal expected_triggers, task.triggers
|
114
|
-
|
115
|
-
expected_callbacks = [
|
116
|
-
:initialized,
|
117
|
-
:state1,
|
118
|
-
:state2,
|
119
|
-
:state3,
|
120
|
-
:state4,
|
121
|
-
:finished
|
122
|
-
]
|
123
|
-
|
124
|
-
assert_equal expected_callbacks, callbacks
|
125
119
|
end
|
126
120
|
|
127
121
|
def test_failing_task
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
122
|
+
engine do
|
123
|
+
task = FailingTask.new
|
124
|
+
|
125
|
+
reported = false
|
126
|
+
|
127
|
+
task.run! do
|
128
|
+
reported = true
|
129
|
+
end
|
130
|
+
|
131
|
+
assert_eventually(5) do
|
132
|
+
task.failed? and reported
|
133
|
+
end
|
139
134
|
|
140
|
-
|
135
|
+
assert task.exception?
|
136
|
+
end
|
141
137
|
end
|
142
138
|
|
143
139
|
def test_with_context
|
@@ -156,19 +152,21 @@ class PigeonTaskTest < Test::Unit::TestCase
|
|
156
152
|
end
|
157
153
|
|
158
154
|
def test_block_notification
|
159
|
-
|
155
|
+
engine do
|
156
|
+
task = Pigeon::Task.new
|
160
157
|
|
161
|
-
|
158
|
+
states_triggered = [ ]
|
162
159
|
|
163
|
-
|
164
|
-
|
165
|
-
|
160
|
+
task.run! do |state|
|
161
|
+
states_triggered << state
|
162
|
+
end
|
166
163
|
|
167
|
-
|
168
|
-
|
169
|
-
|
164
|
+
assert_eventually(5) do
|
165
|
+
task.finished?
|
166
|
+
end
|
170
167
|
|
171
|
-
|
168
|
+
assert_equal [ :initialized, :finished ], states_triggered
|
169
|
+
end
|
172
170
|
end
|
173
171
|
|
174
172
|
def test_priority_order
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pigeon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,12 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
description: Pigeon is a simple way to get started building an EventMachine engine
|
26
31
|
that's intended to run as a background job.
|
27
32
|
email: github@tadman.ca
|
@@ -83,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
88
|
version: '0'
|
84
89
|
requirements: []
|
85
90
|
rubyforge_project:
|
86
|
-
rubygems_version: 1.8.
|
91
|
+
rubygems_version: 1.8.24
|
87
92
|
signing_key:
|
88
93
|
specification_version: 3
|
89
94
|
summary: Simple daemonized EventMachine engine framework with plug-in support
|