disquo 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/disquo.gemspec +1 -1
- data/lib/disquo/worker.rb +62 -43
- data/spec/disquo/worker_spec.rb +4 -2
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e4a5a02702349eb8b6c55ccda7678d0ec5374f9d
         | 
| 4 | 
            +
              data.tar.gz: 2793c75864c561a6d96833c7a171c687b0bda854
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bd458037bec4658dd490234ca46ab75f82f3f74e40deb1e6a65d95eea6e3ddf49d3a7f0770885389830be92fed26124e3a66422fad584382fc21ec33ee9f0618
         | 
| 7 | 
            +
              data.tar.gz: e0575ada72338c810ee9186104f75b1478d8518f7a91bd5e5ed2218282c1d5c52ea99988b69c8c0550197cbf04d5e2d89919d1a6a7175d21e261f5733572b707
         | 
    
        data/.gitignore
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            pkg/
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/disquo.gemspec
    CHANGED
    
    
    
        data/lib/disquo/worker.rb
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require 'disquo'
         | 
| 2 | 
            -
            require 'concurrent'
         | 
| 3 2 | 
             
            require 'concurrent/executor/fixed_thread_pool'
         | 
| 3 | 
            +
            require 'concurrent/atomic/atomic_fixnum'
         | 
| 4 4 |  | 
| 5 5 | 
             
            class Disquo::Worker
         | 
| 6 6 | 
             
              attr_reader :disque, :queues, :wait_time, :wait_count
         | 
| @@ -10,19 +10,18 @@ class Disquo::Worker | |
| 10 10 | 
             
              # @param [Hash] options
         | 
| 11 11 | 
             
              # @option [Array<String>] :queues queues to watch. Default: ["default"]
         | 
| 12 12 | 
             
              # @option [Integer] :concurrency the number of concurrent threads. Default: 10
         | 
| 13 | 
            -
              # @option [Numeric] :wait_time maximum time (in seconds) to  | 
| 14 | 
            -
               | 
| 15 | 
            -
              def initialize(disque, queues: [Disquo::DEFAULT_QUEUE], concurrency: 10, wait_time: 1, wait_count: 100)
         | 
| 13 | 
            +
              # @option [Numeric] :wait_time maximum time (in seconds) to wait for jobs when retrieving next batch. Default: 1s
         | 
| 14 | 
            +
              def initialize(disque, queues: [Disquo::DEFAULT_QUEUE], concurrency: 10, wait_time: 1)
         | 
| 16 15 | 
             
                @disque     = disque
         | 
| 17 16 | 
             
                @queues     = Array(queues)
         | 
| 18 17 | 
             
                @threads    = Concurrent::FixedThreadPool.new(concurrency)
         | 
| 18 | 
            +
                @busy       = Concurrent::AtomicFixnum.new
         | 
| 19 19 | 
             
                @wait_time  = wait_time
         | 
| 20 | 
            -
                @wait_count = wait_count
         | 
| 21 20 | 
             
              end
         | 
| 22 21 |  | 
| 23 22 | 
             
              # Run starts the worker
         | 
| 24 23 | 
             
              def run
         | 
| 25 | 
            -
                Disquo.logger.info " | 
| 24 | 
            +
                Disquo.logger.info "Worker starting - queues: #{queues.inspect}, concurrency: #{@threads.max_length}"
         | 
| 26 25 |  | 
| 27 26 | 
             
                begin
         | 
| 28 27 | 
             
                  run_cycle
         | 
| @@ -30,14 +29,14 @@ class Disquo::Worker | |
| 30 29 | 
             
                  handle_exception(e)
         | 
| 31 30 | 
             
                end until @stopped
         | 
| 32 31 |  | 
| 32 | 
            +
                Disquo.logger.info "Worker shutting down"
         | 
| 33 33 | 
             
                @threads.shutdown
         | 
| 34 34 | 
             
              end
         | 
| 35 35 |  | 
| 36 36 | 
             
              # Blocks until worker is stopped
         | 
| 37 37 | 
             
              def wait(timeout = nil)
         | 
| 38 | 
            -
                Disquo.logger.info "Waiting for worker shutdown"
         | 
| 39 38 | 
             
                @threads.wait_for_termination(timeout)
         | 
| 40 | 
            -
                Disquo.logger.info " | 
| 39 | 
            +
                Disquo.logger.info "Worker shutdown complete"
         | 
| 41 40 | 
             
              end
         | 
| 42 41 |  | 
| 43 42 | 
             
              # Stops the worker
         | 
| @@ -50,57 +49,69 @@ class Disquo::Worker | |
| 50 49 | 
             
              private
         | 
