Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 715eed85be | |||
| 03651cab6c | |||
| 493e6a7f8f | |||
| c4775450f5 | |||
| cb6957fa51 | |||
| 9633740132 |
+110
-24
@@ -15,7 +15,11 @@ import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service';
|
||||
import { MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant';
|
||||
@@ -115,32 +119,22 @@ export class BackfillOpportunityOwnerFieldCommand extends ActiveOrSuspendedWorks
|
||||
return;
|
||||
}
|
||||
|
||||
const customOwnerField = flatFieldMetadatas.find(
|
||||
(field) =>
|
||||
field.name === 'owner' &&
|
||||
field.universalIdentifier !== ownerUniversalIdentifier,
|
||||
);
|
||||
const customOwnerField =
|
||||
flatFieldMetadatas.find(
|
||||
(field) =>
|
||||
field.name === 'owner' &&
|
||||
field.universalIdentifier !== ownerUniversalIdentifier,
|
||||
// Some self hoster might have run the name renaming successfully but not the joinColumnName
|
||||
// Rather than asking them to restore db also grabbing them here
|
||||
) ?? flatFieldMetadatas.find((field) => field.name === 'ownerOld');
|
||||
|
||||
if (isDefined(customOwnerField)) {
|
||||
if (options.dryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would rename custom owner field to 'ownerOld' in workspace ${workspaceId}`,
|
||||
);
|
||||
} else {
|
||||
await this.fieldMetadataService.updateOneField({
|
||||
updateFieldInput: {
|
||||
id: customOwnerField.id,
|
||||
name: 'ownerOld',
|
||||
label: 'Owner (Old)',
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Renamed custom owner field to 'ownerOld' in workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
await this.renameCustomOwnerFieldToOwnerOld({
|
||||
customOwnerField,
|
||||
flatFieldMetadataMaps,
|
||||
workspaceId,
|
||||
dryRun: options.dryRun,
|
||||
});
|
||||
}
|
||||
|
||||
if (options.dryRun) {
|
||||
@@ -232,4 +226,96 @@ export class BackfillOpportunityOwnerFieldCommand extends ActiveOrSuspendedWorks
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async renameCustomOwnerFieldToOwnerOld({
|
||||
customOwnerField,
|
||||
flatFieldMetadataMaps,
|
||||
workspaceId,
|
||||
dryRun,
|
||||
}: {
|
||||
customOwnerField: FlatFieldMetadata;
|
||||
flatFieldMetadataMaps: MetadataFlatEntityMaps<'fieldMetadata'>;
|
||||
workspaceId: string;
|
||||
dryRun?: boolean;
|
||||
}): Promise<void> {
|
||||
if (dryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would rename custom owner field to 'ownerOld' in workspace and search for colliding foreignKey ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const isMorphOrRelationField =
|
||||
isMorphOrRelationFlatFieldMetadata(customOwnerField);
|
||||
const hasCollidingJoinColumnName =
|
||||
isMorphOrRelationField &&
|
||||
isDefined(customOwnerField.settings.joinColumnName) &&
|
||||
customOwnerField.settings.joinColumnName === 'ownerId';
|
||||
|
||||
await this.fieldMetadataService.updateOneField({
|
||||
updateFieldInput: {
|
||||
id: customOwnerField.id,
|
||||
name: 'ownerOld',
|
||||
label: 'Owner (Old)',
|
||||
...(hasCollidingJoinColumnName
|
||||
? {
|
||||
settings: {
|
||||
...customOwnerField.settings,
|
||||
joinColumnName: `ownerOldId`,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
});
|
||||
this.logger.log(
|
||||
`Renamed custom owner field to 'ownerOld' in workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (!isMorphOrRelationField || hasCollidingJoinColumnName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const relatedFlatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: customOwnerField.relationTargetFieldMetadataId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (
|
||||
!isDefined(relatedFlatFieldMetadata) ||
|
||||
!isMorphOrRelationFlatFieldMetadata(relatedFlatFieldMetadata)
|
||||
) {
|
||||
this.logger.error(
|
||||
`Could not find custom owner relation target field ${customOwnerField.relationTargetFieldMetadataId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const targetHasCollidingJoinColumnName =
|
||||
isDefined(relatedFlatFieldMetadata.settings.joinColumnName) &&
|
||||
relatedFlatFieldMetadata.settings.joinColumnName === 'ownerId';
|
||||
|
||||
if (!targetHasCollidingJoinColumnName) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.fieldMetadataService.updateOneField({
|
||||
updateFieldInput: {
|
||||
id: relatedFlatFieldMetadata.id,
|
||||
settings: {
|
||||
...relatedFlatFieldMetadata.settings,
|
||||
joinColumnName: `ownerOldId`,
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Renamed custom owner field target related field join column name to 'ownerOldId' in workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { ALL_FLAT_ENTITY_MAPS_PROPERTIES } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-maps-properties.constant';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/services/workspace-migration-runner.service';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-16:flush-v2-cache-and-increment-metadata-version',
|
||||
description: 'Flush the whole v2 cache and increment the metadata version',
|
||||
})
|
||||
export class FlushV2CacheAndIncrementMetadataVersionCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
) {
|
||||
super(workspaceRepository, globalWorkspaceOrmManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Flushing v2 cache and incrementing metadata version for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (options.dryRun) {
|
||||
this.logger.log(
|
||||
`DRY RUN: Would flush v2 cache and increment metadata version for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.workspaceMigrationRunnerService.invalidateCache({
|
||||
allFlatEntityMapsKeys: ALL_FLAT_ENTITY_MAPS_PROPERTIES,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Successfully flushed v2 cache and incremented metadata version for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
+14
-8
@@ -126,14 +126,20 @@ export class UpdateTaskOnDeleteActionCommand extends ActiveOrSuspendedWorkspaces
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
};
|
||||
|
||||
await this.fieldMetadataService.updateOneField({
|
||||
updateFieldInput: {
|
||||
id: taskField.id,
|
||||
settings: updatedSettings,
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
});
|
||||
try {
|
||||
await this.fieldMetadataService.updateOneField({
|
||||
updateFieldInput: {
|
||||
id: taskField.id,
|
||||
settings: updatedSettings,
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.debug(`Error details: ${JSON.stringify(error)}`);
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Successfully updated task relation onDelete to CASCADE in workspace ${workspaceId}`,
|
||||
|
||||
+6
-1
@@ -3,10 +3,12 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { BackfillOpportunityOwnerFieldCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-backfill-opportunity-owner-field.command';
|
||||
import { BackfillStandardPageLayoutsCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-backfill-standard-page-layouts.command';
|
||||
import { FlushV2CacheAndIncrementMetadataVersionCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-flush-v2-cache-and-increment-metadata-version.command';
|
||||
import { IdentifyAgentMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-agent-metadata.command';
|
||||
import { IdentifyFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-field-metadata.command';
|
||||
import { IdentifyIndexMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-index-metadata.command';
|
||||
import { IdentifyObjectMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-object-metadata.command';
|
||||
import { IdentifyRemainingEntitiesMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-remaining-entities-metadata.command';
|
||||
import { IdentifyRoleMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command';
|
||||
import { IdentifyViewFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-field-metadata.command';
|
||||
import { IdentifyViewFilterMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-filter-metadata.command';
|
||||
@@ -16,7 +18,6 @@ import { MakeAgentUniversalIdentifierAndApplicationIdNotNullableMigrationCommand
|
||||
import { MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-field-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
import { MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-index-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
import { MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-object-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
import { IdentifyRemainingEntitiesMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-remaining-entities-metadata.command';
|
||||
import { MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-remaining-entities-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
import { MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
import { MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-field-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
@@ -41,6 +42,7 @@ import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entit
|
||||
import { GlobalWorkspaceDataSourceModule } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-datasource.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { TwentyStandardApplicationModule } from 'src/engine/workspace-manager/twenty-standard-application/twenty-standard-application.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/workspace-migration-runner.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
|
||||
|
||||
@Module({
|
||||
@@ -64,6 +66,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
|
||||
GlobalWorkspaceDataSourceModule,
|
||||
TwentyStandardApplicationModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
],
|
||||
providers: [
|
||||
@@ -90,6 +93,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
|
||||
MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
IdentifyRemainingEntitiesMetadataCommand,
|
||||
FlushV2CacheAndIncrementMetadataVersionCommand,
|
||||
],
|
||||
exports: [
|
||||
UpdateTaskOnDeleteActionCommand,
|
||||
@@ -115,6 +119,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
|
||||
MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
IdentifyRemainingEntitiesMetadataCommand,
|
||||
FlushV2CacheAndIncrementMetadataVersionCommand,
|
||||
],
|
||||
})
|
||||
export class V1_16_UpgradeVersionCommandModule {}
|
||||
|
||||
+6
-3
@@ -24,14 +24,15 @@ import { FixNanPositionValuesInNotesCommand } from 'src/database/commands/upgrad
|
||||
import { MigratePageLayoutWidgetConfigurationCommand } from 'src/database/commands/upgrade-version-command/1-15/1-15-migrate-page-layout-widget-configuration.command';
|
||||
import { BackfillOpportunityOwnerFieldCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-backfill-opportunity-owner-field.command';
|
||||
import { BackfillStandardPageLayoutsCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-backfill-standard-page-layouts.command';
|
||||
import { FlushV2CacheAndIncrementMetadataVersionCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-flush-v2-cache-and-increment-metadata-version.command';
|
||||
import { IdentifyAgentMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-agent-metadata.command';
|
||||
import { IdentifyFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-field-metadata.command';
|
||||
import { IdentifyIndexMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-index-metadata.command';
|
||||
import { IdentifyObjectMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-object-metadata.command';
|
||||
import { IdentifyRemainingEntitiesMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-remaining-entities-metadata.command';
|
||||
import { IdentifyRoleMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command';
|
||||
import { IdentifyViewFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-field-metadata.command';
|
||||
import { IdentifyViewFilterMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-filter-metadata.command';
|
||||
import { IdentifyRemainingEntitiesMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-remaining-entities-metadata.command';
|
||||
import { IdentifyViewGroupMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-group-metadata.command';
|
||||
import { IdentifyViewMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-metadata.command';
|
||||
import { MakeAgentUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-agent-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
@@ -107,6 +108,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
protected readonly makeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
protected readonly identifyRemainingEntitiesMetadataCommand: IdentifyRemainingEntitiesMetadataCommand,
|
||||
protected readonly makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
protected readonly flushV2CacheAndIncrementMetadataVersionCommand: FlushV2CacheAndIncrementMetadataVersionCommand,
|
||||
) {
|
||||
super(
|
||||
workspaceRepository,
|
||||
@@ -142,8 +144,6 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
|
||||
const commands_1160: VersionCommands = [
|
||||
this.updateTaskOnDeleteActionCommand,
|
||||
this.backfillOpportunityOwnerFieldCommand,
|
||||
this.backfillStandardPageLayoutsCommand,
|
||||
this.identifyAgentMetadataCommand,
|
||||
this.identifyFieldMetadataCommand,
|
||||
this.identifyObjectMetadataCommand,
|
||||
@@ -153,6 +153,8 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
this.identifyViewFilterMetadataCommand,
|
||||
this.identifyViewGroupMetadataCommand,
|
||||
this.identifyIndexMetadataCommand,
|
||||
this.backfillOpportunityOwnerFieldCommand,
|
||||
this.backfillStandardPageLayoutsCommand,
|
||||
this
|
||||
.makeAgentUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
this
|
||||
@@ -174,6 +176,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
this.identifyRemainingEntitiesMetadataCommand,
|
||||
this
|
||||
.makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
this.flushV2CacheAndIncrementMetadataVersionCommand,
|
||||
];
|
||||
|
||||
this.allCommands = {
|
||||
|
||||
+12
-1
@@ -6,6 +6,7 @@ import {
|
||||
} from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-required-metadata-for-validation.constant';
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
@@ -38,12 +39,18 @@ export class WorkspaceMigrationValidateBuildAndRunService {
|
||||
private readonly logger = new Logger(
|
||||
WorkspaceMigrationValidateBuildAndRunService.name,
|
||||
);
|
||||
private readonly isDebugEnabled: boolean;
|
||||
|
||||
constructor(
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceMigrationBuildOrchestratorService: WorkspaceMigrationBuildOrchestratorService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
) {}
|
||||
twentyConfigService: TwentyConfigService,
|
||||
) {
|
||||
const logLevels = twentyConfigService.get('LOG_LEVELS');
|
||||
|
||||
this.isDebugEnabled = logLevels.includes('debug');
|
||||
}
|
||||
|
||||
private async computeAllRelatedFlatEntityMaps({
|
||||
allFlatEntityOperationByMetadataName,
|
||||
@@ -186,6 +193,10 @@ export class WorkspaceMigrationValidateBuildAndRunService {
|
||||
});
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
if (this.isDebugEnabled) {
|
||||
this.logger.debug(JSON.stringify(validateAndBuildResult, null, 2));
|
||||
}
|
||||
|
||||
return validateAndBuildResult;
|
||||
}
|
||||
|
||||
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command, Option } from 'nest-commander';
|
||||
import {
|
||||
ALL_METADATA_NAME,
|
||||
type AllMetadataName,
|
||||
} from 'twenty-shared/metadata';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
type ActiveOrSuspendedWorkspacesMigrationCommandOptions,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { type RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/services/workspace-migration-runner.service';
|
||||
|
||||
type FlatCacheFlushCommandOptions =
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandOptions & {
|
||||
allMetadata?: boolean;
|
||||
};
|
||||
|
||||
@Command({
|
||||
name: 'cache:flat-cache-invalidate',
|
||||
description:
|
||||
'Flush flat entity cache for specific metadata names and workspaces',
|
||||
})
|
||||
export class FlatCacheInvalidateCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner<FlatCacheFlushCommandOptions> {
|
||||
private metadataNames: string[] = [];
|
||||
private flatMapsKeysToFlush: (keyof AllFlatEntityMaps)[] = [];
|
||||
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
) {
|
||||
super(workspaceRepository, globalWorkspaceOrmManager, dataSourceService);
|
||||
}
|
||||
|
||||
@Option({
|
||||
flags: '--metadataName <metadataName>',
|
||||
description:
|
||||
'Metadata name(s) to flush cache for. Can be specified multiple times.',
|
||||
required: false,
|
||||
})
|
||||
parseMetadataName(val: string): string[] {
|
||||
this.metadataNames.push(val);
|
||||
|
||||
return this.metadataNames;
|
||||
}
|
||||
|
||||
@Option({
|
||||
flags: '--all-metadata',
|
||||
description:
|
||||
'Flush cache for all metadata names. Takes precedence over --metadataName.',
|
||||
required: false,
|
||||
})
|
||||
parseAllMetadata(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
override async runMigrationCommand(
|
||||
passedParams: string[],
|
||||
options: FlatCacheFlushCommandOptions,
|
||||
): Promise<void> {
|
||||
if (!options.allMetadata && this.metadataNames.length === 0) {
|
||||
this.logger.error(
|
||||
'Either --all-metadata or at least one --metadataName must be provided.',
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const validatedMetadataNames = this.validateAndExpandMetadataNames({
|
||||
inputMetadataNames: this.metadataNames,
|
||||
allMetadata: options.allMetadata,
|
||||
});
|
||||
|
||||
if (validatedMetadataNames === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.flatMapsKeysToFlush = this.computeFlatMapsKeysWithRelated(
|
||||
validatedMetadataNames,
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
`Will flush cache for the following flat maps keys: ${this.flatMapsKeysToFlush.join(', ')}`,
|
||||
);
|
||||
|
||||
await super.runMigrationCommand(passedParams, options);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
await this.workspaceMigrationRunnerService.invalidateCache({
|
||||
allFlatEntityMapsKeys: this.flatMapsKeysToFlush,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Successfully invalidated cache for workspace: ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
private validateAndExpandMetadataNames({
|
||||
inputMetadataNames,
|
||||
allMetadata,
|
||||
}: {
|
||||
inputMetadataNames: string[];
|
||||
allMetadata?: boolean;
|
||||
}): AllMetadataName[] | null {
|
||||
const validMetadataNames = Object.keys(
|
||||
ALL_METADATA_NAME,
|
||||
) as AllMetadataName[];
|
||||
|
||||
if (allMetadata) {
|
||||
this.logger.log('Using all metadata names');
|
||||
|
||||
return validMetadataNames;
|
||||
}
|
||||
|
||||
const invalidNames = inputMetadataNames.filter(
|
||||
(name) => !validMetadataNames.includes(name as AllMetadataName),
|
||||
);
|
||||
|
||||
if (invalidNames.length > 0) {
|
||||
this.logger.error(
|
||||
`Invalid metadata name(s) provided: ${invalidNames.join(', ')}`,
|
||||
);
|
||||
this.logger.error(
|
||||
`Valid metadata names are: ${validMetadataNames.join(', ')}, or use --all-metadata`,
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return inputMetadataNames as AllMetadataName[];
|
||||
}
|
||||
|
||||
private computeFlatMapsKeysWithRelated(
|
||||
metadataNames: AllMetadataName[],
|
||||
): ReturnType<typeof getMetadataFlatEntityMapsKey>[] {
|
||||
const allMetadataNamesToFlush = [
|
||||
...new Set([
|
||||
...metadataNames,
|
||||
...metadataNames.flatMap(getMetadataRelatedMetadataNames),
|
||||
]),
|
||||
];
|
||||
|
||||
const allFlatMapsKeys = allMetadataNamesToFlush.map(
|
||||
getMetadataFlatEntityMapsKey,
|
||||
);
|
||||
|
||||
return allFlatMapsKeys;
|
||||
}
|
||||
}
|
||||
+24
-34
@@ -14,7 +14,6 @@ import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/wor
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { WorkspaceMigration } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration';
|
||||
import { WorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
|
||||
import {
|
||||
WorkspaceMigrationRunnerException,
|
||||
WorkspaceMigrationRunnerExceptionCode,
|
||||
@@ -35,19 +34,18 @@ export class WorkspaceMigrationRunnerService {
|
||||
) {}
|
||||
|
||||
private getLegacyCacheInvalidationPromises({
|
||||
workspaceMigration: { actions, workspaceId },
|
||||
allFlatEntityMapsKeys,
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceMigration: Omit<WorkspaceMigration, 'relatedFlatEntityMapsKeys'>;
|
||||
allFlatEntityMapsKeys: (keyof AllFlatEntityMaps)[];
|
||||
workspaceId: string;
|
||||
}): Promise<void>[] {
|
||||
const asyncOperations: Promise<void>[] = [];
|
||||
const shouldIncrementMetadataGraphqlSchemaVersion = actions.some(
|
||||
(action) => {
|
||||
return (
|
||||
action.metadataName === 'objectMetadata' ||
|
||||
action.metadataName === 'fieldMetadata'
|
||||
);
|
||||
},
|
||||
);
|
||||
const flatMapsKeysSet = new Set(allFlatEntityMapsKeys);
|
||||
|
||||
const shouldIncrementMetadataGraphqlSchemaVersion =
|
||||
flatMapsKeysSet.has('flatObjectMetadataMaps') ||
|
||||
flatMapsKeysSet.has('flatFieldMetadataMaps');
|
||||
|
||||
if (shouldIncrementMetadataGraphqlSchemaVersion) {
|
||||
asyncOperations.push(
|
||||
@@ -57,16 +55,15 @@ export class WorkspaceMigrationRunnerService {
|
||||
);
|
||||
}
|
||||
|
||||
const viewRelatedMetadataNames = [
|
||||
'view',
|
||||
'viewFilter',
|
||||
'viewGroup',
|
||||
'viewField',
|
||||
'viewFilterGroup',
|
||||
const viewRelatedFlatMapsKeys: (keyof AllFlatEntityMaps)[] = [
|
||||
'flatViewMaps',
|
||||
'flatViewFilterMaps',
|
||||
'flatViewGroupMaps',
|
||||
'flatViewFieldMaps',
|
||||
'flatViewFilterGroupMaps',
|
||||
];
|
||||
const shouldInvalidFindCoreViewsGraphqlCacheOperation = actions.some(
|
||||
(action) => viewRelatedMetadataNames.includes(action.metadataName),
|
||||
);
|
||||
const shouldInvalidFindCoreViewsGraphqlCacheOperation =
|
||||
viewRelatedFlatMapsKeys.some((key) => flatMapsKeysSet.has(key));
|
||||
|
||||
if (
|
||||
shouldInvalidFindCoreViewsGraphqlCacheOperation ||
|
||||
@@ -80,11 +77,9 @@ export class WorkspaceMigrationRunnerService {
|
||||
);
|
||||
}
|
||||
|
||||
const shouldInvalidateRoleMapCache = actions.some((action) => {
|
||||
return (
|
||||
action.metadataName === 'role' || action.metadataName === 'roleTarget'
|
||||
);
|
||||
});
|
||||
const shouldInvalidateRoleMapCache =
|
||||
flatMapsKeysSet.has('flatRoleMaps') ||
|
||||
flatMapsKeysSet.has('flatRoleTargetMaps');
|
||||
|
||||
if (
|
||||
shouldIncrementMetadataGraphqlSchemaVersion ||
|
||||
@@ -105,14 +100,12 @@ export class WorkspaceMigrationRunnerService {
|
||||
return asyncOperations;
|
||||
}
|
||||
|
||||
private async invalidateCachePostExecution({
|
||||
async invalidateCache({
|
||||
allFlatEntityMapsKeys,
|
||||
workspaceId,
|
||||
actions,
|
||||
}: {
|
||||
allFlatEntityMapsKeys: (keyof AllFlatEntityMaps)[];
|
||||
workspaceId: string;
|
||||
actions: WorkspaceMigrationAction[];
|
||||
}): Promise<void> {
|
||||
this.logger.time(
|
||||
'Runner',
|
||||
@@ -126,10 +119,8 @@ export class WorkspaceMigrationRunnerService {
|
||||
|
||||
const invalidationResults = await Promise.allSettled(
|
||||
this.getLegacyCacheInvalidationPromises({
|
||||
workspaceMigration: {
|
||||
actions,
|
||||
workspaceId,
|
||||
},
|
||||
allFlatEntityMapsKeys,
|
||||
workspaceId,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -214,10 +205,9 @@ export class WorkspaceMigrationRunnerService {
|
||||
|
||||
this.logger.timeEnd('Runner', 'Transaction execution');
|
||||
|
||||
await this.invalidateCachePostExecution({
|
||||
await this.invalidateCache({
|
||||
allFlatEntityMapsKeys,
|
||||
workspaceId,
|
||||
actions,
|
||||
});
|
||||
|
||||
this.logger.timeEnd('Runner', 'Total execution');
|
||||
|
||||
+5
@@ -1,14 +1,17 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DiscoveryModule } from '@nestjs/core';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
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 { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { WorkspaceSchemaMigrationRunnerActionHandlersModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/workspace-schema-migration-runner-action-handlers.module';
|
||||
import { FlatCacheInvalidateCommand } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/commands/flat-cache-invalidate.command';
|
||||
import { WorkspaceMigrationRunnerActionHandlerRegistryService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/registry/workspace-migration-runner-action-handler-registry.service';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/services/workspace-migration-runner.service';
|
||||
|
||||
@@ -23,10 +26,12 @@ import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/wo
|
||||
DiscoveryModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
WorkspaceCacheModule,
|
||||
TypeOrmModule.forFeature([WorkspaceEntity]),
|
||||
],
|
||||
providers: [
|
||||
WorkspaceMigrationRunnerService,
|
||||
WorkspaceMigrationRunnerActionHandlerRegistryService,
|
||||
FlatCacheInvalidateCommand,
|
||||
],
|
||||
exports: [WorkspaceMigrationRunnerService],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user