Итак, у меня есть таблица «Готово», в которой хранятся ссылки на объекты S3, готовые к обработке. В моем приложении, которое использует эти данные и изменяет их, я хочу иметь возможность получить самый последний объект S3, если его соответствующий поставщик не используется или срок действия блокировки этого поставщика истек.
Моя структура таблицы выглядит следующим образом:
ключ (PK) | провайдер | метка времени (созданная в) | заблокирован | ехрх 1005 *
Я использую TypeORM, чтобы создать TRANSACTION, получить самую последнюю (неблокированную) ссылку на объект и обновить все остальные столбцы с этим провайдером, чтобы они также были заблокированы, чтобы мы случайно не потребляли два набора данных от того же провайдера.
Мой код выглядит так:
return getManager().transaction(async (entityManger) => {
const firstReady = await entityManger
.createQueryBuilder(Ready, 'ready')
.setLock('pessimistic_write')
.select()
.orderBy('timestamp')
.where('locked = false or exp < :now', { now: Date.now() })
.getOne();
if (!firstReady) return;
await entityManger
.createQueryBuilder(Ready, 'ready')
.update()
.set({ locked: true, exp: Date.now() + vars.PG.LOCK_EXP })
.where('provider = :provider', { provider: firstReady.provider })
.execute();
logger.debug(`Acquired lock on ${firstReady.provider} and S3 object key ${firstReady.key}`);
return firstReady.key;
});
Я обеспокоен тем, что, если по случайности два потребителя запросят два отдельных ряда у одного и того же провайдера практически в одно и то же время, у меня будет состояние гонки. Я рассмотрел возможность блокировки всей таблицы, когда один потребитель делает этот запрос, но мне интересно, есть ли лучший способ. Спасибо!