Реализация рабочей очереди в postresql
Я хочу сделать постоянную очередь заданий в postgresql. Так что несколько работников могут выбрать одну работу из очереди (используя select for update
с skip locked
), обработайте его и затем удалите из очереди. У меня есть стол:
create table queue (
id serial primary key
some_job_param1 text not null
some_job_param2 text not null
)
Теперь, если есть две работы, то это работает нормально:
worker1
начинает транзакцию и выбирает первую работу
begin;
select * from queue for update skip locked limit 1;
начинает обработку. worker2
делает то же самое и выбирает вторую работу с тем же запросом.
После worker1
выполняет свою работу, удаляет ее из очереди и фиксирует транзакцию:
delete from queue where id=$1;
commit;
Тогда worker1
готов к новой работе, поэтому он делает то же самое. Начинает новую транзакцию, выбирает для работы, которая не заблокирована. Но проблема в том, что рабочих мест больше нет, запрос возвращает ноль строк.
Идеально было бы, если бы запрос блокировался до тех пор, пока не появится новое задание, и он вернет результат. Это как-то возможно? Или я иду в неправильном направлении?
РЕДАКТИРОВАТЬ:
рабочие - это внешний процесс. Таким образом, если работник умер, сеанс умирает, и транзакция также. Тогда выбранная работа больше не будет заблокирована и готова для другого работника. Псевдокод будет выглядеть так:
while (true) {
tx = db.new_transaction()
job_id, param1, param2 = tx.query("select * from queue for update skip locked limit 1")
try {
some_long_processing(param1, param2)
tx.commit()
} catch {
tx.rollback()
}
}