Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleanup store event listeners when process has completed #949

Closed
wants to merge 1 commit into from
Closed

Conversation

k34a
Copy link

@k34a k34a commented Jul 13, 2023

When I connected the PostgreSQL store using connect-session-sequelize, and made session authentication request 11 times (for example - hitting /my-protected-route consecutively), then I get the following warning:

MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 disconnect listeners added to [SequelizeStore]. Use emitter.setMaxListeners() to increase limit
    at _addListener (node:events:587:17)
    at SequelizeStore.addListener (node:events:605:10)
    at session (\open-commerce\backend\node_modules\express-session\index.js:172:9)
    at sessionMiddleware (\open-commerce\backend\middleware\auth\expressSession.ts:15:35)
    at Layer.handle [as handle_request] (\open-commerce\backend\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (\open-commerce\backend\node_modules\express\lib\router\index.js:328:13)
    at \open-commerce\backend\node_modules\express\lib\router\index.js:286:9
    at Function.process_params (\open-commerce\backend\node_modules\express\lib\router\index.js:346:12)
    at next (\open-commerce\backend\node_modules\express\lib\router\index.js:280:10)

Here is the file that I am working on: link

How I am trying to resolve that issue?
Answer: Whenever we use the express-session middleware and move on to next(), we cleanup the event listeners

@@ -187,16 +198,21 @@ function session(options) {
// the store has temporarily disconnected etc
if (!storeReady) {
debug('store is disconnected')
cleanEventListeners();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if a request comes in when the store is not ready, and this removes the listener to make it ready again, then how will the session ever work again? It seems like if the store disconnects and if one request just happened to come in while disconnected, express-session will then never think the store is ever ready again until the entire process is restarted? That seems like a large issue. But I am just starting to take a look at the changes, so maybe I am mistaken. I marked tests are needed, as we'll want to have tests that cover all these new code paths added and probably the scenario I described above too.

@@ -476,16 +492,18 @@ function session(options) {
if (!req.sessionID) {
debug('no SID sent, generating session');
generate();
cleanEventListeners();
Copy link
Contributor

@dougwilson dougwilson Jul 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we remove the event listeners on the store for this condition, which is that a request came in without a session cookie on it? When would they ever get added back so we know when the store becomes disconnected?

@dougwilson
Copy link
Contributor

Here is the file that I am working on: link

Why are you creating a new express-session middleware for every request? It seems that is the issue you are having. You should only make one instance of express-session for your app, not making a new one every time a request comes in. Try the following code:

import { NextFunction, Request, Response } from "express";
import session from "express-session";
import env from "../../config/validateEnv";
import sequelize from "../../db/pgsql";

const SequelizeStore = require("connect-session-sequelize")(session.Store);

const sessionStore = new SequelizeStore({
    db: sequelize,
    tableName: "user_sessions",
});

const sessionMiddleware = session({
      secret: env.EXPRESS_SESSIONS_SECRET,
      store: sessionStore,
      cookie: {
          maxAge: 1000 * 60 * 60 * 24 * 7, // Equals 7 days (7 days * 24 hr/1 day * 60 min/1 hr * 60 sec/1 min * 1000 ms / 1 sec)
      },
      resave: false,
      saveUninitialized: false,
  });

export { sessionMiddleware, sessionStore };

@k34a
Copy link
Author

k34a commented Jul 13, 2023

Here is the file that I am working on: link

Why are you creating a new express-session middleware for every request? It seems that is the issue you are having. You should only make one instance of express-session for your app, not making a new one every time a request comes in. Try the following code:

import { NextFunction, Request, Response } from "express";
import session from "express-session";
import env from "../../config/validateEnv";
import sequelize from "../../db/pgsql";

const SequelizeStore = require("connect-session-sequelize")(session.Store);

const sessionStore = new SequelizeStore({
    db: sequelize,
    tableName: "user_sessions",
});

const sessionMiddleware = session({
      secret: env.EXPRESS_SESSIONS_SECRET,
      store: sessionStore,
      cookie: {
          maxAge: 1000 * 60 * 60 * 24 * 7, // Equals 7 days (7 days * 24 hr/1 day * 60 min/1 hr * 60 sec/1 min * 1000 ms / 1 sec)
      },
      resave: false,
      saveUninitialized: false,
  });

export { sessionMiddleware, sessionStore };

Thanks for the reply @dougwilson, the issue seems to be resolved through this only. Thanks!

Closing the PR now.

@k34a k34a closed this Jul 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants