From 866d8bc0ca58d31956ffec424508279a5a25df37 Mon Sep 17 00:00:00 2001 From: Weiko Date: Mon, 1 Sep 2025 20:54:45 +0200 Subject: [PATCH] Implement workspace datasource destroy for pg pool (#14232) --- .../datasource/workspace.datasource.ts | 24 +++++++++++++++++ .../factories/workspace-datasource.factory.ts | 27 +++---------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts b/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts index af69be11615..90d91d865bf 100644 --- a/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts +++ b/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts @@ -36,6 +36,7 @@ export class WorkspaceDataSource extends DataSource { rolesPermissionsVersion: string; permissionsPerRoleId: ObjectsPermissionsByRoleIdDeprecated; dataSourceWithOverridenCreateQueryBuilder: WorkspaceDataSource; + isPoolSharingEnabled: boolean; constructor( internalContext: WorkspaceInternalContext, @@ -44,6 +45,7 @@ export class WorkspaceDataSource extends DataSource { featureFlagMap: FeatureFlagMap, rolesPermissionsVersion: string, permissionsPerRoleId: ObjectsPermissionsByRoleIdDeprecated, + isPoolSharingEnabled: boolean, ) { super(options); this.internalContext = internalContext; @@ -53,6 +55,7 @@ export class WorkspaceDataSource extends DataSource { this.manager = this.createEntityManager(); this.rolesPermissionsVersion = rolesPermissionsVersion; this.permissionsPerRoleId = permissionsPerRoleId; + this.isPoolSharingEnabled = isPoolSharingEnabled; } override getRepository( @@ -248,4 +251,25 @@ export class WorkspaceDataSource extends DataSource { setFeatureFlagMapVersion(featureFlagMapVersion: string) { this.featureFlagMapVersion = featureFlagMapVersion; } + + override async destroy(): Promise { + if (this.isPoolSharingEnabled) { + // eslint-disable-next-line no-console + console.log( + `PromiseMemoizer Event: A WorkspaceDataSource for workspace ${this.internalContext.workspaceId} is being cleared. Actual pool closure managed by PgPoolSharedService. Not calling dataSource.destroy().`, + ); + // We should NOT call dataSource.destroy() here, because that would end + // the shared pool, potentially affecting other active users of that pool. + // The PgPoolSharedService is responsible for the lifecycle of shared pools. + + return Promise.resolve(); + } else { + // eslint-disable-next-line no-console + console.log( + `PromiseMemoizer Event: A WorkspaceDataSource for workspace ${this.internalContext.workspaceId} is being cleared. Calling safelyDestroyDataSource.`, + ); + + return super.destroy(); + } + } } diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts index e31de40b4a0..23f2b513206 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts @@ -55,28 +55,6 @@ export class WorkspaceDatasourceFactory { private readonly workspaceEventEmitter: WorkspaceEventEmitter, ) {} - private async conditionalDestroyDataSource( - dataSource: WorkspaceDataSource, - ): Promise { - const isPoolSharingEnabled = this.twentyConfigService.get( - 'PG_ENABLE_POOL_SHARING', - ); - - if (isPoolSharingEnabled) { - this.logger.log( - `PromiseMemoizer Event: A WorkspaceDataSource for workspace ${dataSource.internalContext.workspaceId} is being cleared. Actual pool closure managed by PgPoolSharedService. Not calling dataSource.destroy().`, - ); - // We should NOT call dataSource.destroy() here, because that would end - // the shared pool, potentially affecting other active users of that pool. - // The PgPoolSharedService is responsible for the lifecycle of shared pools. - } else { - this.logger.log( - `PromiseMemoizer Event: A WorkspaceDataSource for workspace ${dataSource.internalContext.workspaceId} is being cleared. Calling safelyDestroyDataSource.`, - ); - await this.safelyDestroyDataSource(dataSource); - } - } - private async safelyDestroyDataSource( dataSource: WorkspaceDataSource, ): Promise { @@ -224,13 +202,14 @@ export class WorkspaceDatasourceFactory { cachedFeatureFlagMap, cachedRolesPermissionsVersion, cachedRolesPermissions, + this.twentyConfigService.get('PG_ENABLE_POOL_SHARING'), ); await workspaceDataSource.initialize(); return workspaceDataSource; }, - this.conditionalDestroyDataSource.bind(this), + this.safelyDestroyDataSource.bind(this), ); if (!workspaceDataSource) { @@ -374,7 +353,7 @@ export class WorkspaceDatasourceFactory { try { await this.promiseMemoizer.clearKeys( `${workspaceId}-`, - this.conditionalDestroyDataSource.bind(this), + this.safelyDestroyDataSource.bind(this), ); } catch (error) { // Log and swallow any errors during cleanup to prevent crashes