FlatObjectMetadataMaps and non FP style refactor (#13590)
# Introduction - Retrieveing flat-object-metadata-maps for input transpilation, we decided not to introduce map merge for remaining validation operation for the moment - Refactored the field metadata service v2 to sequentially optimistically render on each iteration
This commit is contained in:
+107
-33
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@@ -13,10 +14,13 @@ import {
|
||||
FieldMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service';
|
||||
import { FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type';
|
||||
import { fromCreateFieldInputToFlatFieldAndItsFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-and-its-flat-object-metadata.util';
|
||||
import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import { mergeFlatFieldMetadatasInFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/merge-flat-field-metadatas-in-flat-object-metadata.util';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { dispatchAndMergeFlatFieldMetadatasInFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/dispatch-and-merge-flat-field-metadatas-in-flat-object-metadatas.util';
|
||||
import { fromObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-maps-to-flat-object-metadatas.util';
|
||||
import { removeFlatFieldMetadataFromFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/remove-flat-field-metadata-from-flat-object-metadatas.util';
|
||||
import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util';
|
||||
import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service';
|
||||
import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service';
|
||||
import { WorkspaceMigrationRunnerV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-migration-runner-v2.service';
|
||||
@@ -58,62 +62,132 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
|
||||
const workspaceId = fieldMetadataInputs[0].workspaceId;
|
||||
|
||||
const { objectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeMetadataMaps(
|
||||
const { flatObjectMetadataMaps: existingFlatObjectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeFlatObjectMetadataMaps(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const existingFlatObjectMetadatas =
|
||||
fromObjectMetadataMapsToFlatObjectMetadatas(objectMetadataMaps);
|
||||
|
||||
const flatFieldMetadatasToCreate = (
|
||||
await Promise.all(
|
||||
fieldMetadataInputs.map(
|
||||
async (fieldMetadataInput) =>
|
||||
await fromCreateFieldInputToFlatFieldAndItsFlatObjectMetadata({
|
||||
existingFlatObjectMetadatas,
|
||||
existingFlatObjectMetadataMaps,
|
||||
rawCreateFieldInput: fieldMetadataInput,
|
||||
}),
|
||||
),
|
||||
)
|
||||
).flat();
|
||||
|
||||
const optimisticRenderedFlatObjectMetadatas =
|
||||
dispatchAndMergeFlatFieldMetadatasInFlatObjectMetadatas({
|
||||
flatObjectMetadatas: existingFlatObjectMetadatas,
|
||||
flatFieldMetadatas: flatFieldMetadatasToCreate,
|
||||
});
|
||||
const existingFlatObjectMetadatas = Object.values(
|
||||
existingFlatObjectMetadataMaps.byId,
|
||||
).map(fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata);
|
||||
|
||||
const flatFieldMetadataValidationPromises = flatFieldMetadatasToCreate.map(
|
||||
(flatFieldMetadataToValidate) =>
|
||||
this.flatFieldMetadataValidatorService.validateOneFlatFieldMetadata({
|
||||
existingFlatObjectMetadatas:
|
||||
removeFlatFieldMetadataFromFlatObjectMetadatas({
|
||||
flatFieldMetadata: flatFieldMetadataToValidate,
|
||||
flatObjectMetadatas: optimisticRenderedFlatObjectMetadatas,
|
||||
}),
|
||||
flatFieldMetadataToValidate,
|
||||
workspaceId,
|
||||
}),
|
||||
const impactedObjectMetadataIds = Array.from(
|
||||
new Set(
|
||||
flatFieldMetadatasToCreate.map(
|
||||
(flatFieldMetadata) => flatFieldMetadata.objectMetadataId,
|
||||
),
|
||||
),
|
||||
);
|
||||
const filterFlatObjectMetadatasByImpactedIds = (
|
||||
flatObjectMetadatas: FlatObjectMetadata[],
|
||||
) =>
|
||||
flatObjectMetadatas.filter((flatObjectMetadata) =>
|
||||
impactedObjectMetadataIds.includes(flatObjectMetadata.id),
|
||||
);
|
||||
const impactedExistingFlatObjectMetadatas =
|
||||
filterFlatObjectMetadatasByImpactedIds(existingFlatObjectMetadatas);
|
||||
|
||||
const allValidationErrors: FailedFlatFieldMetadataValidationExceptions[] =
|
||||
[];
|
||||
let sequentiallyOptimisticallyRenderedFlatObjectMetadatas = structuredClone(
|
||||
existingFlatObjectMetadatas,
|
||||
);
|
||||
|
||||
const createdFlatFieldMetadataValidationResult = (
|
||||
await Promise.all(flatFieldMetadataValidationPromises)
|
||||
)
|
||||
.flat()
|
||||
.filter(isDefined);
|
||||
for (const flatFieldMetadataToCreate of flatFieldMetadatasToCreate) {
|
||||
let otherFlatObjectMetadataToValidate: FlatObjectMetadata | undefined =
|
||||
undefined;
|
||||
|
||||
if (createdFlatFieldMetadataValidationResult.length > 0) {
|
||||
if (
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadataToCreate,
|
||||
FieldMetadataType.RELATION,
|
||||
) ||
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadataToCreate,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
)
|
||||
) {
|
||||
const relatedFlatFieldMetadataToCreate =
|
||||
flatFieldMetadatasToCreate.find(
|
||||
(relatedFlatFieldMetadata) =>
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
relatedFlatFieldMetadata,
|
||||
FieldMetadataType.RELATION,
|
||||
) &&
|
||||
relatedFlatFieldMetadata.id ===
|
||||
flatFieldMetadataToCreate.relationTargetFieldMetadataId,
|
||||
);
|
||||
const relatedFlatObjectMetadata = isDefined(
|
||||
relatedFlatFieldMetadataToCreate,
|
||||
)
|
||||
? existingFlatObjectMetadataMaps.byId[
|
||||
relatedFlatFieldMetadataToCreate.objectMetadataId
|
||||
]
|
||||
: undefined;
|
||||
|
||||
otherFlatObjectMetadataToValidate =
|
||||
isDefined(relatedFlatObjectMetadata) &&
|
||||
isDefined(relatedFlatFieldMetadataToCreate)
|
||||
? mergeFlatFieldMetadatasInFlatObjectMetadata({
|
||||
flatFieldMetadatas: [relatedFlatFieldMetadataToCreate],
|
||||
flatObjectMetadata: relatedFlatObjectMetadata,
|
||||
})
|
||||
: undefined;
|
||||
}
|
||||
|
||||
const validationErrors =
|
||||
await this.flatFieldMetadataValidatorService.validateOneFlatFieldMetadata(
|
||||
{
|
||||
existingFlatObjectMetadatas:
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas,
|
||||
flatFieldMetadataToValidate: flatFieldMetadataToCreate,
|
||||
workspaceId,
|
||||
othersFlatObjectMetadataToValidate: isDefined(
|
||||
otherFlatObjectMetadataToValidate,
|
||||
)
|
||||
? [otherFlatObjectMetadataToValidate]
|
||||
: undefined,
|
||||
},
|
||||
);
|
||||
|
||||
if (validationErrors.length > 0) {
|
||||
allValidationErrors.push(...validationErrors);
|
||||
continue;
|
||||
}
|
||||
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas =
|
||||
dispatchAndMergeFlatFieldMetadatasInFlatObjectMetadatas({
|
||||
flatFieldMetadatas: [flatFieldMetadataToCreate],
|
||||
flatObjectMetadatas:
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas,
|
||||
});
|
||||
}
|
||||
|
||||
if (allValidationErrors.length > 0) {
|
||||
throw new MultipleMetadataValidationErrors(
|
||||
createdFlatFieldMetadataValidationResult,
|
||||
allValidationErrors,
|
||||
'Multiple validation errors occurred while creating field',
|
||||
);
|
||||
}
|
||||
|
||||
const workspaceMigration = this.workspaceMigrationBuilderV2.build({
|
||||
objectMetadataFromToInputs: {
|
||||
from: existingFlatObjectMetadatas,
|
||||
to: optimisticRenderedFlatObjectMetadatas,
|
||||
from: impactedExistingFlatObjectMetadatas,
|
||||
to: filterFlatObjectMetadatasByImpactedIds(
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas,
|
||||
),
|
||||
},
|
||||
inferDeletionFromMissingObjectFieldIndex: false,
|
||||
workspaceId,
|
||||
|
||||
Reference in New Issue
Block a user