From 44c0e9e83fdac44ad51b542b40e89fb5a17183f1 Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Thu, 18 Dec 2025 11:09:13 +0800 Subject: [PATCH] perf: redis del;perf: cron app run (#6113) * cron app run * perf: redis del --- document/content/docs/upgrading/4-14/4145.mdx | 2 + document/data/doc-last-modified.json | 2 +- packages/service/common/cache/index.ts | 4 +- projects/app/next.config.js | 9 ++ projects/app/src/service/core/app/utils.ts | 146 ++++++++++-------- 5 files changed, 95 insertions(+), 68 deletions(-) diff --git a/document/content/docs/upgrading/4-14/4145.mdx b/document/content/docs/upgrading/4-14/4145.mdx index 19c06200c..186a5efa3 100644 --- a/document/content/docs/upgrading/4-14/4145.mdx +++ b/document/content/docs/upgrading/4-14/4145.mdx @@ -10,10 +10,12 @@ description: 'FastGPT V4.14.5 更新说明' ## ⚙️ 优化 +1. 优化获取 redis 所有 key 的逻辑,避免大量获取时导致阻塞。 ## 🐛 修复 1. MCP 工具创建时,使用自定义鉴权头会报错。 +2. 获取对话日志列表时,如果用户头像为空,会抛错。 ## 插件 diff --git a/document/data/doc-last-modified.json b/document/data/doc-last-modified.json index ff68ce8cb..4225a2bf8 100644 --- a/document/data/doc-last-modified.json +++ b/document/data/doc-last-modified.json @@ -120,7 +120,7 @@ "document/content/docs/upgrading/4-14/4142.mdx": "2025-11-18T19:27:14+08:00", "document/content/docs/upgrading/4-14/4143.mdx": "2025-11-26T20:52:05+08:00", "document/content/docs/upgrading/4-14/4144.mdx": "2025-12-16T14:56:04+08:00", - "document/content/docs/upgrading/4-14/4145.mdx": "2025-12-17T17:44:38+08:00", + "document/content/docs/upgrading/4-14/4145.mdx": "2025-12-18T10:17:10+08:00", "document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00", diff --git a/packages/service/common/cache/index.ts b/packages/service/common/cache/index.ts index 0744ddcd8..aedeb5b55 100644 --- a/packages/service/common/cache/index.ts +++ b/packages/service/common/cache/index.ts @@ -24,9 +24,7 @@ export const refreshVersionKey = async (key: `${SystemCacheKeyEnum}`, id?: strin const keys = await getAllKeysByPrefix(pattern); if (keys.length > 0) { const pipeline = redis.pipeline(); - for (const k of keys) { - pipeline.del(k); - } + pipeline.del(keys); await pipeline.exec(); } } else { diff --git a/projects/app/next.config.js b/projects/app/next.config.js index 6f8e2bf93..ef732fc08 100644 --- a/projects/app/next.config.js +++ b/projects/app/next.config.js @@ -50,6 +50,15 @@ const nextConfig = { }, webpack(config, { isServer, nextRuntime }) { + // Ignore autoprefixer warnings from third-party libraries + config.ignoreWarnings = [ + ...(config.ignoreWarnings || []), + { + module: /@scalar\/api-reference-react/, + message: /autoprefixer/, + }, + ]; + Object.assign(config.resolve.alias, { '@mongodb-js/zstd': false, '@aws-sdk/credential-providers': false, diff --git a/projects/app/src/service/core/app/utils.ts b/projects/app/src/service/core/app/utils.ts index c9784dedc..e8f6685e5 100644 --- a/projects/app/src/service/core/app/utils.ts +++ b/projects/app/src/service/core/app/utils.ts @@ -1,13 +1,17 @@ import { getErrText } from '@fastgpt/global/common/error/utils'; import { getNextTimeByCronStringAndTimezone } from '@fastgpt/global/common/string/time'; import { getNanoid } from '@fastgpt/global/common/string/tools'; -import { delay, retryFn } from '@fastgpt/global/common/system/utils'; +import { batchRun, retryFn } from '@fastgpt/global/common/system/utils'; import { ChatItemValueTypeEnum, ChatRoleEnum, ChatSourceEnum } from '@fastgpt/global/core/chat/constants'; -import { type UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; +import type { + AIChatItemValueItemType, + UserChatItemValueItemType, + ChatHistoryItemResType +} from '@fastgpt/global/core/chat/type'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { getWorkflowEntryNodeIds, @@ -21,7 +25,6 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controlle import { saveChat } from '@fastgpt/service/core/chat/saveChat'; import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants'; import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch'; -import { getUserChatInfo } from '@fastgpt/service/support/user/team/utils'; import { getRunningUserInfoByTmbId } from '@fastgpt/service/support/user/team/utils'; import { createChatUsageRecord } from '@fastgpt/service/support/wallet/usage/controller'; @@ -30,19 +33,28 @@ export const getScheduleTriggerApp = async () => { // 1. Find all the app const apps = await retryFn(() => { - return MongoApp.find({ - scheduledTriggerConfig: { $exists: true }, - scheduledTriggerNextTime: { $lte: new Date() } - }); + return MongoApp.find( + { + scheduledTriggerConfig: { $exists: true }, + scheduledTriggerNextTime: { $lte: new Date() } + }, + { + _id: 1, + scheduledTriggerConfig: 1, + scheduledTriggerNextTime: 1, + name: 1, + teamId: 1, + tmbId: 1 + } + ).lean(); }); // 2. Run apps - await Promise.allSettled( - apps.map(async (app) => { + await batchRun( + apps, + async (app) => { if (!app.scheduledTriggerConfig) return; const chatId = getNanoid(); - // random delay 0 ~ 60s - await delay(Math.floor(Math.random() * 60 * 1000)); // Get app latest version const { versionId, nodes, edges, chatConfig } = await retryFn(() => @@ -52,7 +64,7 @@ export const getScheduleTriggerApp = async () => { { type: ChatItemValueTypeEnum.text, text: { - content: app.scheduledTriggerConfig?.defaultPrompt + content: app.scheduledTriggerConfig.defaultPrompt || '' } } ]; @@ -67,8 +79,47 @@ export const getScheduleTriggerApp = async () => { }) ); + const onSave = async ({ + error, + durationSeconds = 0, + assistantResponses = [], + flowResponses = [], + system_memories + }: { + error?: any; + durationSeconds?: number; + assistantResponses?: AIChatItemValueItemType[]; + flowResponses?: ChatHistoryItemResType[]; + system_memories?: Record; + }) => + saveChat({ + chatId, + appId: app._id, + versionId, + teamId: String(app.teamId), + tmbId: String(app.tmbId), + nodes, + appChatConfig: chatConfig, + variables: {}, + isUpdateUseTime: false, // owner update use time + newTitle: 'Cron Job', + source: ChatSourceEnum.cronJob, + userContent: { + obj: ChatRoleEnum.Human, + value: userQuery + }, + aiContent: { + obj: ChatRoleEnum.AI, + value: assistantResponses, + [DispatchNodeResponseKeyEnum.nodeResponse]: flowResponses, + memories: system_memories + }, + durationSeconds, + errorMsg: getErrText(error) + }); + try { - const { flowUsages, assistantResponses, flowResponses, durationSeconds, system_memories } = + const { assistantResponses, flowResponses, durationSeconds, system_memories } = await retryFn(async () => { return dispatchWorkFlow({ chatId, @@ -96,62 +147,29 @@ export const getScheduleTriggerApp = async () => { const error = flowResponses[flowResponses.length - 1]?.error; // Save chat - await saveChat({ - chatId, - appId: app._id, - versionId, - teamId: String(app.teamId), - tmbId: String(app.tmbId), - nodes, - appChatConfig: chatConfig, - variables: {}, - isUpdateUseTime: false, // owner update use time - newTitle: 'Cron Job', - source: ChatSourceEnum.cronJob, - userContent: { - obj: ChatRoleEnum.Human, - value: userQuery - }, - aiContent: { - obj: ChatRoleEnum.AI, - value: assistantResponses, - [DispatchNodeResponseKeyEnum.nodeResponse]: flowResponses, - memories: system_memories - }, + await onSave({ + error, durationSeconds, - errorMsg: getErrText(error) + assistantResponses, + flowResponses, + system_memories }); } catch (error) { - addLog.error('Schedule trigger error', error); + addLog.error('[Schedule app] run error', error); - await saveChat({ - chatId, - appId: app._id, - teamId: String(app.teamId), - tmbId: String(app.tmbId), - nodes, - appChatConfig: chatConfig, - variables: {}, - isUpdateUseTime: false, // owner update use time - newTitle: 'Cron Job', - source: ChatSourceEnum.cronJob, - userContent: { - obj: ChatRoleEnum.Human, - value: userQuery - }, - aiContent: { - obj: ChatRoleEnum.AI, - value: [], - [DispatchNodeResponseKeyEnum.nodeResponse]: [] - }, - durationSeconds: 0, - errorMsg: getErrText(error) + await onSave({ + error + }).catch(); + } finally { + // update next time + const nextTime = getNextTimeByCronStringAndTimezone(app.scheduledTriggerConfig); + await retryFn(() => + MongoApp.updateOne({ _id: app._id }, { $set: { scheduledTriggerNextTime: nextTime } }) + ).catch((err) => { + addLog.error(`[Schedule app] error update next time`, err); }); } - - // update next time - app.scheduledTriggerNextTime = getNextTimeByCronStringAndTimezone(app.scheduledTriggerConfig); - await app.save().catch(); - }) + }, + 50 ); };