From d640b93096320a5c230d3174028108cd37932839 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Fri, 31 Oct 2025 17:20:51 +0100 Subject: [PATCH] Improve v2 and cache invalidation perfs (#15467) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Introduction Log are debug logs of `packages/twenty-server/test/integration/metadata/suites/object-metadata/create-delete-and-create-object-metadata-v2.integration-spec.ts`run ten times in a row on clean db reset ## Next Will improve cache computation to lighter invalidation. RelationLoad `query` does not seem to work with typeorm so I'll continue the custom integration i've started in https://github.com/twentyhq/twenty/tree/optimize-cache-read-v2 ## Integration tests duration Significant test duration improvement too ### Before image ### After image ## What's next - The legacy cache invalidation removal - Factorizing redis calls in only one operation ## Autogenerated performance comparison ( including mutation refactor too ) [Before](https://gist.github.com/prastoin/3c1e21fa9e3b3ce4b0716902ff4a2dd6) [After](https://gist.github.com/prastoin/7bfddd14bfded2e4991a9378970a026d) The optimized implementation shows **dramatic performance improvements** across all metrics: - ๐Ÿš€ **Cache Invalidation**: 156.3ms โ†’ 76.8ms (**50.9% faster**) - ๐Ÿš€ **Builder Operations**: 21.3ms โ†’ 14.2ms (**33.3% faster**) - โšก **Consistency**: 16.4% more predictable performance --- ## 1. Overall Performance Summary | Component | Before (avg) | After (avg) | Best (After) | Worst (After) | Improvement | |-----------|-------------|-------------|--------------|---------------|-------------| | **Total Execution Time** | 180.2ms | 110.5ms | 52.3ms | 585.9ms | **38.7% faster** โšกโšก | | **Cache Invalidation** | 156.3ms | 76.8ms | 47.8ms | 285.1ms | **50.9% faster** โšกโšกโšก | | **Transaction Execution** | 22.4ms | 22.1ms | 0.99ms | 314.2ms | Similar | | **Initial Cache Retrieval** | 0.81ms | 2.08ms | 0.21ms | 8.24ms | Similar | | **Entity Builder (total)** | 21.3ms | 14.2ms | 0.36ms | 42.5ms | **33.3% faster** โšก | ### Total Execution Time Distribution #### Before (Legacy Sequential) ``` Time (ms) Count Percentage Visualization < 150 18 16% โ–ˆโ–ˆโ–ˆโ–ˆ 150-180 32 29% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 180-210 35 32% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 210-250 17 15% โ–ˆโ–ˆโ–ˆโ–ˆ 250-350 6 5% โ–ˆ > 350 2 2% โ–Œ ``` #### After (Optimized Parallel) ``` Time (ms) Count Percentage Visualization < 70 28 31% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 70-100 31 34% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 100-150 18 20% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 150-200 8 9% โ–ˆโ–ˆ 200-300 4 4% โ–ˆ > 300 2 2% โ–Œ ``` --- ## 2. Builder Performance Breakdown ### Field Metadata Builder | Operation | Before (avg) | After (avg) | Improvement | |-----------|-------------|-------------|-------------| | Matrix computation | 3.5ms | 3.4ms | Similar | | Creation validation | 15.2ms | 2.1ms | **86% faster** โšกโšกโšก | | Deletion validation | 0.08ms | 0.06ms | Similar | | Update validation | 1.3ms | 0.09ms | **93% faster** โšกโšกโšก | | Entity processing | 18.6ms | 11.8ms | **37% faster** โšก | | **Total validateAndBuild** | **21.3ms** | **14.2ms** | **33% faster** โšก | #### Performance Distribution ``` Before: โ–โ–‚โ–„โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–†โ–„โ–‚โ– (wide spread, 15-28ms range) After: โ–โ–โ–ƒโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ƒโ–โ– (tight clustering, 10-18ms range) ``` ## 4. Cache Invalidation Performance Breakdown ### Cache Invalidation Summary | Metric | Before (Legacy) | After (Optimized) | Improvement | |--------|-----------------|-------------------|-------------| | **Best Time** | 131.965ms | 47.833ms | **63.7% faster** โšกโšกโšก | | **10th Percentile** | 140.2ms | 51.7ms | **63.1% faster** โšกโšกโšก | | **25th Percentile** | 146.1ms | 54.4ms | **62.7% faster** โšกโšกโšก | | **Median (50th)** | 155.1ms | 63.4ms | **59.1% faster** โšกโšกโšก | | **Average** | 156.3ms | 76.8ms | **50.9% faster** โšกโšกโšก | | **75th Percentile** | 160.2ms | 90.2ms | **43.7% faster** โšกโšก | | **90th Percentile** | 191.7ms | 100.2ms | **47.7% faster** โšกโšก | | **95th Percentile** | 235.6ms | 110.3ms | **53.2% faster** โšกโšกโšก | | **99th Percentile** | 278.2ms | 224.9ms | **19.1% faster** โšก | | **Worst Time** | 383.914ms | 285.102ms | **25.7% faster** โšก | ### Cache Invalidation Time Distribution #### Before (Legacy Sequential) ``` Time (ms) Count Percentage Visualization 130-140 3 3% โ–Š 140-150 15 14% โ–ˆโ–ˆโ–ˆโ–ˆ 150-160 48 44% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 160-180 31 28% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 180-220 8 7% โ–ˆโ–ˆ 220-280 3 3% โ–Š > 280 2 2% โ–Œ ``` #### After (Optimized Parallel + Intersection) ``` Time (ms) Count Percentage Visualization < 50 3 3% โ–Š 50-60 27 25% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 60-70 25 23% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 70-90 25 23% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 90-100 15 14% โ–ˆโ–ˆโ–ˆโ–ˆ 100-120 8 7% โ–ˆโ–ˆ 120-150 3 3% โ–Š > 150 4 4% โ–ˆ ``` ## 6. Performance Consistency Analysis ### Standard Deviation & Variance | Metric | Before | After | Improvement | |--------|--------|-------|-------------| | **Cache Invalidation Std Dev** | 42.1ms | 35.2ms | **16.4% more consistent** โšก | | **Total Execution Std Dev** | 68.3ms | 89.1ms | Slightly more variable | | **Coefficient of Variation (Cache)** | 26.9% | 45.8% | More variance | | **Outliers (> 2ฯƒ)** | 5 cases | 3 cases | **40% fewer outliers** โšก | --- --- .../application/application-sync.service.ts | 12 +- ...ace-flat-cron-trigger-map-cache.service.ts | 16 +- ...atabase-event-trigger-map-cache.service.ts | 39 ++-- ...metadata-many-to-one-relations.constant.ts | 2 +- ...ate-empty-all-flat-entity-maps.constant.ts | 19 ++ ...create-empty-flat-entity-maps.constant.ts} | 11 +- .../empty-all-flat-entity-maps.constant.ts | 18 -- ...y-or-all-flat-entity-maps-cache.service.ts | 41 ++-- .../metadata-many-to-one-join-column.type.ts | 6 + ...many-to-one-related-metadata-names.type.ts | 3 +- .../get-sub-flat-entity-maps-or-throw.util.ts | 4 +- ...-to-flat-field-metadatas-to-create.spec.ts | 4 +- ...e-flat-field-metadata-map-cache.service.ts | 139 +++++++++---- ...n-field-input-transpilations-error.util.ts | 2 +- ...ph-or-relation-flat-field-metadata.util.ts | 2 +- .../workspace-flat-index-map-cache.service.ts | 17 +- .../flat-object-metadata-maps.mock.ts | 4 +- ...-flat-object-metadata-map-cache.service.ts | 97 ++++++--- ...space-flat-view-field-map-cache.service.ts | 16 +- ...pace-flat-view-filter-map-cache.service.ts | 16 +- ...space-flat-view-group-map-cache.service.ts | 16 +- .../flat-view/flat-view.module.ts | 12 +- .../workspace-flat-view-map-cache.service.ts | 86 +++++--- ...ce-flat-route-trigger-map-cache.service.ts | 16 +- ...t-serverless-function-map-cache.service.ts | 39 ++-- .../regroup-entities-by-related-entity-id.ts | 39 ++++ .../workspace-flat-map-cache.module.ts | 4 +- ...ty-orchestrator-actions-report.constant.ts | 22 ++- ...ty-orchestrator-failure-report.constant.ts | 20 +- ...ce-migration-build-orchestrator.service.ts | 10 +- ...ject-and-create-field-actions.util.spec.ts | 14 +- ...ject-and-delete-field-actions.util.spec.ts | 12 +- ...ity-maps-through-mutation-or-throw.util.ts | 54 +++++ ...ity-maps-through-mutation-or-throw.util.ts | 60 ++++++ ...-created-updated-matrix-dispatcher.util.ts | 28 ++- ...ity-maps-through-mutation-or-throw.util.ts | 28 +++ ...-v2-cron-trigger-action-builder.service.ts | 19 +- ...e-event-trigger-actions-builder.service.ts | 19 +- ...ration-v2-field-actions-builder.service.ts | 75 +++---- ...ration-v2-index-actions-builder.service.ts | 98 +++++---- ...ation-v2-object-actions-builder.service.ts | 19 +- ...2-route-trigger-actions-builder.service.ts | 19 +- ...erless-function-actions-builder.service.ts | 19 +- ...n-v2-view-field-actions-builder.service.ts | 110 +++++------ ...-v2-view-filter-actions-builder.service.ts | 82 ++++---- ...n-v2-view-group-actions-builder.service.ts | 108 +++++----- ...gration-v2-view-actions-builder.service.ts | 187 +++++++++--------- ...ace-entity-migration-builder-v2.service.ts | 68 ++++--- .../types/flat-entity-validation-args.type.ts | 2 +- .../flat-entity-validation-result.type.ts | 2 - .../flat-cron-trigger-validator.service.ts | 13 +- ...atabase-event-trigger-validator.service.ts | 16 +- .../flat-field-metadata-validator.service.ts | 28 +-- .../flat-index-metadata-validator.service.ts | 9 +- .../flat-object-metadata-validator.service.ts | 8 +- .../flat-route-trigger-validator.service.ts | 10 +- .../flat-view-field-validator.service.ts | 21 +- .../flat-view-filter-validator.service.ts | 14 +- .../flat-view-group-validator.service.ts | 16 +- .../services/flat-view-validator.service.ts | 6 +- .../workspace-migration-runner-v2.service.ts | 70 ++++--- 61 files changed, 1120 insertions(+), 846 deletions(-) create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/create-empty-all-flat-entity-maps.constant.ts rename packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/{empty-flat-entity-maps.constant.ts => create-empty-flat-entity-maps.constant.ts} (51%) delete mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/empty-all-flat-entity-maps.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type.ts create mode 100644 packages/twenty-server/src/engine/workspace-flat-map-cache/utils/regroup-entities-by-related-entity-id.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util.ts diff --git a/packages/twenty-server/src/engine/core-modules/application/application-sync.service.ts b/packages/twenty-server/src/engine/core-modules/application/application-sync.service.ts index e10ed2c3a8..a8a2e9b4c5 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application-sync.service.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application-sync.service.ts @@ -2,8 +2,8 @@ import { Injectable, Logger } from '@nestjs/common'; import { parse } from 'path'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME, AllMetadataName } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity'; import { @@ -18,12 +18,13 @@ import { ServerlessFunctionTriggerManifest, } from 'src/engine/core-modules/application/types/application.types'; import { ApplicationVariableEntityService } from 'src/engine/core-modules/applicationVariable/application-variable.service'; +import { Sources } from 'src/engine/core-modules/file-storage/types/source.type'; import { CronTriggerV2Service } from 'src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service'; import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { DatabaseEventTriggerV2Service } from 'src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service'; import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { getFlatEntitiesByApplicationId } from 'src/engine/metadata-modules/flat-entity/utils/get-flat-entities-by-application-id.util'; import { getSubFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util'; @@ -34,7 +35,6 @@ import { ServerlessFunctionLayerService } from 'src/engine/metadata-modules/serv import { ServerlessFunctionV2Service } from 'src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service'; import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service'; -import { Sources } from 'src/engine/core-modules/file-storage/types/source.type'; @Injectable() export class ApplicationSyncService { @@ -851,15 +851,15 @@ export class ApplicationSyncService { fromToAllFlatEntityMaps: { flatObjectMetadataMaps: { from: fromFlatObjectMetadataMaps, - to: EMPTY_FLAT_ENTITY_MAPS, + to: createEmptyFlatEntityMaps(), }, flatIndexMaps: { from: fromFlatIndexMetadataMaps, - to: EMPTY_FLAT_ENTITY_MAPS, + to: createEmptyFlatEntityMaps(), }, flatFieldMetadataMaps: { from: fromFlatFieldMetadataMaps, - to: EMPTY_FLAT_ENTITY_MAPS, + to: createEmptyFlatEntityMaps(), }, }, workspaceId, diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service.ts index 041edc4f8a..3cdd4418f4 100644 --- a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service.ts @@ -12,11 +12,11 @@ import { CronTriggerEntity, } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatCronTriggerMaps') @@ -43,7 +43,9 @@ export class WorkspaceFlatCronTriggerMapCacheService extends WorkspaceFlatMapCac }, }); - return cronTriggers.reduce((flatCronTriggerMaps, cronTriggerEntity) => { + const flatCronTriggerMaps = createEmptyFlatEntityMaps(); + + for (const cronTriggerEntity of cronTriggers) { const flatCronTrigger = { ...removePropertiesFromRecord(cronTriggerEntity, [ ...CRON_TRIGGER_ENTITY_RELATION_PROPERTIES, @@ -52,10 +54,12 @@ export class WorkspaceFlatCronTriggerMapCacheService extends WorkspaceFlatMapCac cronTriggerEntity.universalIdentifier ?? cronTriggerEntity.id, } satisfies FlatCronTrigger; - return addFlatEntityToFlatEntityMapsOrThrow({ + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatCronTrigger, - flatEntityMaps: flatCronTriggerMaps, + flatEntityMapsToMutate: flatCronTriggerMaps, }); - }, EMPTY_FLAT_ENTITY_MAPS); + } + + return flatCronTriggerMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service.ts index a1640c09f6..1182277e3c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service.ts @@ -12,11 +12,11 @@ import { DatabaseEventTriggerEntity, } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatDatabaseEventTriggerMaps') @@ -44,23 +44,24 @@ export class WorkspaceFlatDatabaseEventTriggerMapCacheService extends WorkspaceF }, }); - return databaseEventTriggers.reduce( - (flatDatabaseEventTriggerMaps, databaseEventTriggerEntity) => { - const flatDatabaseEventTrigger = { - ...removePropertiesFromRecord(databaseEventTriggerEntity, [ - ...DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES, - ]), - universalIdentifier: - databaseEventTriggerEntity.universalIdentifier ?? - databaseEventTriggerEntity.id, - } satisfies FlatDatabaseEventTrigger; + const flatDatabaseEventTriggerMaps = createEmptyFlatEntityMaps(); - return addFlatEntityToFlatEntityMapsOrThrow({ - flatEntity: flatDatabaseEventTrigger, - flatEntityMaps: flatDatabaseEventTriggerMaps, - }); - }, - EMPTY_FLAT_ENTITY_MAPS, - ); + for (const databaseEventTriggerEntity of databaseEventTriggers) { + const flatDatabaseEventTrigger = { + ...removePropertiesFromRecord(databaseEventTriggerEntity, [ + ...DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES, + ]), + universalIdentifier: + databaseEventTriggerEntity.universalIdentifier ?? + databaseEventTriggerEntity.id, + } satisfies FlatDatabaseEventTrigger; + + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ + flatEntity: flatDatabaseEventTrigger, + flatEntityMapsToMutate: flatDatabaseEventTriggerMaps, + }); + } + + return flatDatabaseEventTriggerMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant.ts index 6ec79a3658..67617a4f69 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant.ts @@ -1,5 +1,5 @@ -import { type ExtractPropertiesThatEndsWithId } from 'twenty-shared/types'; import { type AllMetadataName } from 'twenty-shared/metadata'; +import { type ExtractPropertiesThatEndsWithId } from 'twenty-shared/types'; import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type'; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/create-empty-all-flat-entity-maps.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/create-empty-all-flat-entity-maps.constant.ts new file mode 100644 index 0000000000..233b64772c --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/create-empty-all-flat-entity-maps.constant.ts @@ -0,0 +1,19 @@ +import { + ALL_METADATA_NAME, + type AllMetadataName, +} from 'twenty-shared/metadata'; + +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; +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'; + +export const createEmptyAllFlatEntityMaps = (): AllFlatEntityMaps => + ( + Object.keys(ALL_METADATA_NAME) as AllMetadataName[] + ).reduce( + (acc, metadataName) => ({ + ...acc, + [getMetadataFlatEntityMapsKey(metadataName)]: createEmptyFlatEntityMaps(), + }), + {} as AllFlatEntityMaps, + ); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant.ts similarity index 51% rename from packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant.ts rename to packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant.ts index eaa7bf1bd5..9cff142b9d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant.ts @@ -1,8 +1,9 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type'; -export const EMPTY_FLAT_ENTITY_MAPS = { - byId: {}, - idByUniversalIdentifier: {}, - universalIdentifiersByApplicationId: {}, -} as const satisfies FlatEntityMaps; +export const createEmptyFlatEntityMaps = () => + ({ + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }) as const satisfies FlatEntityMaps; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/empty-all-flat-entity-maps.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/empty-all-flat-entity-maps.constant.ts deleted file mode 100644 index a75246485c..0000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/empty-all-flat-entity-maps.constant.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { - ALL_METADATA_NAME, - type AllMetadataName, -} from 'twenty-shared/metadata'; - -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; -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'; - -export const EMPTY_ALL_FLAT_ENTITY_MAPS = ( - Object.keys(ALL_METADATA_NAME) as AllMetadataName[] -).reduce( - (acc, metadataName) => ({ - ...acc, - [getMetadataFlatEntityMapsKey(metadataName)]: EMPTY_FLAT_ENTITY_MAPS, - }), - {} as AllFlatEntityMaps, -); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service.ts index b4fecb3616..bb89f2d72e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service.ts @@ -33,23 +33,32 @@ export class WorkspaceManyOrAllFlatEntityMapsCacheService { ? flatMapsKeys : ALL_FLAT_ENTITY_MAPS_PROPERTIES; - for (const flatMapKey of keysToProcess) { - try { - const service = this.cacheRegistry.getCacheServiceOrThrow( - flatMapKey as K[number], - ); + const results = await Promise.allSettled( + keysToProcess.map(async (flatMapKey) => { + try { + const service = this.cacheRegistry.getCacheServiceOrThrow( + flatMapKey as K[number], + ); - await action({ - flatMapKey: flatMapKey, - service, - }); - } catch (error) { - this.logger.error( - `Failed to run action on flat entity maps of ${flatMapKey}`, - error, - ); - throw error; - } + return await action({ + flatMapKey: flatMapKey, + service, + }); + } catch (error) { + this.logger.error( + `Failed to run action on flat entity maps of ${flatMapKey}`, + error, + ); + throw error; + } + }), + ); + + const failures = results.filter((result) => result.status === 'rejected'); + + if (failures.length > 0) { + this.logger.error(`${failures.length} operations failed`); + throw new Error(`Failed to process ${failures.length} flat entity maps`); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type.ts new file mode 100644 index 0000000000..77025ccdc3 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type.ts @@ -0,0 +1,6 @@ +import { type AllMetadataName } from 'twenty-shared/metadata'; + +import { type ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant'; + +export type MetadataManyToOneJoinColumn = + keyof (typeof ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY)[T]; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-related-metadata-names.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-related-metadata-names.type.ts index efef68a37c..75c45a1688 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-related-metadata-names.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-related-metadata-names.type.ts @@ -1,9 +1,10 @@ import { type AllMetadataName } from 'twenty-shared/metadata'; import { type ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant'; +import { type MetadataManyToOneJoinColumn } from 'src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type'; export type MetadataManyToOneRelatedMetadataNames = Extract< - (typeof ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY)[T][keyof (typeof ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY)[T]], + (typeof ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY)[T][MetadataManyToOneJoinColumn], AllMetadataName >; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util.ts index abd615a90d..61427588d6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util.ts @@ -1,4 +1,4 @@ -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type'; import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; @@ -21,5 +21,5 @@ export const getSubFlatEntityMapsOrThrow = ({ flatEntity, flatEntityMaps: acc, }); - }, EMPTY_FLAT_ENTITY_MAPS); + }, createEmptyFlatEntityMaps()); }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts index 9632fb11bf..d02761852e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts @@ -5,7 +5,7 @@ import { FieldMetadataType } from 'twenty-shared/types'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { fromCreateFieldInputToFlatFieldMetadatasToCreate, @@ -25,7 +25,7 @@ const flatObjectMetadataMaps = [ flatEntity: flatObjectMetadata, flatEntityMaps: flatObjectMetadataMaps, }); -}, EMPTY_FLAT_ENTITY_MAPS); +}, createEmptyFlatEntityMaps()); type TestCase = EachTestingContext<{ input: FromCreateFieldInputToFlatObjectMetadataArgs; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts index 40c592fa37..7408bfdd80 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts @@ -7,13 +7,18 @@ import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decora import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { fromFieldMetadataEntityToFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-field-metadata-entity-to-flat-field-metadata.util'; +import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity'; +import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-flat-map-cache/utils/regroup-entities-by-related-entity-id'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatFieldMetadataMaps') @@ -25,6 +30,14 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceFlatMapC cacheStorageService: CacheStorageService, @InjectRepository(FieldMetadataEntity) private readonly fieldMetadataRepository: Repository, + @InjectRepository(ViewFieldEntity) + private readonly viewFieldRepository: Repository, + @InjectRepository(ViewFilterEntity) + private readonly viewFilterRepository: Repository, + @InjectRepository(ViewGroupEntity) + private readonly viewGroupRepository: Repository, + @InjectRepository(ViewEntity) + private readonly viewRepository: Repository, ) { super(cacheStorageService); } @@ -34,48 +47,88 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceFlatMapC }: { workspaceId: string; }): Promise> { - const fieldMetadatas = await this.fieldMetadataRepository.find({ - where: { - workspaceId, - }, - select: { - viewFields: { - id: true, - }, - viewFilters: { - id: true, - }, - viewGroups: { - id: true, - }, - kanbanAggregateOperationViews: { - id: true, - }, - calendarViews: { - id: true, - }, - }, - withDeleted: true, - relations: [ - 'viewFields', - 'viewFilters', - 'viewGroups', - 'kanbanAggregateOperationViews', - 'calendarViews', - ], - }); + const [fieldMetadatas, viewFields, viewFilters, viewGroups, views] = + await Promise.all([ + this.fieldMetadataRepository.find({ + where: { workspaceId }, + withDeleted: true, + }), + this.viewFieldRepository.find({ + where: { workspaceId }, + select: ['id', 'fieldMetadataId'], + withDeleted: true, + }), + this.viewFilterRepository.find({ + where: { workspaceId }, + select: ['id', 'fieldMetadataId'], + withDeleted: true, + }), + this.viewGroupRepository.find({ + where: { workspaceId }, + select: ['id', 'fieldMetadataId'], + withDeleted: true, + }), + this.viewRepository.find({ + where: { workspaceId }, + select: [ + 'id', + 'kanbanAggregateOperationFieldMetadataId', + 'calendarFieldMetadataId', + ], + withDeleted: true, + }), + ]); - return fieldMetadatas.reduce( - (flatFieldMetadataMaps, fieldMetadataEntity) => { - const flatFieldMetadata = - fromFieldMetadataEntityToFlatFieldMetadata(fieldMetadataEntity); + const [ + viewFieldsByFieldId, + viewFiltersByFieldId, + viewGroupsByFieldId, + calendarViewsByFieldId, + kanbanViewsByFieldId, + ] = ( + [ + { + entities: viewFields, + foreignKey: 'fieldMetadataId', + }, + { + entities: viewFilters, + foreignKey: 'fieldMetadataId', + }, + { + entities: viewGroups, + foreignKey: 'fieldMetadataId', + }, + { + entities: views, + foreignKey: 'calendarFieldMetadataId', + }, + { + entities: views, + foreignKey: 'kanbanAggregateOperationFieldMetadataId', + }, + ] as const + ).map(regroupEntitiesByRelatedEntityId); - return addFlatEntityToFlatEntityMapsOrThrow({ - flatEntity: flatFieldMetadata, - flatEntityMaps: flatFieldMetadataMaps, - }); - }, - EMPTY_FLAT_ENTITY_MAPS, - ); + const flatFieldMetadataMaps = createEmptyFlatEntityMaps(); + + for (const fieldMetadataEntity of fieldMetadatas) { + const flatFieldMetadata = fromFieldMetadataEntityToFlatFieldMetadata({ + ...fieldMetadataEntity, + viewFields: viewFieldsByFieldId.get(fieldMetadataEntity.id) || [], + viewFilters: viewFiltersByFieldId.get(fieldMetadataEntity.id) || [], + viewGroups: viewGroupsByFieldId.get(fieldMetadataEntity.id) || [], + kanbanAggregateOperationViews: + kanbanViewsByFieldId.get(fieldMetadataEntity.id) || [], + calendarViews: calendarViewsByFieldId.get(fieldMetadataEntity.id) || [], + } as FieldMetadataEntity); + + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ + flatEntity: flatFieldMetadata, + flatEntityMapsToMutate: flatFieldMetadataMaps, + }); + } + + return flatFieldMetadataMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts index d5c9773e07..b7840bd942 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts @@ -25,7 +25,7 @@ export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilatio throw new WorkspaceMigrationBuilderExceptionV2( { report: { - ...EMPTY_ORCHESTRATOR_FAILURE_REPORT, + ...EMPTY_ORCHESTRATOR_FAILURE_REPORT(), objectMetadata: [ { errors: failedInputTranspilationErrors, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts index 07842276d4..579da4a010 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts @@ -7,7 +7,7 @@ import { type FlatFieldMetadataTypeValidationArgs } from 'src/engine/metadata-mo import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; export const validateMorphOrRelationFlatFieldMetadata = async ({ - dependencyOptimisticFlatEntityMaps: { flatObjectMetadataMaps }, + mutableDependencyOptimisticFlatEntityMaps: { flatObjectMetadataMaps }, flatEntityToValidate: flatFieldMetadataToValidate, optimisticFlatEntityMaps: optimisticFlatFieldMetadataMaps, remainingFlatEntityMapsToValidate, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts index cbb35b170e..51e397010f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts @@ -6,14 +6,14 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { fromIndexMetadataEntityToFlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/utils/from-index-metadata-entity-to-flat-index-metadata.util'; import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatIndexMaps') @@ -39,6 +39,7 @@ export class WorkspaceFlatIndexMapCacheService extends WorkspaceFlatMapCacheServ workspaceId, }, withDeleted: true, + relationLoadStrategy: 'join', select: { // Note: We need all IndexFieldMetadataEntity in order to build a FlatIndex indexFieldMetadatas: true, @@ -46,13 +47,17 @@ export class WorkspaceFlatIndexMapCacheService extends WorkspaceFlatMapCacheServ relations: ['indexFieldMetadatas'], }); - return indexes.reduce((flatIndexMaps, indexEntity) => { + const flatIndexMaps = createEmptyFlatEntityMaps(); + + for (const indexEntity of indexes) { const flatIndex = fromIndexMetadataEntityToFlatIndexMetadata(indexEntity); - return addFlatEntityToFlatEntityMapsOrThrow({ + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatIndex, - flatEntityMaps: flatIndexMaps, + flatEntityMapsToMutate: flatIndexMaps, }); - }, EMPTY_FLAT_ENTITY_MAPS); + } + + return flatIndexMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/flat-object-metadata-maps.mock.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/flat-object-metadata-maps.mock.ts index 22620f2cff..289dcaeb8e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/flat-object-metadata-maps.mock.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/flat-object-metadata-maps.mock.ts @@ -1,4 +1,4 @@ -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { ALL_FLAT_OBJECT_METADATA_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/all-flat-object-metadatas.mock'; @@ -10,5 +10,5 @@ export const FLAT_OBJECT_METADATA_MAPS_MOCKS = [ flatEntity: flatObjectMetadata, flatEntityMaps: flatObjectMaps, }), - EMPTY_FLAT_ENTITY_MAPS, + createEmptyFlatEntityMaps(), ); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts index 98353da4c9..bc2f8da379 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts @@ -6,14 +6,18 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { fromObjectMetadataEntityToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-entity-to-flat-object-metadata.util'; +import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-flat-map-cache/utils/regroup-entities-by-related-entity-id'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatObjectMetadataMaps') @@ -26,6 +30,12 @@ export class WorkspaceFlatObjectMetadataMapCacheService extends WorkspaceFlatMap @InjectRepository(ObjectMetadataEntity) private readonly objectMetadataRepository: Repository, + @InjectRepository(FieldMetadataEntity) + private readonly fieldMetadataRepository: Repository, + @InjectRepository(IndexMetadataEntity) + private readonly indexMetadataRepository: Repository, + @InjectRepository(ViewEntity) + private readonly viewRepository: Repository, ) { super(cacheStorageService); } @@ -35,36 +45,61 @@ export class WorkspaceFlatObjectMetadataMapCacheService extends WorkspaceFlatMap }: { workspaceId: string; }): Promise> { - const objectMetadatas = await this.objectMetadataRepository.find({ - where: { - workspaceId, - }, - withDeleted: true, - select: { - fields: { - id: true, - }, - indexMetadatas: { - id: true, - }, - views: { - id: true, - }, - }, - relations: ['fields', 'indexMetadatas', 'views'], - }); + const [objectMetadatas, fields, indexMetadatas, views] = await Promise.all([ + this.objectMetadataRepository.find({ + where: { workspaceId }, + withDeleted: true, + }), + this.fieldMetadataRepository.find({ + where: { workspaceId }, + select: ['id', 'objectMetadataId'], + withDeleted: true, + }), + this.indexMetadataRepository.find({ + where: { workspaceId }, + select: ['id', 'objectMetadataId'], + withDeleted: true, + }), + this.viewRepository.find({ + where: { workspaceId }, + select: ['id', 'objectMetadataId'], + withDeleted: true, + }), + ]); - return objectMetadatas.reduce( - (flatObjectMetadataMaps, objectMetadataEntity) => { - const flatObjectMetadata = - fromObjectMetadataEntityToFlatObjectMetadata(objectMetadataEntity); + const [fieldsByObjectId, indexesByObjectId, viewsByObjectId] = ( + [ + { + entities: fields, + foreignKey: 'objectMetadataId', + }, + { + entities: indexMetadatas, + foreignKey: 'objectMetadataId', + }, + { + entities: views, + foreignKey: 'objectMetadataId', + }, + ] as const + ).map(regroupEntitiesByRelatedEntityId); - return addFlatEntityToFlatEntityMapsOrThrow({ - flatEntity: flatObjectMetadata, - flatEntityMaps: flatObjectMetadataMaps, - }); - }, - EMPTY_FLAT_ENTITY_MAPS, - ); + const flatObjectMetadataMaps = createEmptyFlatEntityMaps(); + + for (const objectMetadataEntity of objectMetadatas) { + const flatObjectMetadata = fromObjectMetadataEntityToFlatObjectMetadata({ + ...objectMetadataEntity, + fields: fieldsByObjectId.get(objectMetadataEntity.id) || [], + indexMetadatas: indexesByObjectId.get(objectMetadataEntity.id) || [], + views: viewsByObjectId.get(objectMetadataEntity.id) || [], + } as ObjectMetadataEntity); + + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ + flatEntity: flatObjectMetadata, + flatEntityMapsToMutate: flatObjectMetadataMaps, + }); + } + + return flatObjectMetadataMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-field/services/workspace-flat-view-field-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-field/services/workspace-flat-view-field-map-cache.service.ts index 35b40e6187..9d52493455 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view-field/services/workspace-flat-view-field-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-field/services/workspace-flat-view-field-map-cache.service.ts @@ -6,13 +6,13 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatViewFieldMaps } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-maps.type'; import { fromViewFieldEntityToFlatViewField } from 'src/engine/metadata-modules/flat-view-field/utils/from-view-field-entity-to-flat-view-field.util'; import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatViewFieldMaps') @@ -38,13 +38,17 @@ export class WorkspaceFlatViewFieldMapCacheService extends WorkspaceFlatMapCache withDeleted: true, }); - return existingViewFields.reduce((flatViewFieldMaps, viewFieldEntity) => { + const flatViewFieldMaps = createEmptyFlatEntityMaps(); + + for (const viewFieldEntity of existingViewFields) { const flatViewField = fromViewFieldEntityToFlatViewField(viewFieldEntity); - return addFlatEntityToFlatEntityMapsOrThrow({ + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatViewField, - flatEntityMaps: flatViewFieldMaps, + flatEntityMapsToMutate: flatViewFieldMaps, }); - }, EMPTY_FLAT_ENTITY_MAPS); + } + + return flatViewFieldMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts index 2069d0ff12..3639f69310 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts @@ -6,13 +6,13 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type'; import { fromViewFilterEntityToFlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/utils/from-view-filter-entity-to-flat-view-filter.util'; import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatViewFilterMaps') @@ -38,14 +38,18 @@ export class WorkspaceFlatViewFilterMapCacheService extends WorkspaceFlatMapCach withDeleted: true, }); - return viewFilters.reduce((flatViewFilterMaps, viewFilterEntity) => { + const flatViewFilterMaps = createEmptyFlatEntityMaps(); + + for (const viewFilterEntity of viewFilters) { const flatViewFilter = fromViewFilterEntityToFlatViewFilter(viewFilterEntity); - return addFlatEntityToFlatEntityMapsOrThrow({ + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatViewFilter, - flatEntityMaps: flatViewFilterMaps, + flatEntityMapsToMutate: flatViewFilterMaps, }); - }, EMPTY_FLAT_ENTITY_MAPS); + } + + return flatViewFilterMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-group/services/workspace-flat-view-group-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-group/services/workspace-flat-view-group-map-cache.service.ts index 1b6a81e942..838c5770de 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view-group/services/workspace-flat-view-group-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-group/services/workspace-flat-view-group-map-cache.service.ts @@ -6,13 +6,13 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatViewGroupMaps } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group-maps.type'; import { fromViewGroupEntityToFlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/utils/from-view-group-entity-to-flat-view-group.util'; import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatViewGroupMaps') @@ -38,13 +38,17 @@ export class WorkspaceFlatViewGroupMapCacheService extends WorkspaceFlatMapCache withDeleted: true, }); - return existingViewGroups.reduce((flatViewGroupMaps, viewGroupEntity) => { + const flatViewGroupMaps = createEmptyFlatEntityMaps(); + + for (const viewGroupEntity of existingViewGroups) { const flatViewGroup = fromViewGroupEntityToFlatViewGroup(viewGroupEntity); - return addFlatEntityToFlatEntityMapsOrThrow({ + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatViewGroup, - flatEntityMaps: flatViewGroupMaps, + flatEntityMapsToMutate: flatViewGroupMaps, }); - }, EMPTY_FLAT_ENTITY_MAPS); + } + + return flatViewGroupMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view/flat-view.module.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view/flat-view.module.ts index 7d44ec14a0..e3d728c121 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view/flat-view.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view/flat-view.module.ts @@ -2,10 +2,20 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { WorkspaceFlatViewMapCacheService } from 'src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service'; +import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity'; import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; @Module({ - imports: [TypeOrmModule.forFeature([ViewEntity])], + imports: [ + TypeOrmModule.forFeature([ + ViewEntity, + ViewFieldEntity, + ViewFilterEntity, + ViewGroupEntity, + ]), + ], providers: [WorkspaceFlatViewMapCacheService], exports: [WorkspaceFlatViewMapCacheService], }) diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts index 7ec8f35491..d96f193e38 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts @@ -6,13 +6,17 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { type FlatViewMaps } from 'src/engine/metadata-modules/flat-view/types/flat-view-maps.type'; import { fromViewEntityToFlatView } from 'src/engine/metadata-modules/flat-view/utils/from-view-entity-to-flat-view.util'; +import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity'; import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-flat-map-cache/utils/regroup-entities-by-related-entity-id'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatViewMaps') @@ -22,6 +26,12 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceFlatMapCacheServi cacheStorageService: CacheStorageService, @InjectRepository(ViewEntity) private readonly viewRepository: Repository, + @InjectRepository(ViewFieldEntity) + private readonly viewFieldRepository: Repository, + @InjectRepository(ViewFilterEntity) + private readonly viewFilterRepository: Repository, + @InjectRepository(ViewGroupEntity) + private readonly viewGroupRepository: Repository, ) { super(cacheStorageService); } @@ -31,29 +41,61 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceFlatMapCacheServi }: { workspaceId: string; }): Promise { - const views = await this.viewRepository.find({ - where: { - workspaceId, - }, - select: { - viewFields: { - id: true, - }, - viewFilters: { - id: true, - }, - }, - relations: ['viewFields', 'viewFilters', 'viewGroups'], - withDeleted: true, - }); + const [views, viewFields, viewFilters, viewGroups] = await Promise.all([ + this.viewRepository.find({ + where: { workspaceId }, + withDeleted: true, + }), + this.viewFieldRepository.find({ + where: { workspaceId }, + select: ['id', 'viewId'], + withDeleted: true, + }), + this.viewFilterRepository.find({ + where: { workspaceId }, + select: ['id', 'viewId'], + withDeleted: true, + }), + this.viewGroupRepository.find({ + where: { workspaceId }, + select: ['id', 'viewId'], + withDeleted: true, + }), + ]); - return views.reduce((flatViewMaps, viewEntity) => { - const flatView = fromViewEntityToFlatView(viewEntity); + const [viewFieldsByViewId, viewFiltersByViewId, viewGroupsByViewId] = ( + [ + { + entities: viewFields, + foreignKey: 'viewId', + }, + { + entities: viewFilters, + foreignKey: 'viewId', + }, + { + entities: viewGroups, + foreignKey: 'viewId', + }, + ] as const + ).map(regroupEntitiesByRelatedEntityId); - return addFlatEntityToFlatEntityMapsOrThrow({ + const flatViewMaps = createEmptyFlatEntityMaps(); + + for (const viewEntity of views) { + const flatView = fromViewEntityToFlatView({ + ...viewEntity, + viewFields: viewFieldsByViewId.get(viewEntity.id) || [], + viewFilters: viewFiltersByViewId.get(viewEntity.id) || [], + viewGroups: viewGroupsByViewId.get(viewEntity.id) || [], + } as ViewEntity); + + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatView, - flatEntityMaps: flatViewMaps, + flatEntityMapsToMutate: flatViewMaps, }); - }, EMPTY_FLAT_ENTITY_MAPS); + } + + return flatViewMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/route-trigger/services/workspace-flat-route-trigger-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/route-trigger/services/workspace-flat-route-trigger-map-cache.service.ts index 5793a19289..2105d57252 100644 --- a/packages/twenty-server/src/engine/metadata-modules/route-trigger/services/workspace-flat-route-trigger-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/route-trigger/services/workspace-flat-route-trigger-map-cache.service.ts @@ -7,9 +7,8 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { ROUTE_TRIGGER_ENTITY_RELATION_PROPERTIES, RouteTriggerEntity, @@ -17,6 +16,7 @@ import { import { FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger/types/flat-route-trigger.type'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatRouteTriggerMaps') @@ -43,7 +43,9 @@ export class WorkspaceFlatRouteTriggerMapCacheService extends WorkspaceFlatMapCa }, }); - return routeTriggers.reduce((flatRouteTriggerMaps, routeTriggerEntity) => { + const flatRouteTriggerMaps = createEmptyFlatEntityMaps(); + + for (const routeTriggerEntity of routeTriggers) { const flatRouteTrigger = { ...removePropertiesFromRecord(routeTriggerEntity, [ ...ROUTE_TRIGGER_ENTITY_RELATION_PROPERTIES, @@ -52,10 +54,12 @@ export class WorkspaceFlatRouteTriggerMapCacheService extends WorkspaceFlatMapCa routeTriggerEntity.universalIdentifier ?? routeTriggerEntity.id, } satisfies FlatRouteTrigger; - return addFlatEntityToFlatEntityMapsOrThrow({ + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatRouteTrigger, - flatEntityMaps: flatRouteTriggerMaps, + flatEntityMapsToMutate: flatRouteTriggerMaps, }); - }, EMPTY_FLAT_ENTITY_MAPS); + } + + return flatRouteTriggerMaps; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts index d7416e1600..5631d2c712 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts @@ -7,9 +7,8 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { SERVERLESS_FUNCTION_ENTITY_RELATION_PROPERTIES, ServerlessFunctionEntity, @@ -17,6 +16,7 @@ import { import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; @Injectable() @WorkspaceFlatMapCache('flatServerlessFunctionMaps') @@ -44,23 +44,24 @@ export class WorkspaceFlatServerlessFunctionMapCacheService extends WorkspaceFla withDeleted: true, }); - return serverlessFunctions.reduce( - (flatServerlessFunctionMaps, serverlessFunctionEntity) => { - const flatServerlessFunction = { - ...removePropertiesFromRecord(serverlessFunctionEntity, [ - ...SERVERLESS_FUNCTION_ENTITY_RELATION_PROPERTIES, - ]), - universalIdentifier: - serverlessFunctionEntity.universalIdentifier ?? - serverlessFunctionEntity.id, - } satisfies FlatServerlessFunction; + const flatServerlessFunctionMaps = createEmptyFlatEntityMaps(); - return addFlatEntityToFlatEntityMapsOrThrow({ - flatEntity: flatServerlessFunction, - flatEntityMaps: flatServerlessFunctionMaps, - }); - }, - EMPTY_FLAT_ENTITY_MAPS, - ); + for (const serverlessFunctionEntity of serverlessFunctions) { + const flatServerlessFunction = { + ...removePropertiesFromRecord(serverlessFunctionEntity, [ + ...SERVERLESS_FUNCTION_ENTITY_RELATION_PROPERTIES, + ]), + universalIdentifier: + serverlessFunctionEntity.universalIdentifier ?? + serverlessFunctionEntity.id, + } satisfies FlatServerlessFunction; + + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ + flatEntity: flatServerlessFunction, + flatEntityMapsToMutate: flatServerlessFunctionMaps, + }); + } + + return flatServerlessFunctionMaps; } } diff --git a/packages/twenty-server/src/engine/workspace-flat-map-cache/utils/regroup-entities-by-related-entity-id.ts b/packages/twenty-server/src/engine/workspace-flat-map-cache/utils/regroup-entities-by-related-entity-id.ts new file mode 100644 index 0000000000..a23ada1c0f --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-flat-map-cache/utils/regroup-entities-by-related-entity-id.ts @@ -0,0 +1,39 @@ +import { isDefined } from 'class-validator'; +import { type AllMetadataName } from 'twenty-shared/metadata'; + +import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type'; +import { type MetadataManyToOneJoinColumn } from 'src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type'; + +export type RegroupEntitiesByRelatedEntityIdArgs = + MetadataManyToOneJoinColumn extends never + ? never + : { + entities: MetadataEntity[]; + foreignKey: MetadataManyToOneJoinColumn; + }; +export const regroupEntitiesByRelatedEntityId = ({ + entities, + foreignKey, +}: RegroupEntitiesByRelatedEntityIdArgs) => { + const entitiesByRelatedEntityId = new Map(); + + for (const entity of entities) { + const currentRelatedEntityId = entity[ + foreignKey as keyof MetadataEntity + ] as string; + + if (!isDefined(currentRelatedEntityId)) { + continue; + } + + if (!entitiesByRelatedEntityId.has(currentRelatedEntityId)) { + entitiesByRelatedEntityId.set(currentRelatedEntityId, []); + } + + entitiesByRelatedEntityId + .get(currentRelatedEntityId)! + .push({ id: entity.id }); + } + + return entitiesByRelatedEntityId; +}; diff --git a/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts b/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts index 6808ad106b..710b0cae80 100644 --- a/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts +++ b/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts @@ -10,6 +10,7 @@ import { WorkspaceFlatViewFieldMapCacheService } from 'src/engine/metadata-modul import { WorkspaceFlatViewFilterMapCacheService } from 'src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service'; import { WorkspaceFlatViewGroupMapCacheService } from 'src/engine/metadata-modules/flat-view-group/services/workspace-flat-view-group-map-cache.service'; import { WorkspaceFlatViewMapCacheService } from 'src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service'; +import { IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity'; import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity'; @@ -31,10 +32,11 @@ import { WorkspaceFlatMapCacheRegistryService } from 'src/engine/workspace-flat- ViewEntity, ViewFieldEntity, ViewFilterEntity, + ViewGroupEntity, IndexMetadataEntity, + IndexFieldMetadataEntity, FieldMetadataEntity, ObjectMetadataEntity, - ViewGroupEntity, ]), ], providers: [ diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts index 03599b150c..41e1dfcf12 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts @@ -3,13 +3,15 @@ import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type'; import { getMetadataEmptyWorkspaceMigrationActionRecord } from 'src/engine/workspace-manager/workspace-migration-v2/utils/get-metadata-empty-workspace-migration-action-record.util'; -export const EMPTY_ORCHESTRATOR_ACTIONS_REPORT = ( - Object.keys(ALL_METADATA_NAME) as (keyof typeof ALL_METADATA_NAME)[] -).reduce( - (orchestratorReport, metadataName) => ({ - ...orchestratorReport, - [metadataName]: - getMetadataEmptyWorkspaceMigrationActionRecord(metadataName), - }), - {} as OrchestratorActionsReport, -); +export const createEmptyOrchestratorActionsReport = + (): OrchestratorActionsReport => + ( + Object.keys(ALL_METADATA_NAME) as (keyof typeof ALL_METADATA_NAME)[] + ).reduce( + (orchestratorReport, metadataName) => ({ + ...orchestratorReport, + [metadataName]: + getMetadataEmptyWorkspaceMigrationActionRecord(metadataName), + }), + {} as OrchestratorActionsReport, + ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-failure-report.constant.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-failure-report.constant.ts index 031fb04ac2..748e3a3f63 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-failure-report.constant.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-failure-report.constant.ts @@ -2,12 +2,14 @@ import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; import { type OrchestratorFailureReport } from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type'; -export const EMPTY_ORCHESTRATOR_FAILURE_REPORT = ( - Object.keys(ALL_METADATA_NAME) as (keyof typeof ALL_METADATA_NAME)[] -).reduce( - (orchestratorReport, metadataName) => ({ - ...orchestratorReport, - [metadataName]: [], - }), - {} as OrchestratorFailureReport, -); +export const EMPTY_ORCHESTRATOR_FAILURE_REPORT = + (): OrchestratorFailureReport => + ( + Object.keys(ALL_METADATA_NAME) as (keyof typeof ALL_METADATA_NAME)[] + ).reduce( + (orchestratorReport, metadataName) => ({ + ...orchestratorReport, + [metadataName]: [], + }), + {} as OrchestratorFailureReport, + ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts index 01abd98e7e..ea05af1f0f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts @@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common'; import { isDefined } from 'twenty-shared/utils'; -import { EMPTY_ALL_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-all-flat-entity-maps.constant'; +import { createEmptyAllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-all-flat-entity-maps.constant'; import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type'; -import { EMPTY_ORCHESTRATOR_ACTIONS_REPORT } from 'src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant'; +import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant'; import { EMPTY_ORCHESTRATOR_FAILURE_REPORT } from 'src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-failure-report.constant'; import { WorkspaceMigrationOrchestratorBuildArgs, @@ -65,7 +65,7 @@ export class WorkspaceMigrationBuildOrchestratorService { }; }, { - ...EMPTY_ALL_FLAT_ENTITY_MAPS, + ...createEmptyAllFlatEntityMaps(), ...dependencyAllFlatEntityMaps, }, ); @@ -81,10 +81,10 @@ export class WorkspaceMigrationBuildOrchestratorService { | WorkspaceMigrationOrchestratorSuccessfulResult > { const orchestratorActionsReport = structuredClone({ - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), }); const orchestratorFailureReport = structuredClone( - EMPTY_ORCHESTRATOR_FAILURE_REPORT, + EMPTY_ORCHESTRATOR_FAILURE_REPORT(), ); const optimisticAllFlatEntityMaps = this.setupOptimisticCache({ diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util.spec.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util.spec.ts index 8bc07a6da8..7fe5dd2895 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util.spec.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util.spec.ts @@ -6,7 +6,7 @@ import { FieldMetadataType } from 'twenty-shared/types'; import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock'; import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock'; -import { EMPTY_ORCHESTRATOR_ACTIONS_REPORT } from 'src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant'; +import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant'; import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type'; import { aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions } from 'src/engine/workspace-manager/workspace-migration-v2/utils/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util'; import { type CreateFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/types/workspace-migration-field-action-v2'; @@ -26,7 +26,7 @@ describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', 'should aggregate single object with multiple fields into one object action', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [ { @@ -83,7 +83,7 @@ describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', 'should keep separate field actions when no matching object action exists', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [], updated: [], @@ -147,7 +147,7 @@ describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', title: 'should handle multiple objects with their respective fields', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [ { @@ -228,7 +228,7 @@ describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', 'should handle mixed scenario with some fields merged and some kept separate', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [ { @@ -293,7 +293,7 @@ describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', 'should aggregate multiple field actions for the same object when no create object action exists', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [], updated: [], @@ -356,7 +356,7 @@ describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', { title: 'should handle empty actions report', context: { - input: EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + input: createEmptyOrchestratorActionsReport(), expected: { expectCreateFieldActionPerObjectMetadataId: {}, expectCreateObjectActionPerObjectMetadataId: {}, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-delete-object-and-delete-field-actions.util.spec.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-delete-object-and-delete-field-actions.util.spec.ts index d5ad48964a..1841aa4520 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-delete-object-and-delete-field-actions.util.spec.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/aggregate-orchestrator-actions-report-delete-object-and-delete-field-actions.util.spec.ts @@ -3,7 +3,7 @@ import { type EachTestingContext, } from 'twenty-shared/testing'; -import { EMPTY_ORCHESTRATOR_ACTIONS_REPORT } from 'src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant'; +import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant'; import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type'; import { aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions } from 'src/engine/workspace-manager/workspace-migration-v2/utils/aggregate-orchestrator-actions-report-delete-object-and-delete-field.util'; import { type DeleteFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/types/workspace-migration-field-action-v2'; @@ -23,7 +23,7 @@ describe('aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions', title: 'should remove field actions when parent object is being deleted', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [], updated: [], @@ -63,7 +63,7 @@ describe('aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions', title: 'should keep field actions when no parent object is being deleted', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [], updated: [], @@ -94,7 +94,7 @@ describe('aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions', 'should handle mixed scenario with some fields removed and some kept', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [], updated: [], @@ -136,7 +136,7 @@ describe('aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions', title: 'should handle multiple objects with mixed field deletions', context: { input: { - ...EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + ...createEmptyOrchestratorActionsReport(), objectMetadata: { created: [], updated: [], @@ -187,7 +187,7 @@ describe('aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions', { title: 'should handle empty actions report', context: { - input: EMPTY_ORCHESTRATOR_ACTIONS_REPORT, + input: createEmptyOrchestratorActionsReport(), expected: { expectDeleteFieldActionPerObjectMetadataId: {}, expectDeleteObjectActionPerObjectMetadataId: {}, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util.ts new file mode 100644 index 0000000000..29815d3649 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util.ts @@ -0,0 +1,54 @@ +import { isDefined } from 'twenty-shared/utils'; + +import { + FlatEntityMapsException, + FlatEntityMapsExceptionCode, +} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception'; +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type'; + +type AddFlatEntityToFlatEntityMapsThroughMutationOrThrowArgs< + T extends FlatEntity, +> = { + flatEntity: T; + flatEntityMapsToMutate: FlatEntityMaps; +}; + +export const addFlatEntityToFlatEntityMapsThroughMutationOrThrow = < + T extends FlatEntity, +>({ + flatEntity, + flatEntityMapsToMutate, +}: AddFlatEntityToFlatEntityMapsThroughMutationOrThrowArgs): void => { + if (isDefined(flatEntityMapsToMutate.byId[flatEntity.id])) { + throw new FlatEntityMapsException( + 'addFlatEntityToFlatEntityMapsThroughMutationOrThrow: flat entity to add already exists', + FlatEntityMapsExceptionCode.ENTITY_ALREADY_EXISTS, + ); + } + + flatEntityMapsToMutate.byId[flatEntity.id] = flatEntity; + + flatEntityMapsToMutate.idByUniversalIdentifier[ + flatEntity.universalIdentifier + ] = flatEntity.id; + + if (isDefined(flatEntity.applicationId)) { + const existingUniversalIdentifiers = + flatEntityMapsToMutate.universalIdentifiersByApplicationId[ + flatEntity.applicationId + ]; + + if (isDefined(existingUniversalIdentifiers)) { + if ( + !existingUniversalIdentifiers.includes(flatEntity.universalIdentifier) + ) { + existingUniversalIdentifiers.push(flatEntity.universalIdentifier); + } + } else { + flatEntityMapsToMutate.universalIdentifiersByApplicationId[ + flatEntity.applicationId + ] = [flatEntity.universalIdentifier]; + } + } +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util.ts new file mode 100644 index 0000000000..8b24c39666 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util.ts @@ -0,0 +1,60 @@ +import { isDefined } from 'twenty-shared/utils'; + +import { + FlatEntityMapsException, + FlatEntityMapsExceptionCode, +} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception'; +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type'; + +export type DeleteFlatEntityFromFlatEntityMapsThroughMutationOrThrowArgs< + T extends FlatEntity, +> = { + entityToDeleteId: string; + flatEntityMapsToMutate: FlatEntityMaps; +}; + +export const deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow = < + T extends FlatEntity, +>({ + flatEntityMapsToMutate, + entityToDeleteId, +}: DeleteFlatEntityFromFlatEntityMapsThroughMutationOrThrowArgs): void => { + const entityToDelete = flatEntityMapsToMutate.byId[entityToDeleteId]; + + if (!isDefined(entityToDelete)) { + throw new FlatEntityMapsException( + 'deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow: entity to delete not found', + FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND, + ); + } + + delete flatEntityMapsToMutate.byId[entityToDeleteId]; + + delete flatEntityMapsToMutate.idByUniversalIdentifier[ + entityToDelete.universalIdentifier + ]; + + if (isDefined(entityToDelete.applicationId)) { + const universalIdentifiers = + flatEntityMapsToMutate.universalIdentifiersByApplicationId[ + entityToDelete.applicationId + ]; + + if (isDefined(universalIdentifiers)) { + const index = universalIdentifiers.indexOf( + entityToDelete.universalIdentifier, + ); + + if (index !== -1) { + universalIdentifiers.splice(index, 1); + } + + if (universalIdentifiers.length === 0) { + delete flatEntityMapsToMutate.universalIdentifiersByApplicationId[ + entityToDelete.applicationId + ]; + } + } + } +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util.ts index 315906b51c..84c1a4c3e4 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util.ts @@ -1,16 +1,16 @@ +import { type AllMetadataName } from 'twenty-shared/metadata'; import { type FromTo } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; -import { type AllMetadataName } from 'twenty-shared/metadata'; import { ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-properties-to-compare-and-stringify.constant'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type'; import { type FlatEntityPropertiesToStringify } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-stringify.type'; import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type'; import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type'; import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { compareTwoFlatEntity } from 'src/engine/metadata-modules/flat-entity/utils/compare-two-flat-entity.util'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; export type DeletedCreatedUpdatedMatrix = { @@ -46,8 +46,8 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = < buildOptions, }: FlatEntityDeletedCreatedUpdatedMatrixDispatcherArgs): DeletedCreatedUpdatedMatrix => { const initialDispatcher: DeletedCreatedUpdatedMatrix = { - createdFlatEntityMaps: EMPTY_FLAT_ENTITY_MAPS, - deletedFlatEntityMaps: EMPTY_FLAT_ENTITY_MAPS, + createdFlatEntityMaps: createEmptyFlatEntityMaps(), + deletedFlatEntityMaps: createEmptyFlatEntityMaps(), updatedFlatEntityMaps: { byId: {} }, }; @@ -59,11 +59,10 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = < if (toMap.has(universalIdentifier)) { continue; } - initialDispatcher.deletedFlatEntityMaps = - addFlatEntityToFlatEntityMapsOrThrow({ - flatEntity: fromEntity, - flatEntityMaps: initialDispatcher.deletedFlatEntityMaps, - }); + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ + flatEntity: fromEntity, + flatEntityMapsToMutate: initialDispatcher.deletedFlatEntityMaps, + }); } } @@ -71,11 +70,10 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = < if (fromMap.has(universalIdentifier)) { continue; } - initialDispatcher.createdFlatEntityMaps = - addFlatEntityToFlatEntityMapsOrThrow({ - flatEntity: toFlatEntity, - flatEntityMaps: initialDispatcher.createdFlatEntityMaps, - }); + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ + flatEntity: toFlatEntity, + flatEntityMapsToMutate: initialDispatcher.createdFlatEntityMaps, + }); } const { propertiesToCompare, propertiesToStringify } = diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util.ts new file mode 100644 index 0000000000..80eaa7175f --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util.ts @@ -0,0 +1,28 @@ +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; +import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util'; + +export type ReplaceFlatEntityInFlatEntityMapsThroughMutationOrThrowArgs< + T extends FlatEntity, +> = { + flatEntity: T; + flatEntityMapsToMutate: FlatEntityMaps; +}; + +export const replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow = < + T extends FlatEntity, +>({ + flatEntity, + flatEntityMapsToMutate, +}: ReplaceFlatEntityInFlatEntityMapsThroughMutationOrThrowArgs): void => { + deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({ + flatEntityMapsToMutate, + entityToDeleteId: flatEntity.id, + }); + + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ + flatEntity, + flatEntityMapsToMutate, + }); +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service.ts index 06329ef53d..eca52d8a8e 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service.ts @@ -39,10 +39,7 @@ export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends Worksp }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityToValidate: flatCronTriggerToValidate, - } = args; + const { flatEntityToValidate: flatCronTriggerToValidate } = args; return { status: 'success', @@ -50,7 +47,6 @@ export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends Worksp type: 'create_cron_trigger', cronTrigger: flatCronTriggerToValidate, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -74,10 +70,7 @@ export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends Worksp }; } - const { - flatEntityToValidate: flatCronTriggerToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatCronTriggerToValidate } = args; return { status: 'success', @@ -85,7 +78,6 @@ export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends Worksp type: 'delete_cron_trigger', cronTriggerId: flatCronTriggerToValidate.id, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -106,11 +98,7 @@ export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends Worksp ...validationResult, }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateCronTriggerAction: UpdateCronTriggerAction = { type: 'update_cron_trigger', @@ -121,7 +109,6 @@ export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends Worksp return { status: 'success', action: updateCronTriggerAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service.ts index 60d983dd04..550b25215d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service.ts @@ -41,10 +41,7 @@ export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService exten }; } - const { - flatEntityToValidate: flatDatabaseEventTriggerToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatDatabaseEventTriggerToValidate } = args; return { status: 'success', @@ -52,7 +49,6 @@ export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService exten type: 'create_database_event_trigger', databaseEventTrigger: flatDatabaseEventTriggerToValidate, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -78,10 +74,7 @@ export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService exten }; } - const { - flatEntityToValidate: flatDatabaseEventTriggerToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatDatabaseEventTriggerToValidate } = args; return { status: 'success', @@ -89,7 +82,6 @@ export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService exten type: 'delete_database_event_trigger', databaseEventTriggerId: flatDatabaseEventTriggerToValidate.id, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -115,11 +107,7 @@ export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService exten }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateDatabaseEventTriggerAction: UpdateDatabaseEventTriggerAction = { type: 'update_database_event_trigger', @@ -130,7 +118,6 @@ export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService exten return { status: 'success', action: updateDatabaseEventTriggerAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service.ts index f259cb474d..6eca5b4fa6 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util'; import { UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/types/workspace-migration-field-action-v2'; import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; @@ -45,26 +45,26 @@ export class WorkspaceMigrationV2FieldActionsBuilderService extends WorkspaceEnt const { flatEntityToValidate: flatFieldMetadataToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatFieldMetadataToValidate.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); - const updatedFlatObjectMetadataMaps = - replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatObjectMetadata, - fieldMetadataIds: [ - ...flatObjectMetadata.fieldMetadataIds, - flatFieldMetadataToValidate.id, - ], - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, - }); + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatObjectMetadata, + fieldMetadataIds: [ + ...flatObjectMetadata.fieldMetadataIds, + flatFieldMetadataToValidate.id, + ], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); return { status: 'success', @@ -73,9 +73,6 @@ export class WorkspaceMigrationV2FieldActionsBuilderService extends WorkspaceEnt objectMetadataId: flatFieldMetadataToValidate.objectMetadataId, flatFieldMetadatas: [flatFieldMetadataToValidate], }, - dependencyOptimisticFlatEntityMaps: { - flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, - }, }; } @@ -99,26 +96,27 @@ export class WorkspaceMigrationV2FieldActionsBuilderService extends WorkspaceEnt const { flatEntityToValidate: flatFieldMetadataToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatFieldMetadataToValidate.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); - const updatedFlatObjectMetadataMaps = isDefined(flatObjectMetadata) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatObjectMetadata, - fieldMetadataIds: flatObjectMetadata.fieldMetadataIds.filter( - (id) => id !== flatFieldMetadataToValidate.id, - ), - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps; + if (isDefined(flatObjectMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatObjectMetadata, + fieldMetadataIds: flatObjectMetadata.fieldMetadataIds.filter( + (id) => id !== flatFieldMetadataToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); + } return { status: 'success', @@ -127,9 +125,6 @@ export class WorkspaceMigrationV2FieldActionsBuilderService extends WorkspaceEnt fieldMetadataId: flatFieldMetadataToValidate.id, objectMetadataId: flatFieldMetadataToValidate.objectMetadataId, }, - dependencyOptimisticFlatEntityMaps: { - flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, - }, }; } @@ -155,12 +150,7 @@ export class WorkspaceMigrationV2FieldActionsBuilderService extends WorkspaceEnt }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - optimisticFlatEntityMaps, - } = args; + const { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps } = args; const flatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatEntityId, @@ -177,7 +167,6 @@ export class WorkspaceMigrationV2FieldActionsBuilderService extends WorkspaceEnt return { status: 'success', action: updateFieldAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts index cce05d6d2c..b004e16e9c 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts @@ -1,15 +1,15 @@ import { Injectable } from '@nestjs/common'; import { t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatEntityMapsExceptionCode } from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception'; -import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util'; import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type'; @@ -44,26 +44,26 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt const { flatEntityToValidate: flatIndexToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatIndexToValidate.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); - const updatedFlatObjectMetadataMaps = - replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatObjectMetadata, - indexMetadataIds: [ - ...flatObjectMetadata.indexMetadataIds, - flatIndexToValidate.id, - ], - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, - }); + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatObjectMetadata, + indexMetadataIds: [ + ...flatObjectMetadata.indexMetadataIds, + flatIndexToValidate.id, + ], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); return { status: 'success', @@ -71,10 +71,6 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt type: 'create_index', flatIndexMetadata: flatIndexToValidate, }, - dependencyOptimisticFlatEntityMaps: { - ...dependencyOptimisticFlatEntityMaps, - flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, - }, }; } @@ -95,26 +91,27 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt const { flatEntityToValidate: flatIndexToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatIndexToValidate.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); - const updatedFlatObjectMetadataMaps = isDefined(flatObjectMetadata) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatObjectMetadata, - indexMetadataIds: flatObjectMetadata.indexMetadataIds.filter( - (id) => id !== flatIndexToValidate.id, - ), - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps; + if (isDefined(flatObjectMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatObjectMetadata, + indexMetadataIds: flatObjectMetadata.indexMetadataIds.filter( + (id) => id !== flatIndexToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); + } return { status: 'success', @@ -122,10 +119,6 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt type: 'delete_index', flatIndexMetadataId: flatIndexToValidate.id, }, - dependencyOptimisticFlatEntityMaps: { - ...dependencyOptimisticFlatEntityMaps, - flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, - }, }; } @@ -133,7 +126,7 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatIndexMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, buildOptions, workspaceId, }: FlatEntityUpdateValidationArgs): Promise< @@ -160,11 +153,11 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt const deletionValidationResult = this.flatIndexValidatorService.validateFlatIndexDeletion({ buildOptions, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, optimisticFlatEntityMaps: optimisticFlatIndexMaps, workspaceId, flatEntityToValidate: flatEntity, - remainingFlatEntityMapsToValidate: EMPTY_FLAT_ENTITY_MAPS, + remainingFlatEntityMapsToValidate: createEmptyFlatEntityMaps(), }); if (deletionValidationResult.errors.length > 0) { @@ -181,17 +174,23 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt }), }; + const tempOptimisticFlatIndexMaps = structuredClone( + optimisticFlatIndexMaps, + ); + + deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({ + entityToDeleteId: flatEntity.id, + flatEntityMapsToMutate: tempOptimisticFlatIndexMaps, + }); + const creationValidationResult = this.flatIndexValidatorService.validateFlatIndexCreation({ buildOptions, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, workspaceId, flatEntityToValidate: updatedFlatIndex, - optimisticFlatEntityMaps: deleteFlatEntityFromFlatEntityMapsOrThrow({ - entityToDeleteId: flatEntity.id, - flatEntityMaps: optimisticFlatIndexMaps, - }), - remainingFlatEntityMapsToValidate: EMPTY_FLAT_ENTITY_MAPS, + optimisticFlatEntityMaps: tempOptimisticFlatIndexMaps, + remainingFlatEntityMapsToValidate: createEmptyFlatEntityMaps(), }); if (creationValidationResult.errors.length > 0) { @@ -213,7 +212,6 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt flatIndexMetadata: updatedFlatIndex, }, ], - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service.ts index 9f8fa839c5..31f13aa7fa 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service.ts @@ -39,10 +39,7 @@ export class WorkspaceMigrationV2ObjectActionsBuilderService extends WorkspaceEn }; } - const { - flatEntityToValidate: flatObjectMetadataToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatObjectMetadataToValidate } = args; return { status: 'success', @@ -51,7 +48,6 @@ export class WorkspaceMigrationV2ObjectActionsBuilderService extends WorkspaceEn flatFieldMetadatas: [], flatObjectMetadata: flatObjectMetadataToValidate, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -73,10 +69,7 @@ export class WorkspaceMigrationV2ObjectActionsBuilderService extends WorkspaceEn }; } - const { - flatEntityToValidate: flatObjectMetadataToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatObjectMetadataToValidate } = args; return { status: 'success', @@ -84,7 +77,6 @@ export class WorkspaceMigrationV2ObjectActionsBuilderService extends WorkspaceEn type: 'delete_object', objectMetadataId: flatObjectMetadataToValidate.id, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -108,11 +100,7 @@ export class WorkspaceMigrationV2ObjectActionsBuilderService extends WorkspaceEn }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateObjectAction: UpdateObjectAction = { type: 'update_object', @@ -123,7 +111,6 @@ export class WorkspaceMigrationV2ObjectActionsBuilderService extends WorkspaceEn return { status: 'success', action: updateObjectAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service.ts index ae9dab46a3..3888f16174 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service.ts @@ -39,10 +39,7 @@ export class WorkspaceMigrationV2RouteTriggerActionsBuilderService extends Works }; } - const { - flatEntityToValidate: flatRouteTriggerToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatRouteTriggerToValidate } = args; return { status: 'success', @@ -50,7 +47,6 @@ export class WorkspaceMigrationV2RouteTriggerActionsBuilderService extends Works type: 'create_route_trigger', routeTrigger: flatRouteTriggerToValidate, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -74,10 +70,7 @@ export class WorkspaceMigrationV2RouteTriggerActionsBuilderService extends Works }; } - const { - flatEntityToValidate: flatRouteTriggerToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatRouteTriggerToValidate } = args; return { status: 'success', @@ -85,7 +78,6 @@ export class WorkspaceMigrationV2RouteTriggerActionsBuilderService extends Works type: 'delete_route_trigger', routeTriggerId: flatRouteTriggerToValidate.id, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -109,11 +101,7 @@ export class WorkspaceMigrationV2RouteTriggerActionsBuilderService extends Works }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateRouteTriggerAction: UpdateRouteTriggerAction = { type: 'update_route_trigger', @@ -124,7 +112,6 @@ export class WorkspaceMigrationV2RouteTriggerActionsBuilderService extends Works return { status: 'success', action: updateRouteTriggerAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts index bd8bb42e61..08fe87d2a9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts @@ -81,10 +81,7 @@ export class WorkspaceMigrationV2ServerlessFunctionActionsBuilderService extends }; } - const { - flatEntityToValidate: flatServerlessFunctionToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatServerlessFunctionToValidate } = args; return { status: 'success', @@ -92,7 +89,6 @@ export class WorkspaceMigrationV2ServerlessFunctionActionsBuilderService extends type: 'create_serverless_function', serverlessFunction: flatServerlessFunctionToValidate, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -116,10 +112,7 @@ export class WorkspaceMigrationV2ServerlessFunctionActionsBuilderService extends }; } - const { - flatEntityToValidate: flatServerlessFunctionToValidate, - dependencyOptimisticFlatEntityMaps, - } = args; + const { flatEntityToValidate: flatServerlessFunctionToValidate } = args; return { status: 'success', @@ -127,7 +120,6 @@ export class WorkspaceMigrationV2ServerlessFunctionActionsBuilderService extends type: 'delete_serverless_function', serverlessFunctionId: flatServerlessFunctionToValidate.id, }, - dependencyOptimisticFlatEntityMaps, }; } @@ -153,11 +145,7 @@ export class WorkspaceMigrationV2ServerlessFunctionActionsBuilderService extends }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateServerlessFunctionAction: UpdateServerlessFunctionAction = { type: 'update_serverless_function', @@ -168,7 +156,6 @@ export class WorkspaceMigrationV2ServerlessFunctionActionsBuilderService extends return { status: 'success', action: updateServerlessFunctionAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts index b0cc2b35bc..372e0726ae 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util'; import { UpdateViewFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/types/workspace-migration-view-field-action-v2.type'; import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; @@ -43,38 +43,39 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac const { flatEntityToValidate: flatViewFieldToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewFieldToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); - const updatedFlatFieldMetadataMaps = - replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatFieldMetadata, - viewFieldIds: [ - ...flatFieldMetadata.viewFieldIds, - flatViewFieldToValidate.id, - ], - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, - }); + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatFieldMetadata, + viewFieldIds: [ + ...flatFieldMetadata.viewFieldIds, + flatViewFieldToValidate.id, + ], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); const flatView = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewFieldToValidate.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ flatEntity: { ...flatView, viewFieldIds: [...flatView.viewFieldIds, flatViewFieldToValidate.id], }, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); return { @@ -83,11 +84,6 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac type: 'create_view_field', viewField: flatViewFieldToValidate, }, - dependencyOptimisticFlatEntityMaps: { - ...dependencyOptimisticFlatEntityMaps, - flatViewMaps: updatedFlatViewMaps, - flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, - }, }; } @@ -111,43 +107,45 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac const { flatEntityToValidate: flatViewFieldToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFieldToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); - const updatedFlatFieldMetadataMaps = isDefined(flatFieldMetadata) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatFieldMetadata, - viewFieldIds: flatFieldMetadata.viewFieldIds.filter( - (id) => id !== flatViewFieldToValidate.id, - ), - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps; + if (isDefined(flatFieldMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatFieldMetadata, + viewFieldIds: flatFieldMetadata.viewFieldIds.filter( + (id) => id !== flatViewFieldToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + } const flatView = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFieldToValidate.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewMaps = isDefined(flatView) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatView, - viewFieldIds: flatView.viewFieldIds.filter( - (id) => id !== flatViewFieldToValidate.id, - ), - }, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatViewMaps; + if (isDefined(flatView)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatView, + viewFieldIds: flatView.viewFieldIds.filter( + (id) => id !== flatViewFieldToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, + }); + } return { status: 'success', @@ -155,11 +153,6 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac type: 'delete_view_field', viewFieldId: flatViewFieldToValidate.id, }, - dependencyOptimisticFlatEntityMaps: { - ...dependencyOptimisticFlatEntityMaps, - flatViewMaps: updatedFlatViewMaps, - flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, - }, }; } @@ -181,11 +174,7 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateViewFieldAction: UpdateViewFieldAction = { type: 'update_view_field', @@ -196,7 +185,6 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac return { status: 'success', action: updateViewFieldAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts index b78ad8dad3..163ebb3137 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util'; import { UpdateViewFilterAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/workspace-migration-view-filter-action-v2.type'; import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; @@ -43,38 +43,40 @@ export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends Workspa const { flatEntityToValidate: flatViewFilterToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatView = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewFilterToValidate.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ flatEntity: { ...flatView, viewFilterIds: [...flatView.viewFilterIds, flatViewFilterToValidate.id], }, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); const flatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewFilterToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatFieldMetadata, + viewFilterIds: [ + ...flatFieldMetadata.viewFilterIds, + flatViewFilterToValidate.id, + ], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); - const updatedFlatFieldMetadataMaps = - replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatFieldMetadata, - viewFilterIds: [ - ...flatFieldMetadata.viewFilterIds, - flatViewFilterToValidate.id, - ], - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, - }); return { status: 'success', @@ -82,10 +84,6 @@ export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends Workspa type: 'create_view_filter', viewFilter: flatViewFilterToValidate, }, - dependencyOptimisticFlatEntityMaps: { - flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, - flatViewMaps: updatedFlatViewMaps, - }, }; } @@ -109,25 +107,26 @@ export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends Workspa const { flatEntityToValidate: flatViewFilterToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatView = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFilterToValidate.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewMaps = isDefined(flatView) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatView, - viewFilterIds: flatView.viewFilterIds.filter( - (id) => id !== flatViewFilterToValidate.id, - ), - }, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatViewMaps; + if (isDefined(flatView)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatView, + viewFilterIds: flatView.viewFilterIds.filter( + (id) => id !== flatViewFilterToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, + }); + } return { status: 'success', @@ -135,10 +134,6 @@ export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends Workspa type: 'delete_view_filter', viewFilterId: flatViewFilterToValidate.id, }, - dependencyOptimisticFlatEntityMaps: { - ...dependencyOptimisticFlatEntityMaps, - flatViewMaps: updatedFlatViewMaps, - }, }; } @@ -160,11 +155,7 @@ export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends Workspa }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateViewFilterAction: UpdateViewFilterAction = { type: 'update_view_filter', @@ -175,7 +166,6 @@ export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends Workspa return { status: 'success', action: updateViewFilterAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-group/workspace-migration-v2-view-group-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-group/workspace-migration-v2-view-group-actions-builder.service.ts index 3b1ac05279..0a5cd69713 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-group/workspace-migration-v2-view-group-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-group/workspace-migration-v2-view-group-actions-builder.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util'; import { UpdateViewGroupAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-group/types/workspace-migration-view-group-action-v2.type'; import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; @@ -43,39 +43,40 @@ export class WorkspaceMigrationV2ViewGroupActionsBuilderService extends Workspac const { flatEntityToValidate: flatViewGroupToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatView = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewGroupToValidate.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ flatEntity: { ...flatView, viewGroupIds: [...flatView.viewGroupIds, flatViewGroupToValidate.id], }, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); const flatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewGroupToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); - const updatedFlatFieldMetadataMaps = - replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatFieldMetadata, - viewGroupIds: [ - ...flatFieldMetadata.viewGroupIds, - flatViewGroupToValidate.id, - ], - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, - }); + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatFieldMetadata, + viewGroupIds: [ + ...flatFieldMetadata.viewGroupIds, + flatViewGroupToValidate.id, + ], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); return { status: 'success', @@ -83,10 +84,6 @@ export class WorkspaceMigrationV2ViewGroupActionsBuilderService extends Workspac type: 'create_view_group', viewGroup: flatViewGroupToValidate, }, - dependencyOptimisticFlatEntityMaps: { - flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, - flatViewMaps: updatedFlatViewMaps, - }, }; } @@ -110,43 +107,45 @@ export class WorkspaceMigrationV2ViewGroupActionsBuilderService extends Workspac const { flatEntityToValidate: flatViewGroupToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatView = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewGroupToValidate.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewMaps = isDefined(flatView) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatView, - viewGroupIds: flatView.viewGroupIds.filter( - (id) => id !== flatViewGroupToValidate.id, - ), - }, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatViewMaps; + if (isDefined(flatView)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatView, + viewGroupIds: flatView.viewGroupIds.filter( + (id) => id !== flatViewGroupToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, + }); + } const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewGroupToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); - const updatedFlatFieldMetadataMaps = isDefined(flatFieldMetadata) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatFieldMetadata, - viewGroupIds: flatFieldMetadata.viewGroupIds.filter( - (id) => id !== flatViewGroupToValidate.id, - ), - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps; + if (isDefined(flatFieldMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatFieldMetadata, + viewGroupIds: flatFieldMetadata.viewGroupIds.filter( + (id) => id !== flatViewGroupToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + } return { status: 'success', @@ -154,10 +153,6 @@ export class WorkspaceMigrationV2ViewGroupActionsBuilderService extends Workspac type: 'delete_view_group', viewGroupId: flatViewGroupToValidate.id, }, - dependencyOptimisticFlatEntityMaps: { - flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, - flatViewMaps: updatedFlatViewMaps, - }, }; } @@ -179,11 +174,7 @@ export class WorkspaceMigrationV2ViewGroupActionsBuilderService extends Workspac }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateViewGroupAction: UpdateViewGroupAction = { type: 'update_view_group', @@ -194,7 +185,6 @@ export class WorkspaceMigrationV2ViewGroupActionsBuilderService extends Workspac return { status: 'success', action: updateViewGroupAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts index 1c99021bbe..06324244c3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util'; import { UpdateViewAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/types/workspace-migration-view-action-v2.type'; import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; @@ -40,22 +40,23 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti const { flatEntityToValidate: flatViewToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewToValidate.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); + + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatObjectMetadata, + viewIds: [...flatObjectMetadata.viewIds, flatViewToValidate.id], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); - const updatedFlatObjectMetadataMaps = - replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatObjectMetadata, - viewIds: [...flatObjectMetadata.viewIds, flatViewToValidate.id], - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, - }); const kanbanFieldMetadata = isDefined( flatViewToValidate.kanbanAggregateOperationFieldMetadataId, @@ -64,45 +65,47 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti flatEntityId: flatViewToValidate.kanbanAggregateOperationFieldMetadataId, flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }) : undefined; - const updatedFlatFieldMetadataMapsWithKanban = isDefined( - kanbanFieldMetadata, - ) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...kanbanFieldMetadata, - kanbanAggregateOperationViewIds: [ - ...kanbanFieldMetadata.kanbanAggregateOperationViewIds, - flatViewToValidate.id, - ], - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps; + + if (isDefined(kanbanFieldMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...kanbanFieldMetadata, + kanbanAggregateOperationViewIds: [ + ...kanbanFieldMetadata.kanbanAggregateOperationViewIds, + flatViewToValidate.id, + ], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + } const calendarFieldMetadata = isDefined( flatViewToValidate.calendarFieldMetadataId, ) ? findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewToValidate.calendarFieldMetadataId, - flatEntityMaps: updatedFlatFieldMetadataMapsWithKanban, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }) : undefined; - const updatedFlatFieldMetadataMaps = isDefined(calendarFieldMetadata) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...calendarFieldMetadata, - calendarViewIds: [ - ...calendarFieldMetadata.calendarViewIds, - flatViewToValidate.id, - ], - }, - flatEntityMaps: updatedFlatFieldMetadataMapsWithKanban, - }) - : updatedFlatFieldMetadataMapsWithKanban; + + if (isDefined(calendarFieldMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...calendarFieldMetadata, + calendarViewIds: [ + ...calendarFieldMetadata.calendarViewIds, + flatViewToValidate.id, + ], + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + } return { status: 'success', @@ -110,10 +113,6 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti type: 'create_view', view: flatViewToValidate, }, - dependencyOptimisticFlatEntityMaps: { - flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, - flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, - }, }; } @@ -134,26 +133,27 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti const { flatEntityToValidate: flatViewToValidate, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, } = args; const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewToValidate.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); - const updatedFlatObjectMetadataMaps = isDefined(flatObjectMetadata) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...flatObjectMetadata, - viewIds: flatObjectMetadata.viewIds.filter( - (id) => id !== flatViewToValidate.id, - ), - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps; + if (isDefined(flatObjectMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...flatObjectMetadata, + viewIds: flatObjectMetadata.viewIds.filter( + (id) => id !== flatViewToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); + } const kanbanFieldMetadata = isDefined( flatViewToValidate.kanbanAggregateOperationFieldMetadataId, @@ -162,46 +162,46 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti flatEntityId: flatViewToValidate.kanbanAggregateOperationFieldMetadataId, flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }) : undefined; - const updatedFlatFieldMetadataMapsWithKanban = isDefined( - kanbanFieldMetadata, - ) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...kanbanFieldMetadata, - kanbanAggregateOperationViewIds: - kanbanFieldMetadata.kanbanAggregateOperationViewIds.filter( - (id) => id !== flatViewToValidate.id, - ), - }, - flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, - }) - : dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps; + if (isDefined(kanbanFieldMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...kanbanFieldMetadata, + kanbanAggregateOperationViewIds: + kanbanFieldMetadata.kanbanAggregateOperationViewIds.filter( + (id) => id !== flatViewToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + } const calendarFieldMetadata = isDefined( flatViewToValidate.calendarFieldMetadataId, ) ? findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewToValidate.calendarFieldMetadataId, - flatEntityMaps: updatedFlatFieldMetadataMapsWithKanban, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }) : undefined; - const updatedFlatFieldMetadataMaps = isDefined(calendarFieldMetadata) - ? replaceFlatEntityInFlatEntityMapsOrThrow({ - flatEntity: { - ...calendarFieldMetadata, - calendarViewIds: calendarFieldMetadata.calendarViewIds.filter( - (id) => id !== flatViewToValidate.id, - ), - }, - flatEntityMaps: updatedFlatFieldMetadataMapsWithKanban, - }) - : updatedFlatFieldMetadataMapsWithKanban; + if (isDefined(calendarFieldMetadata)) { + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ + flatEntity: { + ...calendarFieldMetadata, + calendarViewIds: calendarFieldMetadata.calendarViewIds.filter( + (id) => id !== flatViewToValidate.id, + ), + }, + flatEntityMapsToMutate: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + } return { status: 'success', @@ -209,10 +209,6 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti type: 'delete_view', viewId: flatViewToValidate.id, }, - dependencyOptimisticFlatEntityMaps: { - flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, - flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, - }, }; } @@ -231,11 +227,7 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti }; } - const { - dependencyOptimisticFlatEntityMaps, - flatEntityId, - flatEntityUpdates, - } = args; + const { flatEntityId, flatEntityUpdates } = args; const updateViewAction: UpdateViewAction = { type: 'update_view', @@ -246,7 +238,6 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti return { status: 'success', action: updateViewAction, - dependencyOptimisticFlatEntityMaps, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service.ts index 0b66fa445e..781baae499 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service.ts @@ -1,8 +1,8 @@ import { Inject } from '@nestjs/common'; +import { AllMetadataName } from 'twenty-shared/metadata'; import { type FromTo } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; -import { AllMetadataName } from 'twenty-shared/metadata'; import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; import { @@ -11,12 +11,12 @@ import { } from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception'; import { MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type'; import { MetadataValidationRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type'; -import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; -import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util'; +import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util'; import { flatEntityDeletedCreatedUpdatedMatrixDispatcher } from 'src/engine/workspace-manager/workspace-migration-v2/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util'; import { getMetadataEmptyWorkspaceMigrationActionRecord } from 'src/engine/workspace-manager/workspace-migration-v2/utils/get-metadata-empty-workspace-migration-action-record.util'; +import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util'; import { FailedFlatEntityValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-flat-entity-validate-and-build.type'; import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type'; @@ -48,11 +48,15 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< public async validateAndBuild({ buildOptions, - dependencyOptimisticFlatEntityMaps, + dependencyOptimisticFlatEntityMaps: inputDependencyOptimisticFlatEntityMaps, from: fromFlatEntityMaps, to: toFlatEntityMaps, workspaceId, }: ValidateAndBuildArgs): Promise> { + const mutableDependencyOptimisticFlatEntityMaps = structuredClone( + inputDependencyOptimisticFlatEntityMaps, + ); + this.logger.time(`EntityBuilder ${this.metadataName}`, 'validateAndBuild'); this.logger.time( `EntityBuilder ${this.metadataName}`, @@ -83,13 +87,13 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< ); this.logger.time(`EntityBuilder ${this.metadataName}`, 'entity processing'); - let optimisticFlatEntityMaps = structuredClone(fromFlatEntityMaps); + const optimisticFlatEntityMaps = structuredClone(fromFlatEntityMaps); const actionsResult = getMetadataEmptyWorkspaceMigrationActionRecord( this.metadataName, ); const allValidationResult: FailedFlatEntityValidateAndBuild['errors'] = []; - let remainingFlatEntityMapsToCreate = structuredClone( + const remainingFlatEntityMapsToCreate = structuredClone( createdFlatEntityMaps, ); @@ -108,14 +112,13 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< ); } - remainingFlatEntityMapsToCreate = - deleteFlatEntityFromFlatEntityMapsOrThrow({ - entityToDeleteId: flatEntityToCreateId, - flatEntityMaps: remainingFlatEntityMapsToCreate, - }); + deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({ + entityToDeleteId: flatEntityToCreateId, + flatEntityMapsToMutate: remainingFlatEntityMapsToCreate, + }); const validationResult = await this.validateFlatEntityCreation({ - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, flatEntityToValidate: flatEntityToCreate, optimisticFlatEntityMaps, workspaceId, @@ -128,12 +131,10 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< continue; } - optimisticFlatEntityMaps = addFlatEntityToFlatEntityMapsOrThrow({ + addFlatEntityToFlatEntityMapsThroughMutationOrThrow({ flatEntity: flatEntityToCreate, - flatEntityMaps: optimisticFlatEntityMaps, + flatEntityMapsToMutate: optimisticFlatEntityMaps, }); - dependencyOptimisticFlatEntityMaps = - validationResult.dependencyOptimisticFlatEntityMaps; actionsResult.created.push( ...(Array.isArray(validationResult.action) @@ -151,7 +152,7 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< 'deletion validation', ); - let remainingFlatEntityMapsToDelete = structuredClone( + const remainingFlatEntityMapsToDelete = structuredClone( deletedFlatEntityMaps, ); @@ -169,14 +170,13 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< ); } - remainingFlatEntityMapsToDelete = - deleteFlatEntityFromFlatEntityMapsOrThrow({ - entityToDeleteId: flatEntityToDeleteId, - flatEntityMaps: remainingFlatEntityMapsToDelete, - }); + deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({ + entityToDeleteId: flatEntityToDeleteId, + flatEntityMapsToMutate: remainingFlatEntityMapsToDelete, + }); const validationResult = await this.validateFlatEntityDeletion({ - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, flatEntityToValidate: flatEntityToDelete, optimisticFlatEntityMaps: optimisticFlatEntityMaps, workspaceId, @@ -189,12 +189,10 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< continue; } - optimisticFlatEntityMaps = deleteFlatEntityFromFlatEntityMapsOrThrow({ + deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({ entityToDeleteId: flatEntityToDelete.id, - flatEntityMaps: optimisticFlatEntityMaps, + flatEntityMapsToMutate: optimisticFlatEntityMaps, }); - dependencyOptimisticFlatEntityMaps = - validationResult.dependencyOptimisticFlatEntityMaps; actionsResult.deleted.push( ...(Array.isArray(validationResult.action) @@ -223,7 +221,7 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< const validationResult = await this.validateFlatEntityUpdate({ flatEntityUpdates: flatEntityToUpdate.updates, flatEntityId: flatEntityToUpdateId, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, optimisticFlatEntityMaps: optimisticFlatEntityMaps, workspaceId, buildOptions, @@ -253,12 +251,10 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< }), }; - optimisticFlatEntityMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({ flatEntity: updatedFlatEntity, - flatEntityMaps: optimisticFlatEntityMaps, + flatEntityMapsToMutate: optimisticFlatEntityMaps, }); - dependencyOptimisticFlatEntityMaps = - validationResult.dependencyOptimisticFlatEntityMaps; actionsResult.updated.push( ...(Array.isArray(validationResult.action) @@ -281,7 +277,8 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< status: 'fail', errors: allValidationResult, optimisticFlatEntityMaps, - dependencyOptimisticFlatEntityMaps, + dependencyOptimisticFlatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps, }; } @@ -294,7 +291,8 @@ export abstract class WorkspaceEntityMigrationBuilderV2Service< status: 'success', actions: actionsResult, optimisticFlatEntityMaps, - dependencyOptimisticFlatEntityMaps, + dependencyOptimisticFlatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps, }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type.ts index 43bd0516f1..4a22d573cb 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type.ts @@ -8,7 +8,7 @@ import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-mana export type FlatEntityValidationArgs = { flatEntityToValidate: MetadataFlatEntity; optimisticFlatEntityMaps: MetadataFlatEntityMaps; - dependencyOptimisticFlatEntityMaps: MetadataValidationRelatedFlatEntityMaps; + mutableDependencyOptimisticFlatEntityMaps: MetadataValidationRelatedFlatEntityMaps; workspaceId: string; remainingFlatEntityMapsToValidate: MetadataFlatEntityMaps; buildOptions: WorkspaceMigrationBuilderOptions; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type.ts index 82b8b2c509..95a54731e3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type.ts @@ -1,7 +1,6 @@ import { type AllMetadataName } from 'twenty-shared/metadata'; import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type'; -import { type MetadataValidationRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type'; import { type MetadataWorkspaceMigrationAction } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type'; import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; @@ -14,7 +13,6 @@ export type FlatEntityValidationReturnType< action: | MetadataWorkspaceMigrationAction | MetadataWorkspaceMigrationAction[]; - dependencyOptimisticFlatEntityMaps: MetadataValidationRelatedFlatEntityMaps; } | ({ status: 'fail'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service.ts index 961388be0a..ee9c00167b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { msg, t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { CronTriggerExceptionCode } from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception'; import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; @@ -19,7 +19,7 @@ export class FlatCronTriggerValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.cronTrigger >): FailedFlatEntityValidation { @@ -52,7 +52,7 @@ export class FlatCronTriggerValidatorService { }; const serverlessFunction = - dependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[ updatedFlatCronTrigger.serverlessFunctionId ]; @@ -98,7 +98,7 @@ export class FlatCronTriggerValidatorService { public async validateFlatCronTriggerCreation({ flatEntityToValidate: flatCronTriggerToValidate, optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs): Promise< FailedFlatEntityValidation > { @@ -123,9 +123,8 @@ export class FlatCronTriggerValidatorService { } const serverlessFunction = - dependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps?.byId?.[ - flatCronTriggerToValidate.serverlessFunctionId - ]; + mutableDependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps + ?.byId?.[flatCronTriggerToValidate.serverlessFunctionId]; if (!isDefined(serverlessFunction)) { validationResult.errors.push({ diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service.ts index 17e4a247b9..9b3a6e289f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { msg, t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { DatabaseEventTriggerExceptionCode } from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception'; import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; @@ -20,7 +20,7 @@ export class FlatDatabaseEventTriggerValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.databaseEventTrigger >): FailedFlatEntityValidation { @@ -54,9 +54,8 @@ export class FlatDatabaseEventTriggerValidatorService { }; const serverlessFunction = - dependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps?.byId?.[ - updatedFlatDatabaseEventTrigger.serverlessFunctionId - ]; + mutableDependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps + ?.byId?.[updatedFlatDatabaseEventTrigger.serverlessFunctionId]; if (!isDefined(serverlessFunction)) { validationResult.errors.push({ @@ -103,7 +102,7 @@ export class FlatDatabaseEventTriggerValidatorService { public async validateFlatDatabaseEventTriggerCreation({ flatEntityToValidate: flatDatabaseEventTriggerToValidate, optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.databaseEventTrigger >): Promise> { @@ -131,9 +130,8 @@ export class FlatDatabaseEventTriggerValidatorService { } const serverlessFunction = - dependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps?.byId?.[ - flatDatabaseEventTriggerToValidate.serverlessFunctionId - ]; + mutableDependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps + ?.byId?.[flatDatabaseEventTriggerToValidate.serverlessFunctionId]; if (!isDefined(serverlessFunction)) { validationResult.errors.push({ diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts index b4d571178e..afb65413dd 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; import { msg } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; -import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/metadata-modules/flat-entity/constant/empty-flat-entity-maps.constant'; +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FLAT_FIELD_METADATA_RELATION_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-relation-properties-to-compare.constant'; import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service'; import { FlatFieldMetadataRelationPropertiesToCompare } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-relation-properties-to-compare.type'; @@ -31,7 +31,7 @@ export class FlatFieldMetadataValidatorService { flatEntityId, flatEntityUpdates: updates, optimisticFlatEntityMaps: optimisticFlatFieldMetadataMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, workspaceId, buildOptions, }: FlatEntityUpdateValidationArgs< @@ -70,7 +70,7 @@ export class FlatFieldMetadataValidatorService { }; const flatObjectMetadata = - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ flatFieldMetadataToValidate.objectMetadataId ]; @@ -152,14 +152,14 @@ export class FlatFieldMetadataValidatorService { const fieldMetadataTypeValidationErrors = await this.flatFieldMetadataTypeValidatorService.validateFlatFieldMetadataTypeSpecificities( { - dependencyOptimisticFlatEntityMaps: { + mutableDependencyOptimisticFlatEntityMaps: { flatObjectMetadataMaps: - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }, optimisticFlatEntityMaps: optimisticFlatFieldMetadataMaps, flatEntityToValidate: flatFieldMetadataToValidate, buildOptions, - remainingFlatEntityMapsToValidate: EMPTY_FLAT_ENTITY_MAPS, + remainingFlatEntityMapsToValidate: createEmptyFlatEntityMaps(), workspaceId, }, ); @@ -174,7 +174,7 @@ export class FlatFieldMetadataValidatorService { validateFlatFieldMetadataDeletion({ flatEntityToValidate: { id: flatFieldMetadataToDeleteId }, optimisticFlatEntityMaps: optimisticFlatFieldMetadataMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.fieldMetadata >): FailedFlatEntityValidation { @@ -205,7 +205,7 @@ export class FlatFieldMetadataValidatorService { }; const relatedFlatObjectMetadata = - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ flatFieldMetadataToDelete.objectMetadataId ]; @@ -225,12 +225,12 @@ export class FlatFieldMetadataValidatorService { const relationTargetObjectMetadataHasBeenDeleted = isMorphOrRelationFlatFieldMetadata(flatFieldMetadataToDelete) && !isDefined( - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ flatFieldMetadataToDelete.relationTargetObjectMetadataId ], ); const parentObjectMetadataHasBeenDeleted = !isDefined( - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ flatFieldMetadataToDelete.objectMetadataId ], ); @@ -265,7 +265,7 @@ export class FlatFieldMetadataValidatorService { async validateFlatFieldMetadataCreation({ flatEntityToValidate: flatFieldMetadataToValidate, optimisticFlatEntityMaps: optimisticFlatFieldMetadataMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, workspaceId, buildOptions, remainingFlatEntityMapsToValidate, @@ -283,7 +283,7 @@ export class FlatFieldMetadataValidatorService { }; const parentFlatObjectMetadata = - dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps.byId[ flatFieldMetadataToValidate.objectMetadataId ]; @@ -343,7 +343,7 @@ export class FlatFieldMetadataValidatorService { validationResult.errors.push( ...(await this.flatFieldMetadataTypeValidatorService.validateFlatFieldMetadataTypeSpecificities( { - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, flatEntityToValidate: flatFieldMetadataToValidate, buildOptions, optimisticFlatEntityMaps: optimisticFlatFieldMetadataMaps, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-index-metadata-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-index-metadata-validator.service.ts index 27e0bf778f..707b7fc67f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-index-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-index-metadata-validator.service.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { msg, t } from '@lingui/core/macro'; +import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; import { FieldMetadataType } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; -import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { isValidUniqueFieldDefaultValueCombination } from 'src/engine/metadata-modules/field-metadata/utils/is-valid-unique-input.util'; @@ -49,7 +49,7 @@ export class FlatIndexValidatorService { public validateFlatIndexCreation({ flatEntityToValidate: flatIndexToValidate, optimisticFlatEntityMaps: optimisticFlatIndexMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.index >): FailedFlatEntityValidation { @@ -77,7 +77,8 @@ export class FlatIndexValidatorService { const relatedObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatIndexToValidate.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); if (!isDefined(relatedObjectMetadata)) { @@ -117,7 +118,7 @@ export class FlatIndexValidatorService { const relatedFlatField = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatIndexField.fieldMetadataId, flatEntityMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); if (!isDefined(relatedFlatField)) { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts index d9250c5dd5..2b17b077fc 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts @@ -20,7 +20,7 @@ export class FlatObjectMetadataValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatObjectMetadataMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.objectMetadata >): FailedFlatEntityValidation { @@ -83,7 +83,7 @@ export class FlatObjectMetadataValidatorService { ...validateFlatObjectMetadataIdentifiers({ flatObjectMetadata: updatedFlatObjectMetadata, flatFieldMetadataMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }), ); } @@ -156,7 +156,7 @@ export class FlatObjectMetadataValidatorService { public async validateFlatObjectMetadataCreation({ flatEntityToValidate: flatObjectMetadataToValidate, optimisticFlatEntityMaps: optimisticFlatObjectMetadataMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.objectMetadata >): Promise> { @@ -195,7 +195,7 @@ export class FlatObjectMetadataValidatorService { ...validateFlatObjectMetadataIdentifiers({ flatObjectMetadata: flatObjectMetadataToValidate, flatFieldMetadataMaps: - dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }), ); objectValidationResult.errors.push( diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-route-trigger-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-route-trigger-validator.service.ts index 3a56ec4c51..981d796ad6 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-route-trigger-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-route-trigger-validator.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { msg, t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { RouteTriggerExceptionCode } from 'src/engine/metadata-modules/route-trigger/exceptions/route-trigger.exception'; import { FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger/types/flat-route-trigger.type'; @@ -19,7 +19,7 @@ export class FlatRouteTriggerValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatRouteTriggerMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.routeTrigger >): FailedFlatEntityValidation { @@ -52,7 +52,7 @@ export class FlatRouteTriggerValidatorService { }; const serverlessFunction = - dependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[ updatedFlatRouteTrigger.serverlessFunctionId ]; @@ -98,7 +98,7 @@ export class FlatRouteTriggerValidatorService { public async validateFlatRouteTriggerCreation({ flatEntityToValidate: flatRouteTriggerToValidate, optimisticFlatEntityMaps: optimisticFlatRouteTriggerMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs): Promise< FailedFlatEntityValidation > { @@ -140,7 +140,7 @@ export class FlatRouteTriggerValidatorService { } const serverlessFunction = - dependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[ flatRouteTriggerToValidate.serverlessFunctionId ]; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts index a5b4fc8236..87eb17562b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { msg, t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; 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'; @@ -23,7 +23,7 @@ export class FlatViewFieldValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatViewFieldMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.viewField >): FailedFlatEntityValidation { @@ -63,7 +63,7 @@ export class FlatViewFieldValidatorService { const flatView = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: updatedFlatViewField.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); if (!isDefined(flatView)) { @@ -78,7 +78,8 @@ export class FlatViewFieldValidatorService { const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatView.objectMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, }); if (!isDefined(flatObjectMetadata)) { @@ -118,7 +119,7 @@ export class FlatViewFieldValidatorService { public validateFlatViewFieldDeletion({ flatEntityToValidate: { id: viewFieldIdToDelete }, optimisticFlatEntityMaps: optimisticFlatViewFieldMaps, - dependencyOptimisticFlatEntityMaps: { + mutableDependencyOptimisticFlatEntityMaps: { flatFieldMetadataMaps, flatObjectMetadataMaps, }, @@ -181,7 +182,7 @@ export class FlatViewFieldValidatorService { public validateFlatViewFieldCreation({ flatEntityToValidate: flatViewFieldToValidate, optimisticFlatEntityMaps: optimisticFlatViewFieldMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.viewField >): FailedFlatEntityValidation { @@ -210,7 +211,8 @@ export class FlatViewFieldValidatorService { const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFieldToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); if (!isDefined(flatFieldMetadata)) { @@ -222,7 +224,7 @@ export class FlatViewFieldValidatorService { } const flatView = - dependencyOptimisticFlatEntityMaps.flatViewMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps.byId[ flatViewFieldToValidate.viewId ]; @@ -256,7 +258,8 @@ export class FlatViewFieldValidatorService { } const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, flatEntityId: flatView.objectMetadataId, }); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts index 4d380e618f..03ce9fbb98 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { msg, t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; @@ -19,7 +19,7 @@ export class FlatViewFilterValidatorService { validateFlatViewFilterCreation({ flatEntityToValidate: flatViewFilterToValidate, optimisticFlatEntityMaps: optimisticFlatViewFilterMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.viewFilter >): FailedFlatEntityValidation { @@ -46,7 +46,7 @@ export class FlatViewFilterValidatorService { const referencedView = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFilterToValidate.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); if (!isDefined(referencedView)) { @@ -59,7 +59,8 @@ export class FlatViewFilterValidatorService { const referencedFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFilterToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); if (!isDefined(referencedFieldMetadata)) { @@ -109,7 +110,7 @@ export class FlatViewFilterValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatViewFilterMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.viewFilter >): FailedFlatEntityValidation { @@ -142,7 +143,8 @@ export class FlatViewFilterValidatorService { const referencedFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: updatedFlatViewFilter.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); if (!isDefined(referencedFieldMetadata)) { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-group-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-group-validator.service.ts index 5c80bffa2b..a843ab405b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-group-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-group-validator.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { msg, t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type'; @@ -18,7 +18,7 @@ export class FlatViewGroupValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatViewGroupMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.viewGroup >): FailedFlatEntityValidation { @@ -58,7 +58,7 @@ export class FlatViewGroupValidatorService { const flatView = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: updatedFlatViewGroup.viewId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + flatEntityMaps: mutableDependencyOptimisticFlatEntityMaps.flatViewMaps, }); if (!isDefined(flatView)) { @@ -71,7 +71,8 @@ export class FlatViewGroupValidatorService { const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: updatedFlatViewGroup.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); if (!isDefined(flatFieldMetadata)) { @@ -116,7 +117,7 @@ export class FlatViewGroupValidatorService { public validateFlatViewGroupCreation({ flatEntityToValidate: flatViewGroupToValidate, optimisticFlatEntityMaps: optimisticFlatViewGroupMaps, - dependencyOptimisticFlatEntityMaps, + mutableDependencyOptimisticFlatEntityMaps, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.viewGroup >): FailedFlatEntityValidation { @@ -145,7 +146,8 @@ export class FlatViewGroupValidatorService { const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewGroupToValidate.fieldMetadataId, - flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + flatEntityMaps: + mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, }); if (!isDefined(flatFieldMetadata)) { @@ -157,7 +159,7 @@ export class FlatViewGroupValidatorService { } const flatView = - dependencyOptimisticFlatEntityMaps.flatViewMaps.byId[ + mutableDependencyOptimisticFlatEntityMaps.flatViewMaps.byId[ flatViewGroupToValidate.viewId ]; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service.ts index 6c7a2deb35..6990336acf 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service.ts @@ -1,6 +1,6 @@ import { msg, t } from '@lingui/core/macro'; -import { isDefined } from 'twenty-shared/utils'; import { type ALL_METADATA_NAME } from 'twenty-shared/metadata'; +import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type'; @@ -17,7 +17,7 @@ export class FlatViewValidatorService { flatEntityId, flatEntityUpdates, optimisticFlatEntityMaps: optimisticFlatViewMaps, - dependencyOptimisticFlatEntityMaps: { flatFieldMetadataMaps }, + mutableDependencyOptimisticFlatEntityMaps: { flatFieldMetadataMaps }, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.view >): FailedFlatEntityValidation { @@ -95,7 +95,7 @@ export class FlatViewValidatorService { public async validateFlatViewCreation({ flatEntityToValidate: flatViewToValidate, optimisticFlatEntityMaps: optimisticFlatViewMaps, - dependencyOptimisticFlatEntityMaps: { + mutableDependencyOptimisticFlatEntityMaps: { flatFieldMetadataMaps, flatObjectMetadataMaps, }, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts index d7734ee22f..b48345c7a5 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts @@ -30,11 +30,12 @@ export class WorkspaceMigrationRunnerV2Service { private readonly logger: LoggerService, ) {} - private async invalidateLegacyCache({ + private getLegacyCacheInvalidationPromises({ workspaceMigration: { actions, workspaceId }, }: { workspaceMigration: WorkspaceMigrationV2; - }) { + }): Promise[] { + const asyncOperations: Promise[] = []; const shouldIncrementMetadataGraphqlSchemaVersion = actions.some( (action) => { switch (action.type) { @@ -54,13 +55,15 @@ export class WorkspaceMigrationRunnerV2Service { ); if (shouldIncrementMetadataGraphqlSchemaVersion) { - await this.workspaceMetadataVersionService.incrementMetadataVersion( - workspaceId, - ); - await this.workspacePermissionsCacheService.recomputeRolesPermissionsCache( - { + asyncOperations.push( + this.workspaceMetadataVersionService.incrementMetadataVersion( workspaceId, - }, + ), + ); + asyncOperations.push( + this.workspacePermissionsCacheService.recomputeRolesPermissionsCache({ + workspaceId, + }), ); } @@ -92,11 +95,15 @@ export class WorkspaceMigrationRunnerV2Service { shouldInvalidFindCoreViewsGraphqlCacheOperation || shouldIncrementMetadataGraphqlSchemaVersion ) { - await this.workspaceCacheStorageService.flushGraphQLOperation({ - operationName: FIND_ALL_CORE_VIEWS_GRAPHQL_OPERATION, - workspaceId, - }); + asyncOperations.push( + this.workspaceCacheStorageService.flushGraphQLOperation({ + operationName: FIND_ALL_CORE_VIEWS_GRAPHQL_OPERATION, + workspaceId, + }), + ); } + + return asyncOperations; } run = async ({ @@ -170,19 +177,34 @@ export class WorkspaceMigrationRunnerV2Service { `Cache invalidation ${flatEntitiesCacheToInvalidate.join()}`, ); - await this.flatEntityMapsCacheService.invalidateFlatEntityMaps({ - workspaceId, - flatMapsKeys: [ - ...new Set([ - ...flatEntityMapsToInvalidate, - ...(relatedFlatEntityMapsKeys ?? []), - ]), - ], - }); + const invalidationResults = await Promise.allSettled([ + this.flatEntityMapsCacheService.invalidateFlatEntityMaps({ + workspaceId, + flatMapsKeys: [ + ...new Set([ + ...flatEntityMapsToInvalidate, + ...(relatedFlatEntityMapsKeys ?? []), + ]), + ], + }), + ...this.getLegacyCacheInvalidationPromises({ + workspaceMigration: { + actions, + workspaceId, + relatedFlatEntityMapsKeys, + }, + }), + ]); - await this.invalidateLegacyCache({ - workspaceMigration: { actions, workspaceId, relatedFlatEntityMapsKeys }, - }); + const invalidationFailures = invalidationResults.filter( + (result) => result.status === 'rejected', + ); + + if (invalidationFailures.length > 0) { + throw new Error( + `Failed to invalidate ${invalidationFailures.length} cache operations`, + ); + } this.logger.timeEnd( 'Runner',