If there’s a queue of work todo in a table that is going to be periodically polled by a number of different worker clients…what’s the best way to prevent each worker from getting the same item to work on?
Say a table like: ItemId, LastAttemptDateTime, AttemptCount, and various item details.
Given an index on LastAttemptDateTime and sorted in ascending order and various clients are querying the table to grab an item to be worked on.
I use a stored procedure in MS SQL to do this…something like:
CREATE PROCEDURE GetNextQueueItem AS
SET NOCOUNT ON
DECLARE @ItemId INT
UPDATE myqueue SET @ItemId=ItemId, AttemptCount=AttemptCount+1, LastAttemptDateTime=GetDate()
WHERE ItemId=(SELECT TOP 1 ItemId
FROM myqueue
ORDER BY LastAttemptDateTime ASC)
SELECT ItemId, AttemptCount, and various item detail fields
FROM myqueue
WHERE ItemId = @ItemId
I’m fairly new to PostgreSQL and was wondering if there’s alternate approaches available. (The TOP 1 will change to LIMIT 1.)
PostgreSQL equivalent could look like this:
Major points
You only need 1 statement to do it all.
UPDATEcan return the updated row in the same command with theRETURNINGclause.State of the row is post-update. There is ways to get the pre-update state if needed.
No need for any variables.
I changed all identifiers to lower case, which is the cleanest style in PostgreSQL.
I renamed your column
LastAttemptDateTimetolast_attempt_tsts .. for “timestamp”, because that’s the name of the timestamp / datetime type in Postgres.
As you mentioned yourself,
LIMIT 1instead ofTOP 1.I use
RETURNS SETOF myqueueas return type.myqueueis the associated row-type of the tablemyqueue– for every table or view a row-type of the same name is automatically created in PostgreSQL.This declaration allows for multiple rows to be returned, but
LIMIT 1guarantees that it will only ever be one.This return type allows for RETURN QUERY to return the resulting row directly without any intermediate step. Fast, clean.
Actually, you don’t need a plpgsql function at all. You can do it with a simple SQL statement: