c5cdf45f85
## Improvements - Add logs to all gql operations and rest calls to help debug CPU issues on the backend. These are temporary and should be removed - Remove nested relations from workflowVersions load (used to add manual triggers in the side bar). On some workspaces this call result in a response of 4MB which is heavy on CPU - Investigated Redis Usage ==> made a few improvements, we are should still migrate to the new cache service once available - investigated db calls in messaging / calendar fetch list + workflow enqueue run cron jobs. Everything seems to be properly batched
91 lines
2.4 KiB
TypeScript
91 lines
2.4 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
|
|
import { logger } from '@sentry/node';
|
|
import { isDefined } from 'twenty-shared/utils';
|
|
|
|
import {
|
|
TwentyORMException,
|
|
TwentyORMExceptionCode,
|
|
} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception';
|
|
|
|
type CacheResult<T, U> = {
|
|
version: T;
|
|
data: U;
|
|
};
|
|
|
|
@Injectable()
|
|
export class GetDataFromCacheWithRecomputeService<T, U> {
|
|
private cache = new Map<string, CacheResult<T, U>>();
|
|
|
|
logger = new Logger(GetDataFromCacheWithRecomputeService.name);
|
|
constructor() {}
|
|
|
|
getFromCacheWithRecompute = async ({
|
|
workspaceId,
|
|
getCacheData,
|
|
getCacheVersion,
|
|
recomputeCache,
|
|
cachedEntityName,
|
|
exceptionCode,
|
|
}: {
|
|
workspaceId: string;
|
|
getCacheData: (workspaceId: string) => Promise<U | undefined>;
|
|
getCacheVersion: (workspaceId: string) => Promise<T | undefined>;
|
|
recomputeCache: (params: { workspaceId: string }) => Promise<void>;
|
|
cachedEntityName: string;
|
|
exceptionCode: TwentyORMExceptionCode;
|
|
}): Promise<CacheResult<T, U>> => {
|
|
let cachedVersion: T | undefined;
|
|
let cachedData: U | undefined;
|
|
|
|
cachedVersion = await getCacheVersion(workspaceId);
|
|
|
|
const cacheKey = `${workspaceId}-${cachedVersion}`;
|
|
const cachedValue = this.cache.get(cacheKey);
|
|
|
|
if (cachedValue) {
|
|
return cachedValue;
|
|
}
|
|
|
|
cachedData = await getCacheData(workspaceId);
|
|
|
|
if (!isDefined(cachedData) || !isDefined(cachedVersion)) {
|
|
logger.warn(
|
|
`Triggering cache recompute for ${cachedEntityName} (workspace ${workspaceId})`,
|
|
{
|
|
cachedVersion,
|
|
cachedData,
|
|
},
|
|
);
|
|
await recomputeCache({ workspaceId });
|
|
|
|
cachedData = await getCacheData(workspaceId);
|
|
cachedVersion = await getCacheVersion(workspaceId);
|
|
|
|
if (!isDefined(cachedData) || !isDefined(cachedVersion)) {
|
|
logger.warn(
|
|
`Data still missing after recompute for ${cachedEntityName} (workspace ${workspaceId})`,
|
|
{
|
|
cachedVersion,
|
|
cachedData,
|
|
},
|
|
);
|
|
throw new TwentyORMException(
|
|
`${cachedEntityName} not found after recompute for workspace ${workspaceId} (missingData: ${!isDefined(cachedData)}, missingVersion: ${!isDefined(cachedVersion)})`,
|
|
exceptionCode,
|
|
);
|
|
}
|
|
}
|
|
|
|
this.cache.set(cacheKey, {
|
|
version: cachedVersion,
|
|
data: cachedData,
|
|
});
|
|
|
|
return {
|
|
version: cachedVersion,
|
|
data: cachedData,
|
|
};
|
|
};
|
|
}
|