Postgres query is not executed on Node.js - javascript

I've got into an issue. Postgres code(query) is not executed at all. I have to mention that the connection with the DB is correctly done.
I've tried to debug the code but I don't really know what's the problem
'use strict';
const config = require('../config');
const emailService = require('./email-service');
const pg = require('pg');
pg.defaults.ssl = true;
module.exports = function(phone_number, user_name, previous_job, years_of_experience, job_vacancy){
console.log('sending email');
let emailContent = 'A new job inquiry from ' + user_name + ' for the job: ' + job_vacancy +
'.<br> Previous job position: ' + previous_job + '.' +
'.<br> Years of experience: ' + years_of_experience + '.' +
'.<br> Phone number: ' + phone_number + '.';
emailService.sendEmail('New job application', emailContent);
try{
var pool = new pg.Pool(config.PG_CONFIG);
pool.connect(function(err, client, done) {
if (err) {
return console.error('Error acquiring client', err.stack);
}
client
.query(
'INSERT into job_applications ' +
'(phone_number, user_name, previous_job, years_of_experience, job_vacancy) ' +
'VALUES($1, $2, $3, $4, $5) RETURNING id',
[phone_number, user_name, previous_job, years_of_experience, job_vacancy],
function(err, result) {
if (err) {
console.log(err);
} else {
console.log('row inserted with id: ' + result.rows[0].id);
}
});
});
}
catch(e){
console.log(e, 'error[][][]')
}
pool.end();
} ```

Related

using .then nodejs

I have a large function that says, okay add this employee to the db based on what the admin entered. But now I need to check, does this user already exist in the db. so I created a function that does just that called getEmployeeNum, but I need to perform a .then in the main function of /addEmployee to say, see what the result of the function getEmployeeNum is before you perform any of the other requests. see the code below:
app.post('/addEmployee', (req, res) => {
if (req.session.loggedin) {
var firstname = req.body.firstname;
var lastname = req.body.lastname;
var username = req.body.username;
var sales = req.body.sales;
var salary = req.body.salary;
var location = req.body.location;
var role = req.body.role;
var admin = req.body.admin;
var employeenum = req.body.employee_num;
var phonenum = req.body.phone_num;
var org = req.body.org;
var pass = "";
var newPassword = req.body.password
getEmployeeNum(req, res, employeenum)
bcrypt.hash(newPassword, saltRounds, function(err, hash) {
pass = hash
addLogin(req, res, pass, firstname, lastname, username, sales, salary, location, role, admin, employeenum, phonenum)
});
var addEmployee = "insert into EMPLOYEES (FIRSTNAME, LASTNAME, USERNAME, SALES, SALARY, LOCATION, ROLE, ADMIN, EMPLOYEE_NUM, PHONENUM, ORGANIZATION) VALUES ('" +
req.body.firstname +
"', '" +
req.body.lastname +
"', '" +
req.body.username +
"', '" +
req.body.sales +
"', '" +
req.body.salary +
"', '" +
req.body.location +
"', '" +
req.body.role +
"', '" +
req.body.admin +
"', '" +
req.body.employee_num +
"', '" +
phonenum +
"', '" +
org +
"' )";
ibmdb.open(ibmdbconnMaster, function(err, conn) {
if (err) return console.log(err);
conn.query(addEmployee, function(err, rows) {
if (err) {
console.log(err);
}
registerEmail(username, firstname, lastname, req, res)
res.redirect('/employees')
})
})
} else {
res.render('login.ejs')
}
})
function getEmployeeNum(req, res, employeenum) {
var getEmployeeNum = "select * from employees"
ibmdb.open(ibmdbconnMaster, function(err, conn) {
if (err) return console.log(err);
conn.query(getEmployeeNum, function(err, rows) {
if (err) {
console.log(err);
}
for (var i = 0; i < rows.length; i++) {
var employee_num = rows[i]["EMPLOYEE_NUM"]
if (employeenum == employee_num) {
alert("employee already exists")
res.render("addEmployee.ejs")
}
}
conn.close(function() {
// console.log("closed the function /index");
});
});
})
}
is this the right way to do it, or is there a better way? Thanks :)
I see that you're using the callback version of SQL driver. I'll assume that you;re working with mysql2 for simplicity wise.
There is actually a promise version of mysql2 driver
const mysql = require('mysql2/promise');
I'll share with you some of the common patterns I use when working with DB.
// Create a pool for connection
const pool = mysql.createPool({
connectionLimit: process.env.SQL_CON_LIMIT,
host: process.env.SQL_SERVER,
port: process.env.SQL_PORT,
user: process.env.SQL_USERNAME,
password: process.env.SQL_PASSWORD,
database: process.env.SQL_SCHEME,
timezone: process.env.SQL_TIMEZONE,
});
// To use async to test the connection via conn.ping() before launch server
const p1 = (async () => {
const conn = await pool.getConnection();
await conn.ping();
conn.release();
return true;
})();
// test connection for SQL, add other into array as you like
Promise.all([p1])
.then(() => {
app.listen(PORT, () =>
console.info(
`Application started on port http://localhost:${PORT}/ at ${new Date()}`
)
);
})
.catch((err) => {
console.error('Cannot connect: ', err);
});
The code block above is for setting up, and test connection before starting the server. This can avoid the rare case where DB is not initialized before the request came in (As the server can start before connecting to DB)
const makeQuery = (query, pool) => {
return async (args) => {
const conn = await pool.getConnection();
try {
let results = await conn.query(query, args || []);
return results[0]; // Result of query is in index 0
} catch (error) {
console.log(error);
} finally {
conn.release();
}
};
};
// Sample query
const queryCheckLogin =
'SELECT COUNT(*) as "match" FROM user WHERE user_id = ? AND password = ?';
// Make it into function!
const checkLogin = makeQuery(queryCheckLogin, pool);
app.post('/api/login', async (req, res) => {
let { user_id, password } = req.body;
// Obtain sha1 password from submitted password
password = sha1(password);
try {
let results = await checkLogin([user_id, password]);
// Return the credential (supposedly token) when record is matched
if (results[0]['match'] !== 0) {
res.status(200).json({ login: 'success', user_id, password });
} else {
// return 401 if record not found
res.status(401).json({ error: 'No such username or password' });
}
} catch (error) {
console.log(error);
res.status(400).json(error);
}
});
The code block above shows the factory function to deal with the general form of getting the result from a query, so you won't clutter the logic in middleware. So you will write out whatever query you will do, make it into function via makeQuery, and just use the resulting function.
Using async...await will also make the code cleaner, however, this depends on the version of codebase you're working on. However, the sample above do works for .then as well.

How do you trigger cloud functions when someone follows someone else using Firebase? I'm using Atom and Xcode

I'm using Firebase and I want to trigger a notification when 'person A' follows 'person B'.
This is my code:
exports.observeFollowing = functions.database.ref('/added/{followerID}/{followingID}').onCreate((snapshot, context) => {
var followerID = context.params.followerID;
var followingID = context.params.followingID;
console.log('User: ' + followerID + ' is following: ' + followingID);
//trying to figure out fcmtoken to send a notification
return admin.database().ref('/users/' + followingID).once('value', snapshot => {
var userWeAreFollowing = snapshot.val();
return admin.database().ref('/users/' + followerID).once('value', snapshot => {
var userDoingTheFollowing = snapshot.val();
var payload = {
notification: {
title: "Someone added you as a friend",
body: userDoingTheFollowing.username + ' is now following you'
}
}
return admin.messaging().sendToDevice(userWeAreFollowing.fcmToken, payload)
.then(response => {
console.log("Successfully sent message:", response);
return response
}).catch(function(error) {
console.log("Error sending message:", error);
});
})
})
});
The console prints the ('User: ' + followerID + ' is following: ' + followingID) part but doesn't show the notification. I've tested cloud notifications before and they worked but this doesn't work for some reason. In the logs, it says:
Successfully sent message: { results: [ { error:
[FirebaseMessagingError] } ]," "failureCount: 1," "successCount: 0,"
So I know that everything up until the console.log('User: ' + followerID + ' is following: ' + followingID); works. But I'm not sure if the notification function is even being called. Am I missing a semicolon or something else? I really can't figure it out. Also, what does failureCount mean? Is it talking about the notifications function?
As explained in the Cloud Functions doc, you need to manage the asynchronous Firebase operations by using promises. You are using the callback version of the once() method: you need to use the promise version, as follows:
exports.observeFollowing = functions.database.ref('/added/{followerID}/{followingID}').onCreate((snapshot, context) => {
const followerID = context.params.followerID;
const followingID = context.params.followingID;
let userWeAreFollowing;
console.log('User: ' + followerID + ' is following: ' + followingID);
return admin.database().ref('/users/' + followingID).once('value')
.then(snapshot => {
userWeAreFollowing = snapshot.val();
return admin.database().ref('/users/' + followerID).once('value')
})
.then(snapshot => {
const userDoingTheFollowing = snapshot.val();
const payload = {
notification: {
title: "Someone added you as a friend",
body: userDoingTheFollowing.username + ' is now following you'
}
}
return admin.messaging().sendToDevice(userWeAreFollowing.fcmToken, payload)
}).catch(function (error) {
console.log("Error sending message:", error);
return null;
});
});
If you want to log a message in the console upon success do as follows:
// ...
.then(snapshot => {
const userDoingTheFollowing = snapshot.val();
const payload = {
notification: {
title: "Someone added you as a friend",
body: userDoingTheFollowing.username + ' is now following you'
}
}
return admin.messaging().sendToDevice(userWeAreFollowing.fcmToken, payload)
})
.then(response => {
console.log("Successfully sent message:", response);
return null;
}).catch(function (error) {
console.log("Error sending message:", error);
return null;
});

promise inside cron only executes once

I'm really stuck here. Promises, by definition, only return once. However, I need to figure out a way to get promises working with the cron module. Below is a shortened version of what I'm trying to do. Everything executes just fine the first time but after that the promise never resolves.
Unfortunately I'm stuck using the node-pool module which is where the promise comes from. This module is required for connection pooling with HANA databases.
Thanks!
var pool = require('generic-pool');
var servers = require('../config/servers');
var CronJob = require('cron').CronJob;
var hdb = require('hdb'); // database driver
var factories = {};
var pools = {};
for (let i = 0; i < servers.length; i++) {
factories[servers[i].name] = {
create: function(){
return new Promise(function(resolve, reject){
var client = hdb.createClient({
host: servers[i].host,
port: servers[i].port,
user: servers[i].user,
password: servers[i].password
});
resolve(client);
});
},
destroy: function(client){
if (!client.hadError && client.readyState !== 'closed') {
client.end();
}
}
};
pools[servers[i].name] = pool.createPool(factories[servers[i].name]);
}
var job = new CronJob({
cronTime: '0 * * * *',
onTick: () => {
async.waterfall([
(callbackWF) => {
var resourcePromise = pools[name].acquire();
console.log(moment().format('YYYY-MM-DD HH:mm:ss.SS - ') + 'Attempting to resolve promise for Name: ' + name + ' Table: ' + table);
resourcePromise.then( (client) => {
console.log(moment().format('YYYY-MM-DD HH:mm:ss.SS - ') + 'Got promise for Name: ' + name + ' Table: ' + table);
if (client.readyState != 'connected') {
client.connect( (err) => {
if (err) {
console.log(moment().format('YYYY-MM-DD HH:mm:ss.SS - ') + 'Error while connecting to client. Name: ' + name + ' Host: ' + host + ' Port: ' + port + ' User: ' + user + ' Error: ' + JSON.stringify(err));
return callbackWF('error', client);
}
callbackWF(null, client);
});
} else {
callbackWF(null, client);
}
}).catch( (err) => {
if (err) {
console.log(moment().format('YYYY-MM-DD HH:mm:ss.SS - ') + 'Error getting promise for connection pool. Name: ' + name + ' Host: ' + host + ' Port: ' + port + ' User: ' + user + ' Error: ' + JSON.stringify(err));
callbackWF('error');
}
console.log(moment().format('YYYY-MM-DD HH:mm:ss.SS - ') + 'Caught promise');
});
},
// Get data for table.
(client, callbackWF) => {
client.exec(select, {rowsAsArray: true}, (err, rows) => {
if (err) {
console.log(moment().format('YYYY-MM-DD HH:mm:ss.SS - ') + 'Error while getting data from ' + name + " table: " + table + ". " + err + select);
return callbackWF(err, client);
}
callbackWF(null, client);
});
}
], (err, client) => {
if (typeof client != 'undefined') {
console.log(moment().format('YYYY-MM-DD HH:mm:ss.SS - ') + 'Releasing pool for Name: ' + name + ' Table: ' + table);
pools[name].release(client);
}
});
},
start: true,
timeZone: 'UTC'
});
I don't see anything wrong with this. A promise might only return once, but you can totally call then() on it as many times as you want.

node.js: looping, email each matching row from query but it it emails the same user by # number of matches?

I have a node.js email server that works fine however I noticed a problem. If the query string found 4 rows, it would send four emails but only to the first result instead of to each found email address.
var mysql = require('mysql');
var nodemailer = require('nodemailer');
// Amazon SES is sending the emails - uses this module for node
var ses = require('nodemailer-ses-transport');
//transport for connecting with Amazon SES
var transporter = nodemailer.createTransport(ses({
accessKeyId: '****************',
SecretAccessKey: '*************'
}));
// Mysql Connection to database
var connection = mysql.createConnection({
*****connection info goes here *****
});
//Connect to mysql database and check for errors
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;}
});
var querystring1 = 'SELECT `date_created`,`first_name`,`last_name`,`email` FROM `users` WHERE TIMESTAMPDIFF(SECOND,date_created, NOW()) <=298 AND `email`!="" LIMIT 0,5';
connection.query(querystring1, function (err, row) {
if (err) throw err;
for (var i in row) {
// Email content; change text to html to have html emails. row[i].column name will pull relevant database info
var sendit = {
to: row[i].email,
from: '******#******',
subject: 'Hi ' + row[i].first_name + ', Thanks for joining ******!',
html: {path:__dirname + '/templates/welcome.html'}
};
// Send emails
transporter.sendMail(sendit,function(error,response){
if (error) {
console.log(error);
}else{
console.log("Message sent1: " + row[i].first_name);}
transporter.close();}
)
}});
....
How do I have it loop through each found row and send a custom email using row data individual row data?
Do not close the transporter until all your emails are sent.
var querystring1 = 'SELECT `date_created`,`first_name`,`last_name`,`email` FROM `users` WHERE TIMESTAMPDIFF(SECOND,date_created, NOW()) <=298 AND `email`!="" LIMIT 0,5';
connection.query(querystring1, function (err, row) { if (err) throw err;
var toSend=[];
for (var i in row) { // Email content; change text to html to have html emails.
toSend.push({//row[i].column name will pull relevant database info
to: row[i].email,
from: '******#******',
subject: 'Hi ' + row[i].first_name + ', Thanks for joining ******!',
html: {path:__dirname + '/templates/welcome.html'}
});
}
// Send emails
async.eachSeries(toSend, function( sendit, callback) {
transporter.sendMail(sendit,function(error,response){
if (error) {
callback(error);
}else{
console.log("Message sent1: " + sendit.to); callback();
}
)},function(err){if (err) throw (err); console.log("Finished")};
});
});
try this
// Send emails
(function (mail) {
transporter.sendMail(mail,function(error,response){
if (error) {
console.log(error);
}else{
console.log("Message sent1: " + mail.first_name);}
transporter.close();
}
)
)(sendit);
Please use this one, I have tested and it works fine:
function sendmail(sendit, username){
transporter.sendMail(sendit,function(error,response){
if (error) {
console.log(error);
} else {
console.log("Message sent: " + username);}
transporter.close();
}
)
};
for (var i in row) {
var sendit = {
to: row[i].email,
from: 'sandeepv#gmail.com',
subject: 'Hi ' + row[i].first_name + ', Thanks for joining!',
html: {path:__dirname + '/welcome.html'},
};
// Send email
sendmail(sendit, row[i].first_name);
}

Express - app.del() deleting all items

I am using a button to go to the delete route and I am passing to it a key to identify which team to delete. Instead of deleting just one team it deletes ALL teams when using the route. Any ideas?
Delete button:
button#teamDelete.btn.btn-danger.btn-mini(type="submit", value="Delete Team") Delete
script(type='text/javascript')
$('#teamDelete').live('click',function(){
var teamId = #{teamData.key};
$.post('/team/' + teamId, { _method : 'delete' }, function(response) {
console.log(response);
});
});
Team routes:
app.get('/team'/*, lim("Must be logged in to see teams")*/, getAllTeams, function(req, res){
util.log('Serving request for url [GET] ' + req.route.path);
// Pass it the list of all Teams
res.render('team', {'teamsList' : req.teamsList} );
});
/**
* POST /team
* Save new Team
*/
app.post('/team', function(req, res) {
util.log('Serving request for url [POST] ' + req.route.path);
// Output to console the contents of req.body
// console.log('body: ', req.body);
// console.log('body.teamForm: ', req.body.teamForm);
// console.log('body.teamForm.name: ', req.body.teamForm.name);
// console.log('body.teamForm.teamKey: ', req.body.teamForm.teamKey);
// Get data from teamForm
var teamForm = req.body.teamForm;
// Save team in teamForm as new Team
var name = teamForm.name;
var team = new Team();
team.name = name;
// Save new Team to datbase
team.save(function(err){
var message = '';
var retStatus = '';
// No error - Successful Save
if(!err){
util.log('Successfully created new team: ' + name);
message = 'Successfully created new team: ' + name;
retStatus = 'success';
}
// Error - Unsuccessful Save, show error
else {
util.log('Error while creating team: ' + name + ' error : ' + util.inspect(err));
if(err.code === 11000){
message = 'Team already exists';
}
retStatus = 'failure';
}
// Return whether the Save was successful
res.json({
'retStatus' : retStatus,
'message' : message
});
});
});
/**
* GET /team/:key
* Get Team details by key
*/
app.get('/team/:key', function(req, res) {
util.log('Serving request for url [GET] ' + req.route.path);
Team.findByKey(req.params.key, function(err, teamData){
if(!err && teamData){
teamData = teamData;
res.render('teamDetails', { 'teamData' : teamData } );
} else {
util.log('Error in fetching Team by key : ' + req.params.key);
res.json({
'retStatus' : 'failure',
'msg' : 'Error in fetching Team by key ' + req.params.key
});
}
});
});
/**
* DEL /team/:key
* Delete Team by key
*/
app.del('/team/:key', function(req, res) {
util.log('Serving request for url [DEL] ' + req.route.path);
util.log(req.params.key);
Team.remove(req.params.key, function(err){
var message = '';
var retStatus = '';
if (!err) {
util.log('Successfully deleting Team with key: ' + req.params.key);
message = 'Successfully deleting Team with key: ' + req.params.key;
retStatus = 'Success';
} else {
util.log('Error deleting Team with key: ' + req.params.key + 'Error: ' + util.inspect(err));
res.json({
'retStatus' : 'failure',
'msg' : 'Error in fetching Team with key ' + req.params.key
});
}
});
});
Well, you haven't indicated, but I presume Team is a mongoose model, in which case you are not properly specifying your conditions parameter, which must be an object of key/value criteria. Try:
Team.remove({key: req.params.key}, function (err) {});
http://mongoosejs.com/docs/api.html#model_Model.remove

Categories

Resources