pigeon 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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.8.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
- @options = options || { }
263
+ wrap_chain(:initialize) do
264
+ @options = options || { }
247
265
 
248
- @task_lock = Mutex.new
249
- @task_locks = { }
266
+ @task_lock = Mutex.new
267
+ @task_locks = { }
250
268
 
251
- @task_register_lock = Mutex.new
252
- @registered_tasks = { }
269
+ @task_register_lock = Mutex.new
270
+ @registered_tasks = { }
253
271
 
254
- self.logger ||= self.engine_logger
255
- self.logger.level = Pigeon::Logger::DEBUG if (self.debug?)
272
+ self.logger ||= self.engine_logger
273
+ self.logger.level = Pigeon::Logger::DEBUG if (self.debug?)
256
274
 
257
- @dispatcher = { }
275
+ @dispatcher = { }
258
276
 
259
- run_chain(:after_initialize)
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
- run_chain(:before_start)
273
-
274
- STDOUT.sync = true
291
+ wrap_chain(:start) do
292
+ STDOUT.sync = true
275
293
 
276
- logger.info("Engine \##{id} Running")
277
-
278
- run_chain(:after_start)
294
+ logger.info("Engine \##{id} Running")
279
295
 
280
- switch_to_effective_user! if (self.class.user)
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
- run_chain(:before_stop)
343
-
344
- EventMachine.stop_event_loop
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 run_chain(chain_name, instance)
381
- chain = instance_variable_get(:"@_#{chain_name}_chain")
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
- self.class.run_chain(chain_name, self)
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!
@@ -46,43 +46,47 @@ class Pigeon::Launcher
46
46
  end
47
47
 
48
48
  def run(pid)
49
- puts "#{@engine.name} now running. [%d]" % pid
50
- puts "Use ^C to terminate."
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
- puts "#{@engine.name} now running. [%d]" % pid
54
+ log "#{@engine.name} now running. [%d]" % pid
55
55
  end
56
56
 
57
57
  def stop(pid)
58
58
  if (pid)
59
- puts "#{@engine.name} shut down. [%d]" % pid
59
+ log "#{@engine.name} shut down. [%d]" % pid
60
60
  else
61
- puts "#{@engine.name} was not running."
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
- puts "#{@engine.name} running. [%d]" % pid
67
+ log "#{@engine.name} running. [%d]" % pid
68
68
  else
69
- puts "#{@engine.name} is not running."
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
- puts "#{@engine.name} terminated. [%d]" % old_pid
75
+ log "#{@engine.name} terminated. [%d]" % old_pid
76
76
  end
77
77
 
78
- puts "#{@engine.name} now running. [%d]" % pid
78
+ log "#{@engine.name} now running. [%d]" % pid
79
79
  end
80
80
 
81
81
  def shutdown(pid)
82
- puts "Shutting down."
82
+ log "Shutting down."
83
83
  end
84
84
 
85
85
  def usage
86
- puts "Usage: #{File.basename($0)} [start|stop|restart|status|run]"
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
@@ -19,4 +19,5 @@ end
19
19
  # issue where requiring it later causes a run-time Interrupt exception.
20
20
  require 'pigeon/logger'
21
21
 
22
+ # The fastthread library is not essential, so loading errors can be ignored.
22
23
  require 'fastthread' rescue nil
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.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-04-04"
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.17"
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
- if (Gem.available?('eventmachine'))
11
+ begin
12
12
  gem 'eventmachine'
13
- else
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
- @engine_thread = Thread.new do
42
- Thread.abort_on_exception = true
43
-
44
- # Create a thread for the engine to run on
45
- begin
46
- Pigeon::Engine.launch do |new_engine|
47
- @engine = new_engine
48
-
49
- Thread.new do
50
- # Execute the test code in a separate thread to avoid blocking
51
- # the EventMachine loop.
52
- begin
53
- yield
54
- rescue Object => exception
55
- ensure
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
- queue = Pigeon::Queue.new
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
- task = Pigeon::Task.new
25
+ assert_equal 1, queue.length
26
+ assert !queue.empty?
17
27
 
18
- queue << task
28
+ found_task = queue.pop
19
29
 
20
- assert_equal 1, queue.length
21
- assert !queue.empty?
30
+ assert_equal task, found_task
22
31
 
23
- found_task = queue.pop
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
- queue = Pigeon::Queue.new
41
+ engine do
42
+ queue = Pigeon::Queue.new
41
43
 
42
- processor = Pigeon::Processor.new(queue) do |task|
43
- (task.tag % 2) == 1
44
- end
44
+ processor = Pigeon::Processor.new(queue) do |task|
45
+ (task.tag % 2) == 1
46
+ end
45
47
 
46
- assert_equal false, processor.task?
48
+ assert_equal false, processor.task?
47
49
 
48
- queue << TaggedTask.new(0)
50
+ queue << TaggedTask.new(0)
49
51
 
50
- assert_equal false, processor.task?
51
- assert_equal 1, queue.length
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
- queue << TaggedTask.new(1)
59
+ queue << TaggedTask.new(1)
54
60
 
55
- assert_equal true, processor.task?
56
- assert_equal 1, queue.length
61
+ assert_eventually(1) do
62
+ queue.length == 1
63
+ end
64
+
65
+ assert_equal 1, queue.length
57
66
 
58
- assert_eventually(5) do
59
- !processor.task?
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
- task = Pigeon::Task.new
48
+ engine do
49
+ task = Pigeon::Task.new
59
50
 
60
- reported = 0
51
+ reported = 0
61
52
 
62
- task.run! do
63
- reported = 1
64
- end
53
+ task.run! do
54
+ reported = 1
55
+ end
65
56
 
66
- assert_eventually(5) do
67
- task.finished? and reported > 0
68
- end
57
+ assert_eventually(5) do
58
+ task.finished? and reported > 0
59
+ end
69
60
 
70
- assert_equal 1, reported
71
- assert_equal :finished, task.state
61
+ assert_equal 1, reported
62
+ assert_equal :finished, task.state
72
63
 
73
- assert_equal nil, task.exception
64
+ assert_equal nil, task.exception
74
65
 
75
- assert_equal @engine.object_id, task.engine.object_id
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
- task = ExampleTask.new
87
-
88
- callbacks = [ ]
89
-
90
- task.run! do |state|
91
- callbacks << state
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
- task = FailingTask.new
129
-
130
- reported = false
131
-
132
- task.run! do
133
- reported = true
134
- end
135
-
136
- assert_eventually(5) do
137
- task.failed? and reported
138
- end
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
- assert task.exception?
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
- task = Pigeon::Task.new
155
+ engine do
156
+ task = Pigeon::Task.new
160
157
 
161
- states_triggered = [ ]
158
+ states_triggered = [ ]
162
159
 
163
- task.run! do |state|
164
- states_triggered << state
165
- end
160
+ task.run! do |state|
161
+ states_triggered << state
162
+ end
166
163
 
167
- assert_eventually(5) do
168
- task.finished?
169
- end
164
+ assert_eventually(5) do
165
+ task.finished?
166
+ end
170
167
 
171
- assert_equal [ :initialized, :finished ], states_triggered
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.8.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-04-04 00:00:00.000000000 Z
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: &2152583160 !ruby/object:Gem::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: *2152583160
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.17
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