UNPKG

delta-sync

Version:

A lightweight framework for bi-directional database synchronization with automatic version tracking and conflict resolution.

373 lines (294 loc) 10.3 kB
# DeltaSync [![npm version](https://img.shields.io/npm/v/delta-sync.svg)](https://www.npmjs.com/package/delta-sync) [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC) **一个轻量级跨平台数据同步引擎** DeltaSync 是一个专门为现代应用设计的数据同步框架,它能帮助开发者轻松实现数据的双向同步、离线存储和冲突处理。无论是 Web 应用、移动应用还是桌面应用,DeltaSync 都能提供一致的同步体验。 ## 核心特性 - **轻量灵活**: 核心代码不到2000行,依赖极少 - **适配器模式**: 轻松对接任意数据库系统 - **版本控制**: 自动跟踪数据变更,使用基于时间戳的版本号 - **增量同步**: 通过检查点机制仅同步变更数据,大幅提升性能 - **离线支持**: 完整的离线工作能力,网络恢复后自动同步 - **类型安全**: 使用 TypeScript 编写,提供完整类型定义 - **批量处理**: 支持批量数据同步 - **完整事件**: 提供丰富的同步事件回调 - **墓碑机制**: 完善的删除追踪机制,支持保留策略 ## 安装 ```bash npm install delta-sync ``` ## 快速开始 1. 创建数据库适配器: ```typescript import { DatabaseAdapter } from 'delta-sync'; class MyDatabaseAdapter implements DatabaseAdapter { async readStore<T extends { id: string }>( storeName: string, limit?: number, offset?: number ): Promise<{ items: T[]; hasMore: boolean }> { // 实现数据读取逻辑 } async listStoreItems( storeName: string, offset?: number, since?: number, before?: number ): Promise<{ items: Array<{ id: string; _ver: number; store?: string; deleted?: boolean }>; hasMore?: boolean; offset?: number; }> { // 实现列表项逻辑(用于同步视图) } async readBulk<T extends { id: string }>( storeName: string, ids: string[] ): Promise<T[]> { // 实现批量读取逻辑 } async putBulk<T extends { id: string }>( storeName: string, items: T[] ): Promise<T[]> { // 实现批量写入逻辑 } async deleteBulk(storeName: string, ids: string[]): Promise<void> { // 实现批量删除逻辑 } async clearStore(storeName: string): Promise<boolean> { // 实现清空存储逻辑 } } ``` 2. 初始化同步引擎: ```typescript import { SyncEngine } from 'delta-sync'; const localAdapter = new MyDatabaseAdapter(); const cloudAdapter = new MyCloudAdapter(); // 指定需要同步的存储 const storesToSync = ['notes', 'tasks', 'tombStones']; const engine = new SyncEngine(localAdapter, storesToSync, { autoSync: { enabled: true, pullInterval: 60000, // 每60秒自动同步 pushDebounce: 10000 // 本地更改10秒后推送 }, onStatusUpdate: (status) => { console.log('同步状态:', status); } }); // 初始化引擎 await engine.initialize(); // 设置云端适配器 await engine.setCloudAdapter(cloudAdapter); ``` 3. 数据操作: ```typescript // 保存数据(单个或批量) await engine.save('notes', { id: '1', title: '测试笔记', content: '内容...' }); // 保存多个项目 await engine.save('notes', [ { id: '1', title: '笔记1', content: '...' }, { id: '2', title: '笔记2', content: '...' } ]); // 删除数据 await engine.delete('notes', '1'); // 或删除多个 await engine.delete('notes', ['1', '2']); ``` ## 同步原理 DeltaSync 采用基于版本的增量同步机制: 1. **版本追踪**: 每个数据项都有一个 `_ver` 字段(基于时间戳的版本号) 2. **变更追踪**: 使用 `SyncView` 存储所有数据的最新版本信息,用于快速比对 3. **同步模式**: - **全量同步**: 使用 SyncView 比对本地和云端的所有数据 - **增量同步**: 使用检查点机制,仅同步自上次同步以来的变更 - **推送**: 将本地新版本数据推送到云端 - **拉取**: 拉取云端新版本数据到本地 - **冲突处理**: 采用"最新版本胜出"策略(更高的 `_ver` 获胜) 4. **墓碑机制**: - 已删除的项目会被追踪在特殊的 `tombStones` 存储中 - 墓碑默认保留180天 - 确保删除操作在所有设备间正确传播 5. **离线支持**: - 离线时正常工作 - 变更会被缓存,网络恢复后自动同步 - 防止重复同步 ## 高级功能 ### 同步方法 ```typescript // 全量同步(先拉取后推送) await engine.fullSync(); // 仅拉取远程更改(全量比对) await engine.pull(); // 增量拉取(仅拉取自上次同步以来的变更) await engine.incrementalPull(); // 仅推送本地更改 await engine.push(); ``` ### 自定义同步选项 ```typescript engine.updateSyncOptions({ maxRetries: 3, // 最大重试次数 timeout: 30000, // 超时时间(ms) batchSize: 100, // 批量同步大小 maxFileSize: 10485760, // 最大文件大小(10MB) fileChunkSize: 1048576, // 文件分片大小(1MB) autoSync: { enabled: true, pullInterval: 60000, // 拉取间隔(ms) pushDebounce: 10000, // 推送防抖延迟(ms) retryDelay: 3000 // 重试延迟(ms) } }); ``` ### 同步事件监听 ```typescript const options = { onStatusUpdate: (status: SyncStatus) => { console.log('同步状态:', status); }, onSyncProgress: (progress: { processed: number; total: number }) => { console.log(`进度: ${progress.processed}/${progress.total}`); }, onVersionUpdate: (version: number) => { console.log('最新版本已更新到:', version); }, onChangePushed: (changes: DataChangeSet) => { console.log('推送变更:', changes); }, onChangePulled: (changes: DataChangeSet) => { console.log('拉取变更:', changes); }, onPullAvailableCheck: () => { // 返回 true 表示允许拉取 return navigator.onLine; }, onPushAvailableCheck: () => { // 返回 true 表示允许推送 return navigator.onLine; } }; ``` ### 存储管理 ```typescript // 清空本地存储 await engine.clearLocalStores('notes'); await engine.clearLocalStores(['notes', 'tasks']); // 清空云端存储 await engine.clearCloudStores('notes'); await engine.clearCloudStores(['notes', 'tasks']); ``` ### 自动同步控制 ```typescript // 启用自动同步 engine.enableAutoSync(60000); // 60秒间隔 // 禁用自动同步 engine.dispose(); // 同时清除定时器并重置状态 ``` ## 适配器开发 开发自定义适配器需实现 `DatabaseAdapter` 接口: ```typescript export interface DatabaseAdapter { readStore<T extends { id: string }>( storeName: string, limit?: number, offset?: number ): Promise<{ items: T[]; hasMore: boolean }>; listStoreItems( storeName: string, offset?: number, since?: number, before?: number ): Promise<{ items: SyncViewItem[]; hasMore?: boolean; offset?: number; }>; readBulk<T extends { id: string }>( storeName: string, ids: string[] ): Promise<T[]>; putBulk<T extends { id: string }>( storeName: string, items: T[] ): Promise<T[]>; deleteBulk(storeName: string, ids: string[]): Promise<void>; clearStore(storeName: string): Promise<boolean>; } ``` **重要提示:** - `listStoreItems` 应按 `_ver` 降序返回项目,以便高效的基于检查点的增量同步 - `listStoreItems` 中的 `since` 参数用于增量同步(仅返回 `_ver > since` 的项目) - `before` 参数可用于过滤旧的墓碑数据 - 项目必须包含 `id` 和 `_ver` 字段 ## 技术架构 ### 核心组件 1. **SyncEngine**: 主同步控制器 - 管理同步生命周期 - 协调本地和云端操作 - 处理自动同步调度 - 提供数据操作方法(save, delete) 2. **SyncView**: 用于快速比对的数据视图 - 存储轻量级元数据(id、版本、存储、删除标志) - 支持高效的差异计算 - 通过检查点支持增量同步 3. **DatabaseAdapter**: 数据库接口 - 提供统一的数据访问 - 抽象数据库操作 - 确保跨平台兼容性 4. **检查点机制**: - 跟踪每个存储的最新版本 - 支持高效的增量同步 - 减少大数据集的数据传输 ### 同步状态 ```typescript export enum SyncStatus { REJECTED = -3, // 推送被可用性检查拒绝 ERROR = -2, // 错误状态 OFFLINE = -1, // 离线状态 IDLE = 0, // 空闲状态 UPLOADING = 1, // 上传进行中 DOWNLOADING = 2, // 下载进行中 OPERATING = 3, // 操作进行中(清空存储等) CHECKING = 4, // 检查云端变更中 } ``` ### 版本控制 - 每个数据项都有一个 `_ver`(版本)字段 - 版本号基于时间戳(自纪元以来的毫秒数) - 支持冲突检测和解决(最新版本胜出) - 版本在保存操作时自动分配 ### 数据结构 所有数据项必须包含: - `id: string` - 唯一标识符 - `_ver: number` - 版本号(时间戳) 示例: ```typescript interface Note { id: string; _ver: number; // 由 SyncEngine 自动设置 title: string; content: string; // ... 其他字段 } ``` ## 性能考虑 - **批量处理**: 所有操作都使用批量处理以提高效率 - **增量同步**: 检查点机制显著减少数据传输 - **防抖机制**: 本地更改在推送前会进行防抖处理,减少网络调用 - **内存高效**: SyncView 使用轻量级元数据而非完整数据 - **懒加载**: 数据在同步操作期间按需加载 ## 最佳实践 1. **存储命名**: 如果需要删除追踪,请始终在 `storesToSync` 数组中包含 `'tombStones'` 2. **初始化**: 使用引擎前始终调用 `engine.initialize()` 3. **错误处理**: 在适配器中实现适当的错误处理 4. **版本管理**: 永远不要手动修改 `_ver` 字段 - 让 SyncEngine 处理它 5. **清理**: 完成后调用 `engine.dispose()` 以清理定时器和资源 ## 许可证 ISC