#sync #file-sync #file-synchronization #remote #client #store #namespaces

bin+lib cooklang-sync-client

cooklang-sync 的客户端库

7 个版本

0.1.6 2024 年 8 月 9 日
0.1.5 2024 年 8 月 7 日
0.1.0 2024 年 6 月 19 日

文件系统 中排名第 521

Download history 115/week @ 2024-06-14 24/week @ 2024-06-21 2/week @ 2024-06-28 139/week @ 2024-07-26 382/week @ 2024-08-02 129/week @ 2024-08-09

每月下载量 650

MPL-2.0 许可证

51KB
1K SLoC

远程模式

服务器文件日志 - 存储所有更改

命名空间 ID (NSID) 相对路径在命名空间日志 ID (JID):在命名空间内单调递增

BlockServer - 可以存储块或检索块

  • RocksDB 可能可行

Q

  • 在哪里存储块?s3 对如此小的文件来说太贵了,也许便宜的分片化键值数据库更合适?

本地数据库模式

文件

jid: 整数路径 // 相对于当前目录格式:text|binary modified: Unix 时间戳 size: 整数 is_symlink: 布尔值 checksum: varchar

用例

  • 客户端需要从元服务器 (MS) 更新文件
    • S 在轮询期间收到通知,/path/bla 文件已更新
    • 发送包含命名空间和当前光标的列表请求
    • MS 返回自上次传递以来的所有 JIDs 及其哈希值(也许除了同一个文件多次更新的情况,只返回最后一个?)
    • S
  • 客户端需要上传文件到服务器
    • S 尝试提交当前文件它有 commit(/path/bla, [h1,h2,h3])
    • MS 返回列表
  • 程序刚刚开始
    • S 检查最新的 journal_id
    • 如果本地最新的 journal_id 相同,它将不执行任何操作
    • 如果本地最新的 journal_id
  • 文件在本地被删除
  • 文件在本地被移动
  • 文件被重命名
  • 文件中的一行被编辑
  • 文件中添加了一行
  • 文件中的一行被删除

如果最新的 jid 在远程更大,则从远程同步下载,如果元数据,大小不同,则上传到远程并在提交后将存储到本地数据库中

Q

  • 我是否需要服务层次结构,或者它们都应该独立?
  • 共享应该如何工作?
  • 如何进行线程化?多个模块和多个文件
  • 我是否需要同步文件元数据?

我们为嗅探文件系统、哈希、提交、存储批处理、列表、检索批处理和重建分别使用单独的线程,使我们能够跨多个文件并行化此过程。我们使用压缩和 rsync 来最小化存储批处理/检索批处理请求的大小。

同步器

  • 检查数据库是否有未分配的 jid
  • 当找到未分配的jid时,它会尝试提交,提交后,它将使用新的jid更新本地数据库。
  • 如果块不在本地,它会尝试下载它。
  • 如果块不存在于远程,它会尝试上传它。

commit("breakfast/Mexican Style Burrito.cook", "h1,h2,h3");

Q

  • 按行处理有问题吗?=> seek无法工作,需要存储块大小以有效地进行seek。
  • 未组装的文件应存储块在哪里?
  • 如何理解远程创建的新文件?
  • 如何理解文件已被删除?
  • 如何理解?

INDEXER

  • 按计划同步文件和本地数据库(例如,每分钟一次)。
  • 监视更改并触发同步。
  • 每天清理数据库一次。

Q

  • 是否需要复制未更改的jid?还是只需更新更新的?=> 更新所有内容是有意义的。
  • 删除和移动时会发生什么?

CHUNKER

Chunker的作用是处理哈希和文件的持久性。它操作文本文件,块的大小不是固定的,而是每个块是文件的一行。

  • 给定路径,它将生成文件的哈希列表:fn hashify(file_path: String) -> io::Result<Vec<String>>
  • 给定路径和哈希列表,它将保存文件的新版本:fn save(file_path: String, Vec<String>) -> io::Result<String>。如果缓存没有特定块哈希的内容,则应引发错误。
  • 可以从缓存中读取特定块的文本:fn read_chunk(chunk: String) -> io::Result<String>
  • 可以将特定块的文本写入缓存:fn save_chunk(chunk: String, content: String) -> io::Result<String>
  • 给定两个哈希值向量,可以比较它们是否相同 fn compare_sets(left: Vec<String>, right: Vec<String>) -> bool
  • 给定一个哈希值,可以检查缓存是否包含其内容。 fn check_chunk(chunk: String>) -> io::Result<bool>

Q

  • 字符串将很短,80-100个符号。应该使用什么作为哈希函数?哈希的大小应该是多少?我认为是10的平方根。你可以测试一下!

  • 空文件应该与已删除的不同

待办事项

  • 上传/下载捆绑

  • 只读

  • 命名空间

  • 适当的错误处理

  • 报告意外缓存行为错误

  • 不需要在每个非200响应中抛出未知错误

  • 移除克隆

  • 限制最大文件大小

  • 配置结构体

  • 先拉取更改还是先本地重新索引?研究可能的冲突场景

  • 提取到核心共享数据结构

  • 在数据库上进行垃圾回收

  • 测试测试测试

  • 监控指标(缓存饱和度,缺失)

  • 防止DDoS攻击 https://github.com/rousan/multer-rs/blob/master/examples/prevent_dos_attack.rs

  • 自动更新客户端

开源

  • 如何保持它对开源可用(一个用户?)
  • 添加文档
  • 绘制数据流

依赖关系

~39–56MB
~1M SLoC