Created
June 23, 2016 15:35
-
-
Save petrokoriakin/0c8a1cbeacb45db1949d3e485c14fc0d to your computer and use it in GitHub Desktop.
resque uniq - another interesting task
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'resque-loner' | |
class Jobs::Base | |
include Resque::Plugins::UniqueJob | |
@queue = :small_queue | |
class << self | |
def uniq?(*args) | |
@arguments = args | |
!already_working? | |
end | |
def already_working? | |
Resque::Worker. | |
working. | |
select { |w| match_queue?(w) && match_args?(w) }. | |
size > 1 | |
end | |
def match_queue?(worker) | |
worker.job['queue'] == @queue.to_s | |
end | |
def match_args?(worker) | |
if payload = worker.job.try(:[], 'payload') | |
payload.try(:[], 'class') == self.to_s && | |
payload.try(:[] , 'args') == @arguments | |
end | |
end | |
# def already_working? | |
# queue = @queue | |
# klass = self | |
# args = @arguments | |
# queue_workers = Resque::Worker.working.select { |worker| worker.job['queue'] == queue.to_s } | |
# workers = queue_workers.select do |worker| | |
# payload = worker.job.try(:[], 'payload') | |
# if payload.present? | |
# payload.try(:[], 'class') == klass.to_s && payload.try(:[] , 'args') == args | |
# else | |
# false | |
# end | |
# end | |
# workers.size > 1 | |
# end | |
def perform param | |
return false unless uniq?(param) | |
true | |
end | |
end | |
end | |
require 'spec_helper' | |
describe Jobs::Base do | |
subject { described_class } | |
it 'responds to .perform' do | |
subject.should respond_to :perform | |
end | |
it 'it goes to :small_queue by default' do | |
subject.instance_variable_get(:@queue).should == :small_queue | |
end | |
it 'responds to .already_working?' do | |
subject.should respond_to :already_working? | |
end | |
it 'responds to .loner_ttl' do | |
subject.should respond_to :loner_ttl | |
end | |
describe '.already_working?' do | |
subject { Jobs::Base.perform('some value') } | |
it 'checks if there are any workers' do | |
Resque::Worker.stub(:working).and_return([]) | |
subject.should be_true | |
end | |
it 'checks if there are workers with the same queue' do | |
mock_worker = double( | |
:worker, | |
:job => {'queue' => 'small_queue'} | |
) | |
Resque::Worker.stub(:working).and_return([mock_worker]) | |
subject.should be_true | |
end | |
it 'checks if matching workers have payload' do | |
mock_worker = double( | |
:worker, | |
:job => {'queue' => 'small_queue', 'payload' => {'class' => ZrTestReportWorker, 'args' => 'another value'}} | |
) | |
Resque::Worker.stub(:working).and_return([mock_worker]) | |
subject.should be_true | |
end | |
it 'checks if matching workers have all the things inside payload' do | |
payload = double(:payload) | |
job = double(:job) | |
worker = double(:worker) | |
Resque::Worker.stub(:working).and_return([worker, worker]) | |
worker.should_receive(:job).exactly(4).and_return(job) | |
job.should_receive(:[]).with('queue').twice.and_return('small_queue') | |
job.should_receive(:try).with(:[], 'payload').twice.and_return(payload) | |
payload.should_receive(:try).with(:[], 'class').twice.and_return('Jobs::Base') | |
payload.should_receive(:try).with(:[], 'args').twice.and_return(['some value']) | |
subject.should be_false | |
end | |
it 'knows if there is more then one matched worker' do | |
matched_worker = double( | |
:worker, | |
:job => {'queue' => 'small_queue', 'payload' => {'class' => 'Jobs::Base', 'args' => ['some value']}} | |
) | |
another_matched_worker = double( | |
:worker, | |
:job => {'queue' => 'small_queue', 'payload' => {'class' => 'Jobs::Base', 'args' => ['some value']}} | |
) | |
another_worker = double( | |
:worker, | |
:job => {'queue' => 'report_queue', 'payload' => {'class' => 'ZrTestReportWorker', 'args' => ['some value']}} | |
) | |
Resque::Worker.stub(:working).and_return([matched_worker, another_worker, another_matched_worker]) | |
subject.should be_false | |
end | |
it 'ignores similiar workers' do | |
matched_worker = double( | |
:worker, | |
:job => {'queue' => 'small_queue', 'payload' => {'class' => 'Jobs::Base', 'args' => ['some value']}} | |
) | |
worker = double( | |
:worker, | |
:job => {'queue' => 'small_queue', 'payload' => {'class' => 'Jobs::Base', 'args' => 'another value'}} | |
) | |
another_worker = double( | |
:worker, | |
:job => {'queue' => 'small_queue', 'payload' => {'class' => 'ZrTestReportWorker', 'args' => 'some value'}} | |
) | |
Resque::Worker.stub(:working).and_return([matched_worker, worker, another_worker]) | |
subject.should be_true | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment