Add command to make sure v1.8 workspaces are not using FULL or PARTIAL sync stages (that should be already deprecated) (#15545)

In v1.8, we have already run a command to deprecate FULL or PARTIAL sync
stages.

However the code was fully deprecated in v1.10 and some workspaces might
still have this status used. This is to double check
This commit is contained in:
Charles Bochet
2025-11-03 12:36:46 +01:00
committed by GitHub
parent 0480ea048c
commit 50eb8c5558
4 changed files with 147 additions and 7 deletions
+7 -7
View File
@@ -46,7 +46,7 @@ export default defineConfig(({ command, mode }) => {
// Please don't increase this limit for main index chunk
// If it gets too big then find modules in the code base
// that can be loaded lazily, there are more!
const MAIN_CHUNK_SIZE_LIMIT = 5.7 * 1024 * 1024; // 5.5MB for main index chunk
const MAIN_CHUNK_SIZE_LIMIT = 5.9 * 1024 * 1024; // 5.5MB for main index chunk
const OTHER_CHUNK_SIZE_LIMIT = 5 * 1024 * 1024; // 5MB for other chunks
const checkers: Checkers = {
@@ -224,7 +224,7 @@ export default defineConfig(({ command, mode }) => {
/*
{
name: 'add-prefetched-modules',
transformIndexHtml(html: string,
transformIndexHtml(html: string,
ctx: {
path: string;
filename: string;
@@ -239,13 +239,13 @@ export default defineConfig(({ command, mode }) => {
(bundle) => bundle.endsWith('.map') === false
);
// Remove existing files and concatenate them into link tags
const prefechBundlesString = modernBundles
.filter((bundle) => html.includes(bundle) === false)
.map((bundle) => `<link rel="prefetch" href="${ctx.server?.config.base}${bundle}">`)
.join('');
// Use regular expression to get the content within <head> </head>
const headContent = html.match(/<head>([\s\S]*)<\/head>/)?.[1] ?? '';
// Insert the content of prefetch into the head
@@ -255,10 +255,10 @@ export default defineConfig(({ command, mode }) => {
/<head>([\s\S]*)<\/head>/,
`<head>${newHeadContent}</head>`
);
return html;
},
}*/
],
@@ -0,0 +1,134 @@
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { Command } from 'nest-commander';
import { DataSource, Repository } from 'typeorm';
import {
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
type RunOnWorkspaceArgs,
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
@Command({
name: 'upgrade:1-10:migrate-channel-partial-full-sync-stages',
description:
'Migrate message and calendar channel partial and full sync stages',
})
export class MigrateChannelPartialFullSyncStagesCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
constructor(
@InjectRepository(WorkspaceEntity)
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
@InjectDataSource()
private readonly coreDataSource: DataSource,
) {
super(workspaceRepository, twentyORMGlobalManager);
}
override async runOnWorkspace({
workspaceId,
options,
}: RunOnWorkspaceArgs): Promise<void> {
this.logger.log(
`Migrating channel sync stages for workspace ${workspaceId}`,
);
const schemaName = getWorkspaceSchemaName(workspaceId);
await this.migrateMessageChannelSyncStages(
workspaceId,
schemaName,
options,
);
await this.migrateCalendarChannelSyncStages(
workspaceId,
schemaName,
options,
);
this.logger.log(
`Successfully migrated channel sync stages for workspace ${workspaceId}`,
);
}
private async migrateMessageChannelSyncStages(
workspaceId: string,
schemaName: string,
options: RunOnWorkspaceArgs['options'],
): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let messageChannelUpdateResult: any;
const tableName = 'messageChannel';
if (options.dryRun) {
this.logger.log(
`Would migrate deprecated messageChannel sync stages for workspace ${workspaceId}`,
);
return;
}
try {
messageChannelUpdateResult = await this.coreDataSource.query(
`UPDATE "${schemaName}"."${tableName}"
SET "syncStage" = 'MESSAGE_LIST_FETCH_PENDING'
WHERE "syncStage" IN ('FULL_MESSAGE_LIST_FETCH_PENDING', 'PARTIAL_MESSAGE_LIST_FETCH_PENDING')`,
);
} catch {
this.logger.log(
`Error (expected) while trying to migrate messageChannel sync stages for workspace ${workspaceId}, nothing to migrate`,
);
return;
}
const messageChannelRowsUpdated = messageChannelUpdateResult[1] || 0;
this.logger.log(
`Migrated ${messageChannelRowsUpdated} messageChannel records from deprecated sync stages in workspace ${workspaceId}`,
);
}
private async migrateCalendarChannelSyncStages(
workspaceId: string,
schemaName: string,
options: RunOnWorkspaceArgs['options'],
): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let calendarChannelUpdateResult: any;
const tableName = 'calendarChannel';
if (options.dryRun) {
this.logger.log(
`Would migrate deprecated calendarChannel sync stages for workspace ${workspaceId}`,
);
return;
}
try {
calendarChannelUpdateResult = await this.coreDataSource.query(
`UPDATE "${schemaName}"."${tableName}"
SET "syncStage" = 'CALENDAR_EVENT_LIST_FETCH_PENDING'
WHERE "syncStage" IN ('FULL_CALENDAR_EVENT_LIST_FETCH_PENDING', 'PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING')`,
);
} catch {
this.logger.log(
`Error (expected) while trying to migrate calendarChannel sync stages for workspace ${workspaceId}, nothing to migrate`,
);
return;
}
const calendarChannelRowsUpdated = calendarChannelUpdateResult[1] || 0;
this.logger.log(
`Migrated ${calendarChannelRowsUpdated} calendarChannel records from deprecated sync stages in workspace ${workspaceId}`,
);
}
}
@@ -5,6 +5,7 @@ import { AddWorkflowRunStopStatusesCommand } from 'src/database/commands/upgrade
import { CleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-clean-orphaned-kanban-aggregate-operation-field-metadata-id.command';
import { MigrateAttachmentAuthorToCreatedByCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-attachment-author-to-created-by.command';
import { MigrateAttachmentTypeToFileCategoryCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-attachment-type-to-file-category.command';
import { MigrateChannelPartialFullSyncStagesCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-channel-partial-full-sync-stages.command';
import { RegenerateSearchVectorsCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-regenerate-search-vectors.command';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -25,6 +26,7 @@ import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-sc
WorkspaceSchemaManagerModule,
],
providers: [
MigrateChannelPartialFullSyncStagesCommand,
MigrateAttachmentAuthorToCreatedByCommand,
MigrateAttachmentTypeToFileCategoryCommand,
RegenerateSearchVectorsCommand,
@@ -37,6 +39,7 @@ import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-sc
RegenerateSearchVectorsCommand,
AddWorkflowRunStopStatusesCommand,
CleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand,
MigrateChannelPartialFullSyncStagesCommand,
],
})
export class V1_10_UpgradeVersionCommandModule {}
@@ -13,6 +13,7 @@ import { AddWorkflowRunStopStatusesCommand } from 'src/database/commands/upgrade
import { CleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-clean-orphaned-kanban-aggregate-operation-field-metadata-id.command';
import { MigrateAttachmentAuthorToCreatedByCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-attachment-author-to-created-by.command';
import { MigrateAttachmentTypeToFileCategoryCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-attachment-type-to-file-category.command';
import { MigrateChannelPartialFullSyncStagesCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-channel-partial-full-sync-stages.command';
import { RegenerateSearchVectorsCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-regenerate-search-vectors.command';
import { FixLabelIdentifierPositionAndVisibilityCommand } from 'src/database/commands/upgrade-version-command/1-6/1-6-fix-label-identifier-position-and-visibility.command';
import { BackfillWorkflowManualTriggerAvailabilityCommand } from 'src/database/commands/upgrade-version-command/1-7/1-7-backfill-workflow-manual-trigger-availability.command';
@@ -59,6 +60,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
protected readonly regenerateSearchVectorsCommand: RegenerateSearchVectorsCommand,
protected readonly addWorkflowRunStopStatusesCommand: AddWorkflowRunStopStatusesCommand,
protected readonly cleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand: CleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand,
protected readonly migrateChannelPartialFullSyncStagesCommand: MigrateChannelPartialFullSyncStagesCommand,
) {
super(
workspaceRepository,
@@ -95,6 +97,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
this.regenerateSearchVectorsCommand,
this.addWorkflowRunStopStatusesCommand,
this.cleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand,
this.migrateChannelPartialFullSyncStagesCommand,
],
afterSyncMetadata: [
this.migrateAttachmentAuthorToCreatedByCommand,