NODE and SQL Server : transaction commit and rollback - node.js

I'm trying to insert an array of data into a table and this has to be done in a single go. I'm trying to implement a transaction with SQL Server in node js.
I can insert the data successfully, but the issue is whenever there is an error, the transaction is still getting committed. I know my code is not correct, can anyone help me correct my code?
saveStockbulkDetails = async(requestBody, res) => {
var toggle = true;
let dDate = new Date();
let currentDate = moment(dDate).format("YYYY-MM-DD");
const transaction = new sql.Transaction(dbconn1);
transaction.begin((err) => {
const request = new sql.Request(dbconn1);
for (let i = 0; i < requestBody.pipeDetails.length; i++) {
console.log(requestBody.pipeDetails[i].heat);
request.query(
"insert into JSULLCStockDB.dbo.ma_smallpipe_shipping_details(jsuordref, itemno, pipeid, heat, loadtallyno, uid_ent, tmstp_ent, date_ent)" +
" values('" +
requestBody.jsuOrder +
"'," +
"'" +
requestBody.itemNo +
"'," +
"'" +
requestBody.pipeDetails[i].pipeid +
"'," +
"'" +
requestBody.pipeDetails[i].heat +
"'," +
"'" +
requestBody.loadTallyNo +
"'," +
"'" +
requestBody.uid_ent +
"'," +
"getDate()," +
"'" +
currentDate +
"')",
(err, res) => {
if (err) {
transaction.rollback((err) => {
console.log("transaction commit rollback");
});
}
}
);
}
console.log(toggle);
if (toggle) {
transaction.commit((err) => {
if (err) {
console.log("transaction commit error!!");
} else {
console.log("transaction commit success!!");
}
});
}
});
}

Related

Create and download text files- Node.js & React.Js

As part of my project, I have to create text files which have to be downloaded as a ".txt".
I am using Node.js and React JavaScript, and I have already tried using the Node.js "fs.writeFile", but the browser doesn't recognize the download, the file name is always being called as the folder name and the file is always empty although the variable is a string and not empty.
I'm calling from the client to this function:
app.post("/downloadnetworks", async (req, res) => {
let selectedApps=req.body.selectedApps;
let arr=await sqlFunctions.createByIds(selectedApps);
res.send();
module.exports.createByIds = (productsArray) => {
return new Promise(function(resolve, reject) {
var bulkedString = '';
var product;
for (let obj of productsArray) {
let query = "select * from...........";
con.query(query, function(err, result, fields) {
if (err) throw err;
let stringifiedJson = JSON.stringify(result)
let parsedJson = JSON.parse(stringifiedJson)
The DB data is being added into the variable 'stringifiedJson', and it continues from here:
let parsedJson = JSON.parse(stringifiedJson) //has all the data from the DB
for (let network of parsedJson) {
if (network.certification_Id) {
bulkedString += network.domain_Name + ", " + network.publisher_Id + ", " + network.relationship + ", " + network.certification_Id;
} else {
bulkedString += network.domain_Name + ", " + network.publisher_Id + ", " +
network.relationship;
}
bulkedString += "\n";
product = network.product;
}
})
fs.writeFile('C:\Work\App ads.txt\App-Ads Files\'' + product + '.txt', bulkedString, 'utf8', (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
}
resolve(bulkedString)
})
}

Waiting query result

I can't succeed into waiting an sql query result
This is what my Code looks like
socket.on('new', async function(information) {
console.log("check no offer en cours");
var checkOffer = "SELECT COUNT(*) as total FROM app__offer WHERE status_id = 1 AND profile_id = " + user.idUser;
doInsert = false;
con.query(checkOffer, function(err, result) {
if (err) throw err;
console.log(result[0].total);
if (result[0].total == 0) {
console.log("can insert");
doInsert = true;
}
}).then(function() {
console.log(doInsert);
if (doInsert) {
console.log("create offer");
var sql = "INSERT INTO app__offer (createdAt,updatedAt, startAt, programmed, startLatitude, startLongitude, commune_id, point_id, status_id,device,profile_id) " +
"VALUES ('" + todayDateTime + "','" + todayDateTime + "','" + todayDateTime + "'," + false + "," + user.latitude + "," + user.longitude + "," + user.idCommuneDestination + "," + user.idPoint + "," + 1 + "," + 'device' + "," + user.idUser + ")";
console.log(sql);
con.query(sql, function(err, result) {
if (err) throw err;
socket.emit('new', result);
});
} else {
console.log("Cet user a déjà une offre en cours");
}
});
Issue is the doInsert Log is executed before the canInsert Log.
I think that con.query() accept the callback and is also "thennable" returning a Promise.
In most cases if the callback is provided, that will be the handler of the result and it wont be passed to the Promise.
So
con.query(query, () => {
// this code is executed when the query ends
}).then(() => {
// this code is executed when the promise attached to .then() is resolved
// in this case con.query() is instant resolved cause a callback parameter is given
})
The solution is to put all in the callback OR all in the promise chain.
I would do like :-
try{
let result = await con.query(checkOffer);
if (result) {
let resultFromAnotherQuery = await con.query(sql);
if (resultFromAnotherQuery){
console.log("done");
}
}
}catch(err) {
console.log(err);
}

sqlite3 nodejs - return data synchronously

Every example I can find on sqlite3 and nodejs just writes the data to the console, which is useless - how do I await a data and return it from a calling method ? Lets say I have :
exports.selectData = function(tableName, parameters, successHandler) {
var dbConn = new sqlite3.Database('./data/myAppsData.db');
dbConn.all("SELECT " + parameters + " FROM " + tableName + "", function(err, rows) {
// what to do here ? or somewhere else ?
});
}
How do I get data (rows) to return from selectData ? Or alternatively, using successHandler callback ? (it is undefined where the comment is)
dbConn.all("SELECT " + parameters + " FROM " + tableName + "", function(err, rows) {
return rows // could replace with JSON.stringify(rows) If you want to pass JSON data
});
Or as ionizer said you could return a promise. If you need to use async/await
exports.selectData = function(tableName, parameters, successHandler) {
var dbConn = new sqlite3.Database('./data/myAppsData.db');
return new Promise((resolve, reject) => {
dbConn.all("SELECT " + parameters + " FROM " + tableName + "",
function(err, rows) {
if(err) {
reject (err);
} else {
resolve(rows);
}
});
});
}

global.gc() doesn't reduce memory after each loop?

I have one api to crawler, I try use global().gc to reduce heap memory after each loop but it doesn't work. Please point what wrong did I do?
It also leads to heap out of memory problem
app.get('/test2', (req, res) => {
res.json({mes: 'is getting data'});
array = [...]; //array contains about 1000 element as link
function something() {
let d = q.defer();
let urls = [];
array.forEach(function (mang, index) {
let tagArray = [];
tagArray = null;
tagArray = [];
//use this function to reduce the memory heap after looping each element of array
global.gc();
for (let i = 1; i <= 4000; i++) {
urls.push(function (callback) {
setTimeout(function () {
let link = 'http://something' + mang.link + '/tag-' + i;
//we will have about 4000 links due to i
let x = link;
let options = {
url: link,
headers: {
'User-Agent': 'MY IPHONE 7s'
}
};
function callback1(error, response, html) {
if (!error) {
let $ = whacko.load(html);
let tag_name = $('h1').text();
tag_name = tag_name.trim();
console.log(tag_name);
let tag_content = $('#content').find('div').contents();
tag_content = tag_content.toString();
if (tag_name !== "" && tag_content !== "") {
let tagObject = new Object();
tagObject.tag_name = tag_name;
tagObject.tag_content = tag_content;
tagObject.tag_number = i;
tagArray.push(tagObject);
if (tagArray.length == 4000) {
tagArray.sort(function (a, b) {
return parseInt(a.tag_number) - parseInt(b.tag_number);
});
for (let v = 0; v < tagArray.length; v++) {
db.query("INSERT INTO `tags` (tag_name, content, tag_number) " +
"SELECT * FROM (SELECT " + "'" + tagArray[v].tag_name + "'" + "," + "'" + tagArray[v].tag_content + "','" + tagArray[v].tag_number + "' as ChapName) AS tmp " +
"WHERE NOT EXISTS (SELECT `tag_name` FROM `tags` WHERE `tag_name`=" + "'" + tagArray[v].tag_name + "'" + ") " +
"LIMIT 1", (err) => {
if (err) {
console.log(err);
}
});
}
urls = null;
}
}
}
}
request(options, callback1);
callback(null, x);
}, 12000);
});
}
});
d.resolve(urls);
return d.promise;
}
something()
.then(function (data) {
let tasks = data;
console.log("start data");
async.parallelLimit(tasks, 40, () => {
console.log("DONE ");
});
})

Node js + Multiple query transaction + Affiliate API data insert into postgresql database

Now i am working with Flipkart affiliate API and get the categories and products insert into my database.
I am using nodejs backend and postgresql database.
I used 4 async loop. But I done something but don't know the correct approach. Here I want to execute the loops in asynchronous and once all the process(loops) end means need to send response. How to I determine the all loops executed successfully. Please anyone suggest the correct approach.
var request = require('request');
var dateFormat = require('date-format');
var async = require('async');
router.get('/getproducts', function(req, res) {
var affiliateIdFrom = 1;
var affiliateUrl = "https://affiliate-api.flipkart.net/affiliate/api/<your affiliate_tracking_id>.json";
request(affiliateUrl, function(error, response, html) {
var resData = JSON.parse(html);
var dataObj = resData.apiGroups.affiliate.apiListings;
async.each(Object.keys(dataObj), function(item, done) {
var objData = dataObj[item].availableVariants['v0.1.0'];
var cname = objData.resourceName;
var curl = objData.get;
client.query('INSERT into product_category (affiliate_from, name, url,created_on) values (' + "'" + affiliateIdFrom + "'" + ',' + "'" + cname + "'" + ',' + "'" + curl + "'" + ',' + "'" + today + "'" + ')', function(err, result) {
if (err) {
console.log(err);
res.send({
data : "Soemthing went wrong",
});
}
done(err, result);
});
}, function(err) {
product.getProductDetails(affiliateIdFrom);
});
});
});
var product = {
getProductDetails : function(aId) {
var today = dateFormat(new Date());
client.query("select * from product_category where affiliate_from = " + aId + " limit 1", function(err, result) {
if (err) {
console.log(err);
}
var categoryList = result.rows;
async.each(categoryList, function(value, done) {
request.get({
headers : {
'Fk-Affiliate-Id' : 'XXXXX',
'Fk-Affiliate-Token' : 'XXXXXXXXXXXXXXXXXXXXXXX'
},
url : value.url
}, function(error, response, body) {
var data = JSON.parse(body);
var dataLength = data.productInfoList.length;
var dataObj = data.productInfoList;
if (dataLength > 0) {
async.each(dataObj, function(value1, done1) {
var productBasicInfo = value1.productBaseInfo.productIdentifier;
var productId = productBasicInfo.productId;
var productDetails = value1.productBaseInfo.productAttributes;
var pTitle = productDetails.title;
var thumbnailUrl = JSON.stringify(productDetails.imageUrls);
var category = productBasicInfo.categoryPaths.categoryPath[0][0].title;
var mrp = productDetails.maximumRetailPrice.amount;
var price = productDetails.sellingPrice.amount;
var prodcutUrl = productDetails.productUrl;
var productDescription = productDetails.productDescription;
if (productDescription != null) {
productDescription = productDescription.replace(/'/g, "\''");
}
var inStock = productDetails.inStock;
var information = JSON.stringify(value1);
var q = 'insert into product(affiliate_from, title, image_url, category_paths, mrp, price, url, description, in_stock, information, created_on) values (' + "'" + aId + "'" + ', ' + "'" + pTitle + "'" + ', ' + "'" + thumbnailUrl + "'" + ', ' + "'" + category + "'" + ', ' + "'" + mrp + "'" + ', ' + "'" + price + "'" + ', ' + "'" + prodcutUrl + "'" + ', ' + "'" + productDescription + "'" + ', ' + "'" + inStock + "'" + ', ' + "'" + information + "'" + ', ' + "'" + today + "'" + ' )';
console.log(q);
client.query(q, function(err, result) {
if (err) {
console.log(err);
} else {
console.log('inserted successfully');
}
});
done1("err", "result");
}, function(err) {
console.log('dddddddddd');
});
}
//console.log(data.productInfoList);
console.log(data.productInfoList.length);
done(err, "result");
});
}, function(err) {
console.log('doneeeeee');
});
});
}
};
The correct approach is to place each of your asynchronous requests inside a transaction, which when finished, will give you the indication of whether the whole set of queries was successful or not.
For example, using pg-promise syntax, your transaction would like this:
db.tx(function () {
return promise.all([
this.query("insert 1 ..."),
this.query("insert 2 ..."),
this.query("insert 3 ...")
]);
})
.then(function (data) {
// success;
}, function (reason) {
// error
});

Resources