Provide a wrapper to execute command on workspace with easier devXP (#10391)

Proposal:
- Add a method in ActiveWorkspaceCommand to loop over workspace safely
(add counter, add try / catch, provide datasource with fresh cache,
destroy datasource => as we do always do it)

Also in this PR:
- make sure we clear all dataSources (and not only the one on metadata
version in RAM)
This commit is contained in:
Charles Bochet
2025-02-21 16:40:33 +01:00
committed by GitHub
parent 7a3e92fe0b
commit d747366bf3
27 changed files with 120 additions and 1393 deletions

View File

@ -14,13 +14,17 @@ import {
} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception';
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
import { CacheManager } from 'src/engine/twenty-orm/storage/cache-manager.storage';
import { CacheKey } from 'src/engine/twenty-orm/storage/types/cache-key.type';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
@Injectable()
export class WorkspaceDatasourceFactory {
private readonly logger = new Logger(WorkspaceDatasourceFactory.name);
private cacheManager = new CacheManager<WorkspaceDataSource>();
private cachedDatasourcePromise: Record<string, Promise<WorkspaceDataSource>>;
private cachedDataSourcePromise: Record<
CacheKey,
Promise<WorkspaceDataSource>
>;
constructor(
private readonly dataSourceService: DataSourceService,
@ -29,7 +33,7 @@ export class WorkspaceDatasourceFactory {
private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService,
private readonly entitySchemaFactory: EntitySchemaFactory,
) {
this.cachedDatasourcePromise = {};
this.cachedDataSourcePromise = {};
}
public async create(
@ -53,16 +57,16 @@ export class WorkspaceDatasourceFactory {
);
}
const cacheKey = `${workspaceId}-${cachedWorkspaceMetadataVersion}`;
const cacheKey: CacheKey = `${workspaceId}-${cachedWorkspaceMetadataVersion}`;
if (cacheKey in this.cachedDatasourcePromise) {
return this.cachedDatasourcePromise[cacheKey];
if (cacheKey in this.cachedDataSourcePromise) {
return this.cachedDataSourcePromise[cacheKey];
}
const creationPromise = (async (): Promise<WorkspaceDataSource> => {
try {
const result = await this.cacheManager.execute(
cacheKey as '`${string}-${string}`',
cacheKey,
async () => {
this.logger.log(
`Creating workspace data source for workspace ${workspaceId} and metadata version ${cachedWorkspaceMetadataVersion}`,
@ -178,22 +182,23 @@ export class WorkspaceDatasourceFactory {
return result;
} finally {
delete this.cachedDatasourcePromise[cacheKey];
delete this.cachedDataSourcePromise[cacheKey];
}
})();
this.cachedDatasourcePromise[cacheKey] = creationPromise;
this.cachedDataSourcePromise[cacheKey] = creationPromise;
return creationPromise;
}
public async destroy(workspaceId: string): Promise<void> {
const cachedWorkspaceMetadataVersion =
await this.workspaceCacheStorageService.getMetadataVersion(workspaceId);
const cacheKeys = (
Object.keys(this.cachedDataSourcePromise) as CacheKey[]
).filter((key) => key.startsWith(`${workspaceId}`));
await this.cacheManager.clearKey(
`${workspaceId}-${cachedWorkspaceMetadataVersion}`,
);
for (const cacheKey of cacheKeys) {
await this.cacheManager.clearKey(cacheKey);
}
}
private async getWorkspaceMetadataVersionFromCache(