Perform cheap thread find

If we process message that is not designated to us
previously we would fire a separate Thread for that.
We don't need to do it. We can cheaply check if thread
is available, if it is, we can perform expensive operation
then.
This commit is contained in:
Kamil Trzciński 2019-08-20 21:09:04 +02:00
parent c2cbfc5c4a
commit 3683d2d251
2 changed files with 17 additions and 12 deletions

View file

@ -110,11 +110,13 @@ module Gitlab
def process_job_cancel(jid)
return unless jid
# since this might take time, process cancel in a new thread
Thread.new do
find_thread(jid) do |thread|
next unless thread
# try to find thread without lock
return unless find_thread_unsafe(jid)
Thread.new do
# try to find a thread, but with guaranteed
# handle that this thread corresponds to actually running job
find_thread_with_lock(jid) do |thread|
Sidekiq.logger.warn(
class: self.class,
action: 'cancel',
@ -130,13 +132,18 @@ module Gitlab
# This method needs to be thread-safe
# This is why it passes thread in block,
# to ensure that we do process this thread
def find_thread(jid)
return unless jid
def find_thread_unsafe(jid)
jobs_thread[jid]
end
def find_thread_with_lock(jid)
# don't try to lock if we cannot find the thread
return unless find_thread_unsafe(jid)
jobs_mutex.synchronize do
thread = jobs_thread[jid]
yield(thread)
thread
find_thread_unsafe(jid).tap do |thread|
yield(thread) if thread
end
end
end

View file

@ -145,9 +145,7 @@ describe Gitlab::SidekiqMonitor do
context 'when jid is not found' do
it 'does not log cancellation message' do
expect(Sidekiq.logger).not_to receive(:warn)
expect(subject).to be_a(Thread)
subject.join
expect(subject).to be_nil
end
end