Skip to main content

meshlet_server/
doc.rs

1use std::path::Path;
2
3use loro::LoroDoc;
4
5const STATE_FILE: &str = "meshlet-server.state";
6
7pub struct ServerDoc {
8    doc: LoroDoc,
9}
10
11impl ServerDoc {
12    pub fn load_or_create(dir: &Path) -> Self {
13        let state_path = dir.join(STATE_FILE);
14
15        if let Ok(data) = std::fs::read(&state_path)
16            && let Ok(doc) = LoroDoc::from_snapshot(&data)
17        {
18            return Self { doc };
19        }
20
21        let doc = LoroDoc::new();
22        doc.set_record_timestamp(true);
23        doc.set_peer_id(0).ok();
24        Self { doc }
25    }
26
27    pub fn save(&self, dir: &Path) -> anyhow::Result<()> {
28        let state_path = dir.join(STATE_FILE);
29        let snapshot = self
30            .doc
31            .export(loro::ExportMode::Snapshot)
32            .map_err(|e| anyhow::anyhow!("export failed: {}", e))?;
33
34        std::fs::create_dir_all(dir)?;
35        std::fs::write(&state_path, snapshot)?;
36        tracing::info!("saved server state to {:?}", state_path);
37        Ok(())
38    }
39
40    pub fn import(&self, data: &[u8]) -> anyhow::Result<()> {
41        self.doc
42            .import(data)
43            .map_err(|e| anyhow::anyhow!("import failed: {}", e))?;
44        Ok(())
45    }
46
47    pub fn export_updates_since(
48        &self,
49        vv: &loro::VersionVector,
50    ) -> anyhow::Result<Vec<u8>> {
51        self.doc
52            .export(loro::ExportMode::Updates {
53                from: std::borrow::Cow::Borrowed(vv),
54            })
55            .map_err(|e| anyhow::anyhow!("export failed: {}", e))
56    }
57
58    pub fn oplog_vv(&self) -> loro::VersionVector {
59        self.doc.oplog_vv().clone()
60    }
61}