procrastinate 0.4.1 → 0.5.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/HISTORY.txt +2 -1
- data/Rakefile +8 -11
- data/examples/server.rb +31 -0
- data/lib/procrastinate.rb +2 -1
- data/lib/procrastinate/implicit.rb +19 -16
- data/lib/procrastinate/process_manager.rb +20 -5
- data/lib/procrastinate/scheduler.rb +59 -13
- data/lib/procrastinate/server.rb +78 -0
- data/lib/procrastinate/task/callable.rb +1 -1
- metadata +88 -40
    
        data/HISTORY.txt
    CHANGED
    
    
    
        data/Rakefile
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            require "rubygems"
         | 
| 2 | 
            -
            require "rdoc/task"
         | 
| 3 2 | 
             
            require 'rspec/core/rake_task'
         | 
| 4 3 | 
             
            require 'rubygems/package_task'
         | 
| 4 | 
            +
            require 'rake/clean'
         | 
| 5 5 |  | 
| 6 6 | 
             
            desc "Run all tests: Exhaustive."
         | 
| 7 7 | 
             
            RSpec::Core::RakeTask.new
         | 
| @@ -15,19 +15,14 @@ task :stats do | |
| 15 15 | 
             
              end
         | 
| 16 16 | 
             
            end
         | 
| 17 17 |  | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
               | 
| 21 | 
            -
               | 
| 22 | 
            -
              rdoc.options << '--fmt' << 'shtml' # explictly set shtml generator
         | 
| 23 | 
            -
              rdoc.template = 'direct' # lighter template used on railsapi.com
         | 
| 24 | 
            -
              rdoc.main = "README"
         | 
| 25 | 
            -
              rdoc.rdoc_files.include("README", "lib/**/*.rb")
         | 
| 26 | 
            -
              rdoc.rdoc_dir = "rdoc"
         | 
| 18 | 
            +
            require 'yard'
         | 
| 19 | 
            +
            YARD::Rake::YardocTask.new do |t|
         | 
| 20 | 
            +
              # t.files   = ['lib/**/*.rb']
         | 
| 21 | 
            +
              # t.options = ['--any', '--extra', '--opts'] # optional
         | 
| 27 22 | 
             
            end
         | 
| 28 23 |  | 
| 29 24 | 
             
            desc 'Clear out RDoc'
         | 
