Implement workspace datasource destroy for pg pool (#14232)

This commit is contained in:
Weiko
2025-09-01 20:54:45 +02:00
committed by GitHub
parent d4ee2b6098
commit 866d8bc0ca
2 changed files with 27 additions and 24 deletions
@@ -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<Entity extends ObjectLiteral>(
@@ -248,4 +251,25 @@ export class WorkspaceDataSource extends DataSource {
setFeatureFlagMapVersion(featureFlagMapVersion: string) {
this.featureFlagMapVersion = featureFlagMapVersion;
}
override async destroy(): Promise<void> {
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();
}
}
}
@@ -55,28 +55,6 @@ export class WorkspaceDatasourceFactory {
private readonly workspaceEventEmitter: WorkspaceEventEmitter,
) {}
private async conditionalDestroyDataSource(
dataSource: WorkspaceDataSource,
): Promise<void> {
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<void> {
@@ -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