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

Memory leak observed for this library #2889

Open
sairaj-baker opened this issue Jan 28, 2025 · 1 comment
Open

Memory leak observed for this library #2889

sairaj-baker opened this issue Jan 28, 2025 · 1 comment

Comments

@sairaj-baker
Copy link

Description

Dynatrace graph with redis:

Image

DynaTrace grpah without redis:

Image

RedisStore.service.ts
`import { RedisStore } from 'connect-redis'; // Correct import for connect-redis
import { createClient, RedisClientType } from 'redis';
import { AppConfigService } from './AppConfig.service';

export class redisStore {
static redisClient: RedisClientType | null = null;

// Load and initialize the Redis client
static async loadRedis() {
if (this.redisClient) {
return; // Avoid reinitializing if already connected
}

const config = AppConfigService.config;
const { redisConfig } = config;

// Create the Redis client
this.redisClient = createClient({
  socket: {
    host: redisConfig?.host,
    port: redisConfig?.port,
    tls: redisConfig?.tls,
  },
  password: redisConfig?.password,
});

// Handle Redis client errors
this.redisClient.on('error', (err: Error) => {
  console.error('Redis Client Error:', err);
});

try {
  // Wait for the Redis client to connect
  await this.redisClient.connect();
  console.log('Connected to Redis');
} catch (err) {
  console.error('Failed to connect to Redis:', err);
  throw err;
}

}

// Create and return a new Redis session store
static getNewStore() {
this.loadRedis();
if (!this.redisClient) {
throw new Error(
'Redis client is not initialized. Call loadRedis() first.'
);
}
if (!this.redisClient.isOpen) {
throw new Error('Redis client is not connected!');
}
return new RedisStore({
client: this.redisClient,
});
}
}
**Session.service.ts**import _ from 'lodash';

import { AppConfigService } from './AppConfig.service';
import session from 'express-session';
import { redisStore } from './RedisStore.service';
import { NeedToUpdateAny } from '../types';

const config = AppConfigService.config;
const { secure, httpOnly, sameSite } = config;

export class SessionService {
static expressSession = session;
static readonly store: any = redisStore.getNewStore();
static isCallFromMicroApp = (url: string, checkArr?: string[]) => {
const originalUrl = /${url .replace(config.baseHref, '') .replace('/?', '') .toLowerCase()};
const url_split = originalUrl.split('/');
const appName = '/' + url_split[1].toLowerCase();
const appIdx = _.findIndex(config.microappServices, { path: appName });
if (!checkArr) return appIdx === -1;
return checkArr.every((path) => path !== appName) && appIdx === -1;
};
static cookiePath = config.baseHref || '/';
static commonConfig = {
...config.decrypt,
name: 'local.cookie',
proxy: true,
saveUninitialized: false,
cookie: { secure, httpOnly, sameSite, path: SessionService.cookiePath },
};

static singleSession = () => {
return this.expressSession({ ...this.commonConfig, resave: true });
};

static multiSession = () => {
const store = this.store;
return this.expressSession({
...this.commonConfig,
resave: false,
store,
});
};

static sessionSetup = (app: NeedToUpdateAny) => {
const config = AppConfigService.config;
if (config.redisConfig) {
app.use(SessionService.multiSession());
} else {
app.use(SessionService.singleSession());
}
};
}
`

Node.js Version

20

Redis Server Version

No response

Node Redis Version

4.7.0

Platform

Windows

Logs

No logs just see spike in the attached graph above with and without Dynatrace
@bobymicroby
Copy link
Member

@sairaj-baker

Thank you for reporting this potential memory leak. Since you're using connect-redis along with other libraries,
we'll need to first determine if the memory leak is specifically in node-redis itself,
rather than in the session handling or other middleware.

Could you create a minimal reproduction that:

  1. Uses only node-redis (without express-session, connect-redis, or other middleware)
  2. Demonstrates the same memory growth pattern
  3. Includes heap snapshots captured using Node's built-in tools before and after the memory growth

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants