0.2.0 cleaning script (#2403)
* Update cleaning script to run on old schema * Add boundaries parameter * Stop requesting data for each workspace/table * Stop checking same as seed if not requested * Minor update * Minor update * Minor update * Minor update * Minor update * Simplify result * Simplify result * Simplify result * Delete updates * Fix issues * Update logs * Remove throw when schema does not exist * Remove missing table in old schema * Remove boundaries parameter * Remove useless trycatch
This commit is contained in:
@ -25,17 +25,19 @@ interface ActivityReport {
|
|||||||
displayName: string;
|
displayName: string;
|
||||||
maxUpdatedAt: string;
|
maxUpdatedAt: string;
|
||||||
inactiveDays: number;
|
inactiveDays: number;
|
||||||
}
|
sameAsSeed: boolean;
|
||||||
|
|
||||||
interface SameAsSeedWorkspace {
|
|
||||||
displayName: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DataCleanResults {
|
interface DataCleanResults {
|
||||||
activityReport: { [key: string]: ActivityReport };
|
[key: string]: ActivityReport;
|
||||||
sameAsSeedWorkspaces: { [key: string]: SameAsSeedWorkspace };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formattedPipelineStagesSeed = pipelineStagesSeed.map((pipelineStage) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { position, ...rest } = pipelineStage;
|
||||||
|
return rest;
|
||||||
|
});
|
||||||
|
|
||||||
@Command({
|
@Command({
|
||||||
name: 'workspaces:clean-inactive',
|
name: 'workspaces:clean-inactive',
|
||||||
description: 'Clean inactive workspaces from the public database schema',
|
description: 'Clean inactive workspaces from the public database schema',
|
||||||
@ -83,7 +85,7 @@ export class DataCleanInactiveCommand extends CommandRunner {
|
|||||||
return Boolean(val);
|
return Boolean(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We look for public tables which contains workspaceId and updatedAt columns
|
// We look for public tables which contain workspaceId and updatedAt columns and exist in production database
|
||||||
getRelevantTables() {
|
getRelevantTables() {
|
||||||
return Object.keys(this.prismaService.client).filter(
|
return Object.keys(this.prismaService.client).filter(
|
||||||
(name) =>
|
(name) =>
|
||||||
@ -96,36 +98,58 @@ export class DataCleanInactiveCommand extends CommandRunner {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTableMaxUpdatedAt(table, workspace) {
|
async getMaxUpdatedAtForAllWorkspaces(tables, workspaces) {
|
||||||
return await this.prismaService.client[table].aggregate({
|
const result = {};
|
||||||
_max: { updatedAt: true },
|
for (const table of tables) {
|
||||||
where: { workspaceId: { equals: workspace.id } },
|
result[table] = {};
|
||||||
});
|
const groupByWorkspaces = await this.prismaService.client[table].groupBy({
|
||||||
|
by: ['workspaceId'],
|
||||||
|
_max: { updatedAt: true },
|
||||||
|
where: {
|
||||||
|
workspaceId: { in: workspaces.map((workspace) => workspace.id) },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
for (const groupByWorkspace of groupByWorkspaces) {
|
||||||
|
result[table][groupByWorkspace.workspaceId] =
|
||||||
|
groupByWorkspace._max.updatedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addMaxUpdatedAtToWorkspaces(result, workspace, table) {
|
async addMaxUpdatedAtToWorkspaces(
|
||||||
const newUpdatedAt = await this.getTableMaxUpdatedAt(table, workspace);
|
result,
|
||||||
if (!result.activityReport[workspace.id]) {
|
workspace,
|
||||||
result.activityReport[workspace.id] = {
|
table,
|
||||||
|
maxUpdatedAtForAllWorkspaces,
|
||||||
|
) {
|
||||||
|
const newUpdatedAt = maxUpdatedAtForAllWorkspaces[table][workspace.id];
|
||||||
|
if (!result[workspace.id]) {
|
||||||
|
result[workspace.id] = {
|
||||||
displayName: workspace.displayName,
|
displayName: workspace.displayName,
|
||||||
maxUpdatedAt: null,
|
maxUpdatedAt: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
newUpdatedAt &&
|
newUpdatedAt &&
|
||||||
newUpdatedAt._max.updatedAt &&
|
new Date(result[workspace.id].maxUpdatedAt) < new Date(newUpdatedAt)
|
||||||
new Date(result.activityReport[workspace.id].maxUpdatedAt) <
|
|
||||||
new Date(newUpdatedAt._max.updatedAt)
|
|
||||||
) {
|
) {
|
||||||
result.activityReport[workspace.id].maxUpdatedAt =
|
result[workspace.id].maxUpdatedAt = newUpdatedAt;
|
||||||
newUpdatedAt._max.updatedAt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async getSeedTableData(workspaces) {
|
||||||
async detectWorkspacesWithSeedDataOnly(result, workspace) {
|
const where = {
|
||||||
|
workspaceId: { in: workspaces.map((workspace) => workspace.id) },
|
||||||
|
};
|
||||||
const companies = await this.prismaService.client.company.findMany({
|
const companies = await this.prismaService.client.company.findMany({
|
||||||
select: { name: true, domainName: true, address: true, employees: true },
|
select: {
|
||||||
where: { workspaceId: { equals: workspace.id } },
|
name: true,
|
||||||
|
domainName: true,
|
||||||
|
address: true,
|
||||||
|
employees: true,
|
||||||
|
workspaceId: true,
|
||||||
|
},
|
||||||
|
where,
|
||||||
});
|
});
|
||||||
const people = await this.prismaService.client.person.findMany({
|
const people = await this.prismaService.client.person.findMany({
|
||||||
select: {
|
select: {
|
||||||
@ -134,121 +158,178 @@ export class DataCleanInactiveCommand extends CommandRunner {
|
|||||||
city: true,
|
city: true,
|
||||||
email: true,
|
email: true,
|
||||||
avatarUrl: true,
|
avatarUrl: true,
|
||||||
|
workspaceId: true,
|
||||||
},
|
},
|
||||||
where: { workspaceId: { equals: workspace.id } },
|
where,
|
||||||
});
|
});
|
||||||
const pipelineStages =
|
const pipelineStages =
|
||||||
await this.prismaService.client.pipelineStage.findMany({
|
await this.prismaService.client.pipelineStage.findMany({
|
||||||
select: {
|
select: {
|
||||||
name: true,
|
name: true,
|
||||||
color: true,
|
color: true,
|
||||||
position: true,
|
|
||||||
type: true,
|
type: true,
|
||||||
|
workspaceId: true,
|
||||||
},
|
},
|
||||||
where: { workspaceId: { equals: workspace.id } },
|
where,
|
||||||
});
|
});
|
||||||
const pipelines = await this.prismaService.client.pipeline.findMany({
|
const pipelines = await this.prismaService.client.pipeline.findMany({
|
||||||
select: {
|
select: {
|
||||||
name: true,
|
name: true,
|
||||||
icon: true,
|
icon: true,
|
||||||
pipelineProgressableType: true,
|
pipelineProgressableType: true,
|
||||||
|
workspaceId: true,
|
||||||
},
|
},
|
||||||
where: { workspaceId: { equals: workspace.id } },
|
where,
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
companies,
|
||||||
|
people,
|
||||||
|
pipelineStages,
|
||||||
|
pipelines,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async detectWorkspacesWithSeedDataOnly(result, workspace, seedTableData) {
|
||||||
|
const companies = seedTableData.companies.reduce((filtered, company) => {
|
||||||
|
if (company.workspaceId === workspace.id) {
|
||||||
|
delete company.workspaceId;
|
||||||
|
filtered.push(company);
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}, []);
|
||||||
|
const people = seedTableData.people.reduce((filtered, person) => {
|
||||||
|
if (person.workspaceId === workspace.id) {
|
||||||
|
delete person.workspaceId;
|
||||||
|
filtered.push(person);
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}, []);
|
||||||
|
const pipelineStages = seedTableData.pipelineStages.reduce(
|
||||||
|
(filtered, pipelineStage) => {
|
||||||
|
if (pipelineStage.workspaceId === workspace.id) {
|
||||||
|
delete pipelineStage.workspaceId;
|
||||||
|
filtered.push(pipelineStage);
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const pipelines = seedTableData.pipelines.reduce((filtered, pipeline) => {
|
||||||
|
if (pipeline.workspaceId === workspace.id) {
|
||||||
|
delete pipeline.workspaceId;
|
||||||
|
filtered.push(pipeline);
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}, []);
|
||||||
if (
|
if (
|
||||||
isEqual(people, peopleSeed) &&
|
isEqual(people, peopleSeed) &&
|
||||||
isEqual(companies, companiesSeed) &&
|
isEqual(companies, companiesSeed) &&
|
||||||
isEqual(pipelineStages, pipelineStagesSeed) &&
|
isEqual(pipelineStages, formattedPipelineStagesSeed) &&
|
||||||
isEqual(pipelines, [pipelinesSeed])
|
isEqual(pipelines, [pipelinesSeed])
|
||||||
) {
|
) {
|
||||||
result.sameAsSeedWorkspaces[workspace.id] = {
|
result[workspace.id].sameAsSeed = true;
|
||||||
displayName: workspace.displayName,
|
} else {
|
||||||
};
|
{
|
||||||
|
result[workspace.id].sameAsSeed = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findInactiveWorkspaces(result, options) {
|
async getWorkspaces(options) {
|
||||||
const where = options.workspaceId
|
const where = options.workspaceId
|
||||||
? { id: { equals: options.workspaceId } }
|
? { id: { equals: options.workspaceId } }
|
||||||
: {};
|
: {};
|
||||||
const workspaces = await this.prismaService.client.workspace.findMany({
|
return await this.prismaService.client.workspace.findMany({
|
||||||
where,
|
where,
|
||||||
|
orderBy: [{ createdAt: 'asc' }],
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findInactiveWorkspaces(workspaces, result) {
|
||||||
const tables = this.getRelevantTables();
|
const tables = this.getRelevantTables();
|
||||||
|
const maxUpdatedAtForAllWorkspaces =
|
||||||
|
await this.getMaxUpdatedAtForAllWorkspaces(tables, workspaces);
|
||||||
|
const seedTableData = await this.getSeedTableData(workspaces);
|
||||||
for (const workspace of workspaces) {
|
for (const workspace of workspaces) {
|
||||||
await this.detectWorkspacesWithSeedDataOnly(result, workspace);
|
|
||||||
for (const table of tables) {
|
for (const table of tables) {
|
||||||
await this.addMaxUpdatedAtToWorkspaces(result, workspace, table);
|
await this.addMaxUpdatedAtToWorkspaces(
|
||||||
|
result,
|
||||||
|
workspace,
|
||||||
|
table,
|
||||||
|
maxUpdatedAtForAllWorkspaces,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
await this.detectWorkspacesWithSeedDataOnly(
|
||||||
|
result,
|
||||||
|
workspace,
|
||||||
|
seedTableData,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filterResults(result, options) {
|
filterResults(result, options) {
|
||||||
for (const workspaceId in result.activityReport) {
|
for (const workspaceId in result) {
|
||||||
const timeDifferenceInSeconds = Math.abs(
|
const timeDifferenceInSeconds = Math.abs(
|
||||||
new Date().getTime() -
|
new Date().getTime() -
|
||||||
new Date(result.activityReport[workspaceId].maxUpdatedAt).getTime(),
|
new Date(result[workspaceId].maxUpdatedAt).getTime(),
|
||||||
);
|
);
|
||||||
const timeDifferenceInDays = Math.ceil(
|
const timeDifferenceInDays = Math.ceil(
|
||||||
timeDifferenceInSeconds / (1000 * 3600 * 24),
|
timeDifferenceInSeconds / (1000 * 3600 * 24),
|
||||||
);
|
);
|
||||||
if (timeDifferenceInDays < options.sameAsSeedDays) {
|
if (
|
||||||
delete result.sameAsSeedWorkspaces[workspaceId];
|
timeDifferenceInDays < options.days &&
|
||||||
}
|
(!result[workspaceId].sameAsSeed ||
|
||||||
if (timeDifferenceInDays < options.days) {
|
timeDifferenceInDays < options.sameAsSeedDays)
|
||||||
delete result.activityReport[workspaceId];
|
) {
|
||||||
|
delete result[workspaceId];
|
||||||
} else {
|
} else {
|
||||||
result.activityReport[workspaceId].inactiveDays = timeDifferenceInDays;
|
result[workspaceId].inactiveDays = timeDifferenceInDays;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(result) {
|
async delete(result, options) {
|
||||||
if (Object.keys(result.activityReport).length) {
|
const workspaceCount = Object.keys(result).length;
|
||||||
console.log('Deleting inactive workspaces');
|
if (workspaceCount) {
|
||||||
|
console.log(
|
||||||
|
`Deleting \x1b[36m${workspaceCount}\x1b[0m inactive since \x1b[36m${options.days} days\x1b[0m or same as seed since \x1b[36m${options.sameAsSeedDays} days\x1b[0m workspaces`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for (const workspaceId in result.activityReport) {
|
let count = 1;
|
||||||
|
for (const workspaceId in result) {
|
||||||
process.stdout.write(`- deleting ${workspaceId} ...`);
|
process.stdout.write(`- deleting ${workspaceId} ...`);
|
||||||
await this.workspaceService.deleteWorkspace({
|
await this.workspaceService.deleteWorkspace({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
console.log(' done!');
|
console.log(
|
||||||
}
|
` done! ....... ${Math.floor((100 * count) / workspaceCount)}%`,
|
||||||
if (Object.keys(result.sameAsSeedWorkspaces).length) {
|
);
|
||||||
console.log('Deleting same as Seed workspaces');
|
count += 1;
|
||||||
}
|
|
||||||
for (const workspaceId in result.sameAsSeedWorkspaces) {
|
|
||||||
process.stdout.write(`- deleting ${workspaceId} ...`);
|
|
||||||
await this.workspaceService.deleteWorkspace({
|
|
||||||
workspaceId,
|
|
||||||
});
|
|
||||||
console.log(' done!');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
displayResults(result) {
|
displayResults(result, totalWorkspacesCount) {
|
||||||
const workspacesToDelete = new Set();
|
|
||||||
for (const workspaceId in result.activityReport) {
|
|
||||||
workspacesToDelete.add(workspaceId);
|
|
||||||
}
|
|
||||||
for (const workspaceId in result.sameAsSeedWorkspaces) {
|
|
||||||
workspacesToDelete.add(workspaceId);
|
|
||||||
}
|
|
||||||
console.log(`${workspacesToDelete.size} workspace(s) will be deleted:`);
|
|
||||||
console.log(result);
|
console.log(result);
|
||||||
|
console.log(
|
||||||
|
`${
|
||||||
|
Object.keys(result).length
|
||||||
|
} out of ${totalWorkspacesCount} workspace(s) checked (${Math.floor(
|
||||||
|
(100 * Object.keys(result).length) / totalWorkspacesCount,
|
||||||
|
)}%) will be deleted`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(
|
async run(
|
||||||
_passedParam: string[],
|
_passedParam: string[],
|
||||||
options: DataCleanInactiveOptions,
|
options: DataCleanInactiveOptions,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const result: DataCleanResults = {
|
const result: DataCleanResults = {};
|
||||||
activityReport: {},
|
const workspaces = await this.getWorkspaces(options);
|
||||||
sameAsSeedWorkspaces: {},
|
const totalWorkspacesCount = workspaces.length;
|
||||||
};
|
console.log(totalWorkspacesCount, 'workspace(s) to analyse');
|
||||||
await this.findInactiveWorkspaces(result, options);
|
await this.findInactiveWorkspaces(workspaces, result);
|
||||||
this.filterResults(result, options);
|
this.filterResults(result, options);
|
||||||
this.displayResults(result);
|
this.displayResults(result, totalWorkspacesCount);
|
||||||
if (!options.dryRun) {
|
if (!options.dryRun) {
|
||||||
options = await this.inquiererService.ask('confirm', options);
|
options = await this.inquiererService.ask('confirm', options);
|
||||||
if (!options.confirmation) {
|
if (!options.confirmation) {
|
||||||
@ -257,7 +338,7 @@ export class DataCleanInactiveCommand extends CommandRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!options.dryRun) {
|
if (!options.dryRun) {
|
||||||
await this.delete(result);
|
await this.delete(result, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -127,7 +127,8 @@ export class DataSourceService implements OnModuleInit, OnModuleDestroy {
|
|||||||
const schemaAlreadyExists = await queryRunner.hasSchema(schemaName);
|
const schemaAlreadyExists = await queryRunner.hasSchema(schemaName);
|
||||||
|
|
||||||
if (!schemaAlreadyExists) {
|
if (!schemaAlreadyExists) {
|
||||||
throw new Error(`Schema ${schemaName} does not exist`);
|
await queryRunner.release();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await queryRunner.dropSchema(schemaName, true, true);
|
await queryRunner.dropSchema(schemaName, true, true);
|
||||||
|
|||||||
@ -103,4 +103,8 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadata> {
|
|||||||
|
|
||||||
return createdFieldMetadata;
|
return createdFieldMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async deleteFieldsMetadata(workspaceId: string) {
|
||||||
|
await this.fieldMetadataRepository.delete({ workspaceId });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export const typeORMMetadataModuleOptions: TypeOrmModuleOptions = {
|
|||||||
schema: 'metadata',
|
schema: 'metadata',
|
||||||
entities: [__dirname + '/**/*.entity{.ts,.js}'],
|
entities: [__dirname + '/**/*.entity{.ts,.js}'],
|
||||||
synchronize: false,
|
synchronize: false,
|
||||||
migrationsRun: true,
|
migrationsRun: false,
|
||||||
migrationsTableName: '_typeorm_migrations',
|
migrationsTableName: '_typeorm_migrations',
|
||||||
migrations: [__dirname + '/migrations/*{.ts,.js}'],
|
migrations: [__dirname + '/migrations/*{.ts,.js}'],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -131,7 +131,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadata> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deleteObjectsAndFieldsMetadata(workspaceId: string) {
|
public async deleteObjectsMetadata(workspaceId: string) {
|
||||||
await this.objectMetadataRepository.delete({ workspaceId });
|
await this.objectMetadataRepository.delete({ workspaceId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { MigrationRunnerModule } from 'src/metadata/migration-runner/migration-r
|
|||||||
import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module';
|
import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module';
|
||||||
import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module';
|
import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module';
|
||||||
import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module';
|
import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module';
|
||||||
|
import { FieldMetadataModule } from 'src/metadata/field-metadata/field-metadata.module';
|
||||||
|
|
||||||
import { TenantInitialisationService } from './tenant-initialisation.service';
|
import { TenantInitialisationService } from './tenant-initialisation.service';
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ import { TenantInitialisationService } from './tenant-initialisation.service';
|
|||||||
TenantMigrationModule,
|
TenantMigrationModule,
|
||||||
MigrationRunnerModule,
|
MigrationRunnerModule,
|
||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
|
FieldMetadataModule,
|
||||||
DataSourceMetadataModule,
|
DataSourceMetadataModule,
|
||||||
],
|
],
|
||||||
exports: [TenantInitialisationService],
|
exports: [TenantInitialisationService],
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { DataSourceService } from 'src/metadata/data-source/data-source.service'
|
|||||||
import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service';
|
import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service';
|
||||||
import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service';
|
import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service';
|
||||||
import { DataSourceMetadata } from 'src/metadata/data-source-metadata/data-source-metadata.entity';
|
import { DataSourceMetadata } from 'src/metadata/data-source-metadata/data-source-metadata.entity';
|
||||||
|
import { FieldMetadataService } from 'src/metadata/field-metadata/services/field-metadata.service';
|
||||||
|
|
||||||
import { standardObjectsPrefillData } from './standard-objects-prefill-data/standard-objects-prefill-data';
|
import { standardObjectsPrefillData } from './standard-objects-prefill-data/standard-objects-prefill-data';
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ export class TenantInitialisationService {
|
|||||||
private readonly tenantMigrationService: TenantMigrationService,
|
private readonly tenantMigrationService: TenantMigrationService,
|
||||||
private readonly migrationRunnerService: MigrationRunnerService,
|
private readonly migrationRunnerService: MigrationRunnerService,
|
||||||
private readonly objectMetadataService: ObjectMetadataService,
|
private readonly objectMetadataService: ObjectMetadataService,
|
||||||
|
private readonly fieldMetadataService: FieldMetadataService,
|
||||||
private readonly dataSourceMetadataService: DataSourceMetadataService,
|
private readonly dataSourceMetadataService: DataSourceMetadataService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -78,9 +80,8 @@ export class TenantInitialisationService {
|
|||||||
|
|
||||||
public async delete(workspaceId: string): Promise<void> {
|
public async delete(workspaceId: string): Promise<void> {
|
||||||
// Delete data from metadata tables
|
// Delete data from metadata tables
|
||||||
await this.objectMetadataService.deleteObjectsAndFieldsMetadata(
|
await this.fieldMetadataService.deleteFieldsMetadata(workspaceId);
|
||||||
workspaceId,
|
await this.objectMetadataService.deleteObjectsMetadata(workspaceId);
|
||||||
);
|
|
||||||
await this.tenantMigrationService.delete(workspaceId);
|
await this.tenantMigrationService.delete(workspaceId);
|
||||||
await this.dataSourceMetadataService.delete(workspaceId);
|
await this.dataSourceMetadataService.delete(workspaceId);
|
||||||
// Delete schema
|
// Delete schema
|
||||||
|
|||||||
Reference in New Issue
Block a user