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:
Weiko
2025-12-01 17:08:21 +01:00
committed by GitHub
parent 4e0545ebc5
commit 1eb2e44058
77 changed files with 1306 additions and 1863 deletions
@@ -17,6 +17,7 @@ import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.
import { WorkspacePermissionsCacheModule } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.module';
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { MessagingModule } from 'src/modules/messaging/messaging.module';
@Global()
@@ -35,6 +36,7 @@ import { MessagingModule } from 'src/modules/messaging/messaging.module';
MessagingModule,
PermissionsModule,
ToolModule,
WorkspaceCacheModule,
],
providers: [ToolService, ToolAdapterService, SearchArticlesTool],
exports: [ToolService, ToolAdapterService, SearchArticlesTool],
@@ -7,9 +7,9 @@ import { UpdateRecordService } from 'src/engine/core-modules/record-crud/service
import { RecordInputTransformerService } from 'src/engine/core-modules/record-transformer/services/record-input-transformer.service';
import { ToolService } from 'src/engine/metadata-modules/ai/ai-tools/services/tool.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { getMockObjectMetadataEntity } from 'src/utils/__test__/get-object-metadata-entity.mock';
// Minimal mock repository type
@@ -28,7 +28,7 @@ describe('ToolService', () => {
const roleId = 'role_1';
let service: ToolService;
let permissionsCacheService: WorkspacePermissionsCacheService;
let workspaceCacheService: WorkspaceCacheService;
const testObject = getMockObjectMetadataEntity({
workspaceId: '',
@@ -75,10 +75,10 @@ describe('ToolService', () => {
},
},
{
provide: WorkspacePermissionsCacheService,
provide: WorkspaceCacheService,
useValue: {
getRolesPermissionsFromCache: jest.fn().mockResolvedValue({
data: {
getOrRecompute: jest.fn().mockResolvedValue({
rolesPermissions: {
[roleId]: {
[testObject.id]: {
canReadObjectRecords: true,
@@ -135,16 +135,17 @@ describe('ToolService', () => {
}).compile();
service = moduleRef.get(ToolService);
permissionsCacheService = moduleRef.get(WorkspacePermissionsCacheService);
workspaceCacheService = moduleRef.get(WorkspaceCacheService);
});
describe('listTools', () => {
it('should return tools based on role permissions', async () => {
const tools = await service.listTools({ unionOf: [roleId] }, workspaceId);
expect(
permissionsCacheService.getRolesPermissionsFromCache,
).toHaveBeenCalledWith({ workspaceId });
expect(workspaceCacheService.getOrRecompute).toHaveBeenCalledWith(
workspaceId,
['rolesPermissions'],
);
// Verify tool keys
expect(tools['create_testObject']).toBeDefined();
@@ -21,8 +21,8 @@ import {
ToolOperation,
} from 'src/engine/metadata-modules/ai/ai-chat-router/types/tool-hints.interface';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
import { computePermissionIntersection } from 'src/engine/twenty-orm/utils/compute-permission-intersection.util';
@@ -32,7 +32,7 @@ export class ToolService {
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
protected readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService,
protected readonly workspaceCacheService: WorkspaceCacheService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly createRecordService: CreateRecordService,
private readonly updateRecordService: UpdateRecordService,
@@ -51,10 +51,10 @@ export class ToolService {
): Promise<ToolSet> {
const tools: ToolSet = {};
const { data: rolesPermissions } =
await this.workspacePermissionsCacheService.getRolesPermissionsFromCache({
workspaceId,
});
const { rolesPermissions } =
await this.workspaceCacheService.getOrRecompute(workspaceId, [
'rolesPermissions',
]);
let objectPermissions;