I'm a newbie as far as node is concerned, so what i am asking here might be plain out stupid, so bear with me.
Below is the code for a node module that connects to a given mongodb database, my problem is on line19 where i am trying to throw the error in case the connection to the db server cannot be made or the db server is down, but node complains , please advise.
Code:-
var dbinit_func = function(db_name){
try{
// require mongoose , if it's not there
// throw an exception and but out
var mongoose = require('mongoose');
}
catch(err){
throw "Error Mongoose Not Found"
}
try{
// connect to the db
mongoose.connect("mongodb://localhost/" + db_name);
// get a reference to the connection object
var db_connection = mongoose.connection;
// subscribe to events on the connection object
db_connection.on('error', function(err){
// holy cow "A Connection Error", shout it out loud
// and but out
throw new Error(err.message);--> This is where the problem Occurs
});
// bind to the connection open event , we just need to
// do it once , so we use the once method on the
// connection object
db_connection.once('open', function(){})
}
catch(err){
// we got an error most probably a connection error
// so we but out from here
throw "Connection Error";
}
}
module.exports = dbinit_func;
Message spitted by Node:-
/Users/tristan625/projects/node_projs/school_web/models/db.js:19
throw new Error(err.message);
^
Your code is written in a synchronous style, as seen by the try/catch blocks. What you must understand, is that the mongoose.connect function is asynchronous. When you call throw new Error(), that call will occur inside of a callback, which is outside the scope of your try/catch blocks, hence you can't handle the error using them.
Your dbinit_func must be written to allow for a callback
Here's a pretty standard way of doing what you're doing
function dbinit_func(db_name, callback) {
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/ + db_name', { auto_reconnect: true });
var db = mongoose.connection;
db.once('error', function(err){
//trigger callback with an error
callback(err);
});
db.once('open', function() {
//trigger callback with success
callback(null, 'DB Connection is open');
});
}
module.exports = dbinit_func;
// to call this function, you'd want to do something like this
var dbinit = require('/path/to/your/module');
dbinit('mydatabasename', function(err, res){
// at this point, there will either be an error
if (err) console.log(err.message);
// else it will be success
console.log(res);
});
Related
I try to move datastorage in my node app to mongo db. But I have a simple problem with mongo db.
I have a button, clicked in website, will call /datastore
app.post('/datastore', (req, res) => {
client.connect(err => {
var dbo = client.db("test");
dbo.listCollections().toArray(function(err, items){
if (err) throw err;
console.log(items);
if (items.length == 0)
console.log("No collections in database")
});
client.close();
});
});
It works fine for the first time I click the button. But if I click the second time the button I get errors messages:
the options [servers] is not supported the options [caseTranslate] is
not supported the options [dbName] is not supported the options
[credentials] is not supported
/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/utils.js:132
throw err;
^
MongoError: Topology was destroyed
at initializeCursor (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb-core/lib/cursor.js:596:25)
at nextFunction (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb-core/lib/cursor.js:456:12)
at CommandCursor.Cursor.next (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb-core/lib/cursor.js:766:3)
at CommandCursor.Cursor._next (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/cursor.js:216:36)
at fetchDocs (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/operations/cursor_ops.js:217:12)
at toArray (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/operations/cursor_ops.js:247:3)
at executeOperation (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/utils.js:416:24)
at CommandCursor.Cursor.toArray (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/cursor.js:829:10)
at client.connect.err (/Users/ingofoerster/Downloads/development/testrunner/start.js:256:35)
at result (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/utils.js:410:17)
at executeCallback (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/utils.js:402:9)
at err (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/operations/mongo_client_ops.js:286:5)
at connectCallback (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/operations/mongo_client_ops.js:265:5)
at topology.connect (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/operations/mongo_client_ops.js:417:5)
at ReplSet.connectHandler (/Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb/lib/topologies/replset.js:343:9)
at Object.onceWrapper (events.js:281:20)
at ReplSet.emit (events.js:193:13)
at /Users/ingofoerster/Downloads/development/testrunner/node_modules/mongodb-core/lib/topologies/replset.js:786:18
at processTicksAndRejections (internal/process/task_queues.js:79:9)
I cannot explain why this happens, because I have the client.close() in my code. Any idea why I can not call the function more than one time?
When you clicked the button for the first time, you are able to get the result as expected, but after getting the result you are also closing the connection by calling
client.close(); , which is not letting MongoDB reconnect for the second time.
Ideally, you should reuse the existing connection instead of calling connect method for each API call.
Connection pooling example is taken from here
var express = require('express');
var mongodb = require('mongodb');
var app = express();
var MongoClient = require('mongodb').MongoClient;
var db;
// Initialize connection once
MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, database) {
if(err) throw err;
db = database;
// Start the application after the database connection is ready
app.listen(3000);
console.log("Listening on port 3000");
});
// Reuse database object in request handlers
app.get("/", function(req, res) {
db.collection("replicaset_mongo_client_collection").find({}, function(err, docs) {
docs.each(function(err, doc) {
if(doc) {
console.log(doc);
}
else {
res.end();
}
});
});
});
In the following code, the MongoClient is already closed when the callback function of collection.insert() is executed. So I'm expecting collection.insert() not to work and throw an error.
But it's working, collection.insert() works fine even when MongoClient is already closed.
How is this possible?
My code :
const MongoClient = require('mongodb').MongoClient,
connectionUrl = 'mongodb://localhost:27017';
myDatabase = 'library',
myCollection = 'books';
MongoClient.connect(connectionUrl, function(Connectionerror, client) {
if (Connectionerror) {
throw Connectionerror;
}
console.log("Successfully connected to server");
var database = client.db(myDatabase),
collection = database.collection(myCollection);
var book = {Author:"Mark Twain",Title:"Tom Sawyer"};
collection.insert(book,function(InsertionError,result){
if(!InsertionError) {
console.log("Success : "+result.ops.length+" book(s) inserted!");
} else console.log("An insertion error was encountered!");
});
client.close();
console.log();
console.log("Mongo Client is closed");
console.log();
});
Execution :
$ node app-test.js
Successfully connected to server
Mongo Client is closed
Success : 1 book(s) inserted!
The book has been inserted AFTER the client has been closed. How is this possible ?
Now, on the other hand, if there are two levels of callbacks (a collection.insert() under a collection.findOne()) then it raises an error, like I would expect (MongoError : server instance pool was destroyed):
const MongoClient = require('mongodb').MongoClient,
connectionUrl = 'mongodb://localhost:27017';
myDatabase = 'library',
myCollection = 'books';
MongoClient.connect(connectionUrl, function(Connectionerror, client) {
if (Connectionerror) {
throw Connectionerror;
}
console.log("Successfully connected to server");
var database = client.db(myDatabase),
collection = database.collection(myCollection);
var book = {Author:"Mark Twain",Title:"Tom Sawyer"};
collection.findOne(book,function(QueryError,bookToFind){
if(!QueryError) {
if (bookToFind != null) {
console.log("This book already exists !");
} else {
collection.insert(book,function(InsertionError,result){
if(!InsertionError) {
console.log("Success : "+result.ops.length+" books inserted!");
} else {
console.log("An insertion error was encountered!");
console.log(InsertionError.stack);
}
});
}
} else console.log("A request errror was encountered !");
});
client.close();
console.log();
console.log("Mongo Client is closed");
console.log();
});
Execution :
$ node app-test2.js
Successfully connected to server
Mongo Client is closed
An insertion error was encountered!
MongoError: server instance pool was destroyed
(...)
The second example works same as the first. 1. Find query gets executed. 2. Till the response comes from database client.close() gets executed. 3. Now when the response is received by the first query, then second query will throw the exception/ error because step2 has closed the connection.
Infact your console.log answers your own question.
In my code below I wish to receive an "order" from the feed and store it in the database.
I understand that the class method marketEvent will be called whenever data is received and accordingly I would need my insert statement within this function.
It would be inefficient to open and close the db connection each time the class method is called so I seek to open the connection and pass the db object through to marketEvent.
I am new to nodejs and web sockets so can't work out how to put it together.
var pg = require("pg")
var conString = "postgres://myusername:mypassword#localhost/poloniex";
var client = new pg.Client(conString);
var autobahn = require('autobahn');
var wsuri = "wss://api.poloniex.com";
var connection = new autobahn.Connection({
url: wsuri,
realm: "realm1"
});
connection.onopen = function (session) {
function marketEvent (args,kwargs) {
client.query("INSERT INTO orderbook(order) values($1)", [args]);
}
session.subscribe('BTC_XMR', marketEvent);
}
connection.onclose = function () {
console.log("Websocket connection closed");
}
client.connect();
connection.open();
I am unaware of "pg" and "autobahn" both. But from the documentation of "pg" package, may I offer you a hint of solution
client.connect() is not meant to be an isolated call. It expects a function delegate to carry out the operation.
connection.onopen = function (session) {
function marketEvent (args,kwargs) {
client.connect(function(err) {
if (err) throw err;
client.query("INSERT ...", [args]);
});
}
session.subscribe('BTC_XMR', marketEvent);
}
About using the connection efficiently, you may be asking for pooling I guess.
var pool = new pg.Pool(config);
pool.connect(function(err, client, done) {
if (err) throw err;
client.query('INSERT ...', function(err, result) {
//call `done()` to release the client back to the pool
done();
});
});
Please refer original source of this suggestion for the exact usage:
https://www.npmjs.com/package/pg
I am currently unsuccessfully trying to persist document to mongodb using nodejs and mongoosejs.
This my code structure:
The start.js simply initializes my app and creates mongod connection detailed in mongodb.js. The connection is succesfully established and can be seen in mongodb console.
this my model.js
var mongoose = require('mongoose');
var regSceham = new mongoose.Schema({
userId: String,
name:String,
mob:String,
email:String
})
var RegistrationModel = mongoose.model('registration', regSceham);
exports.RegistrationModel = RegistrationModel;
this is my datalayer.js:
var mongoose = require('mongoose');
var mongodb = require('./mongodb');
var model = require('./model');
//var RegistrationModel = mongoose.model('RegistrationModel');
/////////////////////////////////
function save(data){
console.log('inside save >>>>> ' + data);
var regModel = new model.RegistrationModel(data);
console.log('after model');
regModel.save(function(err,regModel){
console.log('inside mongoose save');
if(err)
console.log(err);
});
}
require('./model')
exports.save = save;
when I call the save method in datalayer.js the "inside save >>>>> " statement logged to console and then nothing happens. It seems the var regModel = new model.RegistrationModel(data); statement fails without any error and I donot have any clue why. Any suggestion would be highly appreciated.
sample post data as requested :
{
"userId":"tesrwetId",
"name":"Test",
"mob":"2536245632",
"email":"ashdjas#sa.com"
}
Update 24/06
I am starting to think that since the connection to mongoose is established after my model initialization this problem is experienced. I am unable to get the connection to happen before model is initialized.
Below is the file initialisation sequence. Though the mongodb.js(the mongoose connection) is initilaized first, the on connect method gets called after model.js is initialized.
The mongodb.js file:
console.log('mongodb....');
var mongoose = require('mongoose');
var configure = require('./configure');
// create database
//console.log('sadasdasdsa >>>>>>>' + configure.creds.mongodb)
mongoose.connect(configure.creds.mongodb);
mongoose.connection.on('connected', function () {
console.log('MOngodb connection open to ' + configure.creds.mongodb);
require('./model');
});
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('MOngodb connection error: ' + err);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', function () {
console.log('MOngodb connection disconnected');
});
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('MOngodb connection disconnected through app termination');
process.exit(0);
});
});
require('./model');
update 28/06
I have since realised this understanding regarding loading sequence is incorrect. read here
Might have something to do with you're connection using the mongodb library and then trying to save using mongoose. Mongoose has mongodb as a dependency and is probably not resolving to the connection you've made. Remove your mongodb code and use the mongoose connect() function to establish db connection.
something like:
mongoose.connect('mongodb://localhost:port/test', function(err){
if(err) console.log(err);
else console.log('Connected');
});
I've been studying mongoose for three days and I'm a bit confused about the use of these two methods (i know that "mongoose.connection()" will be deprecated in the future...)
The problem is: when I'm trying to convert (from "mongoose.connection()" to "mongoose.createConnection()") the action.js file of this example https://gist.github.com/2785463 it seems to not work for me...
there's my code...
var mongoose = require('mongoose'),
db = mongoose.createConnection('localhost', 'test');
db.on('error', function () {
console.log('Error! Database connection failed.');
});
db.once('open', function (argument) {
console.log('Database connection established!');
mongoose.connection.db.collectionNames(function (error, names) {
if (error) {
console.log('Error: '+ error);
} else {
console.log(names);
};
});
});
and there's my terminal output (typing "node test.js" on my ubuntu terminal..)
Database connection established!
/home/_user_/Scrivania/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:437
throw err;
^
TypeError: Cannot call method 'collectionNames' of undefined
at NativeConnection.<anonymous> (/home/_user_/Scrivania/test2.js:11:25)
at NativeConnection.g (events.js:192:14)
at NativeConnection.EventEmitter.emit (events.js:93:17)
at open (/home/_user_/Scrivania/node_modules/mongoose/lib/connection.js:408:10)
at NativeConnection.Connection.onOpen (/home/_user_/Scrivania/node_modules/mongoose/lib/connection.js:415:5)
at Connection._open (/home/_user_/Scrivania/node_modules/mongoose/lib/connection.js:386:10)
at NativeConnection.doOpen (/home/_user_/Scrivania/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js:47:5)
at Db.open (/home/_user_/Scrivania/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js:287:14)
at Server.connect.connectCallback (/home/_user_/Scrivania/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:235:7)
at g (events.js:192:14)
If you don't call mongoose.connect() then mongoose.connection doesn't contain an an open connection. You should be using the return value from your mongo.createConnection() call instead (that you've saved into db).
So the last section of code should change to:
UPDATED
db.db.collectionNames(function (error, names) {
if (error) {
console.log('Error: '+ error);
} else {
console.log(names);
};
});
I don't see a collectionNames method on Connection; looks like you have to follow properties down into the native connection object to access that (see above code).