diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service.ts index 4d1c16da83..d82a344238 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service.ts @@ -185,102 +185,13 @@ export abstract class WorkspaceEntityMigrationBuilderService< ); this.logger.perfTime( `EntityBuilder ${this.metadataName}`, - 'update validation', - ); - - for (const flatEntityToUpdateUniversalIdentifier in updatedFlatEntityMaps.byUniversalIdentifier) { - const flatEntityUpdate = - updatedFlatEntityMaps.byUniversalIdentifier[ - flatEntityToUpdateUniversalIdentifier - ]; - - if (!isDefined(flatEntityUpdate)) { - throw new FlatEntityMapsException( - 'Could not find flat entity updates in maps dispatcher should never occur', - FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND, - ); - } - - const validationResult = await this.validateFlatEntityUpdate({ - flatEntityUpdate: flatEntityUpdate.update, - optimisticFlatEntityMapsAndRelatedFlatEntityMaps, - workspaceId, - buildOptions, - additionalCacheDataMaps, - universalIdentifier: flatEntityToUpdateUniversalIdentifier, - remainingFlatEntityMapsToValidate: createdFlatEntityMaps, - }); - - if (validationResult.status === 'fail') { - allValidationResult.push(validationResult); - continue; - } - - const existingFlatEntity = findFlatEntityByUniversalIdentifier< - MetadataUniversalFlatEntity - >({ - universalIdentifier: flatEntityToUpdateUniversalIdentifier, - flatEntityMaps: - optimisticFlatEntityMapsAndRelatedFlatEntityMaps[flatEntityMapsKey], - }); - - if (!isDefined(existingFlatEntity)) { - throw new FlatEntityMapsException( - 'Existing flat entity to update post successful validation is not defined, should never occur', - FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND, - ); - } - - const updatedFlatEntity: MetadataUniversalFlatEntity = { - ...existingFlatEntity, - ...flatEntityUpdate.update, - }; - - const diff = Object.fromEntries( - Object.entries(flatEntityUpdate.update).map(([key, after]) => [ - key, - { - before: - existingFlatEntity[key as keyof MetadataUniversalFlatEntity], - after, - }, - ]), - ) as UniversalFlatEntityDiff; - - replaceUniversalFlatEntityInUniversalFlatEntityMapsThroughMutationOrThrow( - { - universalFlatEntity: updatedFlatEntity, - universalFlatEntityMapsToMutate: - optimisticFlatEntityMapsAndRelatedFlatEntityMaps[flatEntityMapsKey], - }, - ); - - actionsResult.update.push( - ...(Array.isArray(validationResult.action) - ? validationResult.action - : [validationResult.action] - ).map((action) => ({ - ...action, - flatEntity: updatedFlatEntity, - diff, - })), - ); - } - - this.logger.perfTimeEnd( - `EntityBuilder ${this.metadataName}`, - 'update validation', + 'creation validation', ); const remainingFlatEntityMapsToCreate = structuredClone( createdFlatEntityMaps, ); - this.logger.perfTime( - `EntityBuilder ${this.metadataName}`, - 'creation validation', - ); - const sortedCreateUniversalIdentifiers = topologicallySortUniversalFlatEntitiesForSelfReferentialFks({ metadataName: this.metadataName, @@ -352,6 +263,93 @@ export abstract class WorkspaceEntityMigrationBuilderService< `EntityBuilder ${this.metadataName}`, 'creation validation', ); + this.logger.perfTime( + `EntityBuilder ${this.metadataName}`, + 'update validation', + ); + + for (const flatEntityToUpdateUniversalIdentifier in updatedFlatEntityMaps.byUniversalIdentifier) { + const flatEntityUpdate = + updatedFlatEntityMaps.byUniversalIdentifier[ + flatEntityToUpdateUniversalIdentifier + ]; + + if (!isDefined(flatEntityUpdate)) { + throw new FlatEntityMapsException( + 'Could not find flat entity updates in maps dispatcher should never occur', + FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND, + ); + } + + const validationResult = await this.validateFlatEntityUpdate({ + flatEntityUpdate: flatEntityUpdate.update, + optimisticFlatEntityMapsAndRelatedFlatEntityMaps, + workspaceId, + buildOptions, + additionalCacheDataMaps, + universalIdentifier: flatEntityToUpdateUniversalIdentifier, + }); + + if (validationResult.status === 'fail') { + allValidationResult.push(validationResult); + continue; + } + + const existingFlatEntity = findFlatEntityByUniversalIdentifier< + MetadataUniversalFlatEntity + >({ + universalIdentifier: flatEntityToUpdateUniversalIdentifier, + flatEntityMaps: + optimisticFlatEntityMapsAndRelatedFlatEntityMaps[flatEntityMapsKey], + }); + + if (!isDefined(existingFlatEntity)) { + throw new FlatEntityMapsException( + 'Existing flat entity to update post successful validation is not defined, should never occur', + FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND, + ); + } + + const updatedFlatEntity: MetadataUniversalFlatEntity = { + ...existingFlatEntity, + ...flatEntityUpdate.update, + }; + + const diff = Object.fromEntries( + Object.entries(flatEntityUpdate.update).map(([key, after]) => [ + key, + { + before: + existingFlatEntity[key as keyof MetadataUniversalFlatEntity], + after, + }, + ]), + ) as UniversalFlatEntityDiff; + + replaceUniversalFlatEntityInUniversalFlatEntityMapsThroughMutationOrThrow( + { + universalFlatEntity: updatedFlatEntity, + universalFlatEntityMapsToMutate: + optimisticFlatEntityMapsAndRelatedFlatEntityMaps[flatEntityMapsKey], + }, + ); + + actionsResult.update.push( + ...(Array.isArray(validationResult.action) + ? validationResult.action + : [validationResult.action] + ).map((action) => ({ + ...action, + flatEntity: updatedFlatEntity, + diff, + })), + ); + } + + this.logger.perfTimeEnd( + `EntityBuilder ${this.metadataName}`, + 'update validation', + ); this.logger.perfTimeEnd( `EntityBuilder ${this.metadataName}`, 'entity processing', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-update-validation-args.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-update-validation-args.type.ts index 005da4ecd0..d1cf1a5560 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-update-validation-args.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-update-validation-args.type.ts @@ -5,7 +5,7 @@ import { type UniversalFlatEntityValidationArgs } from 'src/engine/workspace-man export type FlatEntityUpdateValidationArgs = Omit< UniversalFlatEntityValidationArgs, - 'flatEntityToValidate' + 'flatEntityToValidate' | 'remainingFlatEntityMapsToValidate' > & { flatEntityUpdate: UniversalFlatEntityUpdate; universalIdentifier: string; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-navigation-menu-item-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-navigation-menu-item-validator.service.ts index 135119e99f..5972799eae 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-navigation-menu-item-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-navigation-menu-item-validator.service.ts @@ -284,7 +284,6 @@ export class FlatNavigationMenuItemValidatorService { optimisticFlatEntityMapsAndRelatedFlatEntityMaps: { flatNavigationMenuItemMaps: optimisticFlatNavigationMenuItemMaps, }, - remainingFlatEntityMapsToValidate, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.navigationMenuItem >): FailedFlatEntityValidation<'navigationMenuItem', 'update'> { @@ -353,21 +352,12 @@ export class FlatNavigationMenuItemValidatorService { const newFolderUniversalIdentifier = folderUniversalIdentifierUpdate; - const combinedFlatNavigationMenuItemMaps: MetadataUniversalFlatEntityMaps< - typeof ALL_METADATA_NAME.navigationMenuItem - > = { - byUniversalIdentifier: { - ...remainingFlatEntityMapsToValidate.byUniversalIdentifier, - ...optimisticFlatNavigationMenuItemMaps.byUniversalIdentifier, - }, - }; - const circularDependencyErrors = this.getCircularDependencyValidationErrors( { navigationMenuItemUniversalIdentifier: fromFlatNavigationMenuItem.universalIdentifier, folderUniversalIdentifier: newFolderUniversalIdentifier, - flatNavigationMenuItemMaps: combinedFlatNavigationMenuItemMaps, + flatNavigationMenuItemMaps: optimisticFlatNavigationMenuItemMaps, }, ); @@ -378,7 +368,7 @@ export class FlatNavigationMenuItemValidatorService { const referencedParentNavigationMenuItem = findFlatEntityByUniversalIdentifier({ universalIdentifier: newFolderUniversalIdentifier, - flatEntityMaps: combinedFlatNavigationMenuItemMaps, + flatEntityMaps: optimisticFlatNavigationMenuItemMaps, }); if (!isDefined(referencedParentNavigationMenuItem)) {