Refactor workspace cache service (#16208)
## Context We've recently introduced a new workspace cache service which now acts as a cache access and local storage for all workspace related data, deprecating the individual specific services. - Better performance through multiple caching/fetching strategies - Consistent data access patterns across the codebase - Reduced redis queries through MGET/MSET/PIPELINE with multiple cache keys
This commit is contained in:
@@ -7,11 +7,13 @@ import { WorkspaceFlatApplicationMapCacheService } from 'src/engine/core-modules
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ApplicationEntity, AgentEntity, WorkspaceEntity]),
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
WorkspaceCacheModule,
|
||||
],
|
||||
exports: [ApplicationService, WorkspaceFlatApplicationMapCacheService],
|
||||
providers: [ApplicationService, WorkspaceFlatApplicationMapCacheService],
|
||||
|
||||
@@ -11,17 +11,16 @@ import {
|
||||
ApplicationExceptionCode,
|
||||
} from 'src/engine/core-modules/application/application.exception';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications';
|
||||
import { WorkspaceFlatApplicationMapCacheService } from 'src/engine/core-modules/application/services/workspace-flat-application-map-cache.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { ALL_FLAT_ENTITY_MAPS_PROPERTIES } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-maps-properties.constant';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationService {
|
||||
constructor(
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceFlatApplicationMapCacheService: WorkspaceFlatApplicationMapCacheService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
private readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
) {}
|
||||
@@ -50,12 +49,11 @@ export class ApplicationService {
|
||||
);
|
||||
}
|
||||
|
||||
const flatApplicationMaps =
|
||||
await this.workspaceFlatApplicationMapCacheService.getExistingOrRecomputeFlatMaps(
|
||||
{
|
||||
workspaceId: workspace.id,
|
||||
},
|
||||
);
|
||||
const { flatApplicationMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspace.id, [
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
const twentyStandardApplicationId =
|
||||
flatApplicationMaps.idByUniversalIdentifier[
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier
|
||||
@@ -169,9 +167,9 @@ export class ApplicationService {
|
||||
);
|
||||
|
||||
if (!skipCacheInvalidation) {
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId,
|
||||
});
|
||||
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
}
|
||||
|
||||
return twentyStandardApplication;
|
||||
@@ -221,9 +219,9 @@ export class ApplicationService {
|
||||
|
||||
const savedApplication = await this.applicationRepository.save(application);
|
||||
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId: data.workspaceId,
|
||||
});
|
||||
await this.workspaceCacheService.invalidateAndRecompute(data.workspaceId, [
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
return savedApplication;
|
||||
}
|
||||
@@ -234,9 +232,10 @@ export class ApplicationService {
|
||||
): Promise<ApplicationEntity> {
|
||||
await this.applicationRepository.update({ id }, data);
|
||||
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId: data.workspaceId as string,
|
||||
});
|
||||
await this.workspaceCacheService.invalidateAndRecompute(
|
||||
data.workspaceId as string,
|
||||
['flatApplicationMaps'],
|
||||
);
|
||||
|
||||
const updatedApplication = await this.findById(id);
|
||||
|
||||
@@ -262,14 +261,13 @@ export class ApplicationService {
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId,
|
||||
});
|
||||
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.invalidateFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
await this.workspaceCacheService.invalidateAndRecompute(
|
||||
workspaceId,
|
||||
ALL_FLAT_ENTITY_MAPS_PROPERTIES,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-19
@@ -1,38 +1,28 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { FlatApplicationCacheMaps } from 'src/engine/core-modules/application/types/flat-application-cache-maps.type';
|
||||
import { fromApplicationEntityToFlatApplication } from 'src/engine/core-modules/application/utils/from-application-entity-to-flat-application.util';
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
|
||||
import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator';
|
||||
import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service';
|
||||
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceFlatMapCache(
|
||||
'flatApplicationMaps' as MetadataToFlatEntityMapsKey<AllMetadataName>,
|
||||
) // TODO prastoin introduce SyncableMetadata notion
|
||||
export class WorkspaceFlatApplicationMapCacheService extends WorkspaceFlatMapCacheService<FlatApplicationCacheMaps> {
|
||||
@WorkspaceCache('flatApplicationMaps')
|
||||
export class WorkspaceFlatApplicationMapCacheService extends WorkspaceCacheProvider<FlatApplicationCacheMaps> {
|
||||
constructor(
|
||||
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||
cacheStorageService: CacheStorageService,
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
) {
|
||||
super(cacheStorageService);
|
||||
super();
|
||||
}
|
||||
|
||||
protected async computeFlatMap({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<FlatApplicationCacheMaps> {
|
||||
async computeForCache(
|
||||
workspaceId: string,
|
||||
): Promise<FlatApplicationCacheMaps> {
|
||||
const applicationEntities = await this.applicationRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
|
||||
Reference in New Issue
Block a user