diff --git a/packages/twenty-server/docs/UPGRADE_COMMANDS.md b/packages/twenty-server/docs/UPGRADE_COMMANDS.md index 25fbfcd3ca..3465ba69da 100644 --- a/packages/twenty-server/docs/UPGRADE_COMMANDS.md +++ b/packages/twenty-server/docs/UPGRADE_COMMANDS.md @@ -106,6 +106,24 @@ export class BackfillStandardSkillsCommand The base class `ActiveOrSuspendedWorkspaceCommandRunner` handles workspace iteration and provides `--dry-run`, `--verbose`, and workspace filter options automatically. +### Applying a migration matrix: side-effect vs legacy path + +Commands that build a metadata migration go through `WorkspaceMigrationValidateBuildAndRunService`. Two entry points exist: + +- `validateBuildAndRunWorkspaceMigration` (default): runs the operation matrix through the metadata side-effect engine (`expandWithSideEffects`) before building. The engine injects and cascades engine-owned companions (system fields and relations, the `searchVector` field and its GIN index, `searchFieldMetadata` rows, unique backing indexes). This is what the live API and application manifests rely on, so new commands should use it. +- `validateBuildAndRunLegacyWorkspaceMigration`: skips side-effect expansion and applies the matrix literally, exactly as it was authored. + +The side-effect engine landed in v2.19. Commands authored before then declared their companions explicitly and were never designed to flow through the engine. Running them through it retroactively changes their behavior: it can hard-fail on reserved-identifier collisions (`RESERVED_SYSTEM_UNIVERSAL_IDENTIFIER`) and silently create rows the command never intended (for example, the deterministic `searchFieldMetadata` rows that the standalone `upgrade:2-16:backfill-search-field-metadata` backfill then re-inserts, hitting `IDX_SEARCH_FIELD_METADATA_OBJECT_FIELD_UNIQUE`). + +Rule of thumb: + +- Target version **< 2.19** → use the **legacy** method. +- Target version **>= 2.19** → use the default side-effect method. + +All pre-2.19 commands follow this rule, including `upgrade:2-10:sync-call-recording-standard-objects`: it builds its create-set from the static twenty-standard definition (which declares all of `callRecording`'s fields, including the `searchVector` system field) and runs it through the legacy path so nothing is injected on top. Its matrix contains no `searchFieldMetadata` operations; the deterministic rows are created later in the same upgrade pipeline by `upgrade:2-16:backfill-search-field-metadata`, which derives them from the standard definition. + +Known gap: the static definition does not yet declare `callRecording`'s `searchVector` GIN index (every other searchable standard object declares its GIN index statically), so workspaces upgrading through 2-10 on the legacy path create the `searchVector` column unindexed. The static declaration plus a backfill for already-upgraded workspaces land in a follow-up (twentyhq/core-team-issues#2672), which must ship in the same release as this legacy path. + ## Execution Order Within a given version of Twenty, the upgrade pipeline runs commands in this order, sorted by timestamp within each group: diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500001000-add-compose-email-command-menu-item.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500001000-add-compose-email-command-menu-item.command.ts index 3e5bf0cdda..021a6ecfd6 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500001000-add-compose-email-command-menu-item.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500001000-add-compose-email-command-menu-item.command.ts @@ -92,7 +92,7 @@ export class AddComposeEmailCommandMenuItemCommand extends ActiveOrSuspendedWork } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500004000-backfill-message-thread-subject.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500004000-backfill-message-thread-subject.command.ts index 3640793b11..5346f1d69e 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500004000-backfill-message-thread-subject.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500004000-backfill-message-thread-subject.command.ts @@ -112,7 +112,7 @@ export class BackfillMessageThreadSubjectCommand extends ActiveOrSuspendedWorksp }; const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { @@ -229,7 +229,7 @@ export class BackfillMessageThreadSubjectCommand extends ActiveOrSuspendedWorksp }; const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500006000-deduplicate-engine-commands.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500006000-deduplicate-engine-commands.command.ts index 85f72f7e9f..0d32c5263c 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500006000-deduplicate-engine-commands.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500006000-deduplicate-engine-commands.command.ts @@ -118,7 +118,7 @@ export class DeduplicateEngineCommandsCommand extends ActiveOrSuspendedWorkspace } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500007000-fix-select-all-command-menu-items.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500007000-fix-select-all-command-menu-items.command.ts index 2c3587933a..c35949c8e2 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500007000-fix-select-all-command-menu-items.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500007000-fix-select-all-command-menu-items.command.ts @@ -109,7 +109,7 @@ export class FixSelectAllCommandMenuItemsCommand extends ActiveOrSuspendedWorksp } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500008000-migrate-ai-agent-text-to-json-response-format.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500008000-migrate-ai-agent-text-to-json-response-format.command.ts index 2765b938fc..abe6ce83df 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500008000-migrate-ai-agent-text-to-json-response-format.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500008000-migrate-ai-agent-text-to-json-response-format.command.ts @@ -129,7 +129,7 @@ export class MigrateAiAgentTextToJsonResponseFormatCommand extends ActiveOrSuspe ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { agent: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500013000-refactor-navigation-commands.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500013000-refactor-navigation-commands.command.ts index 429abd1738..7548306c24 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500013000-refactor-navigation-commands.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500013000-refactor-navigation-commands.command.ts @@ -290,7 +290,7 @@ export class RefactorNavigationCommandsCommand extends ActiveOrSuspendedWorkspac } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts index 36b283df65..7f97543b2d 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts @@ -147,7 +147,7 @@ export class FixMessageThreadViewAndLabelIdentifierCommand extends ActiveOrSuspe } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { objectMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500015000-update-search-command-menu-item-labels.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500015000-update-search-command-menu-item-labels.command.ts index 959c50a401..610f4a6c45 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500015000-update-search-command-menu-item-labels.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500015000-update-search-command-menu-item-labels.command.ts @@ -107,7 +107,7 @@ export class UpdateSearchCommandMenuItemLabelsCommand extends ActiveOrSuspendedW } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1775500016000-add-send-email-record-selection-command-menu-items.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1775500016000-add-send-email-record-selection-command-menu-items.command.ts index 53d5f661d8..b95535e837 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1775500016000-add-send-email-record-selection-command-menu-items.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1775500016000-add-send-email-record-selection-command-menu-items.command.ts @@ -103,7 +103,7 @@ export class AddSendEmailRecordSelectionCommandMenuItemsCommand extends ActiveOr } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000002000-backfill-standard-skills.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000002000-backfill-standard-skills.command.ts index 1fd00e52b6..4f55f9aad1 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000002000-backfill-standard-skills.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000002000-backfill-standard-skills.command.ts @@ -87,7 +87,7 @@ export class BackfillStandardSkillsCommand extends ActiveOrSuspendedWorkspaceCom } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { skill: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000003000-fix-merge-command-select-all.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000003000-fix-merge-command-select-all.command.ts index 12e5baa1dd..51555869fb 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000003000-fix-merge-command-select-all.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-22/1-22-workspace-command-1780000003000-fix-merge-command-select-all.command.ts @@ -107,7 +107,7 @@ export class FixMergeCommandSelectAllCommand extends ActiveOrSuspendedWorkspaceC } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000001500-backfill-record-page-layouts.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000001500-backfill-record-page-layouts.command.ts index 2e5f185049..82981743da 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000001500-backfill-record-page-layouts.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000001500-backfill-record-page-layouts.command.ts @@ -182,7 +182,7 @@ export class BackfillRecordPageLayoutsCommand extends ActiveOrSuspendedWorkspace ); const result = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { viewField: { @@ -400,7 +400,7 @@ export class BackfillRecordPageLayoutsCommand extends ActiveOrSuspendedWorkspace ); const result = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { pageLayout: { @@ -544,7 +544,7 @@ export class BackfillRecordPageLayoutsCommand extends ActiveOrSuspendedWorkspace } const result = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { pageLayout: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000005000-update-global-object-context-command-menu-items.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000005000-update-global-object-context-command-menu-items.command.ts index a9e4980aa5..1d5316df7c 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000005000-update-global-object-context-command-menu-items.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-23/1-23-workspace-command-1780000005000-update-global-object-context-command-menu-items.command.ts @@ -110,7 +110,7 @@ export class UpdateGlobalObjectContextCommandMenuItemsCommand extends ActiveOrSu } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1790000000000-gate-export-import-command-menu-items-by-permission-flag.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1790000000000-gate-export-import-command-menu-items-by-permission-flag.command.ts index 148f8a247f..fd3ce3884d 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1790000000000-gate-export-import-command-menu-items-by-permission-flag.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1790000000000-gate-export-import-command-menu-items-by-permission-flag.command.ts @@ -109,7 +109,7 @@ export class GateExportImportCommandMenuItemsByPermissionFlagCommand extends Act } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1795000001000-add-layout-customization-guard-to-edit-commands.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1795000001000-add-layout-customization-guard-to-edit-commands.command.ts index 78a729462e..ff8ed220f0 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1795000001000-add-layout-customization-guard-to-edit-commands.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-1/2-1-workspace-command-1795000001000-add-layout-customization-guard-to-edit-commands.command.ts @@ -148,7 +148,7 @@ export class AddLayoutCustomizationGuardToEditCommandsCommand extends ActiveOrSu } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000045000-rename-conflicting-custom-fields.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000045000-rename-conflicting-custom-fields.command.ts index 89755fa299..bd339f0ee1 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000045000-rename-conflicting-custom-fields.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000045000-rename-conflicting-custom-fields.command.ts @@ -163,7 +163,7 @@ export class RenameConflictingCustomFieldsCommand extends ActiveOrSuspendedWorks ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000050000-add-inactive-generic-standard-fields.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000050000-add-inactive-generic-standard-fields.command.ts index 0303a7f53a..f7b2534875 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000050000-add-inactive-generic-standard-fields.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000050000-add-inactive-generic-standard-fields.command.ts @@ -150,7 +150,7 @@ export class AddInactiveGenericStandardFieldsCommand extends ActiveOrSuspendedWo } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000055000-sync-call-recording-standard-objects.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000055000-sync-call-recording-standard-objects.command.ts index c9c6d5f15d..8908fabde6 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000055000-sync-call-recording-standard-objects.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/2-10-workspace-command-1799000055000-sync-call-recording-standard-objects.command.ts @@ -488,7 +488,7 @@ export class SyncCallRecordingStandardObjectsCommand extends ActiveOrSuspendedWo allFlatEntityOperationByMetadataName, } of collisionRenameMigrations) { const renameResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, applicationUniversalIdentifier, @@ -509,7 +509,7 @@ export class SyncCallRecordingStandardObjectsCommand extends ActiveOrSuspendedWo } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, applicationUniversalIdentifier: diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-13/2-13-workspace-command-1781277470000-sync-create-record-command-availability-expression.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-13/2-13-workspace-command-1781277470000-sync-create-record-command-availability-expression.command.ts index 6460b72a1f..869f84ed78 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-13/2-13-workspace-command-1781277470000-sync-create-record-command-availability-expression.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-13/2-13-workspace-command-1781277470000-sync-create-record-command-availability-expression.command.ts @@ -101,7 +101,7 @@ export class SyncCreateRecordCommandAvailabilityExpressionCommand extends Active } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000040000-fix-standard-relation-field-labels-icons.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000040000-fix-standard-relation-field-labels-icons.command.ts index 8db06781c0..8d42e63592 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000040000-fix-standard-relation-field-labels-icons.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000040000-fix-standard-relation-field-labels-icons.command.ts @@ -120,7 +120,7 @@ export class FixStandardRelationFieldLabelsIconsCommand extends ActiveOrSuspende } const result = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000065000-sync-call-recording-request-status.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000065000-sync-call-recording-request-status.command.ts index 108bad3f03..5593e52f11 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000065000-sync-call-recording-request-status.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000065000-sync-call-recording-request-status.command.ts @@ -141,7 +141,7 @@ export class SyncCallRecordingRequestStatusCommand extends ActiveOrSuspendedWork } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, applicationUniversalIdentifier: diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000066000-drop-calendar-event-recording-preference.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000066000-drop-calendar-event-recording-preference.command.ts index 4eab7403a3..ee376d52ec 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000066000-drop-calendar-event-recording-preference.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-14/2-14-workspace-command-1799000066000-drop-calendar-event-recording-preference.command.ts @@ -72,7 +72,7 @@ export class DropCalendarEventRecordingPreferenceCommand extends ActiveOrSuspend ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, allFlatEntityOperationByMetadataName: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-15/2-15-workspace-command-1800000002000-sync-calendar-event-record-page.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-15/2-15-workspace-command-1800000002000-sync-calendar-event-record-page.command.ts index 2bc9ce77c5..ac0d31e261 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-15/2-15-workspace-command-1800000002000-sync-calendar-event-record-page.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-15/2-15-workspace-command-1800000002000-sync-calendar-event-record-page.command.ts @@ -217,7 +217,7 @@ export class SyncCalendarEventRecordPageCommand extends ActiveOrSuspendedWorkspa } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, applicationUniversalIdentifier: diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100000000-backfill-search-field-metadata.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100000000-backfill-search-field-metadata.command.ts index 6650f39fce..48b88daf5f 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100000000-backfill-search-field-metadata.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100000000-backfill-search-field-metadata.command.ts @@ -7,8 +7,8 @@ import { type RunOnWorkspaceArgs } from 'src/database/commands/command-runners/w import { buildSearchFieldMetadataBackfillOperations } from 'src/database/commands/upgrade-version-command/2-16/utils/build-search-field-metadata-backfill-operations.util'; import { ApplicationService } from 'src/engine/core-modules/application/application.service'; import { RegisteredWorkspaceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-workspace-command.decorator'; -import { computeTwentyStandardApplicationAllFlatEntityMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant'; import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service'; +import { computeTwentyStandardApplicationAllFlatEntityMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant'; import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service'; @RegisteredWorkspaceCommand('2.16.0', 1799100000000) @@ -33,6 +33,15 @@ export class BackfillSearchFieldMetadataCommand extends ActiveOrSuspendedWorkspa }: RunOnWorkspaceArgs): Promise { const isDryRun = options.dryRun ?? false; + // The migration runner only invalidates the flat-maps keys a migration touched, + // so during a cross-version upgrade earlier commands can leave this map stale. + // A stale map breaks the existing-rows dedupe below and re-inserts rows, + // tripping IDX_SEARCH_FIELD_METADATA_OBJECT_FIELD_UNIQUE. Recompute from the + // database before deriving the create-set. + await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [ + 'flatSearchFieldMetadataMaps', + ]); + const { flatObjectMetadataMaps, flatFieldMetadataMaps, @@ -58,16 +67,15 @@ export class BackfillSearchFieldMetadataCommand extends ActiveOrSuspendedWorkspa twentyStandardApplicationId: twentyStandardFlatApplication.id, }); - const { - flatSearchFieldMetadatasToCreateByApplicationUniversalIdentifier, - } = buildSearchFieldMetadataBackfillOperations({ - flatObjectMetadataMaps, - flatFieldMetadataMaps, - flatSearchFieldMetadataMaps, - standardFlatSearchFieldMetadataMaps: - standardAllFlatEntityMaps.flatSearchFieldMetadataMaps, - customApplicationId: workspaceCustomFlatApplication.id, - }); + const { flatSearchFieldMetadatasToCreateByApplicationUniversalIdentifier } = + buildSearchFieldMetadataBackfillOperations({ + flatObjectMetadataMaps, + flatFieldMetadataMaps, + flatSearchFieldMetadataMaps, + standardFlatSearchFieldMetadataMaps: + standardAllFlatEntityMaps.flatSearchFieldMetadataMaps, + customApplicationId: workspaceCustomFlatApplication.id, + }); const applicationUniversalIdentifiers = Object.keys( flatSearchFieldMetadatasToCreateByApplicationUniversalIdentifier, @@ -114,7 +122,7 @@ export class BackfillSearchFieldMetadataCommand extends ActiveOrSuspendedWorkspa } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, allFlatEntityOperationByMetadataName: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100001000-sync-call-recording-status.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100001000-sync-call-recording-status.command.ts index 5d983d6b12..24e4b38d61 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100001000-sync-call-recording-status.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100001000-sync-call-recording-status.command.ts @@ -121,7 +121,7 @@ export class SyncCallRecordingStatusCommand extends ActiveOrSuspendedWorkspaceCo }; const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, applicationUniversalIdentifier: diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000000000-sync-call-recording-navigation-command-menu-item-availability-expression.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000000000-sync-call-recording-navigation-command-menu-item-availability-expression.command.ts index 5b2a3ff491..81a16dbcc3 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000000000-sync-call-recording-navigation-command-menu-item-availability-expression.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000000000-sync-call-recording-navigation-command-menu-item-availability-expression.command.ts @@ -71,7 +71,7 @@ export class SyncCallRecordingNavigationCommandMenuItemAvailabilityExpressionCom ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, workspaceId, diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000001000-add-reply-to-message-participant-role-option.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000001000-add-reply-to-message-participant-role-option.command.ts index c5563e64d3..4436108fa1 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000001000-add-reply-to-message-participant-role-option.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000001000-add-reply-to-message-participant-role-option.command.ts @@ -64,7 +64,7 @@ export class AddReplyToMessageParticipantRoleOptionCommand extends ActiveOrSuspe ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, workspaceId, diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000010000-add-workspace-member-job-title-field.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000010000-add-workspace-member-job-title-field.command.ts index 8679ce14c8..11fcf712c6 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000010000-add-workspace-member-job-title-field.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-17/2-17-workspace-command-1801000010000-add-workspace-member-job-title-field.command.ts @@ -116,7 +116,7 @@ export class AddWorkspaceMemberJobTitleFieldCommand extends ActiveOrSuspendedWor }; const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-18/2-18-workspace-command-1810000005000-add-message-is-draft-field.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-18/2-18-workspace-command-1810000005000-add-message-is-draft-field.command.ts index 7b80a4ba97..a90a29b296 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-18/2-18-workspace-command-1810000005000-add-message-is-draft-field.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-18/2-18-workspace-command-1810000005000-add-message-is-draft-field.command.ts @@ -107,7 +107,7 @@ export class AddMessageIsDraftFieldCommand extends ActiveOrSuspendedWorkspaceCom } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, allFlatEntityOperationByMetadataName: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-2/2-2-workspace-command-1786000000000-set-calendar-event-description-displayed-max-rows.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-2/2-2-workspace-command-1786000000000-set-calendar-event-description-displayed-max-rows.command.ts index c9e4cbb5de..706dbc563e 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-2/2-2-workspace-command-1786000000000-set-calendar-event-description-displayed-max-rows.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-2/2-2-workspace-command-1786000000000-set-calendar-event-description-displayed-max-rows.command.ts @@ -92,7 +92,7 @@ export class SetCalendarEventDescriptionDisplayedMaxRowsCommand extends ActiveOr }; const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777400000000-drop-message-direction-field.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777400000000-drop-message-direction-field.command.ts index c0678a61f8..f43ed0075c 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777400000000-drop-message-direction-field.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777400000000-drop-message-direction-field.command.ts @@ -72,7 +72,7 @@ export class DropMessageDirectionFieldCommand extends ActiveOrSuspendedWorkspace ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777920000000-backfill-image-identifier-field-metadata-id.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777920000000-backfill-image-identifier-field-metadata-id.command.ts index 89a42c492c..c739b6e914 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777920000000-backfill-image-identifier-field-metadata-id.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777920000000-backfill-image-identifier-field-metadata-id.command.ts @@ -100,7 +100,7 @@ export class BackfillImageIdentifierFieldMetadataIdCommand extends ActiveOrSuspe ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { objectMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1798000000000-delete-gauge-widgets.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1798000000000-delete-gauge-widgets.command.ts index 075a97f967..1d1923196d 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1798000000000-delete-gauge-widgets.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1798000000000-delete-gauge-widgets.command.ts @@ -82,7 +82,7 @@ export class DeleteGaugeWidgetsCommand extends ActiveOrSuspendedWorkspaceCommand ); const result = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { pageLayoutWidget: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000001000-normalize-composite-field-defaults.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000001000-normalize-composite-field-defaults.command.ts index 414fffdda0..374816bea7 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000001000-normalize-composite-field-defaults.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000001000-normalize-composite-field-defaults.command.ts @@ -171,7 +171,7 @@ export class NormalizeCompositeFieldDefaultsCommand extends ActiveOrSuspendedWor })); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { fieldMetadata: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000020000-sync-command-menu-item-availability-expressions.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000020000-sync-command-menu-item-availability-expressions.command.ts index c22572f2d2..a2e9209731 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000020000-sync-command-menu-item-availability-expressions.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000020000-sync-command-menu-item-availability-expressions.command.ts @@ -101,7 +101,7 @@ export class SyncCommandMenuItemAvailabilityExpressionsCommand extends ActiveOrS } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000040000-drop-connected-account-standard-object.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000040000-drop-connected-account-standard-object.command.ts index 98aef8f7c5..6450bfa6fe 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000040000-drop-connected-account-standard-object.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-7/2-7-workspace-command-1798000040000-drop-connected-account-standard-object.command.ts @@ -99,7 +99,7 @@ export class DropConnectedAccountStandardObjectCommand extends ActiveOrSuspended ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, allFlatEntityOperationByMetadataName: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798000050000-drop-channel-standard-objects.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798000050000-drop-channel-standard-objects.command.ts index 8192ce6043..26f0cd4a62 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798000050000-drop-channel-standard-objects.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798000050000-drop-channel-standard-objects.command.ts @@ -86,7 +86,7 @@ export class DropChannelStandardObjectsCommand extends ActiveOrSuspendedWorkspac ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, allFlatEntityOperationByMetadataName: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100000000-backfill-relation-join-column-indexes.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100000000-backfill-relation-join-column-indexes.command.ts index 65c18d8e56..c95ea75740 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100000000-backfill-relation-join-column-indexes.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100000000-backfill-relation-join-column-indexes.command.ts @@ -194,7 +194,7 @@ export class BackfillRelationJoinColumnIndexesCommand extends ActiveOrSuspendedW ); const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { isSystemBuild: true, allFlatEntityOperationByMetadataName: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100010000-gate-default-command-menu-items-by-permission-flag.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100010000-gate-default-command-menu-items-by-permission-flag.command.ts index 5b51889af4..6b5e9f4a92 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100010000-gate-default-command-menu-items-by-permission-flag.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100010000-gate-default-command-menu-items-by-permission-flag.command.ts @@ -127,7 +127,7 @@ export class GateDefaultCommandMenuItemsByPermissionFlagCommand extends ActiveOr } const validateAndBuildResult = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { commandMenuItem: { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-9/2-9-workspace-command-1799000030000-backfill-fields-widget-new-field-default-visibility.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-9/2-9-workspace-command-1799000030000-backfill-fields-widget-new-field-default-visibility.command.ts index 2ff9d71421..c92217cd97 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-9/2-9-workspace-command-1799000030000-backfill-fields-widget-new-field-default-visibility.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-9/2-9-workspace-command-1799000030000-backfill-fields-widget-new-field-default-visibility.command.ts @@ -103,7 +103,7 @@ export class BackfillFieldsWidgetNewFieldDefaultVisibilityCommand extends Active updatedWidgets, ] of widgetsToBackfillByApplicationUniversalIdentifier) { const result = - await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration( { allFlatEntityOperationByMetadataName: { pageLayoutWidget: { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-flat-entity-maps.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-flat-entity-maps.service.ts index 116e1c0079..b1ecffea69 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-flat-entity-maps.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-flat-entity-maps.service.ts @@ -28,7 +28,7 @@ import { InferDeletionFromMissingEntities } from 'src/engine/workspace-manager/w export type WorkspaceMigrationRelatedFlatEntityMaps = Partial & WorkspaceMigrationBuilderAdditionalCacheDataMaps; -type FlatEntityMapsBundle = { +export type FlatEntityMapsBundle = { flatApplicationMaps: FlatApplicationCacheMaps; allRelatedFlatEntityMaps: WorkspaceMigrationRelatedFlatEntityMaps; allMetadataNameCacheToCompute: AllMetadataName[]; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service.ts index 571a5f0b32..a9ad88fc56 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service.ts @@ -19,7 +19,10 @@ import { IdByUniversalIdentifierByMetadataName, } from 'src/engine/workspace-manager/workspace-migration/services/utils/enrich-create-workspace-migration-action-with-ids.util'; import { WorkspaceMigrationBuildOrchestratorService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-build-orchestrator.service'; -import { WorkspaceMigrationFlatEntityMapsService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-flat-entity-maps.service'; +import { + FlatEntityMapsBundle, + WorkspaceMigrationFlatEntityMapsService, +} from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-flat-entity-maps.service'; import { WorkspaceMigrationOrchestratorBuildArgs, WorkspaceMigrationOrchestratorFailedResult, @@ -43,6 +46,21 @@ type ValidateBuildAndRunWorkspaceMigrationFromRecordArgs = { dryRun?: boolean; }; +type ValidateBuildAndRunWorkspaceMigrationFromRecordInternalArgs = + ValidateBuildAndRunWorkspaceMigrationFromRecordArgs & { + // Skips the metadata side-effect engine (expandWithSideEffects) and applies the + // matrix literally. Only the deprecated legacy path sets this to true. + skipSideEffectExpandEngine: boolean; + }; + +type ComputeAndRunWorkspaceMigrationFromResolvedOperationsArgs = { + workspaceId: string; + allFlatEntityOperationRecordByMetadataName: AllFlatEntityOperationRecordByMetadataName; + isSystemBuild: boolean; + applicationUniversalIdentifier: string; + dryRun?: boolean; +} & FlatEntityMapsBundle; + @Injectable() export class WorkspaceMigrationValidateBuildAndRunService { private readonly isDebugEnabled: boolean; @@ -185,13 +203,60 @@ export class WorkspaceMigrationValidateBuildAndRunService { }); } - public async validateBuildAndRunWorkspaceMigrationFromRecord({ + public async validateBuildAndRunWorkspaceMigrationFromRecord( + args: ValidateBuildAndRunWorkspaceMigrationFromRecordArgs, + ): Promise< + | WorkspaceMigrationOrchestratorFailedResult + | (WorkspaceMigrationOrchestratorSuccessfulResult & { + hasSchemaMetadataChanged: boolean; + }) + > { + return await this.validateBuildAndRunWorkspaceMigrationFromRecordInternal({ + ...args, + skipSideEffectExpandEngine: false, + }); + } + + /** + * @deprecated Legacy path for upgrade commands authored before the metadata + * side-effect engine landed in v2.19. These commands declare their operation + * matrix literally and must not flow through expandWithSideEffects, which + * would inject engine-owned companions and collide on reserved identifiers. + * See packages/twenty-server/docs/UPGRADE_COMMANDS.md. + */ + public async validateBuildAndRunLegacyWorkspaceMigration({ + allFlatEntityOperationByMetadataName, + workspaceId, + isSystemBuild = false, + applicationUniversalIdentifier, + dryRun, + }: ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs): Promise< + | WorkspaceMigrationOrchestratorFailedResult + | (WorkspaceMigrationOrchestratorSuccessfulResult & { + hasSchemaMetadataChanged: boolean; + }) + > { + return await this.validateBuildAndRunWorkspaceMigrationFromRecordInternal({ + allFlatEntityOperationRecordByMetadataName: + transpileFlatEntityOperationArrayToRecord( + allFlatEntityOperationByMetadataName, + ), + workspaceId, + isSystemBuild, + applicationUniversalIdentifier, + dryRun, + skipSideEffectExpandEngine: true, + }); + } + + private async validateBuildAndRunWorkspaceMigrationFromRecordInternal({ allFlatEntityOperationRecordByMetadataName, workspaceId, isSystemBuild = false, applicationUniversalIdentifier, dryRun, - }: ValidateBuildAndRunWorkspaceMigrationFromRecordArgs): Promise< + skipSideEffectExpandEngine, + }: ValidateBuildAndRunWorkspaceMigrationFromRecordInternalArgs): Promise< | WorkspaceMigrationOrchestratorFailedResult | (WorkspaceMigrationOrchestratorSuccessfulResult & { hasSchemaMetadataChanged: boolean; @@ -213,19 +278,55 @@ export class WorkspaceMigrationValidateBuildAndRunService { }, ); - const sideEffectExpansionResult = - this.metadataSideEffectEngineService.expandWithSideEffects({ - allFlatEntityOperationRecordByMetadataName, - sideEffectRelatedFlatEntityMaps: allRelatedFlatEntityMaps, - context: { - buildOptions: { isSystemBuild, applicationUniversalIdentifier }, - }, - }); + let resolvedFlatEntityOperationRecordByMetadataName = + allFlatEntityOperationRecordByMetadataName; - if (sideEffectExpansionResult.status === 'fail') { - return sideEffectExpansionResult; + if (!skipSideEffectExpandEngine) { + const sideEffectExpansionResult = + this.metadataSideEffectEngineService.expandWithSideEffects({ + allFlatEntityOperationRecordByMetadataName, + sideEffectRelatedFlatEntityMaps: allRelatedFlatEntityMaps, + context: { + buildOptions: { isSystemBuild, applicationUniversalIdentifier }, + }, + }); + + if (sideEffectExpansionResult.status === 'fail') { + return sideEffectExpansionResult; + } + + resolvedFlatEntityOperationRecordByMetadataName = + sideEffectExpansionResult.allFlatEntityOperationRecordByMetadataName; } + return await this.computeAndRunWorkspaceMigrationFromResolvedOperations({ + allFlatEntityOperationRecordByMetadataName: + resolvedFlatEntityOperationRecordByMetadataName, + workspaceId, + isSystemBuild, + applicationUniversalIdentifier, + dryRun, + flatApplicationMaps, + allRelatedFlatEntityMaps, + allMetadataNameCacheToCompute, + }); + } + + private async computeAndRunWorkspaceMigrationFromResolvedOperations({ + allFlatEntityOperationRecordByMetadataName, + workspaceId, + isSystemBuild, + applicationUniversalIdentifier, + dryRun, + flatApplicationMaps, + allRelatedFlatEntityMaps, + allMetadataNameCacheToCompute, + }: ComputeAndRunWorkspaceMigrationFromResolvedOperationsArgs): Promise< + | WorkspaceMigrationOrchestratorFailedResult + | (WorkspaceMigrationOrchestratorSuccessfulResult & { + hasSchemaMetadataChanged: boolean; + }) + > { const { fromToAllFlatEntityMaps, inferDeletionFromMissingEntities, @@ -235,8 +336,7 @@ export class WorkspaceMigrationValidateBuildAndRunService { } = this.workspaceMigrationFlatEntityMapsService.computeFromToAllFlatEntityMapsAndBuildOptions( { - allFlatEntityOperationRecordByMetadataName: - sideEffectExpansionResult.allFlatEntityOperationRecordByMetadataName, + allFlatEntityOperationRecordByMetadataName, applicationUniversalIdentifier, flatApplicationMaps, allRelatedFlatEntityMaps,