Skip to content

Commit

Permalink
fix: cursor behavior when using gc-snapshot
Browse files Browse the repository at this point in the history
  • Loading branch information
zxch3n committed Sep 23, 2024
1 parent 9294648 commit 11af19a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
10 changes: 9 additions & 1 deletion crates/loro-internal/src/loro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,10 @@ impl LoroDoc {
.ok_or(CannotFindRelativePosition::ContainerDeleted)?;
// We know where the target id is when we trace back to the delete_op_id.
let Some(delete_op_id) = find_last_delete_op(&oplog, id, idx) else {
if oplog.trimmed_vv().includes_id(id) {
return Err(CannotFindRelativePosition::HistoryCleared);
}

tracing::error!("Cannot find id {}", id);
return Err(CannotFindRelativePosition::IdNotFound);
};
Expand Down Expand Up @@ -1557,8 +1561,12 @@ impl LoroDoc {
}
}

// FIXME: PERF: This method is quite slow because it iterates all the changes
fn find_last_delete_op(oplog: &OpLog, id: ID, idx: ContainerIdx) -> Option<ID> {
let start_vv = oplog.dag.frontiers_to_vv(&id.into())?;
let start_vv = oplog
.dag
.frontiers_to_vv(&id.into())
.unwrap_or_else(|| oplog.trimmed_vv().to_vv());
for change in oplog.iter_changes_causally_rev(&start_vv, oplog.vv()) {
for op in change.ops.iter().rev() {
if op.container != idx {
Expand Down
59 changes: 58 additions & 1 deletion crates/loro/tests/integration_test/gc_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
};

use super::gen_action;
use loro::{ExportMode, Frontiers, LoroDoc, ID};
use loro::{cursor::CannotFindRelativePosition, ExportMode, Frontiers, LoroDoc, ID};

#[test]
fn test_gc() -> anyhow::Result<()> {
Expand Down Expand Up @@ -240,3 +240,60 @@ fn the_vv_on_gc_doc() -> anyhow::Result<()> {

Ok(())
}

#[test]
fn test_cursor_that_cannot_be_found_when_exporting_gc_snapshot() -> anyhow::Result<()> {
let doc = LoroDoc::new();
doc.set_peer_id(1)?;
doc.get_text("text").insert(0, "Hello world")?;
let c = doc
.get_text("text")
.get_cursor(3, loro::cursor::Side::Left)
.unwrap();
doc.get_text("text").delete(0, 5)?;
doc.commit();
let snapshot = doc.export(loro::ExportMode::gc_snapshot(&doc.oplog_frontiers()));
let new_doc = LoroDoc::new();
new_doc.import(&snapshot)?;
let result = new_doc.get_cursor_pos(&c);
match result {
Ok(v) => {
dbg!(v);
unreachable!()
}
Err(CannotFindRelativePosition::HistoryCleared) => {}
Err(x) => {
dbg!(x);
unreachable!()
}
}
Ok(())
}

#[test]
fn test_cursor_that_can_be_found_when_exporting_gc_snapshot() -> anyhow::Result<()> {
let doc = LoroDoc::new();
doc.set_peer_id(1)?;
doc.get_text("text").insert(0, "Hello world")?;
doc.commit();
let c = doc
.get_text("text")
.get_cursor(3, loro::cursor::Side::Left)
.unwrap();
doc.get_text("text").delete(0, 5)?;
doc.commit();
let snapshot = doc.export(loro::ExportMode::gc_snapshot_from_id(ID::new(1, 10)));
let new_doc = LoroDoc::new();
new_doc.import(&snapshot)?;
let result = new_doc.get_cursor_pos(&c);
match result {
Ok(v) => {
assert_eq!(v.current.pos, 0);
}
Err(x) => {
dbg!(x);
unreachable!()
}
}
Ok(())
}

0 comments on commit 11af19a

Please sign in to comment.