Я борюсь с блокировкой таблицы PostgreSQL, над которой я работаю. В идеале я хочу заблокировать всю таблицу, но отдельные строки будут работать до тех пор, пока они действительно работают.
У меня есть несколько одновременных сценариев ruby, которые все запрашивают центральную базу данных заданий в AWS (через класс DatabaseAccessor
), находят работу, которая еще не была запущена, меняют статус на started
и выполняют ее. Проблема в том, что, поскольку все они запускаются одновременно, они, как правило, все сразу находят одну и ту же незапущенную работу и начинают ее выполнять, тратя время и запутывая результаты.
Я пробовал кучу вещей, .lock
, .transaction
, драгоценный камень fatalistic
, но они, похоже, не работают, по крайней мере, не в pry.
Мой код выглядит следующим образом:
class DatabaseAccessor
require 'pg'
require 'pry'
require 'active_record'
class Jobs < ActiveRecord::Base
enum status: [ :unstarted, :started, :slow, :completed]
end
def initialize(db_credentials)
ActiveRecord::Base.establish_connection(
adapter: db_credentials[:adapter],
database: db_credentials[:database],
username: db_credentials[:username],
password: db_credentials[:password],
host: db_credentials[:host]
)
end
def find_unstarted_job
job = Jobs.where(status: 0).limit(1)
job.started!
job
end
end
У кого-нибудь есть предложения?
РЕДАКТИРОВАТЬ : Кажется, что LOCK TABLE jobs IN ACCESS EXCLUSIVE MODE;
является способом сделать это - однако я борюсь с тем, чтобы потом вернуть результаты этого после обновления. RETURNING *
вернет результаты после обновления, но не внутри транзакции.