Improve v2 and cache invalidation perfs (#15467)

# 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
<img width="2632" height="1402" alt="image"
src="https://github.com/user-attachments/assets/2f1f0ccf-44de-4856-bfe1-4f45a351763a"
/>

### After
<img width="2632" height="1402" alt="image"
src="https://github.com/user-attachments/assets/4bc9e6db-3046-48b9-b903-1464053936c4"
/>


## 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**  |

---
This commit is contained in:
Paul Rastoin
2025-10-31 17:20:51 +01:00
committed by GitHub
parent 2d1a89c4c2
commit d640b93096
61 changed files with 1120 additions and 846 deletions
@@ -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,
@@ -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;
}
}
@@ -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;
}
}
@@ -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';
@@ -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<AllFlatEntityMaps>(
(acc, metadataName) => ({
...acc,
[getMetadataFlatEntityMapsKey(metadataName)]: createEmptyFlatEntityMaps(),
}),
{} as AllFlatEntityMaps,
);
@@ -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<FlatEntity>;
export const createEmptyFlatEntityMaps = () =>
({
byId: {},
idByUniversalIdentifier: {},
universalIdentifiersByApplicationId: {},
}) as const satisfies FlatEntityMaps<FlatEntity>;
@@ -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<AllFlatEntityMaps>(
(acc, metadataName) => ({
...acc,
[getMetadataFlatEntityMapsKey(metadataName)]: EMPTY_FLAT_ENTITY_MAPS,
}),
{} as AllFlatEntityMaps,
);
@@ -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`);
}
}
@@ -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<T extends AllMetadataName> =
keyof (typeof ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY)[T];
@@ -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<T extends AllMetadataName> =
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<T>],
AllMetadataName
>;
@@ -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 = <T extends FlatEntity>({
flatEntity,
flatEntityMaps: acc,
});
}, EMPTY_FLAT_ENTITY_MAPS);
}, createEmptyFlatEntityMaps());
};
@@ -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;
@@ -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<FieldMetadataEntity>,
@InjectRepository(ViewFieldEntity)
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectRepository(ViewGroupEntity)
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
) {
super(cacheStorageService);
}
@@ -34,48 +47,88 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceFlatMapC
}: {
workspaceId: string;
}): Promise<FlatEntityMaps<FlatFieldMetadata>> {
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;
}
}
@@ -25,7 +25,7 @@ export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilatio
throw new WorkspaceMigrationBuilderExceptionV2(
{
report: {
...EMPTY_ORCHESTRATOR_FAILURE_REPORT,
...EMPTY_ORCHESTRATOR_FAILURE_REPORT(),
objectMetadata: [
{
errors: failedInputTranspilationErrors,
@@ -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,
@@ -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;
}
}
@@ -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(),
);
@@ -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<ObjectMetadataEntity>,
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(IndexMetadataEntity)
private readonly indexMetadataRepository: Repository<IndexMetadataEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
) {
super(cacheStorageService);
}
@@ -35,36 +45,61 @@ export class WorkspaceFlatObjectMetadataMapCacheService extends WorkspaceFlatMap
}: {
workspaceId: string;
}): Promise<FlatEntityMaps<FlatObjectMetadata>> {
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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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],
})
@@ -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<ViewEntity>,
@InjectRepository(ViewFieldEntity)
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectRepository(ViewGroupEntity)
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
) {
super(cacheStorageService);
}
@@ -31,29 +41,61 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceFlatMapCacheServi
}: {
workspaceId: string;
}): Promise<FlatViewMaps> {
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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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<T extends AllMetadataName> =
MetadataManyToOneJoinColumn<T> extends never
? never
: {
entities: MetadataEntity<T>[];
foreignKey: MetadataManyToOneJoinColumn<T>;
};
export const regroupEntitiesByRelatedEntityId = <T extends AllMetadataName>({
entities,
foreignKey,
}: RegroupEntitiesByRelatedEntityIdArgs<T>) => {
const entitiesByRelatedEntityId = new Map<string, { id: string }[]>();
for (const entity of entities) {
const currentRelatedEntityId = entity[
foreignKey as keyof MetadataEntity<T>
] as string;
if (!isDefined(currentRelatedEntityId)) {
continue;
}
if (!entitiesByRelatedEntityId.has(currentRelatedEntityId)) {
entitiesByRelatedEntityId.set(currentRelatedEntityId, []);
}
entitiesByRelatedEntityId
.get(currentRelatedEntityId)!
.push({ id: entity.id });
}
return entitiesByRelatedEntityId;
};
@@ -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: [
@@ -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,
);
@@ -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,
);
@@ -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({
@@ -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: {},
@@ -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: {},
@@ -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<T>;
};
export const addFlatEntityToFlatEntityMapsThroughMutationOrThrow = <
T extends FlatEntity,
>({
flatEntity,
flatEntityMapsToMutate,
}: AddFlatEntityToFlatEntityMapsThroughMutationOrThrowArgs<T>): 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];
}
}
};
@@ -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<T>;
};
export const deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow = <
T extends FlatEntity,
>({
flatEntityMapsToMutate,
entityToDeleteId,
}: DeleteFlatEntityFromFlatEntityMapsThroughMutationOrThrowArgs<T>): 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
];
}
}
}
};
@@ -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<T extends AllMetadataName> = {
@@ -46,8 +46,8 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = <
buildOptions,
}: FlatEntityDeletedCreatedUpdatedMatrixDispatcherArgs<T>): DeletedCreatedUpdatedMatrix<T> => {
const initialDispatcher: DeletedCreatedUpdatedMatrix<T> = {
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 } =
@@ -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<T>;
};
export const replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow = <
T extends FlatEntity,
>({
flatEntity,
flatEntityMapsToMutate,
}: ReplaceFlatEntityInFlatEntityMapsThroughMutationOrThrowArgs<T>): void => {
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({
flatEntityMapsToMutate,
entityToDeleteId: flatEntity.id,
});
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
flatEntity,
flatEntityMapsToMutate,
});
};
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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<typeof ALL_METADATA_NAME.index>): 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,
};
}
}
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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,
};
}
}
@@ -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<T>): Promise<ValidateAndBuildReturnType<T>> {
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<T>['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,
};
}
@@ -8,7 +8,7 @@ import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-mana
export type FlatEntityValidationArgs<T extends AllMetadataName> = {
flatEntityToValidate: MetadataFlatEntity<T>;
optimisticFlatEntityMaps: MetadataFlatEntityMaps<T>;
dependencyOptimisticFlatEntityMaps: MetadataValidationRelatedFlatEntityMaps<T>;
mutableDependencyOptimisticFlatEntityMaps: MetadataValidationRelatedFlatEntityMaps<T>;
workspaceId: string;
remainingFlatEntityMapsToValidate: MetadataFlatEntityMaps<T>;
buildOptions: WorkspaceMigrationBuilderOptions;
@@ -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<T, TOperation>
| MetadataWorkspaceMigrationAction<T, TOperation>[];
dependencyOptimisticFlatEntityMaps: MetadataValidationRelatedFlatEntityMaps<T>;
}
| ({
status: 'fail';
@@ -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<FlatCronTrigger> {
@@ -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<typeof ALL_METADATA_NAME.cronTrigger>): Promise<
FailedFlatEntityValidation<FlatCronTrigger>
> {
@@ -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({
@@ -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<FlatDatabaseEventTrigger> {
@@ -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<FailedFlatEntityValidation<FlatDatabaseEventTrigger>> {
@@ -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({
@@ -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<FlatFieldMetadata> {
@@ -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,
@@ -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<FlatIndexMetadata> {
@@ -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)) {
@@ -20,7 +20,7 @@ export class FlatObjectMetadataValidatorService {
flatEntityId,
flatEntityUpdates,
optimisticFlatEntityMaps: optimisticFlatObjectMetadataMaps,
dependencyOptimisticFlatEntityMaps,
mutableDependencyOptimisticFlatEntityMaps,
}: FlatEntityUpdateValidationArgs<
typeof ALL_METADATA_NAME.objectMetadata
>): FailedFlatEntityValidation<FlatObjectMetadata> {
@@ -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<FailedFlatEntityValidation<FlatObjectMetadata>> {
@@ -195,7 +195,7 @@ export class FlatObjectMetadataValidatorService {
...validateFlatObjectMetadataIdentifiers({
flatObjectMetadata: flatObjectMetadataToValidate,
flatFieldMetadataMaps:
dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps,
mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps,
}),
);
objectValidationResult.errors.push(
@@ -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<FlatRouteTrigger> {
@@ -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<typeof ALL_METADATA_NAME.routeTrigger>): Promise<
FailedFlatEntityValidation<FlatRouteTrigger>
> {
@@ -140,7 +140,7 @@ export class FlatRouteTriggerValidatorService {
}
const serverlessFunction =
dependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[
mutableDependencyOptimisticFlatEntityMaps.flatServerlessFunctionMaps.byId[
flatRouteTriggerToValidate.serverlessFunctionId
];
@@ -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<FlatViewField> {
@@ -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<FlatViewField> {
@@ -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,
});
@@ -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<FlatViewFilter> {
@@ -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<FlatViewFilter> {
@@ -142,7 +143,8 @@ export class FlatViewFilterValidatorService {
const referencedFieldMetadata = findFlatEntityByIdInFlatEntityMaps({
flatEntityId: updatedFlatViewFilter.fieldMetadataId,
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps,
flatEntityMaps:
mutableDependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps,
});
if (!isDefined(referencedFieldMetadata)) {
@@ -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<FlatViewGroup> {
@@ -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<FlatViewGroup> {
@@ -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
];
@@ -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<FlatView> {
@@ -95,7 +95,7 @@ export class FlatViewValidatorService {
public async validateFlatViewCreation({
flatEntityToValidate: flatViewToValidate,
optimisticFlatEntityMaps: optimisticFlatViewMaps,
dependencyOptimisticFlatEntityMaps: {
mutableDependencyOptimisticFlatEntityMaps: {
flatFieldMetadataMaps,
flatObjectMetadataMaps,
},
@@ -30,11 +30,12 @@ export class WorkspaceMigrationRunnerV2Service {
private readonly logger: LoggerService,
) {}
private async invalidateLegacyCache({
private getLegacyCacheInvalidationPromises({
workspaceMigration: { actions, workspaceId },
}: {
workspaceMigration: WorkspaceMigrationV2;
}) {
}): Promise<void>[] {
const asyncOperations: Promise<void>[] = [];
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',