mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-30 08:17:06 +02:00
feat(core): Database migration to add workflow dependency index table (#20723)
This commit is contained in:
parent
87d143bdd7
commit
ed3b19a3de
|
|
@ -61,11 +61,8 @@ function mixinStringId<T extends Class<{}, any[]>>(base: T) {
|
|||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mixinTimestamps<T extends Class<{}, any[]>>(base: T) {
|
||||
function mixinUpdatedAt<T extends Class<{}, any[]>>(base: T) {
|
||||
class Derived extends base {
|
||||
@CreateDateColumn(tsColumnOptions)
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn(tsColumnOptions)
|
||||
updatedAt: Date;
|
||||
|
||||
|
|
@ -77,8 +74,19 @@ function mixinTimestamps<T extends Class<{}, any[]>>(base: T) {
|
|||
return Derived;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mixinCreatedAt<T extends Class<{}, any[]>>(base: T) {
|
||||
class Derived extends base {
|
||||
@CreateDateColumn(tsColumnOptions)
|
||||
createdAt: Date;
|
||||
}
|
||||
return Derived;
|
||||
}
|
||||
|
||||
class BaseEntity {}
|
||||
|
||||
export const WithStringId = mixinStringId(BaseEntity);
|
||||
export const WithTimestamps = mixinTimestamps(BaseEntity);
|
||||
export const WithCreatedAt = mixinCreatedAt(BaseEntity);
|
||||
export const WithUpdatedAt = mixinUpdatedAt(BaseEntity);
|
||||
export const WithTimestamps = mixinCreatedAt(mixinUpdatedAt(BaseEntity));
|
||||
export const WithTimestampsAndStringId = mixinStringId(WithTimestamps);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { TestRun } from './test-run.ee';
|
|||
import { User } from './user';
|
||||
import { Variables } from './variables';
|
||||
import { WebhookEntity } from './webhook-entity';
|
||||
import { WorkflowDependency } from './workflow-dependency-entity';
|
||||
import { WorkflowEntity } from './workflow-entity';
|
||||
import { WorkflowHistory } from './workflow-history';
|
||||
import { WorkflowStatistics } from './workflow-statistics';
|
||||
|
|
@ -50,6 +51,7 @@ export {
|
|||
SharedWorkflow,
|
||||
TagEntity,
|
||||
User,
|
||||
WorkflowDependency,
|
||||
WorkflowEntity,
|
||||
WorkflowStatistics,
|
||||
WorkflowTagMapping,
|
||||
|
|
@ -84,6 +86,7 @@ export const entities = {
|
|||
SharedWorkflow,
|
||||
TagEntity,
|
||||
User,
|
||||
WorkflowDependency,
|
||||
WorkflowEntity,
|
||||
WorkflowStatistics,
|
||||
WorkflowTagMapping,
|
||||
|
|
|
|||
69
packages/@n8n/db/src/entities/workflow-dependency-entity.ts
Normal file
69
packages/@n8n/db/src/entities/workflow-dependency-entity.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import {
|
||||
Column,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
Relation,
|
||||
} from '@n8n/typeorm';
|
||||
|
||||
import { WithCreatedAt } from './abstract-entity';
|
||||
import type { WorkflowEntity } from './workflow-entity';
|
||||
|
||||
export type DependencyType = 'credential' | 'nodeType' | 'webhookPath' | 'workflowCall';
|
||||
|
||||
@Entity({ name: 'workflow_dependency' })
|
||||
export class WorkflowDependency extends WithCreatedAt {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
/**
|
||||
* The ID of the workflow the dependency belongs to.
|
||||
*/
|
||||
@Column({ length: 36 })
|
||||
@Index()
|
||||
workflowId: string;
|
||||
|
||||
/**
|
||||
* The version ID of the workflow the dependency belongs to.
|
||||
* Used to ensure consistency between the workflow and dependency tables.
|
||||
*/
|
||||
@Column({ type: 'int' })
|
||||
workflowVersionId: number;
|
||||
|
||||
/**
|
||||
* The type of the dependency.
|
||||
* credential | nodeType | webhookPath | workflowCall
|
||||
*/
|
||||
@Column({ length: 32 })
|
||||
@Index()
|
||||
dependencyType: DependencyType;
|
||||
|
||||
/**
|
||||
* The ID of the dependency, interpreted based on the dependency type.
|
||||
* E.g., for 'credential' it would be the credential ID, for 'nodeType' the node type name, etc.
|
||||
*/
|
||||
@Column({ length: 255 })
|
||||
@Index()
|
||||
dependencyKey: string;
|
||||
|
||||
/**
|
||||
* Additional information about the dependency, interpreted based on the type.
|
||||
* E.g., for 'nodeType' it could be the node ID, for 'webhookPath' the webhook ID.
|
||||
*/
|
||||
@Column({ type: 'varchar', length: 255, nullable: true })
|
||||
dependencyInfo: string | null;
|
||||
|
||||
/**
|
||||
* The version of the index structure. Used for migrations and updates.
|
||||
*/
|
||||
@Column({ type: 'smallint', default: 1 })
|
||||
indexVersionId: number;
|
||||
|
||||
@ManyToOne('WorkflowEntity', {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'workflowId' })
|
||||
workflow: Relation<WorkflowEntity>;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import type { MigrationContext, ReversibleMigration } from '../migration-types';
|
||||
|
||||
export class CreateWorkflowDependencyTable1760314000000 implements ReversibleMigration {
|
||||
async up({ schemaBuilder: { createTable, column } }: MigrationContext) {
|
||||
await createTable('workflow_dependency')
|
||||
.withColumns(
|
||||
column('id').int.primary.autoGenerate2,
|
||||
column('workflowId').varchar(36).notNull,
|
||||
column('workflowVersionId').int.notNull.comment('Version of the workflow'),
|
||||
column('dependencyType')
|
||||
.varchar(32)
|
||||
.notNull.comment(
|
||||
'Type of dependency: "credential", "nodeType", "webhookPath", or "workflowCall"',
|
||||
),
|
||||
column('dependencyKey').varchar(255).notNull.comment('ID or name of the dependency'),
|
||||
column('dependencyInfo')
|
||||
.varchar(255)
|
||||
.comment('Additional info about the dependency, interpreted based on type'),
|
||||
column('indexVersionId')
|
||||
.smallint.notNull.default(1)
|
||||
.comment('Version of the index structure'),
|
||||
)
|
||||
.withForeignKey('workflowId', {
|
||||
tableName: 'workflow_entity',
|
||||
columnName: 'id',
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
.withIndexOn(['workflowId'])
|
||||
.withIndexOn(['dependencyType'])
|
||||
.withIndexOn(['dependencyKey']).withCreatedAt;
|
||||
}
|
||||
|
||||
async down({ schemaBuilder: { dropTable } }: MigrationContext) {
|
||||
await dropTable('workflow_dependency');
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,8 @@ export class Column {
|
|||
| 'timestamp'
|
||||
| 'uuid'
|
||||
| 'double'
|
||||
| 'bigint';
|
||||
| 'bigint'
|
||||
| 'smallint';
|
||||
|
||||
private isGenerated = false;
|
||||
|
||||
|
|
@ -46,6 +47,11 @@ export class Column {
|
|||
return this;
|
||||
}
|
||||
|
||||
get smallint() {
|
||||
this.type = 'smallint';
|
||||
return this;
|
||||
}
|
||||
|
||||
get double() {
|
||||
this.type = 'double';
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,11 @@ export class CreateTable extends TableOperation {
|
|||
return this;
|
||||
}
|
||||
|
||||
get withCreatedAt() {
|
||||
this.columns.push(new Column('createdAt').timestampTimezone().notNull.default('NOW()'));
|
||||
return this;
|
||||
}
|
||||
|
||||
withIndexOn(columnName: string | string[], isUnique = false) {
|
||||
const columnNames = Array.isArray(columnName) ? columnName : [columnName];
|
||||
this.indices.add({ columnNames, isUnique });
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
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';
|
||||
|
|
@ -211,4 +212,5 @@ export const mysqlMigrations: Migration[] = [
|
|||
ChangeValueTypesForInsights1759399811000,
|
||||
CreateChatHubTables1760019379982,
|
||||
UniqueRoleNames1760020838000,
|
||||
CreateWorkflowDependencyTable1760314000000,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ import { AddAudienceColumnToApiKeys1758731786132 } from '../common/1758731786132
|
|||
import { ChangeValueTypesForInsights1759399811000 } from '../common/1759399811000-ChangeValueTypesForInsights';
|
||||
import { CreateChatHubTables1760019379982 } from '../common/1760019379982-CreateChatHubTables';
|
||||
import { UniqueRoleNames1760020838000 } from '../common/1760020838000-UniqueRoleNames';
|
||||
import { CreateWorkflowDependencyTable1760314000000 } from '../common/1760314000000-CreateWorkflowDependencyTable';
|
||||
import type { Migration } from '../migration-types';
|
||||
|
||||
export const postgresMigrations: Migration[] = [
|
||||
|
|
@ -209,4 +210,5 @@ export const postgresMigrations: Migration[] = [
|
|||
ChangeValueTypesForInsights1759399811000,
|
||||
CreateChatHubTables1760019379982,
|
||||
UniqueRoleNames1760020838000,
|
||||
CreateWorkflowDependencyTable1760314000000,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ import type { Migration } from '../migration-types';
|
|||
import { LinkRoleToProjectRelationTable1753953244168 } from './../common/1753953244168-LinkRoleToProjectRelationTable';
|
||||
import { AddProjectIdToVariableTable1758794506893 } from './1758794506893-AddProjectIdToVariableTable';
|
||||
import { CreateChatHubTables1760019379982 } from '../common/1760019379982-CreateChatHubTables';
|
||||
import { CreateWorkflowDependencyTable1760314000000 } from '../common/1760314000000-CreateWorkflowDependencyTable';
|
||||
|
||||
const sqliteMigrations: Migration[] = [
|
||||
InitialMigration1588102412422,
|
||||
|
|
@ -203,6 +204,7 @@ const sqliteMigrations: Migration[] = [
|
|||
ChangeValueTypesForInsights1759399811000,
|
||||
CreateChatHubTables1760019379982,
|
||||
UniqueRoleNames1760020838000,
|
||||
CreateWorkflowDependencyTable1760314000000,
|
||||
];
|
||||
|
||||
export { sqliteMigrations };
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user