Skip to content

Avoid deadlock when creating ready execution #229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/models/solid_queue/ready_execution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def lock_candidates(job_ids, process_id)
return [] if job_ids.none?

SolidQueue::ClaimedExecution.claiming(job_ids, process_id) do |claimed|
where(job_id: claimed.pluck(:job_id)).delete_all
where(id: where(job_id: claimed.pluck(:job_id)).pluck(:id)).delete_all
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only problem with this one is that it introduces another query in the hot path... it's probably ok, but I think we could save it because we've already done a query to ready_executions before, where we select only the job_id. We could select id, job_id, and then filter in memory for the ones that were actually claimed. Let me see how it'd look.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I had in mind:

diff --git a/app/models/solid_queue/claimed_execution.rb b/app/models/solid_queue/claimed_execution.rb
index f2ed58d..c67c62a 100644
--- a/app/models/solid_queue/claimed_execution.rb
+++ b/app/models/solid_queue/claimed_execution.rb
@@ -15,7 +15,7 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution

       insert_all!(job_data)
       where(job_id: job_ids, process_id: process_id).load.tap do |claimed|
-        block.call(claimed)
+        block.call(claimed.map(&:job_id))
       end
     end

diff --git a/app/models/solid_queue/ready_execution.rb b/app/models/solid_queue/ready_execution.rb
index 8eeaddc..2c68cf9 100644
--- a/app/models/solid_queue/ready_execution.rb
+++ b/app/models/solid_queue/ready_execution.rb
@@ -24,20 +24,21 @@ module SolidQueue
           return [] if limit <= 0

           transaction do
-            job_ids = select_candidates(queue_relation, limit)
-            lock_candidates(job_ids, process_id)
+            candidates = select_candidates(queue_relation, limit)
+            lock_candidates(candidates, process_id)
           end
         end

         def select_candidates(queue_relation, limit)
-          queue_relation.ordered.limit(limit).non_blocking_lock.pluck(:job_id)
+          queue_relation.ordered.limit(limit).non_blocking_lock.select(:id, :job_id)
         end

-        def lock_candidates(job_ids, process_id)
-          return [] if job_ids.none?
+        def lock_candidates(executions, process_id)
+          return [] if executions.none?

-          SolidQueue::ClaimedExecution.claiming(job_ids, process_id) do |claimed|
-            where(job_id: claimed.pluck(:job_id)).delete_all
+          SolidQueue::ClaimedExecution.claiming(executions.map(&:job_id), process_id) do |claimed_job_ids|
+            ids_to_delete = executions.index_by(&:job_id).values_at(*claimed_job_ids).map(&:id)
+            where(id: ids_to_delete).delete_all
           end
         end

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @rosa . Thank you for your response.

The solution is good for me. It's more efficient.

Will the fix be included in the next release version?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Let me add that one and get a new version out.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

end
end

Expand Down
Loading