| 51 50 |  | 
| 52 51 | 
             
                def run_cycle
         | 
| 53 | 
            -
                  jobs = next_batch
         | 
| 54 | 
            -
             | 
| 52 | 
            +
                  jobs = Array(next_batch)
         | 
| 55 53 | 
             
                  until @stopped || jobs.empty?
         | 
| 56 54 | 
             
                    job = jobs.shift
         | 
| 57 | 
            -
                     | 
| 55 | 
            +
                    schedule(*job)
         | 
| 58 56 | 
             
                  end
         | 
| 59 57 | 
             
                ensure
         | 
| 60 58 | 
             
                  requeue(jobs) unless jobs.nil? || jobs.empty?
         | 
| 61 59 | 
             
                end
         | 
| 62 60 |  | 
| 63 61 | 
             
                def next_batch
         | 
| 62 | 
            +
                  count = @threads.max_length - @busy.value
         | 
| 63 | 
            +
                  if count < 1
         | 
| 64 | 
            +
                    sleep(wait_time.fdiv(2))
         | 
| 65 | 
            +
                    return
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 64 68 | 
             
                  jobs = disque.with do |cn|
         | 
| 65 | 
            -
                    cn.fetch from: queues, timeout: (wait_time*1000).to_i, count:  | 
| 69 | 
            +
                    cn.fetch from: queues, timeout: (wait_time*1000).to_i, count: count
         | 
| 66 70 | 
             
                  end
         | 
| 71 | 
            +
             | 
| 67 72 | 
             
                  @is_down = nil
         | 
| 68 | 
            -
                   | 
| 69 | 
            -
                rescue => e
         | 
| 70 | 
            -
                   | 
| 71 | 
            -
             | 
| 72 | 
            -
                    handle_exception(e, message: 'Error retrieving jobs:')
         | 
| 73 | 
            -
                  end
         | 
| 74 | 
            -
                  sleep(1)
         | 
| 75 | 
            -
                  []
         | 
| 73 | 
            +
                  jobs
         | 
| 74 | 
            +
                rescue Errno::ECONNREFUSED => e
         | 
| 75 | 
            +
                  handle_disque_exception e, message: "Failed to retrieve jobs:", notrace: true
         | 
| 76 | 
            +
                  nil
         | 
| 76 77 | 
             
                end
         | 
| 77 78 |  | 
| 78 | 
            -
                def  | 
| 79 | 
            +
                def schedule(queue, job_id, payload)
         | 
| 80 | 
            +
                  @busy.increment
         | 
| 79 81 | 
             
                  @threads.post do
         | 
| 80 | 
            -
                    thread_id = Thread.current.object_id.to_s(36)
         | 
| 81 | 
            -
                    Disquo.logger.info { "Process #{payload} - thread: #{thread_id}, job: #{job_id}" }
         | 
| 82 | 
            -
             | 
| 83 82 | 
             
                    begin
         | 
| 84 | 
            -
                       | 
| 85 | 
            -
             | 
| 86 | 
            -
                       | 
| 87 | 
            -
                      job.disque = disque
         | 
| 88 | 
            -
                      job.queue  = queue
         | 
| 89 | 
            -
                      job.job_id = job_id
         | 
| 90 | 
            -
                      job.perform(*args)
         | 
| 91 | 
            -
                    rescue => e
         | 
| 92 | 
            -
                      handle_exception e, message: "Error processing #{payload} - thread: #{thread_id}, job: #{job_id}:"
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                      disque.with {|cn| cn.call :nack, job_id }
         | 
| 95 | 
            -
                      return
         | 
| 83 | 
            +
                      perform(queue, job_id, payload)
         | 
| 84 | 
            +
                    ensure
         | 
| 85 | 
            +
                      @busy.decrement
         | 
| 96 86 | 
             
                    end
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
                end
         | 
| 97 89 |  | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                     | 
| 90 | 
            +
                def perform(queue, job_id, payload)
         | 
| 91 | 
            +
                  thread_id = Thread.current.object_id.to_s(36)
         | 
| 92 | 
            +
                  Disquo.logger.info { "Process #{payload} - thread: #{thread_id}, job: #{job_id}" }
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  begin
         | 
| 95 | 
            +
                    class_name, args = Disquo.load_job(payload)
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                    job = Object.const_get(class_name).new
         | 
| 98 | 
            +
                    job.disque = disque
         | 
| 99 | 
            +
                    job.queue  = queue
         | 
| 100 | 
            +
                    job.job_id = job_id
         | 
| 101 | 
            +
                    job.perform(*args)
         | 
| 102 | 
            +
                  rescue => e
         | 
