MongoDB : Current Topology does not support session - mongodb

I am learning MEAN Stack development. I am trying to execute a transaction.
Steps I followed :
I start the mongod.exe with flag set to --replSet rs0.
Then I start the Mongo Shell.
Then I write following code.
let session: ClientSession | undefined;
try {
const data = req.body;
console.log(data);
const movie = new Movie({ name: data['name'], cast: data['cast'] });
const conn = await db.connect()
session = await conn.startSession()
session.withTransaction(async () => {
const doc = await movie.save({ session: session, validateBeforeSave: true });
SuccessResponse(res);
res.json(doc);
})
await session.commitTransaction()
session.endSession();
} catch (err) {
console.log(err)
await log(err)
if (session) {
//session.abortTransaction();
session.endSession()
}
ServerError(res);
res.end();
}
But I got follwoing error
MongoError: Current topology does not support sessions
Any help.

It seems like if your connection was on a hold (eg. hitting a break point), MongoError: Current topology does not support sessions gets thrown even though Current topology.. part does not have nothing to do with it. Maybe Session connection timed out. Try again would be more appropriate.
So, if you are sure your setup should support sessions, just try again.

Related

Endpoint Not Responding

I'm trying to make CRUD app using mongodb atlas and express when i need to make an GET endpoint its not responding and keeps loading here the code
Get Endpoint:
app.get('/getTodo',(req, res) => {
const cursor = db.getDB().collection(coll).find({});
cursor.toArray(( todos) => {
res.send(todos);
});
}
});
I tried to catch the error using try catch there was no error then i tried to log something after it it logged. I also tried to user async and await samething nothing changed.
what should I do?? what I'm doing wrong??

Insert a user by default in MongoDB in Nest JS (Only when the app starts)

I am changing the project from expressjs to nestjs.
In express, I added an admin user to the database by default in app.ts.
like this:
public async addDefaultAdmin() {
UserModel.find({ role: Roles.admin }).then(async (superAdmin) => {
if (superAdmin.length === 0) {
try {
const newUser = new UserModel({...});
await this.hashPassWord(newUser);
await newUser.save();
console.log("default admin successfully added.");
} catch (error: any) {
console.log(error);
}
}
});
}
I wanted to know how I can do this in NestJS?
Does NestJS or typeOrm have a solution for this issue?
You may need to use lifecycle events. NestJS fires events during application bootstrapping and shutdown.
According to doc, onApplicationBootstrap() event may be helpful in your case.
Called once all modules have been initialized, but before listening for connections.
However, NestJS does not expose a hook after the application starts listening, so in this case you need to run your custom function inside of bootstrap function right after the server could listen to a port.
The pseudocode would be like this:
// main.ts
import { User } from '/path/to/user.entity';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
...
await app.listen(3000);
let user = app.get(getRepositoryToken(User)); // You need to pass the entity file to typeorm
await addDefaultAdmin(user); // Pass the user model, and call the function
}
bootstrap();

Connecting to MongoDB from Vercel

