Runner metadata events (#17841)

# Introduction
Followup https://github.com/twentyhq/twenty/pull/17622

Refactoring the actions handler to be returning a metadata event
It has to be done incrementally, as if not update metadata event would
be stale as depends on the incremental action execution order and
optimistic application

## What's next
- Builder should consume and regroup each metadata even in order to
batch emit them ( within a single metadata actions batch order matters )
=> refactoring https://github.com/twentyhq/twenty/pull/17622 in order to
consume runner returned metadata events
This commit is contained in:
Paul Rastoin
2026-02-11 10:09:54 +01:00
committed by GitHub
parent b0cb29c11c
commit 41e413d7b1
10 changed files with 418 additions and 58 deletions
@@ -11,11 +11,10 @@ export type AllUniversalWorkspaceMigrationAction<
WorkspaceMigrationActionType = WorkspaceMigrationActionType,
> = MetadataUniversalWorkspaceMigrationAction<AllMetadataName, TActionType>;
export type AllFlatWorkspaceMigrationAction =
MetadataFlatWorkspaceMigrationAction<
AllMetadataName,
WorkspaceMigrationActionType
>;
export type AllFlatWorkspaceMigrationAction<
TActionType extends
WorkspaceMigrationActionType = WorkspaceMigrationActionType,
> = MetadataFlatWorkspaceMigrationAction<AllMetadataName, TActionType>;
export { WorkspaceMigrationActionType };
@@ -25,20 +25,35 @@ import {
WorkspaceMigrationRunnerException,
WorkspaceMigrationRunnerExceptionCode,
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/exceptions/workspace-migration-runner.exception';
import { type MetadataEvent } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
import {
WorkspaceMigrationActionRunnerContext,
type WorkspaceMigrationActionRunnerArgs,
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/workspace-migration-action-runner-args.type';
import { deriveMetadataEventsFromCreateAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/derive-metadata-events-from-create-action.util';
import { deriveMetadataEventsFromDeleteAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/derive-metadata-events-from-delete-action.util';
import { deriveMetadataEventsFromUpdateAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/derive-metadata-events-from-update-action.util';
import { optimisticallyApplyCreateActionOnAllFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/optimistically-apply-create-action-on-all-flat-entity-maps.util';
import { optimisticallyApplyDeleteActionOnAllFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/optimistically-apply-delete-action-on-all-flat-entity-maps.util';
import { optimisticallyApplyUpdateActionOnAllFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/optimistically-apply-update-action-on-all-flat-entity-maps.util';
type OptimisticallyApplyActionOnAllFlatEntityMapsArgs<
type FlatActionWithAllFlatEntityMapsArgs<
TFlatAction extends AllFlatWorkspaceMigrationAction,
> = {
flatAction: TFlatAction;
allFlatEntityMaps: AllFlatEntityMaps;
};
export type ActionHandlerExecuteResult<TMetadataName extends AllMetadataName> =
{
partialOptimisticCache: Pick<
AllFlatEntityMaps,
| MetadataRelatedFlatEntityMapsKeys<TMetadataName>
| MetadataToFlatEntityMapsKey<TMetadataName>
>;
metadataEvents: MetadataEvent[];
};
export abstract class BaseWorkspaceMigrationRunnerActionHandlerService<
TActionType extends WorkspaceMigrationActionType,
TMetadataName extends AllMetadataName,
@@ -97,7 +112,7 @@ export abstract class BaseWorkspaceMigrationRunnerActionHandlerService<
private optimisticallyApplyActionOnAllFlatEntityMaps({
flatAction,
allFlatEntityMaps,
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<TFlatAction>): Pick<
}: FlatActionWithAllFlatEntityMapsArgs<TFlatAction>): Pick<
AllFlatEntityMaps,
| MetadataRelatedFlatEntityMapsKeys<TMetadataName>
| MetadataToFlatEntityMapsKey<TMetadataName>
@@ -124,6 +139,29 @@ export abstract class BaseWorkspaceMigrationRunnerActionHandlerService<
}
}
private deriveMetadataEventsFromFlatAction({
flatAction,
allFlatEntityMaps,
}: FlatActionWithAllFlatEntityMapsArgs<TFlatAction>): MetadataEvent[] {
switch (flatAction.type) {
case 'create': {
return deriveMetadataEventsFromCreateAction(flatAction);
}
case 'delete': {
return deriveMetadataEventsFromDeleteAction({
flatAction,
allFlatEntityMaps,
});
}
case 'update': {
return deriveMetadataEventsFromUpdateAction({
flatAction,
allFlatEntityMaps,
});
}
}
}
rollbackForMetadata(
_context: Omit<
WorkspaceMigrationActionRunnerArgs<TUniversalAction>,
@@ -178,13 +216,7 @@ export abstract class BaseWorkspaceMigrationRunnerActionHandlerService<
async execute(
context: WorkspaceMigrationActionRunnerArgs<TUniversalAction>,
): Promise<
Pick<
AllFlatEntityMaps,
| MetadataRelatedFlatEntityMapsKeys<TMetadataName>
| MetadataToFlatEntityMapsKey<TMetadataName>
>
> {
): Promise<ActionHandlerExecuteResult<TMetadataName>> {
const flatAction =
await this.transpileUniversalActionToFlatActionOrThrow(context);
@@ -216,13 +248,18 @@ export abstract class BaseWorkspaceMigrationRunnerActionHandlerService<
});
}
const metadataEvents = this.deriveMetadataEventsFromFlatAction({
flatAction,
allFlatEntityMaps: context.allFlatEntityMaps,
});
const partialOptimisticCache =
this.optimisticallyApplyActionOnAllFlatEntityMaps({
flatAction,
allFlatEntityMaps: context.allFlatEntityMaps,
});
return partialOptimisticCache;
return { partialOptimisticCache, metadataEvents };
}
async rollback(
@@ -8,6 +8,7 @@ import { DataSource } from 'typeorm';
import { LoggerService } from 'src/engine/core-modules/logger/logger.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { type MetadataEvent } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util';
import { getMetadataSerializedRelationNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-serialized-relation-names.util';
@@ -152,7 +153,10 @@ export class WorkspaceMigrationRunnerService {
actions,
applicationUniversalIdentifier,
workspaceId,
}: WorkspaceMigration): Promise<AllFlatEntityMaps> => {
}: WorkspaceMigration): Promise<{
allFlatEntityMaps: AllFlatEntityMaps;
metadataEvents: MetadataEvent[];
}> => {
this.logger.time('Runner', 'Total execution');
this.logger.time('Runner', 'Initial cache retrieval');
@@ -207,8 +211,10 @@ export class WorkspaceMigrationRunnerService {
await queryRunner.connect();
await queryRunner.startTransaction();
const allMetadataEvents: MetadataEvent[] = [];
for (const action of actions) {
const result =
const { partialOptimisticCache, metadataEvents } =
await this.workspaceMigrationRunnerActionHandlerRegistry.executeActionHandler(
{
action,
@@ -224,8 +230,10 @@ export class WorkspaceMigrationRunnerService {
allFlatEntityMaps = {
...allFlatEntityMaps,
...result,
...partialOptimisticCache,
} as typeof allFlatEntityMaps;
allMetadataEvents.push(...metadataEvents);
}
await queryRunner.commitTransaction();
@@ -239,7 +247,7 @@ export class WorkspaceMigrationRunnerService {
this.logger.timeEnd('Runner', 'Total execution');
return allFlatEntityMaps;
return { allFlatEntityMaps, metadataEvents: allMetadataEvents };
} catch (error) {
if (queryRunner.isTransactionActive) {
await queryRunner.rollbackTransaction().catch((error) =>
@@ -0,0 +1,52 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
import { type MetadataUniversalFlatEntityPropertiesToCompare } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/metadata-universal-flat-entity-properties-to-compare.type';
type BaseMetadataEvent<T extends AllMetadataName, TPayload extends object> = {
metadataName: T;
properties: TPayload;
};
export type DeleteMetadataEvent<T extends AllMetadataName> = BaseMetadataEvent<
T,
{ before: MetadataFlatEntity<T> }
> & {
type: 'delete';
};
export type UpdateMetadataEventDiff<
T extends AllMetadataName,
TProperties extends MetadataUniversalFlatEntityPropertiesToCompare<T>,
> = {
[P in TProperties]: {
before: MetadataFlatEntity<T>[P];
after: MetadataFlatEntity<T>[P];
};
};
export type UpdateMetadataEvent<
T extends AllMetadataName,
TProperties extends
MetadataUniversalFlatEntityPropertiesToCompare<T> = MetadataUniversalFlatEntityPropertiesToCompare<T>,
> = BaseMetadataEvent<
T,
{
updatedFields: TProperties[];
diff: UpdateMetadataEventDiff<T, TProperties>;
before: MetadataFlatEntity<T>;
after: MetadataFlatEntity<T>;
}
> & { type: 'update' };
export type CreateMetadataEvent<T extends AllMetadataName> = BaseMetadataEvent<
T,
{
after: MetadataFlatEntity<T>;
}
> & { type: 'create' };
export type MetadataEvent<T extends AllMetadataName = AllMetadataName> =
| DeleteMetadataEvent<T>
| UpdateMetadataEvent<T>
| CreateMetadataEvent<T>;
@@ -0,0 +1,79 @@
import { assertUnreachable } from 'twenty-shared/utils';
import { type AllFlatWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
import {
type CreateMetadataEvent,
type MetadataEvent,
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
export const deriveMetadataEventsFromCreateAction = (
flatAction: AllFlatWorkspaceMigrationAction<'create'>,
): MetadataEvent[] => {
switch (flatAction.metadataName) {
case 'fieldMetadata': {
return flatAction.flatFieldMetadatas.map(
(flatFieldMetadata): CreateMetadataEvent<'fieldMetadata'> => ({
type: 'create',
metadataName: 'fieldMetadata',
properties: {
after: flatFieldMetadata,
},
}),
);
}
case 'objectMetadata': {
const objectEvent: CreateMetadataEvent<'objectMetadata'> = {
type: 'create',
metadataName: 'objectMetadata',
properties: {
after: flatAction.flatEntity,
},
};
const fieldEvents: MetadataEvent[] = flatAction.flatFieldMetadatas.map(
(flatFieldMetadata): CreateMetadataEvent<'fieldMetadata'> => ({
type: 'create',
metadataName: 'fieldMetadata',
properties: {
after: flatFieldMetadata,
},
}),
);
return [objectEvent, ...fieldEvents];
}
case 'view':
case 'viewField':
case 'viewGroup':
case 'rowLevelPermissionPredicate':
case 'rowLevelPermissionPredicateGroup':
case 'viewFilterGroup':
case 'index':
case 'logicFunction':
case 'viewFilter':
case 'role':
case 'roleTarget':
case 'agent':
case 'skill':
case 'pageLayout':
case 'pageLayoutWidget':
case 'pageLayoutTab':
case 'commandMenuItem':
case 'frontComponent':
case 'navigationMenuItem':
case 'webhook': {
return [
{
type: 'create',
metadataName: flatAction.metadataName,
properties: {
after: flatAction.flatEntity,
},
},
];
}
default: {
assertUnreachable(flatAction);
}
}
};
@@ -0,0 +1,66 @@
import { assertUnreachable } from 'twenty-shared/utils';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
import { type AllFlatWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
import { type MetadataEvent } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
export type DeriveMetadataEventsFromDeleteActionArgs = {
flatAction: AllFlatWorkspaceMigrationAction<'delete'>;
allFlatEntityMaps: AllFlatEntityMaps;
};
export const deriveMetadataEventsFromDeleteAction = ({
flatAction,
allFlatEntityMaps,
}: DeriveMetadataEventsFromDeleteActionArgs): MetadataEvent[] => {
switch (flatAction.metadataName) {
case 'fieldMetadata':
case 'objectMetadata':
case 'view':
case 'viewField':
case 'viewGroup':
case 'rowLevelPermissionPredicate':
case 'rowLevelPermissionPredicateGroup':
case 'viewFilterGroup':
case 'index':
case 'logicFunction':
case 'viewFilter':
case 'role':
case 'roleTarget':
case 'agent':
case 'skill':
case 'pageLayout':
case 'pageLayoutWidget':
case 'pageLayoutTab':
case 'commandMenuItem':
case 'frontComponent':
case 'navigationMenuItem':
case 'webhook': {
const flatEntityToDelete = findFlatEntityByIdInFlatEntityMapsOrThrow<
MetadataFlatEntity<typeof flatAction.metadataName>
>({
flatEntityId: flatAction.entityId,
flatEntityMaps:
allFlatEntityMaps[
getMetadataFlatEntityMapsKey(flatAction.metadataName)
],
});
return [
{
type: 'delete',
metadataName: flatAction.metadataName,
properties: {
before: flatEntityToDelete,
},
},
];
}
default: {
assertUnreachable(flatAction);
}
}
};
@@ -0,0 +1,143 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { assertUnreachable } from 'twenty-shared/utils';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
import { type MetadataUniversalFlatEntityPropertiesToCompare } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/metadata-universal-flat-entity-properties-to-compare.type';
import { type AllFlatWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
import {
type UpdateMetadataEventDiff,
type CreateMetadataEvent,
type DeleteMetadataEvent,
type MetadataEvent,
type UpdateMetadataEvent,
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
export type DeriveMetadataEventsFromUpdateActionArgs = {
flatAction: AllFlatWorkspaceMigrationAction<'update'>;
allFlatEntityMaps: AllFlatEntityMaps;
};
const buildUpdateMetadataEvent = <TMetadataName extends AllMetadataName>({
metadataName,
before,
after,
updatedFields,
}: {
metadataName: TMetadataName;
before: MetadataFlatEntity<TMetadataName>;
after: MetadataFlatEntity<TMetadataName>;
updatedFields: MetadataUniversalFlatEntityPropertiesToCompare<TMetadataName>[];
}): UpdateMetadataEvent<TMetadataName> => {
const diff = Object.fromEntries(
updatedFields.map((field) => [
field,
{
before: before[field],
after: after[field],
},
]),
) as UpdateMetadataEventDiff<TMetadataName, (typeof updatedFields)[number]>;
return {
type: 'update',
metadataName,
properties: {
updatedFields,
diff,
before,
after,
},
};
};
export const deriveMetadataEventsFromUpdateAction = ({
flatAction,
allFlatEntityMaps,
}: DeriveMetadataEventsFromUpdateActionArgs): MetadataEvent[] => {
switch (flatAction.metadataName) {
case 'index': {
const fromFlatEntity = findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatAction.entityId,
flatEntityMaps: allFlatEntityMaps['flatIndexMaps'],
});
const toFlatEntity = flatAction.updatedFlatIndex;
const deleteIndexMetadataEvent: DeleteMetadataEvent<'index'> = {
metadataName: 'index',
properties: {
before: fromFlatEntity,
},
type: 'delete',
};
const createIndexMetadataEvent: CreateMetadataEvent<'index'> = {
metadataName: 'index',
properties: {
after: toFlatEntity,
},
type: 'create',
};
return [deleteIndexMetadataEvent, createIndexMetadataEvent];
}
case 'fieldMetadata':
case 'objectMetadata':
case 'view':
case 'viewField':
case 'viewGroup':
case 'rowLevelPermissionPredicate':
case 'rowLevelPermissionPredicateGroup':
case 'viewFilterGroup':
case 'logicFunction':
case 'viewFilter':
case 'role':
case 'roleTarget':
case 'agent':
case 'skill':
case 'pageLayout':
case 'pageLayoutWidget':
case 'pageLayoutTab':
case 'commandMenuItem':
case 'frontComponent':
case 'navigationMenuItem':
case 'webhook': {
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(
flatAction.metadataName,
);
const fromFlatEntity = findFlatEntityByIdInFlatEntityMapsOrThrow<
MetadataFlatEntity<typeof flatAction.metadataName>
>({
flatEntityId: flatAction.entityId,
flatEntityMaps: allFlatEntityMaps[flatEntityMapsKey],
});
const toFlatEntity = {
...fromFlatEntity,
...flatAction.update,
} as MetadataFlatEntity<typeof flatAction.metadataName>;
const updatedFields = Object.keys(
flatAction.update,
) as MetadataUniversalFlatEntityPropertiesToCompare<
typeof flatAction.metadataName
>[];
return [
buildUpdateMetadataEvent({
metadataName: flatAction.metadataName,
before: fromFlatEntity,
after: toFlatEntity,
updatedFields,
}),
];
}
default: {
assertUnreachable(flatAction);
}
}
};
@@ -1,26 +1,18 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { assertUnreachable } from 'twenty-shared/utils';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
import { addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
import { type AllFlatWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
type FlatCreateAction<TMetadataName extends AllMetadataName> =
AllFlatEntityTypesByMetadataName[TMetadataName]['flatActions']['create'];
export type OptimisticallyApplyCreateActionOnAllFlatEntityMapsArgs<
TMetadataName extends AllMetadataName,
> = {
flatAction: FlatCreateAction<TMetadataName>;
export type OptimisticallyApplyCreateActionOnAllFlatEntityMapsArgs = {
flatAction: AllFlatWorkspaceMigrationAction<'create'>;
allFlatEntityMaps: AllFlatEntityMaps;
};
export const optimisticallyApplyCreateActionOnAllFlatEntityMaps = <
TMetadataName extends AllMetadataName,
>({
export const optimisticallyApplyCreateActionOnAllFlatEntityMaps = ({
flatAction,
allFlatEntityMaps,
}: OptimisticallyApplyCreateActionOnAllFlatEntityMapsArgs<TMetadataName>): AllFlatEntityMaps => {
}: OptimisticallyApplyCreateActionOnAllFlatEntityMapsArgs): AllFlatEntityMaps => {
switch (flatAction.metadataName) {
case 'fieldMetadata': {
flatAction.flatFieldMetadatas.forEach((flatEntity) =>
@@ -1,29 +1,21 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { assertUnreachable } from 'twenty-shared/utils';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
import { deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-and-related-entity-maps-through-mutation-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 { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
import { type AllFlatWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
type FlatDeleteAction<TMetadataName extends AllMetadataName> =
AllFlatEntityTypesByMetadataName[TMetadataName]['flatActions']['delete'];
export type OptimisticallyApplyDeleteActionOnAllFlatEntityMapsArgs<
TMetadataName extends AllMetadataName,
> = {
flatAction: FlatDeleteAction<TMetadataName>;
export type OptimisticallyApplyDeleteActionOnAllFlatEntityMapsArgs = {
flatAction: AllFlatWorkspaceMigrationAction<'delete'>;
allFlatEntityMaps: AllFlatEntityMaps;
};
export const optimisticallyApplyDeleteActionOnAllFlatEntityMaps = <
TMetadataName extends AllMetadataName,
>({
export const optimisticallyApplyDeleteActionOnAllFlatEntityMaps = ({
flatAction,
allFlatEntityMaps,
}: OptimisticallyApplyDeleteActionOnAllFlatEntityMapsArgs<TMetadataName>): AllFlatEntityMaps => {
}: OptimisticallyApplyDeleteActionOnAllFlatEntityMapsArgs): AllFlatEntityMaps => {
switch (flatAction.metadataName) {
case 'fieldMetadata':
case 'objectMetadata':
@@ -1,31 +1,23 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { assertUnreachable } from 'twenty-shared/utils';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
import { addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
import { deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-and-related-entity-maps-through-mutation-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 { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
import { type AllFlatWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
type FlatUpdateAction<TMetadataName extends AllMetadataName> =
AllFlatEntityTypesByMetadataName[TMetadataName]['flatActions']['update'];
export type OptimisticallyApplyUpdateActionOnAllFlatEntityMapsArgs<
TMetadataName extends AllMetadataName,
> = {
flatAction: FlatUpdateAction<TMetadataName>;
export type OptimisticallyApplyUpdateActionOnAllFlatEntityMapsArgs = {
flatAction: AllFlatWorkspaceMigrationAction<'update'>;
allFlatEntityMaps: AllFlatEntityMaps;
};
export const optimisticallyApplyUpdateActionOnAllFlatEntityMaps = <
TMetadataName extends AllMetadataName,
>({
export const optimisticallyApplyUpdateActionOnAllFlatEntityMaps = ({
flatAction,
allFlatEntityMaps,
}: OptimisticallyApplyUpdateActionOnAllFlatEntityMapsArgs<TMetadataName>): AllFlatEntityMaps => {
}: OptimisticallyApplyUpdateActionOnAllFlatEntityMapsArgs): AllFlatEntityMaps => {
switch (flatAction.metadataName) {
case 'index': {
const flatIndex = findFlatEntityByIdInFlatEntityMapsOrThrow({