Optimize EntityMetadata caching in GlobalWorkspaceDataSource (#16146)

## Context
EntityMetadata was being rebuilt from scratch on every
findMetadata()/getMetadata() call (~20 times per request). This involved
running EntitySchemaTransformer.transform() and
EntityMetadataBuilder.build() repeatedly, causing unnecessary CPU
overhead.

## Implementation
Cache entityMetadatas in ORMWorkspaceContext: Build EntityMetadata once
during workspace context initialization instead of on every metadata
lookup
Remove redundant entitySchemas caching: Since flatMetadata is already
cached, the additional Redis cache for entitySchemaOptions was
unnecessary overhead
Remove WorkspaceEntitiesStorage: Replaced with direct lookup from
FlatObjectMetadataMap
Simplify getObjectMetadataFromEntityTarget: Now only accepts string
targets, using flat metadata maps directly

Also:
Removed unused injections in some services
This commit is contained in:
Weiko
2025-11-28 10:09:52 +01:00
committed by GitHub
parent fd9ea2f5ee
commit 9620a4b0ba
11 changed files with 45 additions and 148 deletions
@@ -1,8 +1,4 @@
import {
type EntitySchema,
type EntityTarget,
type ObjectLiteral,
} from 'typeorm';
import { type EntityTarget, type ObjectLiteral } from 'typeorm';
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
@@ -11,27 +7,20 @@ import {
TwentyORMException,
TwentyORMExceptionCode,
} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception';
import { WorkspaceEntitiesStorage } from 'src/engine/twenty-orm/storage/workspace-entities.storage';
export const getObjectMetadataFromEntityTarget = <T extends ObjectLiteral>(
entityTarget: EntityTarget<T>,
internalContext: WorkspaceInternalContext,
): FlatObjectMetadata => {
const objectMetadataName =
typeof entityTarget === 'string'
? entityTarget
: WorkspaceEntitiesStorage.getObjectMetadataName(
internalContext.workspaceId,
entityTarget as EntitySchema,
);
if (!objectMetadataName) {
if (typeof entityTarget !== 'string') {
throw new TwentyORMException(
'Object metadata name is missing',
'Entity target must be a string',
TwentyORMExceptionCode.MALFORMED_METADATA,
);
}
const objectMetadataName = entityTarget;
const objectMetadataId =
internalContext.objectIdByNameSingular[objectMetadataName];