I have a SvelteKit application deployed on vercel.app that uses a MongoDB (Atlas). In most cases the database connection works, but sometimes I get a connection error (connection timed out).
If this error occurs, and I try again to do something that uses the database, it immeadiately logs the same error again. This problem persists for some time, and then suddendly the database connection works again.
(When running the app locally with "npm run dev", using the same database, I've never experienced this error.)
To connect to the database, I defined:
mongodb-client.ts:
import { MongoClient } from 'mongodb';
const uri = process.env.DB_URI;
const dbClient = new MongoClient(uri).connect();
export default dbClient;
and use it like this (in several places):
import dbClient from '$lib/server/mongodb-client';
const user = await (await dbClient).db().collection('users').findOne({username: username});
I guess that, when the dbClient Promise is rejected (for whatever reason), it stays rejected and any subsequent await will immediately result in "rejected" (and therefore it will not try to reconnect; except that at some point it will ...?). Is my understanding correct? How should this be implemented correctly? (E.g. Do I need to add some options to the connection URI when this connection is create from a serverless function? Do I need to add some options when creating/connecting the MongoClient? Do I need to do this manually and add a loop, check if the promise is rejected and try again? Or should this be implemented in a completely different way?)
As you probably have guessed I'm new to JavaScript/TypeScript, MongoDB, Serverless and everything ... Thanks for any help and advice!
You can declare a function handling the connection to the database.
You will handle connection errors there and also check if a connection is already established:
import { MongoClient } from 'mongodb';
const uri = process.env.DB_URI;
const dbClient = new MongoClient(uri);
export const connectDb = async () => {
try {
if (!dbClient.isConnected()) {
await dbClient.connect();
}
return await dbClient.db();
} catch (e) {
console.log(e);
process.exit(1); // Or do something else...
}
};
Usage:
import { connectDb } from '$lib/server/mongodb-client';
const db = await connectDb();
const user = await db.collection('users').findOne({username: username});

mongodb force synchronous to find documents [duplicate]

I'm using the Node.JS driver for MongoDB, and I'd like to perform a synchronous query, like such:
function getAThing()
{
var db = new mongo.Db("mydatabase", server, {});
db.open(function(err, db)
{
db.authenticate("myuser", "mypassword", function(err, success)
{
if (success)
{
db.collection("Things", function(err, collection)
{
collection.findOne({ name : "bob"}, function(err, thing)
{
return thing;
});
});
}
});
});
}
The problem is, db.open is an asychronous call (it doesn't block), so the getAThing returns "undefined" and I want it to return the results of the query. I'm sure I could some sort of blocking mechanism, but I'd like to know the right way to do something like this.
ES 6 (Node 8+)
You can utilize async/await
await operator pauses the execution of asynchronous function until the Promise is resolved and returns the value.
This way your code will work in synchronous way:
const query = MySchema.findOne({ name: /tester/gi });
const userData = await query.exec();
console.log(userData)
Older Solution - June 2013 ;)
Now the Mongo Sync is available, this is the right way to make a synchronous MongoDB query in Node.js.
I am using this for the same. You can just write sync method like below:
var Server = require("mongo-sync").Server;
var server = new Server('127.0.0.1');
var result = server.db("testdb").getCollection("testCollection").find().toArray();
console.log(result);
Note: Its dependent on the node-fiber and some issues are there with it on windows 8.
Happy coding :)
There's no way to make this synchronous w/o some sort of terrible hack. The right way is to have getAThing accept a callback function as a parameter and then call that function once thing is available.
function getAThing(callback)
{
var db = new mongo.Db("mydatabase", server, {});
db.open(function(err, db)
{
db.authenticate("myuser", "mypassword", function(err, success)
{
if (success)
{
db.collection("Things", function(err, collection)
{
collection.findOne({ name : "bob"}, function(err, thing)
{
db.close();
callback(err, thing);
});
});
}
});
});
}
Node 7.6+ Update
async/await now provides a way of coding in a synchronous style when using asynchronous APIs that return promises (like the native MongoDB driver does).
Using this approach, the above method can be written as:
async function getAThing() {
let db = await mongodb.MongoClient.connect('mongodb://server/mydatabase');
if (await db.authenticate("myuser", "mypassword")) {
let thing = await db.collection("Things").findOne({ name: "bob" });
await db.close();
return thing;
}
}
Which you can then call from another async function as let thing = await getAThing();.
However, it's worth noting that MongoClient provides a connection pool, so you shouldn't be opening and closing it within this method. Instead, call MongoClient.connect during your app startup and then simplify your method to:
async function getAThing() {
return db.collection("Things").findOne({ name: "bob" });
}
Note that we don't call await within the method, instead directly returning the promise that's returned by findOne.
While it's not strictly synchronous, a pattern I've repeatedly adopted and found very useful is to use co and promisify yield on asynchronous functions. For mongo, you could rewrite the above:
var query = co( function* () {
var db = new mongo.Db("mydatabase", server, {});
db = promisify.object( db );
db = yield db.open();
yield db.authenticate("myuser", "mypassword");
var collection = yield db.collection("Things");
return yield collection.findOne( { name : "bob"} );
});
query.then( result => {
} ).catch( err => {
} );
This means:
You can write "synchronous"-like code with any asynchronous library
Errors are thrown from the callbacks, meaning you don't need the success check
You can pass the result as a promise to any other piece of code

OpenWhisk stops responding, after the first call

I am using Vagrant VM on Windows 10. I have written an action function in Node.Js. This is a light weigh experimental function to check connectivity to MongoDB from OpenWhisk action, written in Node.JS. Following is the code.
function entryPoint(args) {
var mongoose = require('mongoose');
var MongoClient = require('mongodb').MongoClient;
var Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
return new Promise((resolve, reject) => {
mongoose.connect("mongodb://192.168.16.1:27017/angularcrud").then(
() =>
{
var Coin = new Schema({
name: {
type: String
},
price: {
type: Number
}
});
var coinModel = mongoose.model('Coin', Coin);
coinModel.find(function (err, coins){
if(err){
console.log(err);
}
else {
resolve({coins})
}
});
},
err => { return reject(err)}
);
})
}
module.exports.main = entryPoint;
I have zipped the NodeJS files and created the action in wsk. When I run this for the first time
I get the expected results. But when I run it for the second time, the call hands for a minute or so and then I see the following error.
ok: invoked /_/getcoins, but the request has not yet finished, with id 612da4ebb5f64795ada4ebb5f6e7957c
I do not know where do I start investigating, as I am totally new to both OpenWhisk and MongoDb.
To start investigating this, use wsk activation list 612da4ebb5f64795ada4ebb5f6e7957c in this case to get at least the logs of your failed activation.
I think the error handling in your action is not correct. If the find call returns an error, the Promise is never resolved.
I had a brief look at mongooses documentation. find can apparently return a Promise if you call exec on it.
In any case, make sure to use Promise combinators as much as possible, so you're pretty much guaranteed that any edge-case is properly handled and the Promise always completes in one way or the other. If you need to back out for the "manual" creation of Promises, scope them as small as possible.
function entryPoint(args) {
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
return mongoose.connect("mongodb://192.168.16.1:27017/angularcrud").then(() => {
var Coin = new Schema({
name: {
type: String
},
price: {
type: Number
}
});
var coinModel = mongoose.model('Coin', Coin);
return coinModel.find().exec();
});
}
module.exports.main = entryPoint;
A few remarks I have based on the commands:
1. The request has not yet finished, with id 612da4ebb5f64795ada4ebb5f6e7957c
Try "wsk -i activation get 612da4ebb5f64795ada4ebb5f6e7957c" to see the information about this activation. It should be the status or the result in there.
I suspect that this is an asynchronous call. I suggest you can also try "wsk -i action invoke --blocking" to wait for the result to come back. --blocking means to return with results.