perf: cache ServerBlockNoteEditor instance in transformRichTextV2Value (#17844)
## Summary
- `transformRichTextV2Value` was calling `await
import('@blocknote/server-util')` and `ServerBlockNoteEditor.create()`
on **every single invocation**, adding ~90ms of overhead each time
(visible as the highest avg-duration frame in profiling at 93.49ms).
- Cache the `ServerBlockNoteEditor` instance at module level so the
dynamic import + creation only happens once for the lifetime of the
process.
- Also removes debug timing instrumentation (`performance.now()`,
`calculateInputSize`, `Logger`) that is no longer needed.
## Test plan
- [ ] Verify rich text fields (blocknote/markdown) still round-trip
correctly on create and update
- [ ] Confirm reduced CPU time for `transformRichTextV2Value` in
profiling
Made with [Cursor](https://cursor.com)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+11
-26
@@ -1,5 +1,3 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import {
|
||||
type RichTextV2Metadata,
|
||||
@@ -7,35 +5,30 @@ import {
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const logger = new Logger('TransformRichTextV2');
|
||||
// Reuse a single ServerBlockNoteEditor across all calls to avoid
|
||||
// the cost of dynamic import resolution + instance creation (~90ms) on every transform.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let cachedServerBlockNoteEditor: any = null;
|
||||
|
||||
const calculateInputSize = (input: unknown): number => {
|
||||
if (typeof input === 'string') {
|
||||
return Buffer.byteLength(input, 'utf8');
|
||||
}
|
||||
if (typeof input === 'object' && input !== null) {
|
||||
return Buffer.byteLength(JSON.stringify(input), 'utf8');
|
||||
const getServerBlockNoteEditor = async () => {
|
||||
if (!cachedServerBlockNoteEditor) {
|
||||
const { ServerBlockNoteEditor } = await import('@blocknote/server-util');
|
||||
|
||||
cachedServerBlockNoteEditor = ServerBlockNoteEditor.create();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return cachedServerBlockNoteEditor;
|
||||
};
|
||||
|
||||
export const transformRichTextV2Value = async (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
richTextValue: any,
|
||||
): Promise<RichTextV2Metadata> => {
|
||||
const startTime = performance.now();
|
||||
const inputSize = calculateInputSize(richTextValue);
|
||||
|
||||
const parsedValue = isNonEmptyString(richTextValue)
|
||||
? richTextV2ValueSchema.parse(richTextValue)
|
||||
: richTextValue;
|
||||
|
||||
const afterParsingTime = performance.now();
|
||||
|
||||
const { ServerBlockNoteEditor } = await import('@blocknote/server-util');
|
||||
|
||||
const serverBlockNoteEditor = ServerBlockNoteEditor.create();
|
||||
const serverBlockNoteEditor = await getServerBlockNoteEditor();
|
||||
|
||||
// Patch: Handle cases where blocknote to markdown conversion fails for certain block types (custom/code blocks)
|
||||
// Todo : This may be resolved once the server-utils library is updated with proper conversion support - #947
|
||||
@@ -51,8 +44,6 @@ export const transformRichTextV2Value = async (
|
||||
convertedMarkdown = parsedValue.blocknote || null;
|
||||
}
|
||||
|
||||
const afterMarkdownConversionTime = performance.now();
|
||||
|
||||
const convertedBlocknote = parsedValue.markdown
|
||||
? JSON.stringify(
|
||||
await serverBlockNoteEditor.tryParseMarkdownToBlocks(
|
||||
@@ -61,12 +52,6 @@ export const transformRichTextV2Value = async (
|
||||
)
|
||||
: null;
|
||||
|
||||
const endTime = performance.now();
|
||||
|
||||
logger.debug(
|
||||
`transformRichTextV2Value completed - total: ${endTime - startTime}ms, parsing: ${afterParsingTime - startTime}ms, markdown_conversion: ${afterMarkdownConversionTime - afterParsingTime}ms, blocknote_conversion: ${endTime - afterMarkdownConversionTime}ms, size: ${inputSize} bytes`,
|
||||
);
|
||||
|
||||
return {
|
||||
markdown: parsedValue.markdown || convertedMarkdown,
|
||||
blocknote: parsedValue.blocknote || convertedBlocknote,
|
||||
|
||||
Reference in New Issue
Block a user