pkg/dbjobqueue: fix enqueue/dequeue race condition

Currently there is a race condition that occurs between the
dbjobqueue enqueue and dequeue functions. Both queries make
use of the postgres `now()` timestamp function which returns
the timestamp of when the transaction started and not when
the statement is executed. The result of this is a timestamp
for a job's `started_at` field to be earlier than its
`queued_at` field causing a constraint violation.

Since the dequeue query will never be executed before the
enqueue query, changing the postgres timestamp function to
`statement_timestamp()` resolves this issue.
This commit is contained in:
Gianluca Zuccarelli 2022-09-13 13:52:26 +01:00 committed by Ondřej Budai
parent 3d6256a89d
commit 5a4d22cc6d

View file

@ -28,10 +28,10 @@ const (
sqlListen = `LISTEN jobs` sqlListen = `LISTEN jobs`
sqlUnlisten = `UNLISTEN jobs` sqlUnlisten = `UNLISTEN jobs`
sqlEnqueue = `INSERT INTO jobs(id, type, args, queued_at, channel) VALUES ($1, $2, $3, NOW(), $4)` sqlEnqueue = `INSERT INTO jobs(id, type, args, queued_at, channel) VALUES ($1, $2, $3, statement_timestamp(), $4)`
sqlDequeue = ` sqlDequeue = `
UPDATE jobs UPDATE jobs
SET token = $1, started_at = now() SET token = $1, started_at = statement_timestamp()
WHERE id = ( WHERE id = (
SELECT id SELECT id
FROM ready_jobs FROM ready_jobs
@ -45,7 +45,7 @@ const (
sqlDequeueByID = ` sqlDequeueByID = `
UPDATE jobs UPDATE jobs
SET token = $1, started_at = now() SET token = $1, started_at = statement_timestamp()
WHERE id = ( WHERE id = (
SELECT id SELECT id
FROM ready_jobs FROM ready_jobs