Clean soft deleted suspended workspace command and ignore-grace-period flag (#17144)
# Introduction In the https://github.com/twentyhq/core-team-issues/issues/1989 's context we will apply migration through an upgrade command post entity backfill to fit the applied constraint. But suspended soft deleted workspace are not included in the upgrade workspace batches In order to be able to pass the constraint in production, discussed with @FelixMalfait, we will manually clear all the currently suspended and soft deleted workspace ignore their grace period ## Force mode When running the command in force it will ignore the limit per execution ( which really serve the cron job ) and the grace period ## Test Tested on a production extract
This commit is contained in:
+7
-9
@@ -26,6 +26,7 @@ import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-in
|
||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
@@ -60,6 +61,12 @@ describe('WorkspaceService', () => {
|
||||
findOneBy: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: ObjectMetadataService,
|
||||
useValue: {
|
||||
deleteWorkspaceAllObjectMetadata: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(UserWorkspaceEntity),
|
||||
useValue: {
|
||||
@@ -280,16 +287,10 @@ describe('WorkspaceService', () => {
|
||||
.spyOn(workspaceRepository, 'findOne')
|
||||
.mockResolvedValue(mockWorkspace);
|
||||
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
|
||||
jest
|
||||
.spyOn(service, 'deleteMetadataSchemaCacheAndUserWorkspace')
|
||||
.mockResolvedValue({} as WorkspaceEntity);
|
||||
|
||||
await service.deleteWorkspace(mockWorkspace.id, false);
|
||||
|
||||
expect(workspaceRepository.delete).toHaveBeenCalledWith(mockWorkspace.id);
|
||||
expect(
|
||||
service.deleteMetadataSchemaCacheAndUserWorkspace,
|
||||
).toHaveBeenCalled();
|
||||
expect(workspaceRepository.softDelete).not.toHaveBeenCalled();
|
||||
expect(workspaceCacheStorageService.flush).toHaveBeenCalledWith(
|
||||
mockWorkspace.id,
|
||||
@@ -331,9 +332,6 @@ describe('WorkspaceService', () => {
|
||||
.spyOn(workspaceRepository, 'findOne')
|
||||
.mockResolvedValue(mockWorkspace);
|
||||
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
|
||||
jest
|
||||
.spyOn(service, 'deleteMetadataSchemaCacheAndUserWorkspace')
|
||||
.mockResolvedValue({} as WorkspaceEntity);
|
||||
|
||||
await service.deleteWorkspace(mockWorkspace.id, false);
|
||||
|
||||
|
||||
+15
-23
@@ -37,6 +37,7 @@ import {
|
||||
WorkspaceNotFoundDefaultError,
|
||||
} from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
@@ -44,8 +45,8 @@ import {
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { prefillCompanies } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-companies';
|
||||
import { prefillDashboards } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-dashboards';
|
||||
import { prefillOpportunities } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-opportunities';
|
||||
@@ -102,6 +103,7 @@ export class WorkspaceService extends TypeOrmQueryService<WorkspaceEntity> {
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly subdomainManagerService: SubdomainManagerService,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly customDomainManagerService: CustomDomainManagerService,
|
||||
@InjectMessageQueue(MessageQueue.deleteCascadeQueue)
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
@@ -282,20 +284,6 @@ export class WorkspaceService extends TypeOrmQueryService<WorkspaceEntity> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Should be removed once AddWorkspaceForeignKeysMigrationCommand has been run successfully in production
|
||||
* As we will be able to rely on foreignKey delete cascading
|
||||
*/
|
||||
async deleteMetadataSchemaCacheAndUserWorkspace(workspace: WorkspaceEntity) {
|
||||
await this.userWorkspaceService.deleteUserWorkspace({
|
||||
userWorkspaceId: workspace.id,
|
||||
});
|
||||
|
||||
await this.workspaceManagerService.delete(workspace.id);
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async deleteWorkspace(id: string, softDelete = false) {
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: { id },
|
||||
@@ -320,13 +308,6 @@ export class WorkspaceService extends TypeOrmQueryService<WorkspaceEntity> {
|
||||
}
|
||||
this.logger.log(`workspace ${id} user workspaces deleted`);
|
||||
|
||||
await this.workspaceCacheStorageService.flush(
|
||||
workspace.id,
|
||||
workspace.metadataVersion,
|
||||
);
|
||||
await this.flatEntityMapsCacheService.flushFlatEntityMaps({
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
this.logger.log(`workspace ${id} cache flushed`);
|
||||
|
||||
if (this.billingService.isBillingEnabled()) {
|
||||
@@ -341,10 +322,21 @@ export class WorkspaceService extends TypeOrmQueryService<WorkspaceEntity> {
|
||||
return workspace;
|
||||
}
|
||||
|
||||
await this.deleteMetadataSchemaCacheAndUserWorkspace(workspace);
|
||||
// Note: not relying on workspace id FK cascade deletion here to avoid query read timeout later on workspace deletion
|
||||
await this.objectMetadataService.deleteWorkspaceAllObjectMetadata({
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
|
||||
await this.workspaceDataSourceService.deleteWorkspaceDBSchema(workspace.id);
|
||||
|
||||
await this.workspaceCacheStorageService.flush(
|
||||
workspace.id,
|
||||
workspace.metadataVersion,
|
||||
);
|
||||
await this.flatEntityMapsCacheService.flushFlatEntityMaps({
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
|
||||
await this.messageQueueService.add<FileWorkspaceFolderDeletionJobData>(
|
||||
FileWorkspaceFolderDeletionJob.name,
|
||||
{ workspaceId: id },
|
||||
|
||||
@@ -31,6 +31,7 @@ import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.r
|
||||
import { AiAgentModule } from 'src/engine/metadata-modules/ai/ai-agent/ai-agent.module';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { ViewModule } from 'src/engine/metadata-modules/view/view.module';
|
||||
@@ -55,6 +56,7 @@ import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-m
|
||||
UserWorkspaceEntity,
|
||||
PublicDomainEntity,
|
||||
]),
|
||||
ObjectMetadataModule,
|
||||
UserWorkspaceModule,
|
||||
WorkspaceManagerModule,
|
||||
FeatureFlagModule,
|
||||
|
||||
Reference in New Issue
Block a user