app update time

This commit is contained in:
heheer 2025-12-19 11:33:49 +08:00
parent 32affb0df0
commit 284ca367aa
No known key found for this signature in database
GPG Key ID: 37DCB43201661540
13 changed files with 78 additions and 54 deletions

View File

@ -204,3 +204,27 @@ export const deleteAppsImmediate = async ({
).lean();
await Promise.all(evalJobs.map((evalJob) => removeEvaluationJob(evalJob._id)));
};
export async function updateParentFoldersUpdateTime({
parentId,
session
}: {
parentId?: string | null;
session?: ClientSession;
}): Promise<void> {
if (!parentId) return;
const parentApp = await MongoApp.findById(parentId).lean();
if (!parentApp) return;
// Only update if parent is a folder
if (AppFolderTypeList.includes(parentApp.type)) {
await MongoApp.findByIdAndUpdate(parentId, { updateTime: new Date() }, { session });
}
// Recursively update parent folders
await updateParentFoldersUpdateTime({
parentId: parentApp.parentId,
session
});
}

View File

@ -35,7 +35,6 @@ export type Props = {
nodes: StoreNodeItemType[];
appChatConfig?: AppChatConfigType;
variables?: Record<string, any>;
isUpdateUseTime: boolean;
newTitle: string;
source: `${ChatSourceEnum}`;
sourceName?: string;
@ -219,7 +218,6 @@ export async function saveChat(props: Props) {
nodes,
appChatConfig,
variables,
isUpdateUseTime,
newTitle,
source,
sourceName,
@ -393,18 +391,6 @@ export async function saveChat(props: Props) {
} catch (error) {
addLog.error('Push chat log error', error);
}
if (isUpdateUseTime) {
await MongoApp.updateOne(
{ _id: appId },
{
updateTime: new Date()
},
{
...writePrimary
}
).catch();
}
} catch (error) {
addLog.error(`update chat history error`, error);
}

View File

@ -33,6 +33,7 @@ import { isS3ObjectKey } from '@fastgpt/service/common/s3/utils';
import { MongoAppTemplate } from '@fastgpt/service/core/app/templates/templateSchema';
import { getNanoid } from '@fastgpt/global/common/string/tools';
import path from 'node:path';
import { updateParentFoldersUpdateTime } from '@fastgpt/service/core/app/controller';
export type CreateAppBody = {
parentId?: ParentIdType;
@ -243,6 +244,11 @@ export const onCreateApp = async ({
await getS3AvatarSource().refreshAvatar(_avatar, undefined, session);
await updateParentFoldersUpdateTime({
parentId,
session
});
(async () => {
addAuditLog({
tmbId,

View File

@ -10,6 +10,7 @@ import { MongoApp } from '@fastgpt/service/core/app/schema';
import type { StoreSecretValueType } from '@fastgpt/global/common/secret/type';
import { storeSecretValue } from '@fastgpt/service/common/secret/utils';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { updateParentFoldersUpdateTime } from '@fastgpt/service/core/app/controller';
export type UpdateHttpPluginBody = {
appId: string;
@ -50,6 +51,12 @@ async function handler(req: ApiRequestProps<UpdateHttpPluginBody>, res: NextApiR
},
{ session }
);
await updateParentFoldersUpdateTime({
parentId: app.parentId,
session
});
await MongoAppVersion.updateOne(
{ appId },
{

View File

@ -10,6 +10,7 @@ import { getMCPToolSetRuntimeNode } from '@fastgpt/global/core/app/tool/mcpTool/
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { type StoreSecretValueType } from '@fastgpt/global/common/secret/type';
import { storeSecretValue } from '@fastgpt/service/common/secret/utils';
import { updateParentFoldersUpdateTime } from '@fastgpt/service/core/app/controller';
export type updateMCPToolsQuery = {};
@ -51,6 +52,12 @@ async function handler(
},
{ session }
);
await updateParentFoldersUpdateTime({
parentId: app.parentId,
session
});
await MongoAppVersion.updateOne(
{ appId },
{

View File

@ -27,6 +27,7 @@ import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
import { getI18nAppType } from '@fastgpt/service/support/user/audit/util';
import { i18nT } from '@fastgpt/web/i18n/utils';
import { getS3AvatarSource } from '@fastgpt/service/common/s3/sources/avatar';
import { updateParentFoldersUpdateTime } from '@fastgpt/service/core/app/controller';
export type AppUpdateQuery = {
appId: string;
@ -117,7 +118,7 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
await getS3AvatarSource().refreshAvatar(avatar, app.avatar, session);
return MongoApp.findByIdAndUpdate(
const result = await MongoApp.findByIdAndUpdate(
appId,
{
...parseParentIdInMongo(parentId),
@ -137,6 +138,26 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
},
{ session }
);
if (isMove) {
// Update both old and new parent folders
await updateParentFoldersUpdateTime({
parentId: app.parentId,
session
});
await updateParentFoldersUpdateTime({
parentId,
session
});
} else {
// Update current parent folder
await updateParentFoldersUpdateTime({
parentId: parentId || app.parentId,
session
});
}
return result;
};
// Move

View File

@ -13,6 +13,7 @@ import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
import { getI18nAppType } from '@fastgpt/service/support/user/audit/util';
import { i18nT } from '@fastgpt/web/i18n/utils';
import { updateParentFoldersUpdateTime } from '@fastgpt/service/core/app/controller';
async function handler(req: ApiRequestProps<PostPublishAppProps>, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string };
@ -61,6 +62,11 @@ async function handler(req: ApiRequestProps<PostPublishAppProps>, res: NextApiRe
session
}
);
await updateParentFoldersUpdateTime({
parentId: app.parentId,
session
});
});
addAuditLog({
@ -122,6 +128,11 @@ async function handler(req: ApiRequestProps<PostPublishAppProps>, res: NextApiRe
session
}
);
await updateParentFoldersUpdateTime({
parentId: app.parentId,
session
});
});
(async () => {

View File

@ -248,7 +248,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
nodes,
appChatConfig: chatConfig,
variables: newVariables,
isUpdateUseTime: false, // owner update use time
newTitle,
source: ChatSourceEnum.test,
userContent: userQuestion,

View File

@ -326,7 +326,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
})();
// save chat
const isOwnerUse = !shareId && !spaceTeamId && String(tmbId) === String(app.tmbId);
const source = (() => {
if (shareId) {
return ChatSourceEnum.share;
@ -363,7 +362,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
nodes,
appChatConfig: chatConfig,
variables: newVariables,
isUpdateUseTime: isOwnerUse && source === ChatSourceEnum.online, // owner update use time
newTitle,
shareId,
outLinkUid: outLinkUserId,

View File

@ -328,7 +328,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
})();
// save chat
const isOwnerUse = !shareId && !spaceTeamId && String(tmbId) === String(app.tmbId);
const source = (() => {
if (shareId) {
return ChatSourceEnum.share;
@ -365,7 +364,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
nodes,
appChatConfig: chatConfig,
variables: newVariables,
isUpdateUseTime: isOwnerUse && source === ChatSourceEnum.online, // owner update use time
newTitle,
shareId,
outLinkUid: outLinkUserId,

View File

@ -101,7 +101,6 @@ export const getScheduleTriggerApp = async () => {
nodes,
appChatConfig: chatConfig,
variables: {},
isUpdateUseTime: false, // owner update use time
newTitle: 'Cron Job',
source: ChatSourceEnum.cronJob,
userContent: {

View File

@ -257,7 +257,6 @@ export const callMcpServerTool = async ({ key, toolName, inputs }: toolCallProps
nodes,
appChatConfig: chatConfig,
variables: newVariables,
isUpdateUseTime: false, // owner update use time
newTitle,
source: ChatSourceEnum.mcp,
userContent: userQuestion,

View File

@ -31,7 +31,6 @@ const createMockProps = (
outputs: []
}
],
isUpdateUseTime: true,
newTitle: 'Test Chat',
source: 'online' as any,
userContent: {
@ -228,7 +227,7 @@ describe('saveChat', () => {
collectionId: 'collection-1',
sourceId: 'source-1',
sourceName: 'doc.pdf',
score: [{ type: 'embedding', value: 0.95, index: 0 }],
score: [{ type: 'embedding' as const, value: 0.95, index: 0 }],
q: 'What is AI?',
a: 'AI stands for Artificial Intelligence...',
updateTime: new Date()
@ -283,36 +282,6 @@ describe('saveChat', () => {
}
});
it('should update app use time when isUpdateUseTime is true', async () => {
const beforeTime = new Date();
const props = createMockProps(
{ isUpdateUseTime: true },
{ appId: testAppId, teamId: testTeamId, tmbId: testTmbId }
);
await saveChat(props);
const app = await MongoApp.findById(testAppId);
expect(app?.updateTime).toBeDefined();
expect(app!.updateTime.getTime()).toBeGreaterThanOrEqual(beforeTime.getTime());
});
it('should not update app use time when isUpdateUseTime is false', async () => {
const app = await MongoApp.findById(testAppId);
const originalUpdateTime = app!.updateTime;
const props = createMockProps(
{ isUpdateUseTime: false },
{ appId: testAppId, teamId: testTeamId, tmbId: testTmbId }
);
await saveChat(props);
const updatedApp = await MongoApp.findById(testAppId);
expect(updatedApp!.updateTime.getTime()).toBe(originalUpdateTime.getTime());
});
it('should create chat data log with error count when response has error', async () => {
const props = createMockProps(
{