how node js connect with mongodb using tcp? - node.js

How the tcp connection is established and closed during the database call?
The below code is to get lists of databases in mongodb using mongoclient in nodejs
async function main(){
const uri = "mongodb+srv://<username>:<password>#<your-cluster-url>/test?retryWrites=true&w=majority";
const client = new MongoClient(uri);
try {
await client.connect();
await listDatabases(client);
} catch (e) {
console.error(e);
} finally {
await client.close();
}
}
main().catch(console.error);
1.Does the "await client.connect()" establish a tcp connection with mongoDb?
2.Does the "await client.close()"close a tcp connection with mongoDb?
3.How does the mongodb and nodejs communicate using tcp ?

node-mongodb-native's .connect() and .close() manage a Topology of Servers that have Monitored Connections communicating via a MessageStream

Related

Mongo db connection to node js without ODM error handling

I am comfortable with crud operations in mongo db and just want to perform crud operations in my app . I don't have good reason to use ODM .Here's my working code with nodeScheduler as my DB
let {MongoClient} = require('mongodb')
let connect =() =>{
const uri ="mongodb://localhost:27017";
// Create a new MongoClient
const client = new MongoClient(uri);
async function run() {
try {
// Connect the client to the server (optional starting in v4.7)
await client.connect();
// Establish and verify connection
await client.db("nodeScheduler").command({ ping: 1 });
console.log("Connected successfully to server");
} finally {
// Ensures that the client will close when you finish/error
await client.close();
}
}
run().catch(console.dir);
}
My Question is then :
If I give non-existent db then also I am getting in console Connected successfully to server. How do I validate existent db's and existent collections with Mongo Driver

listening server Down or any other events with mongo db driver native on node js

hello im using mongod on nodejs
"mongodb": "^4.9.0"
I want to catch events from client when some bad happens like server Down, reconnect, close, error or others.
In this docs, alot of these events dosent occur https://www.mongodb.com/docs/drivers/node/current/fundamentals/monitoring/cluster-monitoring/
this.client = new Mongodb.MongoClient(this.url);
const eventName = ""; // some events for server down or other
this.client.on(eventName, (event: any) => {
console.log(event);
console.log(`received ${eventName}, ${event}`);
});

socket.io and node cluster: dispatch events to sockets

