Optimize migrate-email-fields-command (#7035)

Quick follow up to prepare for 0.30 release
This commit is contained in:
Charles Bochet 2024-09-15 13:13:35 +02:00 committed by GitHub
parent f54eea0227
commit 872f52990a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 77 additions and 24 deletions

View File

@ -55,9 +55,12 @@ export class MigrateEmailFieldsToEmailsCommand extends ActiveWorkspacesCommandRu
); );
for (const workspaceId of workspaceIds) { for (const workspaceId of workspaceIds) {
let dataSourceMetadata;
let workspaceQueryRunner;
this.logger.log(`Running command for workspace ${workspaceId}`); this.logger.log(`Running command for workspace ${workspaceId}`);
try { try {
const dataSourceMetadata = dataSourceMetadata =
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
workspaceId, workspaceId,
); );
@ -77,10 +80,19 @@ export class MigrateEmailFieldsToEmailsCommand extends ActiveWorkspacesCommandRu
); );
} }
const workspaceQueryRunner = workspaceDataSource.createQueryRunner(); workspaceQueryRunner = workspaceDataSource.createQueryRunner();
await workspaceQueryRunner.connect(); await workspaceQueryRunner.connect();
} catch (error) {
this.logger.log(
chalk.red(
`Could not connect to workspace data source for workspace ${workspaceId}`,
),
);
continue;
}
try {
const customFieldsWithEmailType = const customFieldsWithEmailType =
await this.fieldMetadataRepository.find({ await this.fieldMetadataRepository.find({
where: { where: {
@ -267,17 +279,19 @@ export class MigrateEmailFieldsToEmailsCommand extends ActiveWorkspacesCommandRu
workspaceId, workspaceId,
); );
} }
} finally {
await workspaceQueryRunner.release();
} }
} }
} catch (error) { } catch (error) {
await workspaceQueryRunner.release();
this.logger.log( this.logger.log(
chalk.red( chalk.red(
`Running command on workspace ${workspaceId} failed with error: ${error}`, `Running command on workspace ${workspaceId} failed with error: ${error}`,
), ),
); );
continue; continue;
} finally {
await workspaceQueryRunner.release();
} }
this.logger.log(chalk.green(`Command completed!`)); this.logger.log(chalk.green(`Command completed!`));

View File

@ -30,28 +30,11 @@ export class WorkspaceDatasourceFactory {
workspaceId: string, workspaceId: string,
workspaceMetadataVersion: number | null, workspaceMetadataVersion: number | null,
): Promise<WorkspaceDataSource> { ): Promise<WorkspaceDataSource> {
const latestWorkspaceMetadataVersion =
await this.workspaceCacheStorageService.getMetadataVersion(workspaceId);
if (latestWorkspaceMetadataVersion === undefined) {
await this.workspaceMetadataCacheService.recomputeMetadataCache(
workspaceId,
);
throw new TwentyORMException(
`Metadata version not found for workspace ${workspaceId}`,
TwentyORMExceptionCode.METADATA_VERSION_NOT_FOUND,
);
}
const desiredWorkspaceMetadataVersion = const desiredWorkspaceMetadataVersion =
workspaceMetadataVersion ?? latestWorkspaceMetadataVersion; await this.computeDesiredWorkspaceMetadataVersion(
workspaceId,
if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) { workspaceMetadataVersion,
throw new TwentyORMException(
`Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`,
TwentyORMExceptionCode.METADATA_VERSION_MISMATCH,
); );
}
const workspaceDataSource = await this.cacheManager.execute( const workspaceDataSource = await this.cacheManager.execute(
`${workspaceId}-${desiredWorkspaceMetadataVersion}`, `${workspaceId}-${desiredWorkspaceMetadataVersion}`,
@ -166,4 +149,46 @@ export class WorkspaceDatasourceFactory {
return workspaceDataSource; return workspaceDataSource;
} }
private async computeDesiredWorkspaceMetadataVersion(
workspaceId: string,
workspaceMetadataVersion: number | null,
): Promise<number> {
const latestWorkspaceMetadataVersion =
await this.workspaceCacheStorageService.getMetadataVersion(workspaceId);
if (latestWorkspaceMetadataVersion === undefined) {
await this.workspaceMetadataCacheService.recomputeMetadataCache(
workspaceId,
);
throw new TwentyORMException(
`Metadata version not found for workspace ${workspaceId}`,
TwentyORMExceptionCode.METADATA_VERSION_NOT_FOUND,
);
}
const desiredWorkspaceMetadataVersion =
workspaceMetadataVersion ?? latestWorkspaceMetadataVersion;
if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) {
throw new TwentyORMException(
`Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`,
TwentyORMExceptionCode.METADATA_VERSION_MISMATCH,
);
}
return desiredWorkspaceMetadataVersion;
}
public async destroy(
workspaceId: string,
metadataVersion: number | null,
): Promise<void> {
const desiredWorkspaceMetadataVersion =
this.computeDesiredWorkspaceMetadataVersion(workspaceId, metadataVersion);
await this.cacheManager.clearKey(
`${workspaceId}-${desiredWorkspaceMetadataVersion}`,
);
}
} }

View File

@ -34,6 +34,16 @@ export class CacheManager<T> {
return value; return value;
} }
async clearKey(
cacheKey: CacheKey,
onDelete?: (value: T) => Promise<void> | void,
): Promise<void> {
if (this.cache.has(cacheKey)) {
await onDelete?.(this.cache.get(cacheKey)!);
this.cache.delete(cacheKey);
}
}
async clear(onDelete?: (value: T) => Promise<void> | void): Promise<void> { async clear(onDelete?: (value: T) => Promise<void> | void): Promise<void> {
for (const value of this.cache.values()) { for (const value of this.cache.values()) {
await onDelete?.(value); await onDelete?.(value);

View File

@ -53,4 +53,8 @@ export class TwentyORMGlobalManager {
async loadDataSourceForWorkspace(workspaceId: string) { async loadDataSourceForWorkspace(workspaceId: string) {
await this.workspaceDataSourceFactory.create(workspaceId, null); await this.workspaceDataSourceFactory.create(workspaceId, null);
} }
async destroyDataSourceForWorkspace(workspaceId: string) {
await this.workspaceDataSourceFactory.destroy(workspaceId, null);
}
} }