Rust实时协作库y-sync的使用,y-sync提供高效的CRDT算法实现与多端数据同步功能

Rust实时协作库y-sync的使用,y-sync提供高效的CRDT算法实现与多端数据同步功能

Yjs/Yrs同步协议实现

该crate提供了Yjs/Yrs同步协议的默认实现,它在项目之间共享,可用于在Yjs客户端和Yrs服务器之间进行互操作。

它还实现了awareness协议和相应的Awareness结构。

该实现就像协议本身一样灵活,可以通过自定义实现Protocol trait来扩展。如果不是必要的话,提供了DefaultProtocol

示例代码

use y_sync::sync::Protocol;
use y_sync::sync::DefaultProtocol;
use yrs::Doc;

fn main() {
    // 创建Yrs文档
    let doc = Doc::new();
    
    // 创建默认协议实例
    let protocol = DefaultProtocol::default();
    
    // 获取文档状态向量
    let state_vector = doc.transact().state_vector();
    
    // 编码同步消息
    let sync_message = protocol.encode_sync_message(&state_vector);
    
    // 解码并应用同步消息
    protocol.apply_sync_message(&doc, &sync_message);
    
    // 创建awareness实例
    let awareness = protocol.awareness();
    
    // 更新本地状态
    awareness.set_local_state(Some(vec![1, 2, 3]));
}

完整示例Demo

下面是一个更完整的示例,展示如何使用y-sync进行实时协作:

use std::sync::Arc;
use std::thread;
use yrs::{Doc, Transact};
use y_sync::sync::{DefaultProtocol, Protocol};

fn main() {
    // 创建主文档和协议
    let doc1 = Arc::new(Doc::new());
    let protocol1 = Arc::new(DefaultProtocol::default());
    
    // 创建副本文档和协议
    let doc2 = Arc::new(Doc::new());
    let protocol2 = Arc::new(DefaultProtocol::default());
    
    // 在主文档中插入一些内容
    let text1 = doc1.get_or_insert_text("text");
    let mut txn = doc1.transact();
    text1.insert(&mut txn, 0, "Hello");
    
    // 获取主文档的状态向量
    let state_vector = txn.state_vector();
    
    // 在另一个线程中模拟远程客户端
    let doc1_clone = doc1.clone();
    let doc2_clone = doc2.clone();
    let protocol1_clone = protocol1.clone();
    let protocol2_clone = protocol2.clone();
    
    thread::spawn(move || {
        // 编码同步消息
        let sync_message = protocol1_clone.encode_sync_message(&state_vector);
        
        // 在副本文档中应用同步消息
        protocol2_clone.apply_sync_message(&doc2_clone, &sync_message);
        
        // 验证内容已同步
        let text2 = doc2_clone.get_or_insert_text("text");
        let txn = doc2_clone.transact();
        assert_eq!(text2.get_string(&txn), "Hello");
    });
    
    // 在主线程中继续修改
    text1.insert(&mut txn, 5, " World");
    txn.commit();
    
    // 等待同步完成
    thread::sleep(std::time::Duration::from_millis(100));
    
    // 验证最终同步结果
    let txn = doc2.transact();
    let text2 = doc2.get_or_insert_text("text");
    assert_eq!(text2.get_string(&txn), "Hello World");
}

安装

在项目目录中运行以下Cargo命令:

cargo add y-sync

或者在Cargo.toml中添加以下行:

y-sync = "0.4.0"

文档

更多详细使用方法和API参考,请查看官方文档


1 回复

Rust实时协作库y-sync使用指南

简介

y-sync是一个基于CRDT(Conflict-Free Replicated Data Type)算法的Rust实时协作库,提供高效的多端数据同步功能。它特别适合构建需要实时协作的应用程序,如协同编辑、多人白板等场景。

核心特性

  • 基于Yjs协议的Rust实现
  • 高效的CRDT算法保证数据最终一致性
  • 支持离线编辑和自动冲突解决
  • 轻量级且高性能
  • 提供多种网络协议适配器

安装方法

在Cargo.toml中添加依赖:

[dependencies]
y-sync = "0.1"  # 请使用最新版本

基本使用示例

1. 创建和同步文档

use y_sync::sync::{Doc, Awareness, SyncProtocol};