I have a nodejs cluster server that is using mongo changestream listener, to emit data to clients over socket.io. I'm using Redis to store a userId and the socketId of all the connected users in a hash.
{ userId: 'aaa', socketId: 'bbb' }
The redis clients for storing this data is initialized in the master process.
The mongo changestream is created in the master process.
When the changestream sees a new document, it will send the document to a child process as a message. When the child process receives the message, it can retrieve the userId from the document. With the userId, the socketId for the client connection can be retrieved from redis.
The issue I am having is in trying to emit a message using the socketId after it is retrieved from redis.
I am creating a sockethandler object that contains the socketId. When I use this socketId to emit a socket message, like so:
io.sockets.to(userSocketId)
.emit("confirmOrder", "Your order is being processed!")
I receive an error:
(node:31804) UnhandledPromiseRejectionWarning: Error: The client is closed
at new ClientClosedError (/Users/a999999999/code/*/node_modules/#node-redis/client/dist/lib/errors.js:24:9)
The error is from redis, and originated on the socket emit line written above. ^^
Here is more code from the worker process:
const pubClient = createClient({ host: "127.0.0.1", port: 6379 }),
subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
setupWorker(io);
io.on("connection", (socket) => {
const socketId = socket.id;
socket.emit("connection", "SERVER: you are connected");
socket.on("userConnect", (user) => {
let { userId } = user;
userConnectClient
.HSET(userId, { userId, socketId })
.catch((err) => console.log("ERROR: ", err));
});
});
process.on("message", async ({ type, data }) => {
switch (type) {
case "dispatch:order":
let { order } = JSON.parse(data);
const socketsHandler = await createSocketsHandler(order);
const userSocketId = socketsHandler.user.socketId;
io.sockets
.to(userSocketId)
.emit("confirmOrder", "Your order is being processed!");
break;
}
});
async function createSocketsHandler(order) {
let { userId } = order;
let user = await userConnectClient
.HGETALL(userId)
.catch((err) => console.log(err));
return {
user: user,
};
}
I am temporarily stumped at this point. Currently experimenting with the io object, and trying to find better tools to monitor redis. Any help/questions is appreciated! Thank you!
I've since realized why the redis client was not working properly. I'm making use of publisher and subscriber clients with redis. The problem was, I was creating the redis clients in the worker process of the server. So, whenever the server is making a command to redis, it is not able to do it properly because there is a pair of clients for each worker process, which is not the proper implementation, I believe.
This was solved by creating the redisClient outside of my cluster server code. ;P My server can now properly subscribe to redis client in master and worker process!

create new tedious connection every time for a new API call?

I am working on creating Express JS as my API server, using tedious to connect to my SQL Server DB.
Currently, in every request logic, I'll create a new tedious Connection object, connect to the DB, execute the query, then close the connection.
import { Connection } from 'tedious';
export class Controller {
all(_: Request, res: Response): void {
const connection = new Connection(getConfig()); // create a new connection everytime
connection.on('connect', (err) => {
if (err) {
console.log('Connection Failed');
throw err;
}
getProducts(connection, _, res); // in there at the end, will call connection.close()
});
connection.connect();
}
import { Request, Response } from 'express';
import { Connection, Request as SqlReq } from 'tedious';
export default function getProducts(connection: Connection, _: Request, res: Response) {
const query = `SELECT * FROM Production.Product FOR JSON PATH;`;
let resultJson = ''; // prepare this result in return from SQL query
const sqlReq = new SqlReq(query, (err, _) => {
if (err) {
throw err;
}
// when request finished
connection.close();
res.json(JSON.parse(resultJson));
});
Is it a good or bad practice to create the connect, connect and close every time for a new API call? If there is a better way to handle the connection, may I have any reference or example?
just make sure that the connection is created only once by using this function. It will create the connection only on first call and return the previously created connection on subsequent calls.
var connection = null;
const getConnection = async () => {
if (connection) return connection;
connection = new Connection(getConfig());
return tmp;
};
Then you should leave the connection open by not calling close.
Better use connection pooling in mysql. During app startup, you can create a pool of threads used for db connecting purpose. It will be very fast, if you retrieve from the pool and establish the connection.
After your query execution/ manipulation, ensure to release the connection. So it will go to connection pool and available for further requests.
Ref : How do I create a MySQL connection pool while working with NodeJS and Express?
Ref : Release connection
node.js + mysql connection pooling

Kontainer-di with Mongo Native

I'm trying to get the MongoDB Native Driver to work with Kontainer-di. I want to add the connected client (returned from the connect method) to the container so that I can inject it into the controllers/services directly.
There is an option to use a start function which returns a promise which I thought would work with the mongo native connect function. The database is connected inside the then. My issue is that I'm not sure how I can access the connected database client to add the session to the container.
My code so far looks like:
var mongoClient = require('mongodb').MongoClient;
var promise = require('bluebird');
var mongoFactory = function(config) {
function start() {
return mongoClient.connect("mongodb://127.0.0.1:27017/test", {promiseLibrary: promise})
.then(function(database) {
console.log('mongo connection initialised');
})
.catch(function(err) {
console.error('Error: ', err);
});
}
function stop() {
db.close();
}
return {
start: start,
stop: stop
}
}
module.exports = mongoFactory;
In case somebody else has the same issue as me. I ended up going with the mongojs library instead which doesn't use promises for the connection so the active connection could easily be added to the container.
I still wanted to use promises rather than callbacks for the queries so I used bluebird and it's promisifyAll method.

Resources