From f6f54660be5cbf3bd85a09bf3741eae80c7b3df9 Mon Sep 17 00:00:00 2001 From: VirtualHotBar Date: Tue, 2 Jun 2026 00:26:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20#55=20=E5=8F=8C=E5=90=91=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E9=A6=96=E6=AC=A1=E8=BF=90=E8=A1=8C=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20--resync=20=E6=A0=87=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bisync 失败时自动重试并添加 _resync 参数 - 修复首次运行双向同步时缺少 --resync 导致的失败 - 添加 logger 导入用于记录重试信息 --- src/services/storage/TransferService.ts | 67 +++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/services/storage/TransferService.ts b/src/services/storage/TransferService.ts index 4fe6c10..b753bfc 100644 --- a/src/services/storage/TransferService.ts +++ b/src/services/storage/TransferService.ts @@ -1,5 +1,6 @@ import { rclone_api_post, rclone_api_exec_async } from '../../utils/rclone/request' import { convertStoragePath, formatPathRclone, getFileName } from './StorageManager' +import { logger } from '../LoggerService' /** * Copy a file from one location to another @@ -148,6 +149,7 @@ async function moveDir( * @param destStoragename - Destination storage name * @param destPath - Destination directory path * @param bisync - If true, perform bidirectional sync (default: false) + * @param resync - If true, force resync for bisync (default: false) * @throws Error if source or destination is invalid */ async function sync( @@ -155,7 +157,8 @@ async function sync( path: string, destStoragename: string, destPath: string, - bisync?: boolean + bisync?: boolean, + resync?: boolean ) { //bisync: 双向同步 @@ -191,14 +194,72 @@ async function sync( throw new Error('Invalid source or destination path') } - success = await rclone_api_exec_async('/sync/bisync', { + const params: Record = { path1, path2, - }) + } + + // 添加resync标志以处理首次同步或同步状态丢失的情况 + if (resync) { + params.resync = true + } + + success = await rclone_api_exec_async('/sync/bisync', params) if (!success) { throw new Error(`Bidirectional sync failed: ${path1} <-> ${path2}`) } } } + if (!path || !destPath) { + throw new Error('Source or destination path is empty') + } + + let success: boolean + if (!bisync) { + const srcFs = convertStoragePath(storageName, path, true) + const dstFs = convertStoragePath(destStoragename, destPath, true) + + if (!srcFs || !dstFs) { + throw new Error('Invalid source or destination path') + } + + success = await rclone_api_exec_async('/sync/sync', { + srcFs, + dstFs, + }) + if (!success) { + throw new Error(`Sync failed: ${srcFs} -> ${dstFs}`) + } + } else { + const path1 = convertStoragePath(storageName, path, true) + const path2 = convertStoragePath(destStoragename, destPath, true) + + if (!path1 || !path2) { + throw new Error('Invalid source or destination path') + } + + // 双向同步:首次运行或同步状态丢失时需要 resync + // rclone bisync 要求首次运行时传入 --resync 参数 + // 通过 _async + extra 参数传递 + success = await rclone_api_exec_async('/sync/bisync', { + path1, + path2, + _resync: false, // 默认不 resync,rclone 会自动检测是否需要 + }) + + if (!success) { + // 如果失败,可能是首次运行需要 resync + logger.info('Bisync failed, retrying with --resync flag', 'TransferService', { path1, path2 }) + success = await rclone_api_exec_async('/sync/bisync', { + path1, + path2, + _resync: true, + }) + if (!success) { + throw new Error(`Bidirectional sync failed: ${path1} <-> ${path2}`) + } + } + } +} export { copyFile, copyDir, moveFile, moveDir, sync }