promise - Exiting Loop with ACID Transactions with Knex SQL Query Builder & Bluebird in Node.js -


we're using knex sql query builder perform acid transaction in node , we're experiencing strange behavior while using loop knex. code below takes array of tables , conditionally performs insert or update. first table 'transactionheader' , processed first. then, rows in 'transactiondetail' table processed within overall transaction. new keys (rowids) accumulated in 'rowids' array.

problem: main problem seems impossible exit loop in processtransactiondetail() if there's error returned knex. neither throw nor return exit loop or function. means if there error processing transactiondetail continue process remaining rows before exiting.

    let rowids: any[] = [];      knex.transaction(function(trx) {          // process transactionheader         if (transactionheader.rowid) {              // update transactionheader             trx('transaction')                 .transacting(trx)                 .update(transactionheader)                 .where('rowid', transactionheader.rowid)                 .then(function(transactionrowid) {                     rowids.push({ table: 'transaction', rowid: transactionheader.rowid });                     // update transactiondetail rows.                     processtransactiondetail(transactionrowid, trx);                 })                 .catch(trx.rollback);          } else {              // insert transactionheader             trx('transaction')                 .transacting(trx)                 .insert(transactionheader, 'rowid')                 .then(function(transactionrowid) {                     rowids.push({ table: 'transaction', rowid: transactionrowid });                     // insert transactiondetail rows.                     processtransactiondetail(transactionrowid, trx);                 })                 .catch(trx.rollback);         }      }).then(function(inserts) {         console.log('success!', rowids)         callback(null, { success: true }, { data: rowids })         return;     }).catch(function(error) {         console.error('error', error);         callback(null, {             success: false,             message: error.message         }, { data: rowids })         return;     });      /*     * process transactiondetail rows.     */     function processtransactiondetail(transactionheaderrowid: number, trx) {          var promise: any;         let table: table;         let rowid: number;          (let = 1; < tablestoprocess.length; i++) {              table = tablestoprocess[i];             rowid = table.data[0].rowid;              // update             if (rowid) {                  (let row = 0; row < table.data.length; row++) {                      promise = knex(table.name)                         .transacting(trx)                         .update(table.data[row])                         .where('rowid', rowid)                         .then(function(rowid) {                                                             rowids.push({ table: table.name, rowid: rowid });                         .catch(function(error) {                                                              // --------------------------------                              // **problem**: there no way break loop                              // --------------------------------                              throw 'error';                              return;                              // --------------------------------                         })                  }               // insert             } else {                  (let row = 0; row < table.data.length; row++) {                      promise = knex(table.name)                         .transacting(trx)                         .insert(table.data[row])                         .then(function(rowid) {                             rowids.push({ table: table.name, rowid: rowid });                         })                         .catch(function(error) {                              // --------------------------------                              // **problem**: there no way break loop                              // --------------------------------                              throw 'error';                              return;                              // --------------------------------                         });                 }             }         }          promise.then(function(x) {             promise.then(trx.commit);         });     } 

updated: proper structure? not sure error handlers @ bottom needed.

    knex.transaction(function(trx) {          // update row         function updaterow(table, rowid, row) {             return knex(table.name)                 .transacting(trx)                 .update(row)                 .where('rowid', rowid)                 .then(function(rowid) {                      rowids.push({                         table: table.name,                         rowid: rowid                     });                 });         }          // insert row         function insertrow(table, rowid, row) {             return knex(table.name)                 .transacting(trx)                 .insert(row)                 .then(function(rowid) {                      rowids.push({                         table: table.name,                         rowid: rowid                     });                 });         }          // process tables         promise.mapseries(tablestoprocess, function(table) {              let rowid = table.data[0].rowid;              // choose right function apply rows             var fn = rowid ? updaterow : insertrow;              // fn needs table , rowid             fn = fn.bind(this, table, rowid);              // process rows             return promise.mapseries(table.data, fn)                 .then(function(result) {                      // result array knex promises result                     return result;                  }).catch(function(err) {                     console.log('an error happened');                     //trx.rollback();  // question: needed?                     throw err;     // there way                 });          }).then(function(result) {             console.log('success', result);             trx.commit();             // callback(null, { success: true }, { data: rowids })             // return;         }).catch(function(error) {             console.log('error', error);             trx.rollback();             callback(null, { success: false, message: error.message }, { data: rowids })         });      }).then(function(inserts) {         console.log('success!', rowids)         callback(null, { success: true }, { data: rowids })     }).catch(function(error) {         console.log('error', error);         callback(null, { success: false, message: error.message }, { data: rowids })     }); 

you're dealing promises have use way loop supporting them. there bluebird's mapseries() example:

var promise = require('bluebird');  function updaterow(table, rowid, row) {   return knex(table.name)     .transacting(trx)     .update(table.data[row])     .where('rowid', rowid)     .then(function(rowid) {       rowids.push({         table: table.name,         rowid: rowid       });     }); }  function insertrow(table, rowid, row) {   return knex(table.name)     .transacting(trx)     .insert(table.data[row])     .then(function(rowid) {       rowids.push({         table: table.name,         rowid: rowid       });     }); }  // if there error, iteration stop promise.mapseries(tablestoprocess, function(table) {   rowid = table.data[0].rowid;    // choose right function apply rows   var fn = rowid ? updaterow : insertrow;   // fn need table , rowid   fn = fn.bind(this, table, rowid);    // call fn each row   // if there error, iteration stop   return promise.mapseries(table.data, fn)     .then(function(result) {       // result array knex promises result       return result;     }).catch(function(err) {       console.log('an error happened');       trx.rollback();       throw err;     }); }).then(function(result) {   console.log('all good');   // can safely commit here   trx.commit(); }).catch(function(err) {   console.log('an error happened');   trx.rollback(); }); 

update

about questions:

knex.transaction(function (trx) {     // update row     function updaterow(table, rowid, row) {         return knex(table.name)             .transacting(trx)             .update(row)             .where('rowid', rowid)             .then(function (rowid) {                 rowids.push({                     table: table.name,                     rowid: rowid                 });             });     }      // insert row     function insertrow(table, rowid, row) {         return knex(table.name)             .transacting(trx)             .insert(row)             .then(function (rowid) {                 rowids.push({                     table: table.name,                     rowid: rowid                 });             });     }      // need return here 'then(function (inserts)' , catch work     // process tables     return promise.mapseries(tablestoprocess, function (table) {         let rowid = table.data[0].rowid;          // choose right function apply rows         var fn = rowid ? updaterow : insertrow;          // fn needs table , rowid         fn = fn.bind(this, table, rowid);          // process rows         // if don't special in , catch, can remove them         return promise.mapseries(table.data, fn)             .then(function (result) {                 // result array knex promises result                 return result;             }).catch(function (err) {                 // catch not necessary,                 // can remove don't need here                 console.log('an error happened');                 //trx.rollback();  // question: needed? << // no, mistake, rollback done on other catch                 throw err;     // there way             });     }).then(function (result) {         console.log('success', result);         trx.commit();         return result;         // callback(null, { success: true }, { data: rowids })         // return;     }).catch(function (error) {         console.log('error', error);         trx.rollback();         throw error; // rethrow error when chain, if don't, it's promise resolved (ok)          // below         // callback(null, { success: false, message: error.message }, { data: rowids });     }); }).then(function (inserts) {     console.log('success!', rowids)     callback(null, { success: true }, { data: rowids }) }).catch(function (error) {     console.log('error', error);     callback(null, { success: false, message: error.message }, { data: rowids }) }); 

the 2 , 2 catch @ bottom merged. also, why there callback? it's better not mix promises , callbacks unless can't avoid it.


Comments

Popular posts from this blog

Hatching array of circles in AutoCAD using c# -

ios - UITEXTFIELD InputView Uipicker not working in swift -

Python Pig Latin Translator -