Эти операции блокировки являются исключительными для текущего сеанса соединения, поэтому они должны выполняться в одном и том же блоке транзакции:
await db.tx(async t => {
await t.func('pg_try_advisory_lock', [1]);
// execute all queries here, against 't' context;
// ...
await t.func('pg_advisory_unlock', [1]);
});
- Мы используем метод fun c здесь только для того, чтобы сократить синтаксис.
Это, однако, не выполнит разблокировку, если транзакция завершится неудачей, поэтому, если это вызывает проблемы, вам нужно будет вручную отлавливать ошибки внутри транзакции:
await db.tx(async t => {
await t.func('pg_try_advisory_lock', [1]);
let result, err;
try {
// execute all queries here, against 't' context;
// and set the 'result'...
} catch(e) {
err = e;
}
await t.func('pg_advisory_unlock', [1]);
if(e) {
throw e;
}
return result;
});
ОБНОВЛЕНИЕ
Я использую консультативную блокировку, потому что происходит много других вещей (не идемпотентных, не баз данных) вне этой одной транзакции базы данных, и поскольку запущено несколько экземпляров приложения, блокировка состоит в том, чтобы запретить другим экземплярам выполнять одну и ту же работу одновременно
Я не уверен, как это Тип блокировки может быть полезен для нескольких баз данных или даже для нескольких приложений, поскольку эти блокировки могут работать только в пределах одного сеанса.
Но если вам действительно необходимо выполнить эти блокировки вне В случае транзакции, но при том же соединении, вам нужно будет управлять соединением вручную:
// Somewhere in the beginning of your chain logic,
// you allocate a manually-managed connection:
const dbm = await db.connect();
// Then your lock happens:
await dbm.func('pg_try_advisory_lock', [1]);
// Then you transaction happens...
await dbm.tx(async t => {
// transaction queries
});
// Then your unlock query:
await dbm.func('pg_advisory_unlock', [1]);
// Then you release the connection:
dbm.done();
Вы просто должны быть осторожны с этим, чтобы не пропустить соединения;)