| 103 | 
            +
                    handle_exception e, message: "Error processing #{payload} - thread: #{thread_id}, job: #{job_id}:"
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                    disque.with {|cn| cn.call :nack, job_id }
         | 
| 106 | 
            +
                    return
         | 
| 107 | 
            +
                  end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  begin
         | 
| 110 | 
            +
                    disque.with {|cn| cn.call :ackjob, job_id }
         | 
| 111 | 
            +
                    @is_down = nil
         | 
| 112 | 
            +
                  rescue Errno::ECONNREFUSED => e
         | 
| 113 | 
            +
                    handle_disque_exception e, message: "Failed to ACK job #{job_id}:", notrace: true
         | 
| 114 | 
            +
                    retry unless @stopped
         | 
| 104 115 | 
             
                  end
         | 
| 105 116 | 
             
                end
         | 
| 106 117 |  | 
| @@ -109,11 +120,19 @@ class Disquo::Worker | |
| 109 120 | 
             
                  disque.with {|cn| cn.call :enqueue, *ids }
         | 
| 110 121 | 
             
                end
         | 
| 111 122 |  | 
| 123 | 
            +
                def handle_disque_exception(e, opts = {})
         | 
| 124 | 
            +
                  if !@is_down
         | 
| 125 | 
            +
                    @is_down = true
         | 
| 126 | 
            +
                    handle_exception(e, opts)
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                  sleep(1)
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
             | 
| 112 131 | 
             
                def handle_exception(e, opts = {})
         | 
| 113 132 | 
             
                  lines = [
         | 
| 114 133 | 
             
                    opts[:message],
         | 
| 115 134 | 
             
                    "#{e.class.name}: #{e.message}",
         | 
| 116 | 
            -
                    e.backtrace
         | 
| 135 | 
            +
                    (opts[:notrace] ? nil : e.backtrace),
         | 
| 117 136 | 
             
                  ].compact.flatten
         | 
| 118 137 |  | 
| 119 138 | 
             
                  Disquo.logger.error lines.join("\n")
         | 
    
        data/spec/disquo/worker_spec.rb
    CHANGED
    
    | @@ -3,11 +3,12 @@ require 'spec_helper' | |
| 3 3 | 
             
            RSpec.describe Disquo::Worker do
         | 
| 4 4 |  | 
| 5 5 | 
             
              subject do
         | 
| 6 | 
            -
                described_class.new Disquo.connect, wait_time: 0.1,  | 
| 6 | 
            +
                described_class.new Disquo.connect, wait_time: 0.1, queues: Disquo::TEST::QUEUE
         | 
| 7 7 | 
             
              end
         | 
| 8 8 |  | 
| 9 9 | 
             
              it "should run/process/shutdown" do
         | 
| 10 10 | 
             
                runner = Thread.new { subject.run }
         | 
| 11 | 
            +
                runner.abort_on_exception = true
         | 
| 11 12 |  | 
| 12 13 | 
             
                # seed 200 jobs
         | 
| 13 14 | 
             
                200.times {|n| TestJob.enqueue(n) }
         | 
| @@ -33,12 +34,13 @@ RSpec.describe Disquo::Worker do | |
| 33 34 | 
             
                  queue: "__disquo_test__",
         | 
| 34 35 | 
             
                )
         | 
| 35 36 | 
             
                expect(Disquo::TEST::PERFORMED.last[:job_id]).to match(/^D\w+/)
         | 
| 37 | 
            +
                expect(Disquo::TEST::PERFORMED.map {|e| e[:args].first }).to match_array(0..199)
         | 
| 36 38 | 
             
              end
         | 
| 37 39 |  | 
| 38 40 | 
             
              def wait_for
         | 
| 39 41 | 
             
                20.times do
         | 
| 40 42 | 
             
                  break if yield
         | 
| 41 | 
            -
                  sleep(0. | 
| 43 | 
            +
                  sleep(0.1)
         | 
| 42 44 | 
             
                end
         | 
| 43 45 | 
             
              end
         | 
| 44 46 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: disquo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.3. | 
| 4 | 
            +
              version: 0.3.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Dimitrij Denissenko
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2017-11- | 
| 11 | 
            +
            date: 2017-11-24 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: disque
         | 
| @@ -87,6 +87,7 @@ executables: | |
| 87 87 | 
             
            extensions: []
         | 
| 88 88 | 
             
            extra_rdoc_files: []
         | 
| 89 89 | 
             
            files:
         | 
| 90 | 
            +
            - ".gitignore"
         | 
| 90 91 | 
             
            - ".travis.yml"
         | 
| 91 92 | 
             
            - Gemfile
         | 
| 92 93 | 
             
            - Gemfile.lock
         |