diff --git a/.changeset/two-jokes-happen.md b/.changeset/two-jokes-happen.md new file mode 100644 index 00000000..39764200 --- /dev/null +++ b/.changeset/two-jokes-happen.md @@ -0,0 +1,5 @@ +--- +"loro-crdt": patch +--- + +Add changeCount and opCount methods diff --git a/crates/loro-internal/src/container/richtext/richtext_state.rs b/crates/loro-internal/src/container/richtext/richtext_state.rs index c6025415..ef7365a6 100644 --- a/crates/loro-internal/src/container/richtext/richtext_state.rs +++ b/crates/loro-internal/src/container/richtext/richtext_state.rs @@ -1757,7 +1757,6 @@ impl RichtextState { self.get_index_from_cursor(right, PosType::Entity).unwrap() } - #[tracing::instrument(level = "trace", skip(self))] pub fn get_index_from_cursor( &self, cursor: generic_btree::Cursor, diff --git a/crates/loro-internal/src/loro.rs b/crates/loro-internal/src/loro.rs index 6b0bf741..97038855 100644 --- a/crates/loro-internal/src/loro.rs +++ b/crates/loro-internal/src/loro.rs @@ -1212,7 +1212,17 @@ impl LoroDoc { #[inline] pub fn len_ops(&self) -> usize { let oplog = self.oplog.try_lock().unwrap(); - oplog.vv().iter().map(|(_, ops)| *ops).sum::() as usize + let ans = oplog.vv().iter().map(|(_, ops)| *ops).sum::() as usize; + if oplog.is_shallow() { + let sub = oplog + .shallow_since_vv() + .iter() + .map(|(_, ops)| *ops) + .sum::() as usize; + ans - sub + } else { + ans + } } #[inline] diff --git a/crates/loro-internal/src/oplog/change_store.rs b/crates/loro-internal/src/oplog/change_store.rs index 96dcaaca..522654c7 100644 --- a/crates/loro-internal/src/oplog/change_store.rs +++ b/crates/loro-internal/src/oplog/change_store.rs @@ -433,6 +433,7 @@ impl ChangeStore { } pub fn change_num(&self) -> usize { + self.ensure_block_loaded_in_range(Bound::Unbounded, Bound::Unbounded); let mut inner = self.inner.try_lock().unwrap(); inner .mem_parsed_kv diff --git a/crates/loro-wasm/src/lib.rs b/crates/loro-wasm/src/lib.rs index adc7f7f1..894ae8c7 100644 --- a/crates/loro-wasm/src/lib.rs +++ b/crates/loro-wasm/src/lib.rs @@ -1412,6 +1412,18 @@ impl LoroDoc { console_log!("{:#?}", oplog.diagnose_size()); } + /// Get the number of changes in the oplog. + pub fn changeCount(&self) -> usize { + let borrow_mut = &self.0; + let oplog = borrow_mut.oplog().try_lock().unwrap(); + oplog.len_changes() + } + + /// Get the number of ops in the oplog. + pub fn opCount(&self) -> usize { + self.0.len_ops() + } + /// Get all of changes in the oplog. /// /// Note: this method is expensive when the oplog is large. O(n) diff --git a/crates/loro/tests/loro_rust_test.rs b/crates/loro/tests/loro_rust_test.rs index 7979f022..dee37e9a 100644 --- a/crates/loro/tests/loro_rust_test.rs +++ b/crates/loro/tests/loro_rust_test.rs @@ -2238,3 +2238,21 @@ fn is_deleted() { let container_after = doc.get_map(&container_before.id()); assert!(container_after.is_deleted()); } + +#[test] +fn change_count() { + let doc = LoroDoc::new(); + let n = 1024 * 5; + for i in 0..n { + doc.get_text("text").insert(0, "H").unwrap(); + doc.set_next_commit_message(&format!("{}", i)); + doc.commit(); + } + + doc.compact_change_store(); + assert_eq!(doc.len_changes(), n); + let bytes = doc.export(loro::ExportMode::Snapshot); + let new_doc = LoroDoc::new(); + new_doc.import(&bytes.unwrap()).unwrap(); + assert_eq!(new_doc.len_changes(), n); +}