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 }