fix: gracefully handle unknown fields in SSE optimistic record updates
https://sonarly.com/issue/21148?type=bug When an SSE database event delivers a record update containing custom fields not yet in the frontend's cached metadata, `computeOptimisticRecordFromInput` throws a fatal error that breaks real-time update processing for the session. Fix: Converted the `throw new Error(...)` in `computeOptimisticRecordFromInput` (line 73-77) to `console.warn(...)`. **Why this is safe:** The function's main processing loop (line 80) iterates only over `objectMetadataItem.fields`, not over `recordInput` keys. Unknown fields in `recordInput` are naturally skipped and never included in the output. The `throw` was a defensive assertion added in commit `29745c67568` for mutation-triggered optimistic updates where the frontend controls the input. When SSE real-time events were added (commit `d51c988a9e`), this function started receiving server-controlled data via `useTriggerOptimisticEffectFromSseUpdateEvents`, which passes `event.properties.after` directly — including custom fields that may not yet be in the frontend's stale metadata cache. **What this fixes:** When an SSE event delivers a record containing custom fields (e.g., `testMs` on the `opportunity` object) and the frontend's metadata cache hasn't refreshed yet, the function now logs a warning and continues processing known fields instead of crashing the entire SSE event stream handler. Updated the test from asserting a throw to asserting a `console.warn` call and verifying that known fields (`city: 'Paris'`) are still correctly processed while unknown fields (`unknwon`, `foo`, `bar`) are skipped.
This commit is contained in:
+23
-17
@@ -252,26 +252,32 @@ describe('computeOptimisticRecordFromInput', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if recordInput contains fields unrelated to the current objectMetadata', () => {
|
||||
it('should warn and skip unknown fields if recordInput contains fields unrelated to the current objectMetadata', () => {
|
||||
const cache = new InMemoryCache();
|
||||
const personObjectMetadataItem = getMockObjectMetadataItemOrThrow('person');
|
||||
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
|
||||
|
||||
expect(() =>
|
||||
computeOptimisticRecordFromInput({
|
||||
currentWorkspaceMember,
|
||||
objectMetadataItems: getTestEnrichedObjectMetadataItemsMock(),
|
||||
objectMetadataItem: personObjectMetadataItem,
|
||||
recordInput: {
|
||||
unknwon: 'unknown',
|
||||
foo: 'foo',
|
||||
bar: 'bar',
|
||||
city: 'Paris',
|
||||
},
|
||||
cache,
|
||||
objectPermissionsByObjectMetadataId: {},
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Should never occur, encountered unknown fields unknwon, foo, bar in objectMetadataItem person"`,
|
||||
const result = computeOptimisticRecordFromInput({
|
||||
currentWorkspaceMember,
|
||||
objectMetadataItems: getTestEnrichedObjectMetadataItemsMock(),
|
||||
objectMetadataItem: personObjectMetadataItem,
|
||||
recordInput: {
|
||||
unknwon: 'unknown',
|
||||
foo: 'foo',
|
||||
bar: 'bar',
|
||||
city: 'Paris',
|
||||
},
|
||||
cache,
|
||||
objectPermissionsByObjectMetadataId: {},
|
||||
});
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'computeOptimisticRecordFromInput: skipping unknown fields unknwon, foo, bar in objectMetadataItem person',
|
||||
);
|
||||
expect(result).toEqual({
|
||||
city: 'Paris',
|
||||
});
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
+2
-2
@@ -71,8 +71,8 @@ export const computeOptimisticRecordFromInput = ({
|
||||
},
|
||||
);
|
||||
if (unknownRecordInputFields.length > 0) {
|
||||
throw new Error(
|
||||
`Should never occur, encountered unknown fields ${unknownRecordInputFields.join(', ')} in objectMetadataItem ${objectMetadataItem.nameSingular}`,
|
||||
console.warn(
|
||||
`computeOptimisticRecordFromInput: skipping unknown fields ${unknownRecordInputFields.join(', ')} in objectMetadataItem ${objectMetadataItem.nameSingular}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user