I am running mongodb as a child process from node.js and require to shut down and restart on demand. using Child_Process.kill("SIGINT") would appear to be the correct way but but it leaves mongo in a confused state which won't restart until repaired (or the lockfile is deleted) Is there a better way to do this?
Thanks,
Andy
Doing kill("SIGINT") cause the database to shut down without going through the required steps and could lead to corrupt data files. So i would not recommend do this.
Normal way to stop database is send command { "shutdown" : 1 } or db.shutdownServer() from mongodb shell, but I don't know exactly how to do it from node.js driver.
you can try something like this:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/admin", function(err, db) {
if (err) {
console.log('mongodb is not running');
process.exit(0);
}
else {
db.command({
shutdown : 1
}, function(err, result) {
console.log('shutting down mongodb - ', err.message);
process.exit(0);
});
}
});
you could end a mongodb process using nodeJS on mac
1) save the script below to a script.js
'use strict'
const exec = require('child_process').execSync;
function killport(port) {
var processId = null
try {
processId = exec(`lsof -t -i:${port}`);
} catch (e) {
console.log("could not catch");
}
if (processId !== null) { // if exists kill
try{
if(exec(`kill ${processId}`)){
console.log("closed");
}
} catch(e){
console.log("error executing");
}
}
}
killport(27017);
2) run node script.js
Related
i am running mongodb 4.2, expressjs 4.15, and node 12.13.
while my api was running, i made some changes to mongo configuration. ever since then i have been getting the following error when trying to query a specific collection:
MongoError: Cannot use a session that has ended
at applySession (/Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/core/sessions.js:697:12)
at _command (/Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/core/wireprotocol/command.js:58:17)
at command (/Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/core/wireprotocol/command.js:28:5)
at Object.query (/Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/core/wireprotocol/query.js:57:3)
at Connection.query (/Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/cmap/connection.js:166:8)
at /Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/core/sdam/server.js:316:12
at Object.callback (/Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/cmap/connection_pool.js:347:7)
at /Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/cmap/connection_pool.js:497:23
at /Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/cmap/connection_pool.js:427:7
at callback (/Users/kendallyoder/Documents/api-three/node_modules/mongodb/lib/core/connection/connect.js:97:5)
this only happens on one collection, all the other collections will give data just fine.
im assuming there is a session hung somewhere that i need to clear. i have already killed and restarted all my dev processes, updated npm, reinstalled mongodb, and cleared all "system.sessions" in the config database.
any ideas?
mongo code:
MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, client) {
// console.log("mongo is awake")
// console.dir(MongoClient,{depth:null})
if(err) callback(null, err)
if(client) {
const db = client.db(dbName)
if(action == 'find') {
db.collection(collection).find(query).project(project).sort(sort).limit(limit).toArray().then((records, err) => {
if(err) callback(null, err)
if(records) callback(records, null)
})
}
// other "actions"
client.close()
}
})
Close the connection inside the callback
if(action == 'find') {
db.collection(collection).find(query).project(project).sort(sort).limit(limit).toArray().then((records, err) => {
if(err) callback(null, err)
if(records) callback(records, null)
client.close() <=============== Close here
})
}
When I connect to mongodb from shell using mongo I need to use the following
mongo -u xxxx -p xxxx --authenticationDatabase admin then I get full access... but I cannot find a way to specify the authenticationDatabase while connecting from nodejs this is my code
var MongoCli = require('mongodb').MongoClient;
var url = "mongodb://127.0.0.1:27017/contactapp";
MongoCli.connect(url,function(err,db){
if(err)
{
console.log('Unable to connect');
}
else
{
console.log('Connected at ',url);
db.authenticate('username','password','--authenticationDatabase admin',function(err,res){
if(err)
{
console.log('Error');
}
else
{
console.log('Auth Success');
var collection = db.collection('contact');
collection.find().toArray(function(err,res){
if(err)
{
console.log(err);
}
else if(res.length)
{
console.log('Found ',res);
}
else
{
console.log('No data found');
}
db.close();
});
}
});
}
});
I need to use the authenticationDatabase. Thanks in advance.
Try to change this:
db.authenticate('username','password','--authenticationDatabase admin',function(err,res){
Whit this:
db.admin().authenticate('username', 'password', function(err,res){
I had the same question on using authenticationDatabase with nodeJS, mongodb and mongoose. Passing the whole path with credentials and a flag worked for me
mongodb://username:password#127.0.0.1:27017/databaseName?authSource=admin
authSource is a flag for authenticationDatabase
My problem is that I can't retrieve data from my mongodb database... And I don't know why.
I probably do something wrong, here is a little samble which doesn't work.
var Db = require('mongodb').Db,
Server = require('mongodb').Server;
var db = new Db('akemichat', new Server('localhost', 27017), {w:1});
db.open(function (err, p_db) {
db = p_db;
});
db.collection('rooms', function (err, collection) {
if (!err) {
collection.find().toArray(function(err, items) {
items.forEach(function(room) {
console.log('hello'); // Never call...
});
});
} else {
console.log(err);
}
});
Notice that I have data in my database as shows the following
➜ akemichat git:(master) ✗ mongo
MongoDB shell version: 2.4.7
connecting to: test
> use akemichat
switched to db akemichat
> db.rooms.find()
{ "name" : "home", "_id" : ObjectId("527008e850305d1b7d000001") }
Thanks for help !
Notice: the example program never ends, I don't know why... Maybe because the connection is never closed but if I call the db.close() in the toArray callback, It will never be called because the callback never happends.
So many things in node are asynchronous. Your connection is open after you are trying to read from your collection.
You should query the collection after you know for sure you are connect. Down and dirty:
var Db = require('mongodb').Db,
Server = require('mongodb').Server;
var db = new Db('akemichat', new Server('localhost', 27017), {w:1});
db.open(function (err, p_db) {
db = p_db;
db.collection('rooms', function (err, collection) {
if (!err) {
collection.find().toArray(function(err, items) {
items.forEach(function(room) {
console.log('hello'); // Never call...
});
});
} else {
console.log(err);
}
});
});
I ran this locally and received back the "hello" message. Also your script never finishes because the node process will run until it is closed or crashes. This is by design. Which also means that you don't have to keep opening and closing your mongo connections. You can open a connection when your application starts and close it when your application is shut down.
I can't seem to find a way of retrieving information on the database current operation using the mongodb module in Node.js.
I have tried something this:
mongodb = require 'mongodb'
server = new mongodb.Server 'localhost', 27017
connector = new mongodb.Db 'test', server
connector.open (err, db) ->
if not err?
db.admin().command {currentOp: 1}, (err, doc) ->
if not err?
console.log doc
of course without any result.
Does anybody have a pointer?
The way to do this directly from node mongodb native driver:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://127.0.0.1:27017/', function (err, db) {
if (err) { throw err; }
db.collection('$cmd.sys.inprog').findOne(function (err, data) {
if (err) { throw err; }
console.log(data.inprog);
});
});
Although it's a command on the shell, it is not a real command. Instead, you need to query the $cmd.sys.inprog collection with findOne(). On the MongoDB shell, you would do:
db.$cmd.sys.inprog.findOne();
You'll want to use the currentOp command on MongoDB 3.2 (see the shell definition of db.currentOp for details).
db.eval("return db.currentOp()",function (err, data) {
console.log('currentOp',err,data);
});
implementation using mongoose:
let db = mongoose.connection.db;
db.command({ currentOp: 1 }, function (err, result) {
if (err) {
console.error(`Agenda :: Kill long mongo queries | Error: ${err}`);
} else {
for (let oper in result.inprog) {
let op = result.inprog[oper - 0];
if (op.secs_running > ENUMS.MONGO_KILL_AFTER_SECONDS && op.op === "query" && !op.ns.startsWith("local")) {
console.info(`Agenda :: Kill long mongo queries | Killing opId: ${op.opid} Running over ${op.secs_running}`);
db.killOp(op.opid);
}
}
}
});
Based on gist
This seems to work, disregarding the MongoDB native driver for Node.js.
exec = require('child_process').exec
exec '/usr/bin/mongo --quiet --host="localhost:27017" "test" --eval "printjson(db.currentOp())"', (err, stdout) ->
console.error "#{err.message}" if err?
console.log JSON.parse stdout
Shouldn't this feature be implemented in the driver?
I am using the following code for connecting the CouchBase
couchbase.connect(config.CouchBaseConnector, function (err, CouchBaseDB) {
if (err) {
throw (err)
}
CouchBaseDB.set(keyPush, docPush, function (err, meta) {
if (err) { console.log(err); }
});
}
But its creating multiple number of connection.
Can someone help me out to fix the issue. Basically I want to do something like connection pool and keep re-using.
I came across a doc from CouchBase regarding the same. But not able to figure it out how exactly it works and the steps to deploy the same on windows 7 64-bit version.
Update:
I think moxi-server is not released for Windows OS as of now.
The Couchbase Node SDK is a Connection Pool itself. It is responsible of managing connection to the cluster, be alerted about any change in the server topology (add/remove/failed nodes)
This is why most of the time you put your code in a global callback method and reuse the connection
var express = require('express'),
driver = require('couchbase'),
routes = require('./routes');
dbConfiguration = {
"hosts": ["my-couchbase-server:8091"],
"bucket": "bucket"
}
driver.connect(dbConfiguration, function(err, cb) {
if (err) {
throw (err)
}
// put your application logic here
});
If you want to use a global variable you need to wait for the callback and be sure that the connection is established before using it.
I found the following code is working for me.
Please anyone has better solution please post it, I always welcome that.
GLOBAL.CouchBaseDBConnection = undefined;
function OpenCouchBase(callback) {
if (CouchBaseDBConnection == undefined) {
couchbase.connect(config.CouchBaseConnector, function (err, couchbaseOpenCon) {
if (err)
return console.log("Failed to connect to the CouchBase");
else {
CouchBaseDBConnection = couchbaseOpenCon
callback(null, couchbaseOpenCon);
}
});
}
else { callback(null, CouchBaseDBConnection); }
};
module.exports.OpenPoolCouchBase = OpenCouchBase;
You can use generic resource pool module for Node: node-pool
It is generic pool, so you can adapt it for your needs.
EDIT:
Here is example code:
var poolModule = require('generic-pool');
var pool = poolModule.Pool({
name : 'couch',
create : function(callback) {
couchbase.connect(config.CouchBaseConnector, function (err, couchbaseOpenCon) {
if (err)
return console.log("Failed to connect to the CouchBase");
else {
CouchBaseDBConnection = couchbaseOpenCon
callback(null, couchbaseOpenCon);
}
});
},
destroy : function(client) { client.end(); },
max : 10,
// specifies how long a resource can stay idle in pool before being removed
idleTimeoutMillis : 30000,
// if true, logs via console.log - can also be a function
log : true
});
// acquire connection - callback function is called once a resource becomes available
pool.acquire(function(err, client) {
if (err) {
// handle error - this is generally the err from your
// factory.create function
}
else {
console.log("do whatever you want with the client ...");
pool.release(client);
});
}
});