// 创建新文档
let doc = Doc::new();
let awareness = Awareness::new(doc.clone());

// 获取文档状态向量
let state_vector = doc.encode_state_vector();

// 模拟与其他客户端同步
let mut other_doc = Doc::new();
other_doc.sync(state_vector, &doc.encode_state_as_update(&state_vector));

2. 处理文本协作

use y_sync::types::text::Text;

let doc = Doc::new();
let text = doc.get_or_insert_text("shared-text");

// 本地修改
text.insert(0, "Hello, ")?;

// 模拟远程更新
let update = doc.encode_update_v1();
other_doc.apply_update(update)?;

3. 使用网络同步

use y_sync::net::websocket::{WebSocketProvider, WebSocketReceiver};

// 创建WebSocket连接
let ws_provider = WebSocketProvider::new("ws://example.com/sync".to_string(), doc.clone());

// 处理接收到的消息
let mut receiver = WebSocketReceiver::new();
while let Some(message) = receiver.recv() {
    doc.apply_update(message.update)?;
}

高级功能

1. 自定义数据类型

use y_sync::types::array::Array;

let doc = Doc::new();
let array = doc.get_or_insert_array("shared-array");

array.insert(0, "item1")?;
array.insert(1, 42)?;

2. 处理离线编辑

// 保存文档状态
let saved_state = doc.encode_update_v1();

// 恢复文档
let recovered_doc = Doc::new();
recovered_doc.apply_update(saved_state)?;

3. 使用观察者模式监听变更

use y_sync::observe::Observer;

let observer = Observer::new(doc.clone());
observer.observe(|event| {
    println!("Document changed: {:?}", event);
});

性能建议

  1. 批量处理更新以减少同步频率
  2. 对于大型文档,考虑分块同步
  3. 使用压缩算法减少网络传输数据量

注意事项

  • 所有协作客户端必须使用相同的文档ID
  • 确保网络消息按顺序到达
  • 定期进行全量同步以防止增量同步累积错误

y-sync为Rust开发者提供了强大的实时协作能力,通过其CRDT实现,可以轻松构建各种需要多端同步的应用程序。

完整示例代码

下面是一个完整的协同文本编辑示例,展示了如何使用y-sync实现基本的实时协作功能:

use y_sync::sync::{Doc, SyncProtocol};
use y_sync::types::text::Text;
use y_sync::net::websocket::{WebSocketProvider, WebSocketReceiver};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // 创建主文档
    let doc = Doc::new();
    let text = doc.get_or_insert_text("shared-text");
    
    // 添加初始文本
    text.insert(0, "Hello, World!")?;
    
    // 模拟两个客户端同步
    let mut client_a = Doc::new();
    let mut client_b = Doc::new();
    
    // 同步初始状态
    let state_vector = doc.encode_state_vector();
    let update = doc.encode_state_as_update(&state_vector);
    client_a.sync(state_vector.clone(), &update)?;
    client_b.sync(state_vector, &update)?;
    
    // 客户端A修改文本
    let text_a = client_a.get_or_insert_text("shared-text");
    text_a.insert(7, "Rust ")?;
    
    // 客户端B修改文本
    let text_b = client_b.get_or_insert_text("shared-text");
    text_b.insert(12, "!")?;
    
    // 交换更新
    let update_a = client_a.encode_update_v1();
    let update_b = client_b.encode_update_v1();
    
    client_b.apply_update(update_a)?;
    client_a.apply_update(update_b)?;
    
    // 打印最终结果
    println!("Client A text: {}", text_a.to_string());
    println!("Client B text: {}", text_b.to_string());
    
    // 模拟网络同步
    let ws_provider = WebSocketProvider::new("ws://example.com/sync".to_string(), doc.clone());
    let mut receiver = WebSocketReceiver::new();
    
    // 在实际应用中,这里会有网络循环处理
    // while let Some(message) = receiver.recv() {
    //     doc.apply_update(message.update)?;
    // }
    
    Ok(())
}

这个完整示例展示了:

  1. 创建共享文档和文本类型
  2. 模拟多个客户端之间的同步
  3. 处理并发修改
  4. 基本的网络同步设置

注意:实际网络同步部分需要配合WebSocket服务器实现,示例中只展示了基本结构。

回到顶部