-
Notifications
You must be signed in to change notification settings - Fork 49
Open
Labels
investigationWhy is this happening?Why is this happening?solvedThe question was answered or the problem was solvedThe question was answered or the problem was solved
Description
I’m using a tenant-per-database setup and durable providers for TENANT_KYSELY_CONNECTION.
After upgrading @nestjs-cls/transactional from 2.5.1 to 2.6.0, I noticed an issue:
When making requests in the following sequence — Tenant A → Tenant B → Tenant A —
the second request for Tenant A incorrectly returns Tenant B’s connection (and data) 😅
Here’s the comparison between the versions:
@nestjs-cls/transactional@2.5.1...@nestjs-cls/transactional@2.6.0
I’ll try to create a reproducible example soon, but I’m not doing anything unusual.
Downgrading back to 2.5.1 resolves the issue.
A sample outline of the module. Everything in the registry is correct, it just the front txHost connection a service that uses it.
@Global()
@Module({
imports: [ClsModule],
providers: [TenantKyselyRegistry],
exports: [TenantKyselyRegistry],
})
export class TenantKyselyModule {
public static register(): DynamicModule {
return {
module: TenantKyselyModule,
imports: [
RequestConnectionModule,
VaultModule,
ConfigModule,
ClsModule.forRoot({
plugins: [
new ClsPluginTransactional({
imports: [],
adapter: new TransactionalAdapterKysely({
kyselyInstanceToken: TENANT_KYSELY_CONNECTION,
}),
}),
],
}),
],
providers: [
{
provide: TENANT_KYSELY_CONNECTION,
scope: Scope.REQUEST,
durable: true,
inject: [
REQUEST,
TenantKyselyRegistry,
ConfigService,
],
useFactory: ( request) => {
const tenantId = request.headers['tenant-id']
const { db } = registry.getOrCreate(tenantId, { database: tenantId , ....});
return db;
},
},
],
exports: [TENANT_KYSELY_CONNECTION],
};
}
}
@Injectable()
export class TenantKyselyRegistry implements OnApplicationShutdown {
private readonly registry = new Map<string, PoolEntry>();
private readonly logger = new Logger('TenantKyselyRegistry');
getOrCreate(tenantId: string, poolConfig: PoolConfig): PoolEntry {
const key = `${tenantId}`;
const existing = this.registry.get(key);
if (existing) return existing;
const pool = new Pool(poolConfig);
const db = new Kysely<unknown>({
dialect: new PostgresDialect({ pool }),
});
const entry = { pool, db } as const;
this.registry.set(key, entry);
return entry;
}
async onApplicationShutdown() {
const entries = Array.from(this.registry.values());
await Promise.allSettled(entries.map((e) => e.pool.end()));
this.registry.clear();
}
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
investigationWhy is this happening?Why is this happening?solvedThe question was answered or the problem was solvedThe question was answered or the problem was solved