MongoClient.connect's callback does not invoke
I try to invoke the callback in aws lambda but it doesn't work, however if I remove exports.lambdaHandler and just invoke it by node app.js it works just fine.
exports.lambdaHandler = async (event, context) => {
try {
MongoClient.connect(url, {
useNewUrlParser: true
}, (err, client) => {
console.log("Connected successfully to server");
});
response = {
'statusCode': 200,
'body': JSON.stringify({
message: 'test'
})
}
return response
} catch (err) {
console.log(err);
return err;
}
};
should return
Connected successfully to server
edit
I changed it to await instead. now it's good
exports.lambdaHandler = async (event, context) => {
try {
const client = await MongoClient.connect(url, {
useNewUrlParser: true
})
const db = client.db(dbName)
await db.createCollection(collectionName)
client.close()
return {
'statusCode': 200,
'body': JSON.stringify({
message: 'test'
})
}
} catch (err) {
console.log(err);
return err;
}
};
Try this, it would return the results else throw an error which will be caught below and returned by Lambda
exports.lambdaHandler = async (event, context) => {
try {
MongoClient.connect(url, {useNewUrlParser: true}, (err, client) => {
if (err) { console.log(err); throw(err); }
else {
console.log("Connected successfully to server");
console.log(client);
response = {
'statusCode': 200,
'body': JSON.stringify({message: client})
};
return response;
};
});
} catch (err) {
console.log(err);
return err;
}
};
Related
I'm getting this error when trying to update an entry (in this case, checking a todo and setting it to true/false)
It seems like i'm getting the proper object (seen in the data console log) which makes me wonder why i'm getting [object Object].
Would appreciate any kind of help!
Here's the action :
export function onSaveTodo(todo) {
return async (dispatch) => {
try {
const savedTodo = await todosService.saveTodo(todo);
const action = {
type: 'UPDATE_TODO',
todo: savedTodo,
};
dispatch(action);
} catch (err) {
console.log('cant save todo');
}
};
}
the service :
const BASE_URL = 'todo';
async function saveTodo(todo) {
try {
if (todo._id) {
return httpService.put(BASE_URL, todo);
} else {
return httpService.post(BASE_URL, todo);
}
} catch (err) {
console.log(`could not save todo `, err);
throw err;
}
}
Http service :
export const httpService = {
get(endpoint, data) {
return ajax(endpoint, 'GET', data);
},
post(endpoint, data) {
return ajax(endpoint, 'POST', data);
},
put(endpoint, data) {
console.log('endpoint:', endpoint);
console.log('data:', data);
return ajax(endpoint, 'PUT', data);
},
delete(endpoint, data) {
return ajax(endpoint, 'DELETE', data);
},
};
The backend controller :
async function updateTodo(req, res) {
try {
const { todo } = req.body;
// console.log('todo:', todo);
const savedTodo = await todoService.update(todo);
res.json(savedTodo);
} catch (err) {
logger.error('Failed to update todo', err);
res.status(500).send({ err: 'Failed to update todo' });
}
}
and the backend service :
async function update(todo) {
try {
const newTodo = {
...todo,
_id: ObjectId(todo._id),
};
console.log('newTodo:', newTodo);
const collection = await dbService.getCollection('todo');
await collection.updateOne({ _id: newTodo._id }, { $set: newTodo });
return todo;
} catch (err) {
logger.error(`Can not update toy ${todo._id}`, err);
throw err;
}
}
Earlier I am working with the single connection but now I am trying to create a DB Pool in Nodejs using Mysql.
I am following the Single Pattern or Class-Based Pattern to create a query and other operations
Earlier Configuration (Everything working fine)
const connection = mysql.createConnection({
host: dbConfig.HOST,
user: dbConfig.USER,
password: dbConfig.PASSWORD,
database: dbConfig.DB
});
connection.connect();
connection.query("SET AUTOCOMMIT=false;", (err) => {
if(err){
console.log(err)
console.log("Couldn't set auto commit to false")
}else{
console.log("AutoCommit set to false")
}
});
function query(sql, params, autorollback) {
return new Promise((resolve, reject) => {
//let currentTime = new Date().valueOf();
let query = connection.query(sql, params, (err, resp) => {
if(err && autorollback) {
return resolve(rollback(err));
}
else if (err) {
console.log(err)
return reject(err);
}
//console.log("Time Taken: ", new Date().valueOf() - currentTime, "\n", query.sql);
//console.log(resp);
resolve(resp);
});
});
}
Create Pool Configuration (Didn't get the response from the query)
const connection = mysql.createPool({
host: dbConfig.HOST,
user: dbConfig.USER,
password: dbConfig.PASSWORD,
database: dbConfig.DB,
connectionLimit: 4,
});
connection.getConnection(function (err, conn) {
conn.query("SET AUTOCOMMIT=false;", (err) => {
if (err) {
console.log(err)
console.log("Couldn't set auto commit to false")
} else {
console.log("AutoCommit set to false")
}
});
});
function query(sql, params, autorollback) {
console.log(sql)
return new Promise((resolve, reject) => {
//let currentTime = new Date().valueOf();
connection.getConnection(function (err, conn) {
if (err) {
console.log(err)
return reject(err);
}
let query = conn.query(sql, params, (err, resp) => {
console.log(sql)
if (err && autorollback) {
return resolve(rollback(err));
}
else if (err) {
console.log(err)
return reject(err);
}
//console.log("Time Taken: ", new Date().valueOf() - currentTime, "\n", query.sql);
//console.log(resp);
resolve(resp);
conn.release();
});
})
});
}
You don't have to set autocommit false here.
The beginTransaction()-method sets the autocommit to false by default. You have explicitly call conn.commit() in order to have the queries inside your beginTransaction() to have any effect here.
connection.getConnection(function (err, conn) {
conn.beginTransaction((err) => {
conn.query("YOUR_SQL_QUERY_GOES_HERE", (err) => {
if (err) {
conn.commit();
} else {
console.log("Failed")
}
});
}
});
I am constantly getting the printed out message of "No File Upload" Failed when I select my image and hit upload. It never goes to true..
As you can see, I am not actually uploading here. Just testing the req.files is there something wrong in my router.post? Any input would be appreciated.
router.post('/upload', async (req, res) => {
try {
if(!req.files) {
res.send({
status: false,
message: 'No file uploaded'
});
} else {
res.send({
status: true,
message: 'Files are uploaded',
data: data
});
}
} catch (err) {
res.status(500).send(err);
}
})
module.exports=router
can you share your controller file of it and also you are using async function but not defining await inside of that function,must have to use 'await' when executing async function.
here is the controller file AAmir
let fs = require('fs');
let async = require('async');
function uploaddownFiles(connection, fromFolder, toFolder, sftpmethod) {
return new Promise((resolve, reject) => {
// Getting all file list in given folder of local machine
let fileList = fs.readdirSync(fromFolder);
// filter only files not folders
fileList = fileList.filter(file => {
if (file.includes('.')) return true;
return false;
});
console.log('Total files: ', fileList.length)
if (!fileList.length) return reject('No file to send')
connection.sftp(function (err, sftp) {
if (err) return;
async.eachOfSeries(fileList, (file, key, cb) => {
let moveFrom = `${fromFolder}/${file}`;
let moveTo = `${toFolder}/${file}`;
if (sftpmethod=== 'put')
sftp.fastPut(moveFrom, moveTo, {}, function (uploadError) {
if (uploadError) return cb(uploadError);
console.log("Successfully Uploaded", file);
cb();
});
else if (sftpmethod === 'get')
sftp.fastGet(moveFrom, moveTo, {}, function (uploadError) {
if (uploadError) return cb(uploadError);
console.log("Successfully Downloaded", file);
cb();
});
}, function (err) {
if (err) {
console.log(err);
return reject(err);
} else {
console.log('all files have been uploaded/downloaded');
return resolve();
}
})
});
});
}
I am using async parallel to get data from db in parallel.
When every task is returning the data I am storing it in local object.
From index.js I am calling cacheService.js .
In cacheService.js I am loading data from mysql database and mongo database in to cache object.
Whenever I am doing npm run local run. I am getting following error.
UNHANDLEDREJECTION Error: Callback was already called.
This error is coming from loadMongoData method of cacheService.js.
I have followed other answers on stackoverflow like adding else part
Here is code for cacheService.js.
'use strict';
var cache = [];
class cacheService {
async init() {
await this.loadMongoData();
}
loadMongoData(env, callback1) {
const _this = this;
console.log('Inside loadMongoData')
async.parallel(
{
task1: function (callback) {
CriteriaDef.find({})
.lean()
.exec(function (err, criteriaDefs) {
if (err) {
console.log('Inside err 1')
logger.error('Error fetching CriteriaDef: ', util.inspect(err));
callback(err, null);
} else if (criteriaDefs) {
console.log('Inside criteriaDefs')
if (criteriaDefs.length && criteriaDefs.length > 0) {
console.log('Inside criteriaDefs 1')
global.CRITERIA_DEFS = criteriaDefs;
cache['criteria_defs'] = criteriaDefs;
}
callback(null, null);
}
});
},
task2: function (callback) {
groupDef
.find({})
.lean()
.exec(function (err, groupDefs) {
if (err) {
console.log('Inside err2')
logger.error('Error fetching groupDefs: ', util.inspect(err));
callback(null, err);
} else if (groupDefs) {
console.log('Inside ')
global.groupDefsWithRoles = groupDefs;
let _groupDefs = [];
_.each(groupDefs, function (groupDef) {
var data = {
value: groupDef._id,
label: `${groupDef._id}: ${groupDef.description}`
};
_groupDefs.push(data);
});
global.groupDefs = _groupDefs;
cache['groupDefs'] = _groupDefs;
logger.info('Loaded groupDefs: ', global.groupDefs.length);
callback(null, null);
}
});
},
task3: function (callback) {
jiraProjects.find({$or: [{archived: {$ne: true}}, {archived: {$exists: false}}]}).exec(function (err, jiraProjects) {
if (err) {
console.log('Inside error 3')
logger.error('Error fetching jiraProjects: ', err);
callback(null, err);
} else if (jiraProjects) {
console.log('Inside jira project')
let _jiraProjects = [];
_.each(jiraProjects, function (jiraProject) {
var data = {
value: jiraProject.key,
label: jiraProject.key,
issueType: jiraProject.issueType ? jiraProject.issueType : 'Bug'
};
_jiraProjects.push(data);
});
global.jiraProjectsList = _jiraProjects;
cache['jiraProjects'] = _jiraProjects;
logger.info('Loaded jira projects: ', global.jiraProjectsList.length);
callback(null, null);
}
});
},
task4: function (callback) {
console.log('Inside task4')
callback(null, null);
},
task5: function (callback) {
inputElements
.find({})
.lean()
.exec(function (err, inputElements) {
if (err) {
console.log('Inside error5')
logger.error('Error fetching inputElements: ', util.inspect(err));
callback(null, err);
} else if (inputElements) {
console.log('Inside inputelements')
global.INPUT_ELEMENTS_DEF = inputElements;
cache['INPUT_ELEMENTS_DEF'] = inputElements;
callback(null, null);
}
});
},
task6: function (callback) {
console.log('Inside task6')
sisp.loadProducts('', callback);
}
},
function (err, results) {
if (err) {
console.log('Inside final error')
logger.error("Something went wrong can't start the app: ", util.inspect(err));
callback1(null, err);
} else {
console.log('Inside final else')
logger.info('loaded all globals properly :)');
callback1(null, null);
}
}
)
}
}
export default new cacheService();
I think your problem cuz you use callback inside of promise.
Please change your code like this:
class cacheService {
async init() {
await new Promise((resolve, reject) => {
this.loadMongoData(env, (ignoreArg, error) => {
if (error) {
return reject(error);
}
resolve();
});
});
}
...
}
Tip: in the each task add statement else for call callback, because maybe your statement not handled and your code can't execute prefect
task1: function (callback) {
CriteriaDef.find({})
.lean()
.exec(function (err, criteriaDefs) {
if (err) {
console.log('Inside err 1')
logger.error('Error fetching CriteriaDef: ', util.inspect(err));
callback(err, null);
} else if (criteriaDefs) {
console.log('Inside criteriaDefs')
if (criteriaDefs.length && criteriaDefs.length > 0) {
console.log('Inside criteriaDefs 1')
global.CRITERIA_DEFS = criteriaDefs;
cache['criteria_defs'] = criteriaDefs;
}
callback(null, null);
} else {
callback(null, null);
}
});
},
I'm writing a small Serverless function to query a MSSQL db using the node mssql library (https://www.npmjs.com/package/mssql#callbacks)
I've read the documentation and I think I'm doing everything right but getting confused - I can see the result in my logs, but the main function callback is not being called and therefore data not being outputted by the API (basically the whole thing times out)
Heres my Lambda function:
import {success, error} from './libs/response-lib';
import {EPDBConfig} from "./libs/Database-lib";
import sql from "mssql";
import config from "./config";
export function main(event, context, callback) {
console.log("start");
EPDBConfig().then(dbConfig => {
if(config.debug) console.log("Hello!");
let EPDBconfig = {
user: dbConfig.dbuser,
password: dbConfig.dbpassword,
server: dbConfig.dbhost,
database: dbConfig.dbname
};
sql.connect(EPDBconfig)
.then(pool => {
return pool.request()
.input('student_no', sql.Int, 129546)
.query('select * from Student where StudentNo = #student_no')
}).then(result => {
console.log("success!");
if(config.debug) console.log('result', result);
return result;
}).catch(err => {
if(config.debug) console.log('err1', err);
return err;
});
sql.on('error', err => {
if(config.debug) console.log('err2', err);
return callback(null, error(err));
});
sql.on('done', result => {
if(config.debug) console.log('done', result);
return callback(null, success(result));
});
}).catch(err => {
if(config.debug) console.log('err3', err);
return callback(null, error(err));
})
}
DB Config is pulled from AWS KMS for secure vars
import AWS from "aws-sdk";
import config from "../config";
const kms = new AWS.KMS({
region: AWS.config.region
});
export function EPDBConfig() {
//DECRYPT THE DATABASE CONNECTION DETAILS
return new Promise((resolve, reject) => {
let params = {
CiphertextBlob: Buffer(process.env.epdb, 'base64')
};
kms.decrypt(params, function(err, data) {
if (err) {
reject(err);
} // an error occurred
else {
let dbParams = JSON.parse(String(data.Plaintext));
resolve(dbParams);
}
});
});
}
and response lib:
export function success(data, message) {
return buildResponse(200, true, data, message);
}
export function error(data, message) {
return buildResponse(400, false, data, message);
}
export function unauthorized(data, message) {
return buildResponse(401, false, data, message);
}
export function forbidden(data, message) {
return buildResponse(403, false, data, message);
}
export function exception(data, message) {
return buildResponse(500, false, data, message);
}
function buildResponse(statusCode, successState, data, message) {
var body = {
success: successState,
message: message
};
if (successState) {
body.data = data;
}
return {
statusCode: statusCode,
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify(body)
};
}
Can anyone point out where I'm going wrong here? I think I have a whole pile of promises going on. The sql.on('done', result => { ... doesn't appear to work, and I tried adding 'return callback(null, success(result));' in the area where I have 'success'
Please help me!
So, I endded up resolving this with a bit of refactoring:
import sql from "mssql";
import _ from "lodash";
import {success, error} from './libs/response-lib';
import {DB} from "./libs/Database-lib";
import {Student} from "./models/ep.student";
export function main(event, context, callback) {
DB().then(pool => {
return new Promise((resolve, reject) => {
pool.connect(err => {
if(err) reject(err);
pool.request()
.input('StudentNo', sql.Int, 129546)
.execute('StoredProcedure')
.then(result => {
if(process.env.debug) console.log('result', result);
let student = new Student();
_.assign(student, result.recordset[0]);
resolve(student);
pool.close();
}).catch(err => {
reject(err);
pool.close();
});
});
});
}).then(result => {
if(process.env.debug) console.log('result', result);
callback(null, success(result));
}).catch(err => {
if(process.env.debug) console.log('err', err);
callback(null, error(err));
});
}
The first issue was that I wasn't terminating my connection - just a note that I switched to using a stored procedure as this was always going to be the case.
The second issue was that I wasn't really using promises correctly (i think) I wrapped up my connection in a promise and only when I had the response did I resolve or reject it.