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:
+7
-8
@@ -1,7 +1,7 @@
|
||||
import { AsyncLocalStorage } from 'async_hooks';
|
||||
|
||||
import { type ObjectsPermissionsByRoleId } from 'twenty-shared/types';
|
||||
import { type EntitySchema } from 'typeorm';
|
||||
import { type EntityMetadata } from 'typeorm';
|
||||
|
||||
import { type WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
|
||||
|
||||
@@ -11,22 +11,21 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
export type WorkspaceContext = {
|
||||
export type ORMWorkspaceContext = {
|
||||
authContext: WorkspaceAuthContext;
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
flatIndexMaps: FlatEntityMaps<FlatIndexMetadata>;
|
||||
objectIdByNameSingular: Record<string, string>;
|
||||
metadataVersion: number;
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>;
|
||||
permissionsPerRoleId: ObjectsPermissionsByRoleId;
|
||||
entitySchemas: EntitySchema[];
|
||||
entityMetadatas: EntityMetadata[];
|
||||
};
|
||||
|
||||
export const workspaceContextStorage =
|
||||
new AsyncLocalStorage<WorkspaceContext>();
|
||||
new AsyncLocalStorage<ORMWorkspaceContext>();
|
||||
|
||||
export const getWorkspaceContext = (): WorkspaceContext => {
|
||||
export const getWorkspaceContext = (): ORMWorkspaceContext => {
|
||||
const context = workspaceContextStorage.getStore();
|
||||
|
||||
if (!context) {
|
||||
@@ -39,12 +38,12 @@ export const getWorkspaceContext = (): WorkspaceContext => {
|
||||
};
|
||||
|
||||
export const withWorkspaceContext = <T>(
|
||||
context: WorkspaceContext,
|
||||
context: ORMWorkspaceContext,
|
||||
fn: () => T | Promise<T>,
|
||||
): T | Promise<T> => {
|
||||
return workspaceContextStorage.run(context, fn);
|
||||
};
|
||||
|
||||
export const setWorkspaceContext = (context: WorkspaceContext): void => {
|
||||
export const setWorkspaceContext = (context: ORMWorkspaceContext): void => {
|
||||
workspaceContextStorage.enterWith(context);
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
import { type EntitySchema } from 'typeorm';
|
||||
|
||||
export class WorkspaceEntitiesStorage {
|
||||
private static workspaceEntities = new Map<
|
||||
string,
|
||||
Map<string, EntitySchema>
|
||||
>();
|
||||
|
||||
static setEntitySchema(
|
||||
workspaceId: string,
|
||||
objectMetadataName: string,
|
||||
schema: EntitySchema,
|
||||
): void {
|
||||
if (!this.workspaceEntities.has(workspaceId)) {
|
||||
this.workspaceEntities.set(workspaceId, new Map<string, EntitySchema>());
|
||||
}
|
||||
const workspace = this.workspaceEntities.get(workspaceId);
|
||||
|
||||
workspace?.set(objectMetadataName, schema);
|
||||
}
|
||||
|
||||
static getObjectMetadataName(
|
||||
workspaceId: string,
|
||||
target: EntitySchema,
|
||||
): string | undefined {
|
||||
const workspace = this.workspaceEntities.get(workspaceId);
|
||||
|
||||
return Array.from(workspace?.entries() || []).find(
|
||||
([, schema]) => schema.options.name === target.options.name,
|
||||
)?.[0];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user