транзакции node-postgres с обратными вызовами или асинхронными/ожидающими?

Я использую Node 7.6.0, который поддерживает async/await. Клиентский пул node-postgres поддерживает async/await и имеет хороший пример здесь. Однако в примере для транзакций в node-postgres (здесь) используются обратные вызовы вместо асинхронно/ожидание. Несмотря на этот пример, я решил попробовать транзакции с async/await в быстром тесте:

let client = null;

try {
    client = await this.pool.connect();
} catch (error) {
    console.log('A client pool error occurred:', error);
    return error;
}

try {
    await client.query('BEGIN');
    await client.query('UPDATE foo SET bar = 1');
    await client.query('UPDATE bar SET foo = 2');
    await client.query('COMMIT');
} catch (error) {
    try {
        await client.query('ROLLBACK');
    } catch (rollbackError) {
        console.log('A rollback error occurred:', rollbackError);
    }
    console.log('An error occurred:', error);
    return error;
} finally {
    client.release();
}

return 'Success!';

Кажется, это работает просто отлично, но мне сказал участник node-postgres что это плохая идея. К сожалению, он не стал объяснять, почему это плохая идея, — он просто сказал искать ответ на Stack Overflow.

Почему плохая идея выполнять транзакции с помощью async/await вместо обратных вызовов в node-postgres?


person Rob Johansen    schedule 11.04.2017    source источник
comment
Неплохая идея, если вы переместите логику создания транзакции в другую функцию, а vitaly-t просто хочет использовать любой предлог для продвижения своей библиотеки. Игнорировать комментарий.   -  person Ry-♦    schedule 11.04.2017


Ответы (2)


Создатель node-postgres (brianc) любезно предоставил отличный ответ на мой первоначальный вопрос на GitHub. Короткий ответ: неплохо выполнять транзакции с async/await.

См. его полный ответ здесь: https://github.com/brianc/node-postgres/issues/1252#issuecomment-293899088

person Rob Johansen    schedule 14.04.2017

В дополнение к сообщению Роба Йохансена я хотел бы поделиться своим решением TypeScript:

import { PoolClient } from "pg"
import { pool } from "../database"

const tx = async (callback: (client: PoolClient) => void) => {
  const client = await pool.connect();

  try {
    await client.query('BEGIN')
    try {
      await callback(client)
      await client.query('COMMIT')
    } catch (e) {
      await client.query('ROLLBACK')
    }
  } finally {
    client.release()
  }
}

export { tx }

Применение:

let result;

await tx(async client => {
  const { rows } = await client.query<{ cnt: string }>('SELECT COUNT(*) AS cnt FROM users WHERE username = $1', [username]);
  result = parseInt(rows[0].cnt) > 0;
});
person Alex Herman    schedule 06.01.2021