Question:
So guys, I have a transaction to persist several data in different tables in my database, if by chance a record goes wrong I need it to rollback, after all I depend on the return of one's id to make the persistence of another one, moreover I can't let some tables be persisted and others not. The problem is that my rollback isn't working, I have some methods, they have a Promise so if there's an error, it rejects and in my view it would fall to the runQuery method's catch, then there's a rollback and this rollback to me it would undo the operations, the problem is that the errors are not falling there, and in this case the errors I am generating are several just for testing.
async run(data: any) {
try {
const response = await this.runQuery(data);
return 'response';
} catch (err) {
throw err;
}}
async runQuery(data: any) {
try{
connection.beginTransaction();
data[2].post.Ordem_servico = await this.insertGenericReturn(data[0]);
await this.insertEpisOrder(data[6], data[2].post.Ordem_servico);
data[5].post.Equipamento_FK = await this.insertGenericReturn(data[2]);
data[3].post.Ordem_Servico = data[2].post.Ordem_servico;
data[5].post.Locais_FK = await this.insertGenericReturn(data[3]);
let listOperations : any = await this.insertOperationsOrder(data[4]);
for (const element of listOperations) {
data[5].post.Operacao_FK = element;
await this.insertGenericReturn(data[5]);
}
connection.commit();
return { result: 'Ordem de serviço criada!' }
} catch (err) {
console.log('err runTransaction :>> ', err);
await connection.rollback();
throw err;
}}
private async insertGenericReturn(data: any) {
try {
return new Promise((resolve, reject) => {
connection.query(data.query, data.post, async (err: any, result: any) =>{
if (err) reject({ status: 401, msg: 'Não foi possível realizar a operação!', ...err })
resolve(result.insertId);
});
});
} catch (err) {
throw err;
}}
private async insertEpisOrder(data: any, order: any) {
try {
return new Promise((resolve, reject) => {
for (let index = 0; index < data.post.length; index++) {
data.post[index].ordemServico_idOrdemServico = order;
}
for (const epi of data.post) {
connection.query(data.query, epi, async (err: any, result: any) =>{
if (err) reject({ status: 401, msg: 'Não foi possível realizar a operação!', ...err })
resolve('EPIs cadastrados');
});
}
});
} catch (err) {
throw err;
}}
private async insertOperationsOrder(data: any) {
try {
return new Promise((resolve, reject) => {
let listOperations: any = [];
let response: any;
for (const item of data.post) {
connection.query(data.query, item, async (err: any, result: any) =>{
if (err) reject({ status: 401, msg: 'Não foi possível realizar a operação!', ...err })
listOperations.push(result.insertId);
resolve(listOperations);
});
}
});
} catch (err) {
throw err;
}}
Does anyone have any idea why I wouldn't be going to my rollback? type it goes to those insertion methods but I don't return to the runQuery catch that has the rollback, if you can help I appreciate it!
Answer:
Guys, I decided here and I'll share the resolution, maybe it's useful for someone:
I added a handle in catch the method is this
private getQueryError(err: any): { status: number, err: string } {
const error = Object.assign({}, err);
if (_.has(error, 'code')) return { status: 400, err: 'Não foi possível concluir a operação!' };
if (error.code === 'ER_DUP_ENTRY') return { status: 400, err: 'item já cadastrado!' };
return { status: 400, err: _.get(error, 'message', 'Não foi possível concluir a operação!') }}
And obviously I added calls to this method in my catch in this case:
const error = this.getQueryError(err);
Anyway, I hope it can help someone who is having this difficulty or who is working with transactions.