Improve object record changed performances (#16398)

Using deepEqual, average over 3 calls:
- version trigger 1.53ms
- version steps 38.3ms
- run state 372.8 ms

Using stringified hash, average over 3 calls:
- version trigger 0.07ms
- version steps 0.74 ms
- run state 0.521ms

Short fastDeepEqual
- version trigger 0.028ms
- version steps 0.197ms
- run state 0.214ms

Lib fastDeepEqual
- version trigger 0.038ms
- version steps 0.187ms
- run state 0.230ms
This commit is contained in:
Thomas Trompette
2025-12-08 17:06:53 +01:00
committed by GitHub
parent 859004f4fc
commit ac89b5aff6
4 changed files with 432 additions and 23 deletions
@@ -1,30 +1,30 @@
import deepEqual from 'deep-equal';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, type ObjectRecord } from 'twenty-shared/types';
import { fastDeepEqual } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { buildFieldMapsFromFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/build-field-maps-from-flat-object-metadata.util';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
const isWorkflowVersionStepsOrTrigger = (
objectMetadataItem: FlatObjectMetadata,
key: string,
) => {
return (
objectMetadataItem.standardId === STANDARD_OBJECT_IDS.workflowVersion &&
(key === 'steps' || key === 'trigger')
);
const LARGE_JSON_FIELDS: Record<string, Set<string>> = {
[STANDARD_OBJECT_IDS.workflowVersion]: new Set(['steps', 'trigger']),
[STANDARD_OBJECT_IDS.workflowAutomatedTrigger]: new Set(['settings']),
[STANDARD_OBJECT_IDS.workflowRun]: new Set(['state']),
};
const isWorkflowAutomatedTriggerSettings = (
const isLargeJsonField = (
objectMetadataItem: Pick<FlatObjectMetadata, 'standardId'>,
key: string,
) => {
return (
objectMetadataItem.standardId ===
STANDARD_OBJECT_IDS.workflowAutomatedTrigger && key === 'settings'
);
): boolean => {
const standardId = objectMetadataItem.standardId;
if (!standardId) {
return false;
}
return LARGE_JSON_FIELDS[standardId]?.has(key) ?? false;
};
export const objectRecordChangedValues = (
@@ -46,20 +46,19 @@ export const objectRecordChangedValues = (
const oldRecordValue = oldRecord[key];
const newRecordValue = newRecord[key];
// Temporary ignore workflow json fields changes
if (
isWorkflowAutomatedTriggerSettings(objectMetadataItem, key) ||
isWorkflowVersionStepsOrTrigger(objectMetadataItem, key)
key === 'updatedAt' ||
key === 'searchVector' ||
field?.type === FieldMetadataType.RELATION
) {
return acc;
}
if (
key === 'updatedAt' ||
key === 'searchVector' ||
field?.type === FieldMetadataType.RELATION ||
deepEqual(oldRecordValue, newRecordValue)
) {
if (isLargeJsonField(objectMetadataItem, key)) {
if (fastDeepEqual(oldRecordValue, newRecordValue)) {
return acc;
}
} else if (deepEqual(oldRecordValue, newRecordValue)) {
return acc;
}