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
         |