From ab22aa46e1f1be42c4d4dbaad9887acb35ffefd3 Mon Sep 17 00:00:00 2001 From: Corey Alexander Date: Mon, 3 May 2021 16:19:14 -0400 Subject: [PATCH] Add `SKIP LOCKED` clause to DJ Pickup Query This changes the optimized Postgres strategy to use the `SKIP LOCKED` locking clause. This is 'new' in Postgres 9.5, but thats pretty old for us. What it does is change the locking behavior in this sub-query to do the pickup. Before it would wait behind other locks, meaning that the more workers were competing for jobs, the more locks were occuring. This way new queries will just skip locked rows, and pick up the 'next' available job! --- lib/delayed/backend/active_record.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/delayed/backend/active_record.rb b/lib/delayed/backend/active_record.rb index 62b186a1..01a61c63 100644 --- a/lib/delayed/backend/active_record.rb +++ b/lib/delayed/backend/active_record.rb @@ -130,7 +130,7 @@ def self.reserve_with_scope_using_optimized_postgres(ready_scope, worker, now) # SQL for Postgres if we use a .limit() filter, but it would not # use 'FOR UPDATE' and we would have many locking conflicts quoted_name = connection.quote_table_name(table_name) - subquery = ready_scope.limit(1).lock(true).select("id").to_sql + subquery = ready_scope.limit(1).lock('FOR UPDATE SKIP LOCKED').select("id").to_sql sql = "UPDATE #{quoted_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery}) RETURNING *" reserved = find_by_sql([sql, now, worker.name]) reserved[0]