feat(core): Add an incrementing version counter for the workflow entity (#20816)

This commit is contained in:
mfsiega 2025-10-22 09:53:17 +02:00 committed by GitHub
parent 701f4f8f29
commit dd6145879f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 143 additions and 1 deletions

View File

@ -100,6 +100,9 @@ export class WorkflowEntity extends WithTimestampsAndStringId implements IWorkfl
@Column({ length: 36 })
versionId: string;
@Column({ default: 1 })
versionCounter: number;
@Column({ default: 0 })
triggerCount: number;

View File

@ -0,0 +1,40 @@
import type { MigrationContext, ReversibleMigration } from '../migration-types';
/**
* MySQL-specific migration to add versionCounter column and trigger for auto-incrementing.
*/
export class AddWorkflowVersionColumn1761047826451 implements ReversibleMigration {
async up({ queryRunner, tablePrefix }: MigrationContext) {
const tableName = `${tablePrefix}workflow_entity`;
const triggerName = `${tablePrefix}workflow_version_increment`;
// Add versionCounter column
await queryRunner.query(
`ALTER TABLE \`${tableName}\` ADD COLUMN \`versionCounter\` int NOT NULL DEFAULT 1`,
);
// Create trigger that increments version counter before update.
// NOTE: we're modifying the NEW record before the update happens, so we do it BEFORE the update.
await queryRunner.query(`
CREATE TRIGGER \`${triggerName}\`
BEFORE UPDATE ON \`${tableName}\`
FOR EACH ROW
BEGIN
IF OLD.versionCounter = NEW.versionCounter THEN
SET NEW.versionCounter = OLD.versionCounter + 1;
END IF;
END;
`);
}
async down({ queryRunner, tablePrefix }: MigrationContext) {
const tableName = `${tablePrefix}workflow_entity`;
const triggerName = `${tablePrefix}workflow_version_increment`;
// Drop trigger
await queryRunner.query(`DROP TRIGGER IF EXISTS \`${triggerName}\``);
// Drop column
await queryRunner.query(`ALTER TABLE \`${tableName}\` DROP COLUMN \`versionCounter\``);
}
}

View File

@ -2,7 +2,6 @@ import { DropUnusedChatHubColumns1760965142113 } from './1760965142113-DropUnuse
import { AddAudienceColumnToApiKeys1758731786132 } from '../common/1758731786132-AddAudienceColumnToApiKey';
import { CreateWorkflowDependencyTable1760314000000 } from '../common/1760314000000-CreateWorkflowDependencyTable';
import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns';
import { LinkRoleToProjectRelationTable1753953244168 } from './../common/1753953244168-LinkRoleToProjectRelationTable';
import { InitialMigration1588157391238 } from './1588157391238-InitialMigration';
import { WebhookModel1592447867632 } from './1592447867632-WebhookModel';
import { CreateIndexStoppedAt1594902918301 } from './1594902918301-CreateIndexStoppedAt';
@ -50,6 +49,7 @@ import { CreateTestMetricTable1732271325258 } from './1732271325258-CreateTestMe
import { AddStatsColumnsToTestRun1736172058779 } from './1736172058779-AddStatsColumnsToTestRun';
import { FixTestDefinitionPrimaryKey1739873751194 } from './1739873751194-FixTestDefinitionPrimaryKey';
import { AddProjectIdToVariableTable1758794506893 } from './1758794506893-AddProjectIdToVariableTable';
import { AddWorkflowVersionColumn1761047826451 } from './1761047826451-AddWorkflowVersionColumn';
import { CreateLdapEntities1674509946020 } from '../common/1674509946020-CreateLdapEntities';
import { PurgeInvalidWorkflowConnections1675940580449 } from '../common/1675940580449-PurgeInvalidWorkflowConnections';
import { RemoveResetPasswordColumns1690000000030 } from '../common/1690000000030-RemoveResetPasswordColumns';
@ -106,6 +106,7 @@ import { CreateChatHubTables1760019379982 } from '../common/1760019379982-Create
import { UniqueRoleNames1760020838000 } from '../common/1760020838000-UniqueRoleNames';
import type { Migration } from '../migration-types';
import { UpdateParentFolderIdColumn1740445074052 } from '../mysqldb/1740445074052-UpdateParentFolderIdColumn';
import { LinkRoleToProjectRelationTable1753953244168 } from './../common/1753953244168-LinkRoleToProjectRelationTable';
export const mysqlMigrations: Migration[] = [
InitialMigration1588157391238,
@ -215,4 +216,5 @@ export const mysqlMigrations: Migration[] = [
UniqueRoleNames1760020838000,
CreateWorkflowDependencyTable1760314000000,
DropUnusedChatHubColumns1760965142113,
AddWorkflowVersionColumn1761047826451,
];

View File

@ -0,0 +1,52 @@
import type { MigrationContext, ReversibleMigration } from '../migration-types';
/**
* PostgreSQL-specific migration to add versionCounter column and trigger for auto-incrementing.
*/
export class AddWorkflowVersionColumn1761047826451 implements ReversibleMigration {
async up({ queryRunner, tablePrefix }: MigrationContext) {
const tableName = `${tablePrefix}workflow_entity`;
const triggerName = `${tablePrefix}workflow_version_increment`;
const functionName = `${tablePrefix}increment_workflow_version`;
// Add versionCounter column
await queryRunner.query(
`ALTER TABLE ${tableName} ADD COLUMN "versionCounter" integer NOT NULL DEFAULT 1`,
);
// Create function that increments version counter.
// NOTE: we're modifying the NEW record before the update happens, so we do it BEFORE the update.
await queryRunner.query(`
CREATE OR REPLACE FUNCTION ${functionName}()
RETURNS TRIGGER AS $$
BEGIN
IF NEW."versionCounter" IS NOT DISTINCT FROM OLD."versionCounter" THEN
NEW."versionCounter" = OLD."versionCounter" + 1;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
`);
// Create trigger that calls the function before update
await queryRunner.query(`
CREATE TRIGGER ${triggerName}
BEFORE UPDATE ON ${tableName}
FOR EACH ROW
EXECUTE FUNCTION ${functionName}();
`);
}
async down({ queryRunner, tablePrefix }: MigrationContext) {
const tableName = `${tablePrefix}workflow_entity`;
const triggerName = `${tablePrefix}workflow_version_increment`;
const functionName = `${tablePrefix}increment_workflow_version`;
// Drop trigger and function
await queryRunner.query(`DROP TRIGGER IF EXISTS ${triggerName} ON ${tableName}`);
await queryRunner.query(`DROP FUNCTION IF EXISTS ${functionName}`);
// Drop column
await queryRunner.query(`ALTER TABLE ${tableName} DROP COLUMN "versionCounter"`);
}
}

View File

@ -46,6 +46,7 @@ import { FixExecutionMetadataSequence1721377157740 } from './1721377157740-FixEx
import { MigrateTestDefinitionKeyToString1731582748663 } from './1731582748663-MigrateTestDefinitionKeyToString';
import { UpdateParentFolderIdColumn1740445074052 } from './1740445074052-UpdateParentFolderIdColumn';
import { AddProjectIdToVariableTable1758794506893 } from './1758794506893-AddProjectIdToVariableTable';
import { AddWorkflowVersionColumn1761047826451 } from './1761047826451-AddWorkflowVersionColumn';
import { CreateLdapEntities1674509946020 } from '../common/1674509946020-CreateLdapEntities';
import { PurgeInvalidWorkflowConnections1675940580449 } from '../common/1675940580449-PurgeInvalidWorkflowConnections';
import { RemoveResetPasswordColumns1690000000030 } from '../common/1690000000030-RemoveResetPasswordColumns';
@ -213,4 +214,5 @@ export const postgresMigrations: Migration[] = [
UniqueRoleNames1760020838000,
CreateWorkflowDependencyTable1760314000000,
DropUnusedChatHubColumns1760965142113,
AddWorkflowVersionColumn1761047826451,
];

View File

@ -0,0 +1,41 @@
import type { MigrationContext, ReversibleMigration } from '../migration-types';
/**
* SQLite-specific migration to add versionCounter column and trigger for auto-incrementing.
*/
export class AddWorkflowVersionColumn1761047826451 implements ReversibleMigration {
async up({ queryRunner, tablePrefix }: MigrationContext) {
const tableName = `${tablePrefix}workflow_entity`;
const triggerName = `${tablePrefix}workflow_version_increment`;
// Add versionCounter column
await queryRunner.query(
`ALTER TABLE ${tableName} ADD COLUMN "versionCounter" integer NOT NULL DEFAULT 1`,
);
// Create trigger that increments version counter on update.
// NOTE: we perform the version counter bump AFTER so it isn't overwritten by the original update.
await queryRunner.query(`
CREATE TRIGGER ${triggerName}
AFTER UPDATE ON ${tableName}
FOR EACH ROW
WHEN OLD."versionCounter" = NEW."versionCounter"
BEGIN
UPDATE ${tableName}
SET "versionCounter" = "versionCounter" + 1
WHERE id = NEW.id;
END;
`);
}
async down({ queryRunner, tablePrefix }: MigrationContext) {
const tableName = `${tablePrefix}workflow_entity`;
const triggerName = `${tablePrefix}workflow_version_increment`;
// Drop trigger
await queryRunner.query(`DROP TRIGGER IF EXISTS ${triggerName}`);
// Drop column
await queryRunner.query(`ALTER TABLE ${tableName} DROP COLUMN "versionCounter"`);
}
}

View File

@ -44,6 +44,7 @@ import { MigrateTestDefinitionKeyToString1731582748663 } from './1731582748663-M
import { CreateFolderTable1738709609940 } from './1738709609940-CreateFolderTable';
import { UpdateParentFolderIdColumn1740445074052 } from './1740445074052-UpdateParentFolderIdColumn';
import { AddScopesColumnToApiKeys1742918400000 } from './1742918400000-AddScopesColumnToApiKeys';
import { AddWorkflowVersionColumn1761047826451 } from './1761047826451-AddWorkflowVersionColumn';
import { UniqueWorkflowNames1620821879465 } from '../common/1620821879465-UniqueWorkflowNames';
import { UpdateWorkflowCredentials1630330987096 } from '../common/1630330987096-UpdateWorkflowCredentials';
import { AddNodeIds1658930531669 } from '../common/1658930531669-AddNodeIds';
@ -207,6 +208,7 @@ const sqliteMigrations: Migration[] = [
UniqueRoleNames1760020838000,
CreateWorkflowDependencyTable1760314000000,
DropUnusedChatHubColumns1760965142113,
AddWorkflowVersionColumn1761047826451,
];
export { sqliteMigrations };