#In NestJS, can I delete contextIds in the tenant Map to save RAM for tenants that haven't been used

26 messages · Page 1 of 1 (latest)

pure canyon
#
import {
  ContextId,
  ContextIdFactory,
  ContextIdStrategy,
  HostComponentInfo,
} from '@nestjs/core';
import { Request } from 'express';

const tenants = new Map<string, { contextId: ContextId; lastTime: Date }>();

// can i do this?
setInterval(() => {
  const now = new Date();
  for (const [tenantId, { lastTime }] of tenants.entries()) {
    if (now.getTime() - lastTime.getTime() > 1000 * 60 * 60) {
      console.log(`Tenant ${tenantId} is expired`);
      tenants.delete(tenantId);
    }
  }
}, 1000 * 60);

export class AggregateByTenantContextIdStrategy implements ContextIdStrategy {
  attach(contextId: ContextId, request: Request) {
    /* Extract the tenant identifier from the 
       request object into the tenantId variable */
    console.log('AggregateByTenantContextIdStrategy...');
    const tenantId = request.headers['x-tenant-id']?.toString();

    let tenantSubTreeId: ContextId;
    if (tenants.has(tenantId)) {
      const tenant = tenants.get(tenantId);
      tenantSubTreeId = tenant.contextId;
      tenant.lastTime = new Date();
    } else {
      tenantSubTreeId = ContextIdFactory.create();
      tenants.set(tenantId, { contextId, lastTime: new Date() });
    }

    return {
      resolve: (info: HostComponentInfo) =>
        info.isTreeDurable ? tenantSubTreeId : contextId,
      payload: { tenantId },
    };
  }
}

deft elbow
#

you can delete those entries because tenants Map is working like an in-memory cache, right

#

but I'd do this per access instead of with setInterval

pure canyon
#

thank you very much

#

with nestjs i converted my app to SaaS very quickly, thanks nestjs very much

deft elbow
#

if you want to stay with setInterval, I'd suggest you to call .unref() in the return of setInterval()

pure canyon
#

I removed setinterval as you noted.
About unref I don't understand clearly so will take time to learn. Thank you very much

pure canyon
#

@deft elbow What will happen when an attacker sends fake tenantIds? Will the app create new instances and occupy memory?

I have a middleware that intercepts at the beginning and its task is to check for fake tenantIds.

I have tested it myself, and it seems like the middleware successfully blocked it, but I am not sure if I am correct.

deft elbow
#

What will happen when an attacker sends fake tenantIds?
that's all up to your implementation

#

tenants.has(tenantId) would be false, so I didn't get why you're worried as this is like a 'cache miss', which is a valid path

pure canyon
# deft elbow > What will happen when an attacker sends fake tenantIds? that's all up to your...

I'm not worried about the cache map, I'm worried about something else

I am not sure if NestJS will create multiple instances corresponding to the fake tenant IDs. For example,

a request for tenant 1 results in NewsServices for tenant1,

a request for tenant 2 results in NewsServices for tenant2, which is fine.

But if there are requests for fake tenant 1 to fake tenant 10000, will NestJS create an additional 1000 instances of NewsServices or some other instances?

deft elbow
#

there's no 'fake tenant'

#

unless you implement that yourself

#

in that code you shared is just: a tenant id that is in the map and a tenant id there is not

pure canyon
#

That's not the point I'm trying to make, my English is not good, let me clarify the issue I'm still wondering about.

deft elbow
#

in your case, it will create a new subtree for that 'fake tenant', due to how you've implemented that logic

#

if you want to avoid that, you'd have to have a list of all valid tenant IDs or something like that

pure canyon
#

if i block not valid tenant Ids in middleware

#

Does nestjs create instances of new services?

#

or some thing new instance

deft elbow
#

I've no ideia

#

but it's easy to check it out

pure canyon
#

Thank you for your patience

deft elbow
#

but I'd say that if you raise an exception on that attach, nest won't instantiate anything
That's what I expected, at least