Выполнить откат транзакции до указанной c точки сохранения - PullRequest
0 голосов
/ 27 мая 2020

Я использую управляемые транзакции в своем проекте, и у меня есть случай, когда я хотел бы использовать одну транзакцию и выполнить откат до указанной c точки сохранения в случае сбоя, но всегда фиксировать в конец.

Например, я хочу создать Event и попытаться запустить action. Если action не удается, я хочу отменить любую активность базы данных, которая произошла во время действия, но сохранить запись Event и впоследствии обновить ее результатом.

const transaction = await sequelize.transaction();

const event = await Event.create({ ... }, { transaction });

// I want to mark the savepoint here

try {
  const action = await runAction(transaction);
  event.status = 'success';
  event.action_id = action.id;
} catch (err) {
  // This is where I want to rollback any changes since the savepoint
  event.status = 'failure';
  event.failure_message = err.message;
}

await event.save({ transaction });
await transaction.commit();

Насколько я понимаю, я должен иметь возможность достичь этого, создав новую транзакцию с существующей, эффективно пометив точку сохранения:

const transaction = await sequelize.transaction();

const event = await Event.create({ ... }, { transaction });

const savepoint = await sequelize.transaction({ transaction });

try {
  const action = await runAction(savepoint);
  ...
} catch (err) {
  await savepoint.rollback();
  ...
}

await event.save({ transaction });
await transaction.commit();

Однако это не работает, и все операции, использующие транзакцию в runAction, по-прежнему фиксируются . Есть ли способ добиться этого?

1 Ответ

0 голосов
/ 27 мая 2020

Я понял, что у меня вызывается findOrCreate внутри runAction. Sequelize создает точки сохранения в findOrCreate , если в параметрах указана транзакция.

При создании новой транзакции и предоставлении транзакции в параметрах автоматически создается точка сохранения , как показано здесь . Этой точке сохранения присваивается идентификатор (который основан на индексе новой точки сохранения в родительском элементе), и выполняется запрос базы данных для установки точки сохранения в транзакции. Итак, когда я запустил sequelize.transaction({ transaction });, он создал точку сохранения с именем «transaction-id-1». Позже, когда вызывается findOrCreate и предоставляется транзакция «savepoint», он создает точку сохранения с тем же именем «transaction-id-1», эффективно перезаписывая предыдущую точку сохранения.

Итак, я должен был передать родительскую транзакцию на runAction, а не на savepoint:

const transaction = await sequelize.transaction();

const event = await Event.create({ ... }, { transaction });

const savepoint = await sequelize.transaction({ transaction });

try {
  // Pass parent transaction, rather savepoint transaction
  const action = await runAction(transaction);
  ...
} catch (err) {
  await savepoint.rollback();
  ...
}

await event.save({ transaction });
await transaction.commit();
...