Home > Net >  MongoDB Express cannot use a session that has ended
MongoDB Express cannot use a session that has ended

Time:01-23

I'm getting this error MongoExpiredSessionError: Cannot use a session that has ended.

I've tried the answers proposed in similar questions and they mainly suggest to use the await keyword. But as you will see in my code below, I already have set that keyword for all my database functions.

I'm using a proxy to connect the server and the client(React). Sometimes it works fine, but then when I update some code in my client, for some reason the server will throw this error. Then, when I edit something in my server file, it starts working fine again (until I edit something in the client). I'm guessing that the problem lies in the fact that I'm using a proxy.

I followed this tutorial on how to setup a react app with a node js server. Let me know if there is a better alternative.

Here is my code:

app.post("/getSubscribers", (req, res) => {
  var ssn = req.session;

  req.on("close", function(err1){
    console.log("Connection closed (getSubscribers)");
    console.log(err1);
  })

  if(!ssn.logged_in){
    res.send(JSON.stringify("loggedout"));
  }else{
    (async () => {
        try{
            await client.connect();

            console.log("1 (getSubscribers)");
            const db = await client.db("data");
            console.log("2 (getSubscribers)");
            const collection = await db.collection("subscribers");
            console.log("3 (getSubscribers)");
            const query = {user_id: ssn.user_id};
            console.log("4 (getSubscribers)");
            const cursor = await collection.find(query);
            console.log("5 (getSubscribers)");
            const result = await cursor.toArray();
            console.log("6 (getSubscribers)");
            const count = await cursor.count();
            console.log("7 (getSubscribers)");
            const data = {data: result, count: count}
            console.log("8 (getSubscribers)");

            
            res.send(JSON.stringify(data));
            console.log("9 (getSubscribers)");
        }catch(err){
            console.log("ERROR (getSubscribers)");
            console.log(err);
        }finally{
            console.log("Closing (getSubscribers)")
            await client.close();
        }
    })();
  }
});

and this is the error message:

[0] 1 (getSubscribers)
[0] 2 (getSubscribers)
[0] 3 (getSubscribers)
[0] 4 (getSubscribers)
[0] 5 (getSubscribers)
[0] ERROR (getSubscribers)
[0] MongoExpiredSessionError: Cannot use a session that has ended
[0] Closing (getSubscribers)

Sometimes it stops at #5, sometimes at #6.

As I mentioned, the problem is probably related to the way the server is set up, please check out the link and tell me if this is a good way to set up a server or if I should do it differently.

CodePudding user response:

You're connecting/disconnecting to your db on every request to /getSubscribers. So one reason for the ended session could be that if more than one requests are received on your server, the underlying connection is closed for the first request while the other request is being served.

Anyway, it does not make a lot of sense to connect to your db on every request, instead you should do it while starting up your express-app. I'd use something similar like they did in the official tutorial:

// file ./db/conn.js

const { MongoClient } = require('mongodb');   
const client = new MongoClient(<tbd>, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

let dbConnection;

module.exports = {
  connectToServer: (callback) => {
    client.connect(function (err, db) {
      if (err || !db) {
        return callback(err);
      }

      dbConnection = db.db('<tbd>');
      console.log('Successfully connected to MongoDB.');

      return callback();
    });
  },

  getDb: () => {
    return dbConnection;
  },
};

You can then use it like this in your main app.js file:

const app = express();
// ...
// get MongoDB driver connection
const dbo = require('./db/conn');

// perform a database connection when the server starts
dbo.connectToServer((err) => {
  if (err) {
    console.error(err);
    process.exit();
  }

  // start the Express server
  app.listen(PORT, () => {
    console.log(`Server is running on port: ${PORT}`);
  });
});

app.post("/getSubscribers", async (req, res) => {
  const ssn = req.session;

  if(!ssn.logged_in){
    return res.send(JSON.stringify("loggedout"));
  }
  
  const collection = await dbo.getDb().collection("subscribers");
  // rest of your code above
});
  •  Tags:  
  • Related