Реализация рабочей очереди в 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()
  }
}

0 ответов

Другие вопросы по тегам