refactor(core): Drop unused chat hub columns (no-changelog) (#20973)

This commit is contained in:
Jaakko Husso 2025-10-21 09:57:33 +03:00 committed by GitHub
parent 04438f8f97
commit 8953bf089d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 119 additions and 20 deletions

View File

@ -94,7 +94,7 @@ export class ChatHubChangeConversationTitleRequest extends Z.class({
}) {}
export type ChatHubMessageType = 'human' | 'ai' | 'system' | 'tool' | 'generic';
export type ChatHubMessageState = 'success' | 'error' | 'pending';
export type ChatHubMessageStatus = 'success' | 'error' | 'running' | 'cancelled';
export type ChatSessionId = string; // UUID
export type ChatMessageId = string; // UUID
@ -122,7 +122,7 @@ export interface ChatHubMessageDto {
model: string | null;
workflowId: string | null;
executionId: number | null;
state: ChatHubMessageState;
status: ChatHubMessageStatus;
createdAt: string;
updatedAt: string;

View File

@ -12,7 +12,7 @@ export {
chatHubProviderSchema,
type ChatHubProvider,
type ChatHubMessageType,
type ChatHubMessageState,
type ChatHubMessageStatus,
PROVIDER_CREDENTIAL_TYPE_MAP,
chatModelsRequestSchema,
type ChatModelsRequest,

View File

@ -0,0 +1,36 @@
import type { MigrationContext, ReversibleMigration } from '../migration-types';
const table = {
messages: 'chat_hub_messages',
} as const;
export class DropUnusedChatHubColumns1760965142113 implements ReversibleMigration {
async up({ schemaBuilder: { dropColumns, addColumns, column } }: MigrationContext) {
await dropColumns(table.messages, ['turnId', 'runIndex', 'state']);
await addColumns(table.messages, [
column('status')
.varchar(16)
.default("'success'")
.notNull.comment(
'ChatHubMessageStatus enum, eg. "success", "error", "running", "cancelled"',
),
]);
}
async down({
schemaBuilder: { dropColumns, addColumns, column, addForeignKey },
}: MigrationContext) {
await dropColumns(table.messages, ['status']);
await addColumns(table.messages, [
column('turnId').uuid,
column('runIndex')
.int.notNull.default(0)
.comment('The nth attempt this message has been generated/retried this turn'),
column('state')
.varchar(16)
.default("'active'")
.notNull.comment('ChatHubMessageState enum: "active", "superseded", "hidden", "deleted"'),
]);
await addForeignKey(table.messages, 'turnId', [table.messages, 'id'], undefined, 'CASCADE');
}
}

View File

@ -0,0 +1,57 @@
import type { MigrationContext, ReversibleMigration } from '../migration-types';
const table = {
messages: 'chat_hub_messages',
} as const;
export class DropUnusedChatHubColumns1760965142113 implements ReversibleMigration {
async up({
runQuery,
tablePrefix,
schemaBuilder: { addColumns, dropColumns, column },
}: MigrationContext) {
// MySQL needs to drop foreign keys before dropping a column (turnId) that uses it.
// Name of the FK depends on table prefix, so we can't just hardcode it.
const tableName = `${tablePrefix}${table.messages}`;
const foreignKeys: Array<{ name: string }> = await runQuery(
`SELECT CONSTRAINT_NAME AS name
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = '${tableName}'
AND COLUMN_NAME = 'turnId'
AND REFERENCED_TABLE_NAME IS NOT NULL;`,
);
// There should only be one, but just in case handle multiple
for (const { name } of foreignKeys) {
await runQuery(`ALTER TABLE \`${tableName}\` DROP FOREIGN KEY \`${name}\`;`);
}
await dropColumns(table.messages, ['turnId', 'runIndex', 'state']);
await addColumns(table.messages, [
column('status')
.varchar(16)
.default("'success'")
.notNull.comment(
'ChatHubMessageStatus enum, eg. "success", "error", "running", "cancelled"',
),
]);
}
async down({
schemaBuilder: { dropColumns, addColumns, column, addForeignKey },
}: MigrationContext) {
await dropColumns(table.messages, ['status']);
await addColumns(table.messages, [
column('turnId').uuid,
column('runIndex')
.int.notNull.default(0)
.comment('The nth attempt this message has been generated/retried this turn'),
column('state')
.varchar(16)
.default("'active'")
.notNull.comment('ChatHubMessageState enum: "active", "superseded", "hidden", "deleted"'),
]);
await addForeignKey(table.messages, 'turnId', [table.messages, 'id'], undefined, 'CASCADE');
}
}

View File

@ -1,3 +1,4 @@
import { DropUnusedChatHubColumns1760965142113 } from './1760965142113-DropUnusedChatHubColumns';
import { AddAudienceColumnToApiKeys1758731786132 } from '../common/1758731786132-AddAudienceColumnToApiKey';
import { CreateWorkflowDependencyTable1760314000000 } from '../common/1760314000000-CreateWorkflowDependencyTable';
import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns';
@ -213,4 +214,5 @@ export const mysqlMigrations: Migration[] = [
CreateChatHubTables1760019379982,
UniqueRoleNames1760020838000,
CreateWorkflowDependencyTable1760314000000,
DropUnusedChatHubColumns1760965142113,
];

View File

@ -103,6 +103,7 @@ import { ChangeValueTypesForInsights1759399811000 } from '../common/175939981100
import { CreateChatHubTables1760019379982 } from '../common/1760019379982-CreateChatHubTables';
import { UniqueRoleNames1760020838000 } from '../common/1760020838000-UniqueRoleNames';
import { CreateWorkflowDependencyTable1760314000000 } from '../common/1760314000000-CreateWorkflowDependencyTable';
import { DropUnusedChatHubColumns1760965142113 } from '../common/1760965142113-DropUnusedChatHubColumns';
import type { Migration } from '../migration-types';
export const postgresMigrations: Migration[] = [
@ -211,4 +212,5 @@ export const postgresMigrations: Migration[] = [
CreateChatHubTables1760019379982,
UniqueRoleNames1760020838000,
CreateWorkflowDependencyTable1760314000000,
DropUnusedChatHubColumns1760965142113,
];

View File

@ -101,6 +101,7 @@ import { LinkRoleToProjectRelationTable1753953244168 } from './../common/1753953
import { AddProjectIdToVariableTable1758794506893 } from './1758794506893-AddProjectIdToVariableTable';
import { CreateChatHubTables1760019379982 } from '../common/1760019379982-CreateChatHubTables';
import { CreateWorkflowDependencyTable1760314000000 } from '../common/1760314000000-CreateWorkflowDependencyTable';
import { DropUnusedChatHubColumns1760965142113 } from '../common/1760965142113-DropUnusedChatHubColumns';
const sqliteMigrations: Migration[] = [
InitialMigration1588102412422,
@ -205,6 +206,7 @@ const sqliteMigrations: Migration[] = [
CreateChatHubTables1760019379982,
UniqueRoleNames1760020838000,
CreateWorkflowDependencyTable1760314000000,
DropUnusedChatHubColumns1760965142113,
];
export { sqliteMigrations };

View File

@ -1,4 +1,4 @@
import type { ChatHubProvider, ChatHubMessageType, ChatHubMessageState } from '@n8n/api-types';
import type { ChatHubProvider, ChatHubMessageType, ChatHubMessageStatus } from '@n8n/api-types';
import { ExecutionEntity, WithTimestamps, WorkflowEntity } from '@n8n/db';
import {
Column,
@ -156,8 +156,8 @@ export class ChatHubMessage extends WithTimestamps {
revisions?: Array<Relation<ChatHubMessage>>;
/**
* State of the message, e.g. 'success', 'error'.
* Status of the message, e.g. 'running', 'success', 'error', 'cancelled'.
*/
@Column({ type: 'varchar', length: 16, default: 'success' })
state: ChatHubMessageState;
status: ChatHubMessageStatus;
}

View File

@ -9,7 +9,7 @@ import {
type ChatMessageId,
type ChatSessionId,
ChatHubConversationModel,
ChatHubMessageState,
ChatHubMessageStatus,
} from '@n8n/api-types';
import { Logger } from '@n8n/backend-common';
import {
@ -568,7 +568,7 @@ export class ChatHubService {
message,
selectedModel,
retryOfMessageId,
state: 'error',
status: 'error',
});
throw new OperationalError(`Chat workflow execution failed: ${message}`);
@ -583,7 +583,7 @@ export class ChatHubService {
message,
selectedModel,
retryOfMessageId,
state: 'success',
status: 'success',
});
}
@ -756,7 +756,7 @@ export class ChatHubService {
sessionId: payload.sessionId,
type: 'human',
name: user.firstName || 'User',
state: 'success',
status: 'success',
content: payload.message,
previousMessageId,
revisionOfMessageId,
@ -772,7 +772,7 @@ export class ChatHubService {
message,
selectedModel,
retryOfMessageId,
state,
status,
}: {
id: ChatMessageId;
sessionId: ChatSessionId;
@ -782,7 +782,7 @@ export class ChatHubService {
selectedModel: ModelWithCredentials;
retryOfMessageId?: ChatMessageId;
editOfMessageId?: ChatMessageId;
state?: ChatHubMessageState;
status?: ChatHubMessageStatus;
}) {
await this.messageRepository.createChatMessage({
id,
@ -791,7 +791,7 @@ export class ChatHubService {
executionId: parseInt(executionId, 10),
type: 'ai',
name: 'AI',
state,
status,
content: message,
retryOfMessageId,
...selectedModel,
@ -937,7 +937,7 @@ export class ChatHubService {
model: message.model,
workflowId: message.workflowId,
executionId: message.executionId,
state: message.state,
status: message.status,
createdAt: message.createdAt.toISOString(),
updatedAt: message.updatedAt.toISOString(),

View File

@ -1,4 +1,4 @@
import type { ChatHubMessageState, ChatMessageId, ChatSessionId } from '@n8n/api-types';
import type { ChatHubMessageStatus, ChatMessageId, ChatSessionId } from '@n8n/api-types';
import { withTransaction } from '@n8n/db';
import { Service } from '@n8n/di';
import { DataSource, EntityManager, Repository } from '@n8n/typeorm';
@ -26,7 +26,7 @@ export class ChatHubMessageRepository extends Repository<ChatHubMessage> {
async updateChatMessage(
id: ChatMessageId,
fields: { state: ChatHubMessageState },
fields: { status: ChatHubMessageStatus },
trx?: EntityManager,
) {
return await withTransaction(this.manager, trx, async (em) => {

View File

@ -245,7 +245,7 @@ export const useChatStore = defineStore(CHAT_STORE, () => {
model: null,
workflowId: null,
executionId: null,
state: 'success',
status: 'success',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
previousMessageId: replyToMessageId,
@ -337,7 +337,7 @@ export const useChatStore = defineStore(CHAT_STORE, () => {
model: model?.model ?? null,
workflowId: null,
executionId: null,
state: 'success',
status: 'success',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
previousMessageId,
@ -358,7 +358,7 @@ export const useChatStore = defineStore(CHAT_STORE, () => {
model: null,
workflowId: null,
executionId: null,
state: 'error',
status: 'error',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
previousMessageId: messageId,
@ -410,7 +410,7 @@ export const useChatStore = defineStore(CHAT_STORE, () => {
model: null,
workflowId: null,
executionId: null,
state: 'success',
status: 'success',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
previousMessageId,