fix: transaction cannot be rolled back because it has been finished with state: rollback

(cherry picked from commit 6dacec4158103fd165ec2865ea87ed9d3d4ceaa4)
This commit is contained in:
chenos 2022-09-19 21:03:06 +08:00
parent a645dbf5fd
commit c47f501756

View File

@ -6,7 +6,7 @@ import {
HasOne, HasOne,
Hookable, Hookable,
ModelCtor, ModelCtor,
Transactionable, Transactionable
} from 'sequelize'; } from 'sequelize';
import { Model } from './model'; import { Model } from './model';
import { UpdateGuard } from './update-guard'; import { UpdateGuard } from './update-guard';
@ -130,37 +130,44 @@ export async function updateAssociations(instance: Model, values: any, options:
const keys = Object.keys(values); const keys = Object.keys(values);
for (const key of Object.keys(modelAssociations(instance))) { try {
if (keys.includes(key)) { for (const key of Object.keys(modelAssociations(instance))) {
await updateAssociation(instance, key, values[key], { if (keys.includes(key)) {
...options, await updateAssociation(instance, key, values[key], {
transaction, ...options,
}); transaction,
});
}
} }
}
// update through table values // update through table values
for (const belongsToMany of belongsToManyAssociations(instance)) { for (const belongsToMany of belongsToManyAssociations(instance)) {
// @ts-ignore // @ts-ignore
const throughModel = belongsToMany.through.model; const throughModel = belongsToMany.through.model;
const throughModelName = throughModel.name; const throughModelName = throughModel.name;
if (values[throughModelName] && options.sourceModel) { if (values[throughModelName] && options.sourceModel) {
const where = { const where = {
[belongsToMany.foreignKey]: instance.get(belongsToMany.sourceKey), [belongsToMany.foreignKey]: instance.get(belongsToMany.sourceKey),
[belongsToMany.otherKey]: options.sourceModel.get(belongsToMany.targetKey), [belongsToMany.otherKey]: options.sourceModel.get(belongsToMany.targetKey),
}; };
await throughModel.update(values[throughModel.name], { await throughModel.update(values[throughModel.name], {
where, where,
context: options.context, context: options.context,
transaction, transaction,
}); });
}
} }
}
if (newTransaction) { if (newTransaction) {
await transaction.commit(); await transaction.commit();
}
} catch (error) {
if (newTransaction) {
await transaction.rollback();
}
throw error;
} }
} }
@ -251,7 +258,7 @@ export async function updateSingleAssociation(
return false; return false;
} }
const { context, updateAssociationValues = [], transaction = await model.sequelize.transaction() } = options; const { context, updateAssociationValues = [], transaction } = options;
const keys = getKeysByPrefix(updateAssociationValues, key); const keys = getKeysByPrefix(updateAssociationValues, key);
try { try {
@ -261,9 +268,6 @@ export async function updateSingleAssociation(
const removeAssociation = async () => { const removeAssociation = async () => {
await model[setAccessor](null, { transaction }); await model[setAccessor](null, { transaction });
model.setDataValue(key, null); model.setDataValue(key, null);
if (!options.transaction) {
await transaction.commit();
}
return true; return true;
}; };
@ -273,19 +277,12 @@ export async function updateSingleAssociation(
if (isStringOrNumber(value)) { if (isStringOrNumber(value)) {
await model[setAccessor](value, { context, transaction }); await model[setAccessor](value, { context, transaction });
if (!options.transaction) {
await transaction.commit();
}
return true; return true;
} }
if (value instanceof Model) { if (value instanceof Model) {
await model[setAccessor](value, { context, transaction }); await model[setAccessor](value, { context, transaction });
model.setDataValue(key, value); model.setDataValue(key, value);
if (!options.transaction) {
await transaction.commit();
}
return true; return true;
} }
@ -323,9 +320,6 @@ export async function updateSingleAssociation(
updateAssociationValues: keys, updateAssociationValues: keys,
}); });
model.setDataValue(key, instance); model.setDataValue(key, instance);
if (!options.transaction) {
await transaction.commit();
}
return true; return true;
} }
} }
@ -342,13 +336,7 @@ export async function updateSingleAssociation(
if (association.targetKey) { if (association.targetKey) {
model.setDataValue(association.foreignKey, instance[dataKey]); model.setDataValue(association.foreignKey, instance[dataKey]);
} }
if (!options.transaction) {
await transaction.commit();
}
} catch (error) { } catch (error) {
if (!options.transaction) {
await transaction.rollback();
}
throw error; throw error;
} }
} }
@ -376,7 +364,7 @@ export async function updateMultipleAssociation(
return false; return false;
} }
const { context, updateAssociationValues = [], transaction = await model.sequelize.transaction() } = options; const { context, updateAssociationValues = [], transaction } = options;
const keys = getKeysByPrefix(updateAssociationValues, key); const keys = getKeysByPrefix(updateAssociationValues, key);
try { try {
@ -467,11 +455,7 @@ export async function updateMultipleAssociation(
} }
model.setDataValue(key, list1.concat(list3)); model.setDataValue(key, list1.concat(list3));
if (!options.transaction) {
await transaction.commit();
}
} catch (error) { } catch (error) {
await transaction.rollback();
throw error; throw error;
} }
} }