| 650 | // --------------------------------------------------------------------------- |
| 651 | |
| 652 | export async function runSimpleSync( |
| 653 | backend: ISyncBackend, |
| 654 | onProgress?: (progress: SyncProgress) => void, |
| 655 | options: SimpleSyncOptions = {}, |
| 656 | ): Promise<{ |
| 657 | success: boolean; |
| 658 | changes: number; |
| 659 | filesUploaded: number; |
| 660 | filesDownloaded: number; |
| 661 | filesUploadFailed: number; |
| 662 | filesDownloadFailed: number; |
| 663 | error?: string; |
| 664 | }> { |
| 665 | try { |
| 666 | const { receiveOnly = false, forceApply = false } = options; |
| 667 | onProgress?.({ |
| 668 | phase: "database", |
| 669 | operation: receiveOnly ? "download" : "upload", |
| 670 | completedFiles: 0, |
| 671 | totalFiles: 0, |
| 672 | message: "准备同步...", |
| 673 | }); |
| 674 | |
| 675 | const lastSync = await getLastSyncTimestamp(); |
| 676 | const localDeviceId = await getDeviceId(); |
| 677 | const now = Date.now(); |
| 678 | |
| 679 | // 1. Ensure remote sync directory exists |
| 680 | onProgress?.({ |
| 681 | phase: "database", |
| 682 | operation: receiveOnly ? "download" : "upload", |
| 683 | completedFiles: 0, |
| 684 | totalFiles: 0, |
| 685 | message: "检查远程目录...", |
| 686 | }); |
| 687 | try { |
| 688 | await backend.ensureDirectories(); |
| 689 | } catch (e) { |
| 690 | const msg = e instanceof Error ? e.message : String(e); |
| 691 | throw new Error(`无法创建远程同步目录,请检查存储服务配置和权限:${msg}`); |
| 692 | } |
| 693 | |
| 694 | // 2. Pull and apply all other devices' changesets |
| 695 | onProgress?.({ |
| 696 | phase: "database", |
| 697 | operation: "download", |
| 698 | completedFiles: 0, |
| 699 | totalFiles: 0, |
| 700 | message: "获取其他设备的变更...", |
| 701 | }); |
| 702 | const remoteFiles = await listRemoteDeviceFiles(backend); |
| 703 | console.log(`[SimpleSync] Found ${remoteFiles.length} remote device snapshot(s)`); |
| 704 | |
| 705 | let totalApplied = 0; |
| 706 | let skippedRemoteSnapshots = 0; |
| 707 | for (const { deviceId, path } of remoteFiles) { |
| 708 | // Skip our own file |
| 709 | if (deviceId === localDeviceId) continue; |