Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save petrokoriakin/0c8a1cbeacb45db1949d3e485c14fc0d to your computer and use it in GitHub Desktop.
Save petrokoriakin/0c8a1cbeacb45db1949d3e485c14fc0d to your computer and use it in GitHub Desktop.
resque uniq - another interesting task
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