| 30 | 
            -
            task :clean => [: | 
| 25 | 
            +
            task :clean => [:clobber_package]
         | 
| 31 26 |  | 
| 32 27 | 
             
            # This task actually builds the gem. 
         | 
| 33 28 | 
             
            task :gem => :spec
         | 
| @@ -37,3 +32,5 @@ desc "Generate the gem package." | |
| 37 32 | 
             
            Gem::PackageTask.new(spec) do |pkg|
         | 
| 38 33 | 
             
              # pkg.need_tar = true
         | 
| 39 34 | 
             
            end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            CLEAN << 'doc'
         | 
    
        data/examples/server.rb
    ADDED
    
    | @@ -0,0 +1,31 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            $:.unshift File.dirname(__FILE__) + '/../lib'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'procrastinate'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # * murder lazies
         | 
| 7 | 
            +
            # * maintain worker count
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            scheduler = Procrastinate::Scheduler.start
         | 
| 10 | 
            +
            scheduler.spawn_workers(6) {
         | 
| 11 | 
            +
              # Worker body
         | 
| 12 | 
            +
              loop do
         | 
| 13 | 
            +
                puts "Hiho from worker #{Process.pid}."
         | 
| 14 | 
            +
                sleep rand(1.0) * 3
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            # Wait around until something important happens
         | 
| 19 | 
            +
            r, w = IO.pipe
         | 
| 20 | 
            +
            trap('QUIT') { w.write '.' }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            loop do
         | 
| 23 | 
            +
              IO.select([r], nil, nil)
         | 
| 24 | 
            +
              r.read_nonblock(1000)
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
              # When we reach this point, a QUIT signal has been sent to the process. 
         | 
| 27 | 
            +
              # Abort.
         | 
| 28 | 
            +
              break
         | 
| 29 | 
            +
            end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            scheduler.shutdown
         | 
    
        data/lib/procrastinate.rb
    CHANGED
    
    
| @@ -2,57 +2,58 @@ | |
| 2 2 | 
             
            require 'procrastinate'
         | 
| 3 3 |  | 
| 4 4 | 
             
            module Procrastinate
         | 
| 5 | 
            -
              # call-seq:
         | 
| 6 | 
            -
              #   Procrastinate.scheduler => scheduler
         | 
| 7 | 
            -
              #
         | 
| 8 5 | 
             
              # Returns the scheduler instance. When using procrastinate/implicit, there
         | 
| 9 6 | 
             
              # is one global scheduler to your ruby process, this one.
         | 
| 7 | 
            +
              # 
         | 
| 8 | 
            +
              # @return [Scheduler] singleton scheduler for implicit scheduling.
         | 
| 10 9 | 
             
              #
         | 
| 11 10 | 
             
              def scheduler
         | 
| 12 11 | 
             
                @scheduler ||= Scheduler.start
         | 
| 13 12 | 
             
              end
         | 
| 14 13 | 
             
              module_function :scheduler
         | 
| 15 14 |  | 
| 16 | 
            -
              # call-seq: 
         | 
| 17 | 
            -
              #   Procrastinate.proxy(obj) => proxy
         | 
| 18 | 
            -
              #
         | 
| 19 15 | 
             
              # Creates a proxy that will execute methods called on obj in a child process. 
         | 
| 20 16 | 
             
              #
         | 
| 21 | 
            -
              #  | 
| 22 | 
            -
              #
         | 
| 17 | 
            +
              # @example 
         | 
| 23 18 | 
             
              #   proxy = Procrastinate.proxy("foo")
         | 
| 24 19 | 
             
              #   r     = proxy += "bar"
         | 
| 25 20 | 
             
              #   r.value   # => 'foobar'
         | 
| 26 21 | 
             
              #
         | 
| 22 | 
            +
              # @param obj [Object] Ruby object that the calls need to be proxied to
         | 
| 23 | 
            +
              # @return [Proxy] proxy object that will execute method calls in child 
         | 
| 24 | 
            +
              #   processes
         | 
| 25 | 
            +
              #
         | 
| 27 26 | 
             
              def proxy(obj)
         | 
| 28 27 | 
             
                scheduler.proxy(obj)
         | 
| 29 28 | 
             
              end
         | 
| 30 29 | 
             
              module_function :proxy
         | 
| 31 30 |  | 
| 32 | 
            -
              # call-seq: 
         | 
| 33 | 
            -
              #   Procrastinate.schedule { some_work }
         | 
| 34 | 
            -
              # 
         | 
| 35 31 | 
             
              # Schedules a block to be executed in its own thread. Returns the future that 
         | 
| 36 32 | 
             
              # will return the blocks return value. 
         | 
| 37 33 | 
             
              #
         | 
| 34 | 
            +
              # @example
         | 
| 35 | 
            +
              #   r = Procrastinate.schedule { do_some_work }
         | 
| 36 | 
            +
              #   r.value                                     # => the blocks return value
         | 
| 37 | 
            +
              #
         | 
| 38 | 
            +
              # @param block [Proc] block that will be executed in a child process
         | 
| 39 | 
            +
              # @return [Task::Result] a promise for the blocks return value
         | 
| 40 | 
            +
              #
         | 
| 38 41 | 
             
              def schedule(&block)
         | 
| 39 42 | 
             
                scheduler.schedule(&block)
         | 
| 40 43 | 
             
              end
         | 
| 41 44 | 
             
              module_function :schedule
         | 
| 42 45 |  | 
| 43 | 
            -
              # call-seq: 
         | 
| 44 | 
            -
              #   Procrastinate.join
         | 
| 45 | 
            -
              #
         | 
| 46 46 | 
             
              # Waits for all currently scheduled tasks to complete. This is like calling
         | 
| 47 47 | 
             
              # #value on all result objects, except that nothing is returned.
         | 
| 48 48 | 
             
              #
         | 
| 49 | 
            -
              #  | 
| 50 | 
            -
              #
         | 
| 49 | 
            +
              # @example 
         | 
| 51 50 | 
             
              #   proxy = Procrastinate.proxy("foo")
         | 
| 52 51 | 
             
              #   r     = proxy += "bar"
         | 
| 53 52 | 
             
              #   Procrastinate.join
         | 
| 54 53 | 
             
              #   r.ready? # => true
         | 
| 55 54 | 
             
              #
         | 
| 55 | 
            +
              # @return [void]
         | 
| 56 | 
            +
              #
         | 
| 56 57 | 
             
              def join
         | 
| 57 58 | 
             
                scheduler.join
         | 
| 58 59 | 
             
              end
         | 
| @@ -62,6 +63,8 @@ module Procrastinate | |
| 62 63 | 
             
              # since it consumes almost no resources when not active. This is mainly
         | 
| 63 64 | 
             
              # useful in tests to achieve isolation. 
         | 
| 64 65 | 
             
              #
         | 
| 66 | 
            +
              # @private
         | 
| 67 | 
            +
              #
         | 
| 65 68 | 
             
              def shutdown
         | 
| 66 69 | 
             
                scheduler.shutdown
         | 
| 67 70 | 
             
              end
         | 
| @@ -166,13 +166,18 @@ class Procrastinate::ProcessManager | |
| 166 166 | 
             
                # Ignore: This means that no childs remain. 
         | 
| 167 167 | 
             
              end
         | 
| 168 168 |  | 
| 169 | 
            -
              # Spawns a process to work on +task+. If a block is given, it is called
         | 
| 170 | 
            -
              #  | 
| 169 | 
            +
              # Spawns a process to work on +task+. If a block is given, it is called when
         | 
| 170 | 
            +
              # the task completes. This method should only be called from a strategy
         | 
| 171 171 | 
             
              # inside the dispatchers thread. Otherwise it will expose threading issues. 
         | 
| 172 172 | 
             
              #
         | 
| 173 | 
            -
              #  | 
| 174 | 
            -
              # 
         | 
| 175 | 
            -
              # | 
| 173 | 
            +
              # @example 
         | 
| 174 | 
            +
              #   create_process(wi) { puts "Task is complete" }
         | 
| 175 | 
            +
              #
         | 
| 176 | 
            +
              # @param task [Procrastinate::Task::Callable] task to be run inside the
         | 
| 177 | 
            +
              #   forked process
         | 
| 178 | 
            +
              # @param completion_handler [Proc] completion handler that is called when
         | 
| 179 | 
            +
              #   the process exits
         | 
| 180 | 
            +
              # @return [void]
         | 
| 176 181 | 
             
              #
         | 
| 177 182 | 
             
              def create_process(task, &completion_handler)
         | 
| 178 183 | 
             
                # Tasks that are interested in getting messages from their childs must 
         | 
| @@ -224,4 +229,14 @@ class Procrastinate::ProcessManager | |
| 224 229 | 
             
                  finalize_children
         | 
| 225 230 | 
             
                end
         | 
| 226 231 | 
             
              end
         | 
| 232 | 
            +
             | 
| 233 | 
            +
              # Kills all running processes by sending them a QUIT signal. 
         | 
| 234 | 
            +
              #
         | 
| 235 | 
            +
              # @param signal [String] signal to send to the forked processes.
         | 
| 236 | 
            +
              #
         | 
| 237 | 
            +
              def kill_processes(signal='QUIT')
         | 
| 238 | 
            +
                children.each do |pid, process|
         | 
| 239 | 
            +
                  Process.kill(signal, pid)
         | 
| 240 | 
            +
                end
         | 
| 241 | 
            +
              end
         | 
| 227 242 | 
             
            end
         | 
| @@ -3,16 +3,41 @@ require 'thread' | |
| 3 3 |  | 
| 4 4 | 
             
            # API Frontend for the procrastinate library. Allows scheduling of tasks and
         | 
| 5 5 | 
             
            # workers in seperate processes and provides minimal locking primitives. 
         | 
| 6 | 
            +
            # 
         | 
| 7 | 
            +
            # == Synopsis
         | 
| 8 | 
            +
            #   scheduler = Procrastinate::Scheduler.start
         | 
| 9 | 
            +
            #   
         | 
| 10 | 
            +
            # Schedule a block to run in its own process:
         | 
| 11 | 
            +
            #   result = scheduler.schedule { Process.pid }
         | 
| 12 | 
            +
            #   result.value  # => child process pid
         | 
| 6 13 | 
             
            #
         | 
| 7 | 
            -
            #  | 
| 8 | 
            -
            #  | 
| 9 | 
            -
            #  | 
| 14 | 
            +
            # Or schedule a message call to an object to be run in another process: 
         | 
| 15 | 
            +
            #   proxy = scheduler.proxy(1)
         | 
| 16 | 
            +
            #   result = proxy + 2
         | 
| 17 | 
            +
            #   result.value  # => 3
         | 
| 18 | 
            +
            #   
         | 
| 19 | 
            +
            # You can ask the result value if it is ready yet: 
         | 
| 20 | 
            +
            #   result.ready? # true/false
         | 
| 21 | 
            +
            #
         | 
| 22 | 
            +
            # Stop the scheduler, waiting for all scheduled work to finish:
         | 
| 23 | 
            +
            #   scheduler.shutdown 
         | 
| 24 | 
            +
            # 
         | 
| 25 | 
            +
            # Or shutting down hard, doesn't wait for work to finish: 
         | 
| 26 | 
            +
            #   scheduler.shutting(true)
         | 
| 27 | 
            +
            #
         | 
| 28 | 
            +
            # @note Each scheduler owns its own thread that does all the processing. The
         | 
| 29 | 
            +
            #   interface between your main thread and the procrastinate thread is defined
         | 
| 30 | 
            +
            #   in this class.
         | 
| 10 31 | 
             
            #
         | 
| 11 32 | 
             
            class Procrastinate::Scheduler
         | 
| 33 | 
            +
              # Process manager associated with this scheduler
         | 
| 12 34 | 
             
              attr_reader :manager
         | 
| 35 | 
            +
              # Schedule strategy associated with this scheduler
         | 
| 13 36 | 
             
              attr_reader :strategy
         | 
| 14 | 
            -
               | 
| 37 | 
            +
              # Task queue
         | 
| 38 | 
            +
              attr_reader :task_producer
         | 
| 15 39 |  | 
| 40 | 
            +
              # @see Scheduler.start
         | 
| 16 41 | 
             
              def initialize(strategy)
         | 
| 17 42 | 
             
                @strategy   = strategy || Procrastinate::SpawnStrategy::Default.new
         | 
| 18 43 | 
             
                @manager = Procrastinate::ProcessManager.new
         | 
| @@ -20,11 +45,18 @@ class Procrastinate::Scheduler | |
| 20 45 | 
             
                # State takes three values: :running, :soft_shutdown, :real_shutdown
         | 
| 21 46 | 
             
                # :soft_shutdown will not accept any new tasks and wait for completion
         | 
| 22 47 | 
             
                # :real_shutdown will stop as soon as possible (still closing down nicely)
         | 
| 23 | 
            -
                @state | 
| 24 | 
            -
                 | 
| 48 | 
            +
                @state          = :running
         | 
| 49 | 
            +
                
         | 
| 50 | 
            +
                # If we're used in server mode, this will be replaced with a task producer
         | 
| 51 | 
            +
                # that produces new worker processes.
         | 
| 52 | 
            +
                @task_producer  = Queue.new
         | 
| 25 53 | 
             
              end
         | 
| 26 54 |  | 
| 27 | 
            -
              # Starts a new scheduler
         | 
| 55 | 
            +
              # Starts a new scheduler.
         | 
| 56 | 
            +
              # 
         | 
| 57 | 
            +
              # @param strategy [SpawnStrategy] strategy to use when spawning new processes.
         | 
| 58 | 
            +
              #   Will default to {SpawnStrategy::Default}.
         | 
| 59 | 
            +
              # @return [Scheduler]
         | 
| 28 60 | 
             
              #
         | 
| 29 61 | 
             
              def self.start(strategy=nil)
         | 
| 30 62 | 
             
                new(strategy).
         | 
| @@ -37,11 +69,13 @@ class Procrastinate::Scheduler | |
| 37 69 | 
             
              # Returns a proxy for the +worker+ instance that will allow executing its
         | 
| 38 70 | 
             
              # methods in a new process. 
         | 
| 39 71 | 
             
              #
         | 
| 40 | 
            -
              #  | 
| 41 | 
            -
              #
         | 
| 72 | 
            +
              # @example
         | 
| 42 73 | 
             
              #   proxy = scheduler.proxy(worker)
         | 
| 43 74 | 
             
              #   status = proxy.do_some_work    # will execute later and in its own process
         | 
| 44 75 | 
             
              #
         | 
| 76 | 
            +
              # @param worker [Object] Ruby object that executes the work
         | 
| 77 | 
            +
              # @return [Proxy]
         | 
| 78 | 
            +
              #
         | 
| 45 79 | 
             
              def proxy(worker)
         | 
| 46 80 | 
             
                return Procrastinate::Proxy.new(worker, self)
         | 
| 47 81 | 
             
              end
         | 
| @@ -50,6 +84,8 @@ class Procrastinate::Scheduler | |
| 50 84 | 
             
              # used inside task execution processes; If you call it from your main 
         | 
| 51 85 | 
             
              # process, the result is undefined.
         | 
| 52 86 | 
             
              #
         | 
| 87 | 
            +
              # @return [Runtime]
         | 
| 88 | 
            +
              #
         | 
| 53 89 | 
             
              def runtime
         | 
| 54 90 | 
             
                Procrastinate::Runtime.new
         | 
| 55 91 | 
             
              end
         | 
| @@ -57,6 +93,16 @@ class Procrastinate::Scheduler | |
| 57 93 | 
             
              # Called by the proxy to schedule work. You can implement your own Task
         | 
| 58 94 | 
             
              # classes; the relevant interface consists of only a #run method. 
         | 
| 59 95 | 
             
              #
         | 
| 96 | 
            +
              # @overload schedule(task=nil)
         | 
| 97 | 
            +
              #   Runs task in its own worker process.
         | 
| 98 | 
            +
              #   @param task [#run] task to be run in its own worker process
         | 
| 99 | 
            +
              #   @return [Task::Result]
         | 
| 100 | 
            +
              #
         | 
| 101 | 
            +
              # @overload schedule(&block)
         | 
| 102 | 
            +
              #   Executes the Ruby block in its own worker process.
         | 
| 103 | 
            +
              #   @param block [Proc] block to be executed in worker process
         | 
| 104 | 
            +
              #   @return [Task::Result]
         | 
| 105 | 
            +
              #
         | 
| 60 106 | 
             
              def schedule(task=nil, &block)
         | 
| 61 107 | 
             
                fail "Shutting down..." if @state != :running
         | 
| 62 108 |  | 
| @@ -67,7 +113,7 @@ class Procrastinate::Scheduler | |
| 67 113 | 
             
                  task = Procrastinate::Task::Callable.new(block)
         | 
| 68 114 | 
             
                end
         | 
| 69 115 |  | 
| 70 | 
            -
                 | 
| 116 | 
            +
                task_producer << task
         | 
| 71 117 |  | 
| 72 118 | 
             
                # Create an occasion for spawning
         | 
| 73 119 | 
             
                manager.wakeup
         | 
| @@ -87,7 +133,7 @@ class Procrastinate::Scheduler | |
| 87 133 | 
             
                # Wait until all tasks are done.
         | 
| 88 134 | 
             
                loop do
         | 
| 89 135 | 
             
                  manager.wakeup
         | 
| 90 | 
            -
                  break if  | 
| 136 | 
            +
                  break if task_producer.empty? && manager.process_count==0
         | 
| 91 137 | 
             
                  sleep 0.01
         | 
| 92 138 | 
             
                end
         | 
| 93 139 |  | 
| @@ -115,8 +161,8 @@ private | |
| 115 161 | 
             
              #   *control thread* 
         | 
| 116 162 | 
             
              #
         | 
| 117 163 | 
             
              def spawn
         | 
| 118 | 
            -
                while strategy.should_spawn? && ! | 
| 119 | 
            -
                  task =  | 
| 164 | 
            +
                while strategy.should_spawn? && !task_producer.empty?
         | 
| 165 | 
            +
                  task = task_producer.pop
         | 
| 120 166 | 
             
                  strategy.notify_spawn
         | 
| 121 167 | 
             
                  manager.create_process(task) do
         | 
| 122 168 | 
             
                    strategy.notify_dead
         | 
| @@ -0,0 +1,78 @@ | |
| 1 | 
            +
            module Procrastinate
         | 
| 2 | 
            +
              class Server
         | 
| 3 | 
            +
                def initialize
         | 
| 4 | 
            +
                  @manager  = Procrastinate::ProcessManager.new
         | 
| 5 | 
            +
                  @state    = :new
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                def start(n, activity_check_interval=nil, &block)
         | 
| 9 | 
            +
                  fail "Already running server." unless @state == :new
         | 
| 10 | 
            +
                  
         | 
| 11 | 
            +
                  @block    = block
         | 
| 12 | 
            +
                  @strategy = Procrastinate::SpawnStrategy::Throttled.new(n)
         | 
| 13 | 
            +
                  @state    = :running
         | 
| 14 | 
            +
                  @check_interval = activity_check_interval
         | 
| 15 | 
            +
                  
         | 
| 16 | 
            +
                  start_thread
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                def shutdown
         | 
| 20 | 
            +
                  fail "For shutdown, server must be running." unless @state == :running
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  @state = :shutdown
         | 
| 23 | 
            +
                  @manager.wakeup
         | 
| 24 | 
            +
                  
         | 
| 25 | 
            +
                  @thread.join if @thread
         | 
| 26 | 
            +
                  
         | 
| 27 | 
            +
                  @thread = nil
         | 
| 28 | 
            +
                  @state  = :new
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
                
         | 
| 31 | 
            +
              private
         | 
| 32 | 
            +
                def start_thread
         | 
| 33 | 
            +
                  @thread = Thread.start(&method(:control_thread_main))
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
                
         | 
| 36 | 
            +
                # @note This method runs in the control thread only.
         | 
| 37 | 
            +
                #
         | 
| 38 | 
            +
                def spawn_new_workers
         | 
| 39 | 
            +
                  while @strategy.should_spawn?
         | 
| 40 | 
            +
                    task = Procrastinate::Task::Callable.new(@block)
         | 
| 41 | 
            +
                    
         | 
| 42 | 
            +
                    @strategy.notify_spawn
         | 
| 43 | 
            +
                    @manager.create_process(task) do
         | 
| 44 | 
            +
                      @strategy.notify_dead
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
                
         | 
| 49 | 
            +
                # @note This method runs in the control thread only.
         | 
| 50 | 
            +
                #
         | 
| 51 | 
            +
                def control_thread_main
         | 
| 52 | 
            +
                  # Start managers work
         | 
| 53 | 
            +
                  @manager.setup
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  # Loop until someone requests a shutdown.
         | 
| 56 | 
            +
                  loop do
         | 
| 57 | 
            +
                    spawn_new_workers
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    @manager.step
         | 
| 60 | 
            +
                    
         | 
| 61 | 
            +
                    break if @state == :shutdown
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                  
         | 
| 64 | 
            +
                  @manager.kill_processes
         | 
| 65 | 
            +
                  @manager.teardown
         | 
| 66 | 
            +
                rescue => ex
         | 
| 67 | 
            +
                  # Sometimes exceptions vanish silently. This will avoid that, even though
         | 
| 68 | 
            +
                  # they should abort the whole process.
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  warn "Exception #{ex.inspect} caught."
         | 
| 71 | 
            +
                  ex.backtrace.first(5).each do |line|
         | 
| 72 | 
            +
                    warn line
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  raise
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: procrastinate
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.5.0
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -10,85 +10,136 @@ authors: | |
| 10 10 | 
             
            autorequire: 
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2012- | 
| 13 | 
            +
            date: 2012-12-18 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: state_machine
         | 
| 17 | 
            -
               | 
| 18 | 
            -
             | 
| 17 | 
            +
              prerelease: false
         | 
| 18 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 19 19 | 
             
                requirements:
         | 
| 20 20 | 
             
                - - ~>
         | 
| 21 21 | 
             
                  - !ruby/object:Gem::Version
         | 
| 22 | 
            -
                    version:  | 
| 22 | 
            +
                    version: '1.1'
         | 
| 23 | 
            +
                none: false
         | 
| 23 24 | 
             
              type: :runtime
         | 
| 24 | 
            -
               | 
| 25 | 
            -
             | 
| 25 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 26 | 
            +
                requirements:
         | 
| 27 | 
            +
                - - ~>
         | 
| 28 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            +
                    version: '1.1'
         | 
| 30 | 
            +
                none: false
         | 
| 26 31 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 27 32 | 
             
              name: cod
         | 
| 28 | 
            -
               | 
| 29 | 
            -
             | 
| 33 | 
            +
              prerelease: false
         | 
| 34 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 35 | 
             
                requirements:
         | 
| 31 36 | 
             
                - - ~>
         | 
| 32 37 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            -
                    version: '0. | 
| 38 | 
            +
                    version: '0.5'
         | 
| 39 | 
            +
                none: false
         | 
| 34 40 | 
             
              type: :runtime
         | 
| 35 | 
            -
               | 
| 36 | 
            -
             | 
| 41 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 42 | 
            +
                requirements:
         | 
| 43 | 
            +
                - - ~>
         | 
| 44 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 45 | 
            +
                    version: '0.5'
         | 
| 46 | 
            +
                none: false
         | 
| 37 47 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 38 48 | 
             
              name: rake
         | 
| 39 | 
            -
               | 
| 40 | 
            -
             | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 41 51 | 
             
                requirements:
         | 
| 42 52 | 
             
                - - ! '>='
         | 
| 43 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 44 54 | 
             
                    version: '0'
         | 
| 55 | 
            +
                none: false
         | 
| 45 56 | 
             
              type: :development
         | 
| 46 | 
            -
               | 
| 47 | 
            -
             | 
| 57 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - ! '>='
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '0'
         | 
| 62 | 
            +
                none: false
         | 
| 48 63 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 49 64 | 
             
              name: rspec
         | 
| 50 | 
            -
               | 
| 51 | 
            -
             | 
| 65 | 
            +
              prerelease: false
         | 
| 66 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 52 67 | 
             
                requirements:
         | 
| 53 68 | 
             
                - - ! '>='
         | 
| 54 69 | 
             
                  - !ruby/object:Gem::Version
         | 
| 55 70 | 
             
                    version: '0'
         | 
| 71 | 
            +
                none: false
         | 
| 56 72 | 
             
              type: :development
         | 
| 57 | 
            -
               | 
| 58 | 
            -
             | 
| 73 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 74 | 
            +
                requirements:
         | 
| 75 | 
            +
                - - ! '>='
         | 
| 76 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 77 | 
            +
                    version: '0'
         | 
| 78 | 
            +
                none: false
         | 
| 59 79 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 60 80 | 
             
              name: flexmock
         | 
| 61 | 
            -
               | 
| 62 | 
            -
             | 
| 81 | 
            +
              prerelease: false
         | 
| 82 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 63 83 | 
             
                requirements:
         | 
| 64 84 | 
             
                - - ! '>='
         | 
| 65 85 | 
             
                  - !ruby/object:Gem::Version
         | 
| 66 86 | 
             
                    version: '0'
         | 
| 87 | 
            +
                none: false
         | 
| 67 88 | 
             
              type: :development
         | 
| 68 | 
            -
               | 
| 69 | 
            -
             | 
| 89 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 90 | 
            +
                requirements:
         | 
| 91 | 
            +
                - - ! '>='
         | 
| 92 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 93 | 
            +
                    version: '0'
         | 
| 94 | 
            +
                none: false
         | 
| 70 95 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 71 96 | 
             
              name: guard
         | 
| 72 | 
            -
               | 
| 73 | 
            -
             | 
| 97 | 
            +
              prerelease: false
         | 
| 98 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 74 99 | 
             
                requirements:
         | 
| 75 100 | 
             
                - - ! '>='
         | 
| 76 101 | 
             
                  - !ruby/object:Gem::Version
         | 
| 77 102 | 
             
                    version: '0'
         | 
| 103 | 
            +
                none: false
         | 
| 78 104 | 
             
              type: :development
         | 
| 79 | 
            -
               | 
| 80 | 
            -
             | 
| 105 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 106 | 
            +
                requirements:
         | 
| 107 | 
            +
                - - ! '>='
         | 
| 108 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 109 | 
            +
                    version: '0'
         | 
| 110 | 
            +
                none: false
         | 
| 81 111 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 82 112 | 
             
              name: growl
         | 
| 83 | 
            -
               | 
| 84 | 
            -
             | 
| 113 | 
            +
              prerelease: false
         | 
| 114 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 85 115 | 
             
                requirements:
         | 
| 86 116 | 
             
                - - ! '>='
         | 
| 87 117 | 
             
                  - !ruby/object:Gem::Version
         | 
| 88 118 | 
             
                    version: '0'
         | 
| 119 | 
            +
                none: false
         | 
| 89 120 | 
             
              type: :development
         | 
| 121 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 122 | 
            +
                requirements:
         | 
| 123 | 
            +
                - - ! '>='
         | 
| 124 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 125 | 
            +
                    version: '0'
         | 
| 126 | 
            +
                none: false
         | 
| 127 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 128 | 
            +
              name: yard
         | 
| 90 129 | 
             
              prerelease: false
         | 
| 91 | 
            -
               | 
| 130 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 131 | 
            +
                requirements:
         | 
| 132 | 
            +
                - - ! '>='
         | 
| 133 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 134 | 
            +
                    version: '0'
         | 
| 135 | 
            +
                none: false
         | 
| 136 | 
            +
              type: :development
         | 
| 137 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 138 | 
            +
                requirements:
         | 
| 139 | 
            +
                - - ! '>='
         | 
| 140 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 141 | 
            +
                    version: '0'
         | 
| 142 | 
            +
                none: false
         | 
| 92 143 | 
             
            description: 
         | 
| 93 144 | 
             
            email:
         | 
| 94 145 | 
             
            - kaspar.schiess@absurd.li
         | 
| @@ -109,6 +160,7 @@ files: | |
| 109 160 | 
             
            - lib/procrastinate/proxy.rb
         | 
| 110 161 | 
             
            - lib/procrastinate/runtime.rb
         | 
| 111 162 | 
             
            - lib/procrastinate/scheduler.rb
         | 
| 163 | 
            +
            - lib/procrastinate/server.rb
         | 
| 112 164 | 
             
            - lib/procrastinate/spawn_strategy/default.rb
         | 
| 113 165 | 
             
            - lib/procrastinate/spawn_strategy/simple.rb
         | 
| 114 166 | 
             
            - lib/procrastinate/spawn_strategy/throttled.rb
         | 
| @@ -122,6 +174,7 @@ files: | |
| 122 174 | 
             
            - lib/procrastinate.rb
         | 
| 123 175 | 
             
            - examples/locking.rb
         | 
| 124 176 | 
             
            - examples/pascal.rb
         | 
| 177 | 
            +
            - examples/server.rb
         | 
| 125 178 | 
             
            - examples/simple.rb
         | 
| 126 179 | 
             
            - examples/throttled.rb
         | 
| 127 180 | 
             
            homepage: http://github.com/kschiess/procrastinate
         | 
| @@ -133,27 +186,22 @@ rdoc_options: | |
| 133 186 | 
             
            require_paths:
         | 
| 134 187 | 
             
            - lib
         | 
| 135 188 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 136 | 
            -
              none: false
         | 
| 137 189 | 
             
              requirements:
         | 
| 138 190 | 
             
              - - ! '>='
         | 
| 139 191 | 
             
                - !ruby/object:Gem::Version
         | 
| 140 192 | 
             
                  version: '0'
         | 
| 141 | 
            -
                  segments:
         | 
| 142 | 
            -
                  - 0
         | 
| 143 | 
            -
                  hash: 3407763989240963082
         | 
| 144 | 
            -
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 145 193 | 
             
              none: false
         | 
| 194 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 146 195 | 
             
              requirements:
         | 
| 147 196 | 
             
              - - ! '>='
         | 
| 148 197 | 
             
                - !ruby/object:Gem::Version
         | 
| 149 198 | 
             
                  version: '0'
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                  - 0
         | 
| 152 | 
            -
                  hash: 3407763989240963082
         | 
| 199 | 
            +
              none: false
         | 
| 153 200 | 
             
            requirements: []
         | 
| 154 201 | 
             
            rubyforge_project: 
         | 
| 155 | 
            -
            rubygems_version: 1.8. | 
| 202 | 
            +
            rubygems_version: 1.8.24
         | 
| 156 203 | 
             
            signing_key: 
         | 
| 157 204 | 
             
            specification_version: 3
         | 
| 158 205 | 
             
            summary: Framework to run tasks in separate processes.
         | 
| 159 206 | 
             
            test_files: []
         | 
| 207 | 
            +
            has_rdoc: 
         |