Commit 6fb93ef8 by Archer Committed by GitHub

fix: s3 del worker while (#6133)

* stop design doc

* remove invalid doc

* fix: s3 del worker while

* fix: s3 del worker while

* perf: regx
parent b0a48603
...@@ -19,6 +19,7 @@ description: 'FastGPT V4.14.5 更新说明' ...@@ -19,6 +19,7 @@ description: 'FastGPT V4.14.5 更新说明'
2. 获取对话日志列表时,如果用户头像为空,会抛错。 2. 获取对话日志列表时,如果用户头像为空,会抛错。
3. chatAgent 未开启问题优化时,前端 UI 显示开启。 3. chatAgent 未开启问题优化时,前端 UI 显示开启。
4. 加载默认模型时,maxTokens 字段未赋值,导致模型最大响应值配置为空。 4. 加载默认模型时,maxTokens 字段未赋值,导致模型最大响应值配置为空。
5. S3 文件清理队列因网络稳定问题出现阻塞,导致删除任务不再执行。
## 插件 ## 插件
...@@ -120,7 +120,7 @@ ...@@ -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/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/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/4144.mdx": "2025-12-16T14:56:04+08:00",
"document/content/docs/upgrading/4-14/4145.mdx": "2025-12-20T13:11:02+08:00", "document/content/docs/upgrading/4-14/4145.mdx": "2025-12-21T19:15:10+08:00",
"document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+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/41.mdx": "2025-08-02T19:38:37+08:00",
"document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00",
......
...@@ -43,33 +43,65 @@ export const addS3DelJob = async (data: S3MQJobData): Promise<void> => { ...@@ -43,33 +43,65 @@ export const addS3DelJob = async (data: S3MQJobData): Promise<void> => {
export const prefixDel = async (bucket: S3BaseBucket, prefix: string) => { export const prefixDel = async (bucket: S3BaseBucket, prefix: string) => {
addLog.debug(`[S3 delete] delete prefix: ${prefix}`); addLog.debug(`[S3 delete] delete prefix: ${prefix}`);
let tasks: Promise<any>[] = []; let tasks: Promise<any>[] = [];
return new Promise<void>(async (resolve, reject) => { return new Promise<void>((resolve, reject) => {
let timer: NodeJS.Timeout;
const stream = bucket.listObjectsV2(prefix, true); const stream = bucket.listObjectsV2(prefix, true);
let settled = false;
const finish = (error?: any) => {
if (settled) return;
settled = true;
if (timer) {
clearTimeout(timer);
}
stream?.removeAllListeners?.();
stream?.destroy?.();
if (error) {
addLog.error(`[S3 delete] delete prefix failed`, error);
reject(error);
} else {
resolve();
}
};
// stream 可能会中断,没有触发 end 和 error,导致 promise 不返回,需要增加定时器兜底。
timer = setTimeout(() => {
addLog.error(`[S3 delete] delete prefix timeout: ${prefix}`);
finish('Timeout');
}, 60000);
stream.on('data', (file) => { stream.on('data', (file) => {
if (!file.name) return; if (!file.name) return;
tasks.push(bucket.removeObject(file.name)); tasks.push(bucket.removeObject(file.name));
}); });
stream.on('end', async () => { stream.on('end', async () => {
if (tasks.length === 0) { if (tasks.length === 0) {
return resolve(); return finish();
} }
if (timer) {
clearTimeout(timer);
}
const results = await Promise.allSettled(tasks); const results = await Promise.allSettled(tasks);
const failed = results.some((r) => r.status === 'rejected'); const failed = results.some((r) => r.status === 'rejected');
if (failed) { if (failed) {
addLog.error(`[S3 delete] delete prefix failed: ${prefix}`); return finish('Some deletes failed');
reject('Some deletes failed');
} }
resolve(); finish();
}); });
stream.on('error', (err) => { stream.on('error', (err) => {
if (isFileNotFoundError(err)) { if (isFileNotFoundError(err)) {
return resolve(); return finish();
} }
addLog.error(`[S3 delete] delete prefix: ${prefix} error`, err); addLog.error(`[S3 delete] delete prefix: ${prefix} error`, err);
reject(err); return finish(err);
});
stream.on('pause', () => {
addLog.warn(`[S3 delete] delete prefix: ${prefix} paused`);
stream.resume();
}); });
}); });
}; };
......
...@@ -176,7 +176,8 @@ class PgClass { ...@@ -176,7 +176,8 @@ class PgClass {
const time = Date.now() - start; const time = Date.now() - start;
if (time > 300) { if (time > 300) {
addLog.warn(`pg query time: ${time}ms, sql: ${sql}`); const safeSql = sql.replace(/'\[[^\]]*?\]'/g, "'[x]'");
addLog.warn(`pg query time: ${time}ms, sql: ${safeSql}`);
} }
return res; return res;
......
...@@ -52,6 +52,7 @@ export const deleteTeamAllDatasets = async (teamId: string) => { ...@@ -52,6 +52,7 @@ export const deleteTeamAllDatasets = async (teamId: string) => {
); );
}; };
// 批量删除函数
const deleteDatasets = async ({ const deleteDatasets = async ({
teamId, teamId,
datasets datasets
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment