Skip to content

Commit f2800b7

Browse files
authored
chore: observe row meta (#449)
* chore: observe row meta * chore: fmt
1 parent d788242 commit f2800b7

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

collab/src/database/rows/row.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::database::database::timestamp;
1919

2020
use crate::database::rows::{
2121
Cell, Cells, CellsUpdate, RowChangeSender, RowMeta, RowMetaUpdate, subscribe_row_data_change,
22+
subscribe_row_meta_change,
2223
};
2324
use crate::error::CollabError;
2425

@@ -83,7 +84,9 @@ impl DatabaseRow {
8384
let body = DatabaseRowBody::open(row_id, &mut collab)?;
8485
if let Some(change_tx) = change_tx {
8586
let origin = collab.origin().clone();
86-
subscribe_row_data_change(origin, row_id, &body.data, change_tx);
87+
let meta_change_tx = change_tx.clone();
88+
subscribe_row_data_change(origin.clone(), row_id, &body.data, change_tx);
89+
subscribe_row_meta_change(origin, row_id, &body.meta, meta_change_tx);
8790
}
8891
Ok(Self {
8992
row_id,
@@ -101,7 +104,9 @@ impl DatabaseRow {
101104
let body = DatabaseRowBody::create(row_id, &mut collab, row);
102105
if let Some(change_tx) = change_tx {
103106
let origin = collab.origin().clone();
104-
subscribe_row_data_change(origin, row_id, &body.data, change_tx);
107+
let meta_change_tx = change_tx.clone();
108+
subscribe_row_data_change(origin.clone(), row_id, &body.data, change_tx);
109+
subscribe_row_meta_change(origin, row_id, &body.meta, meta_change_tx);
105110
}
106111
Self {
107112
row_id,

collab/src/database/rows/row_observer.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::core::origin::CollabOrigin;
2-
use crate::database::rows::{Cell, ROW_CELLS, ROW_HEIGHT, ROW_VISIBILITY, Row};
2+
use crate::database::rows::{
3+
Cell, ROW_CELLS, ROW_HEIGHT, ROW_VISIBILITY, Row, RowMetaKey, meta_id_from_row_id,
4+
};
35
use crate::entity::uuid_validation::RowId;
46

57
use crate::preclude::{DeepObservable, EntryChange, Event, MapRef, TransactionMut};
@@ -32,6 +34,10 @@ pub enum RowChange {
3234
value: Cell,
3335
is_local_change: bool,
3436
},
37+
DidUpdateRowMeta {
38+
row_id: RowId,
39+
is_local_change: bool,
40+
},
3541
DidUpdateRowComment {
3642
row: Row,
3743
is_local_change: bool,
@@ -63,6 +69,38 @@ pub(crate) fn subscribe_row_data_change(
6369
});
6470
}
6571

72+
pub(crate) fn subscribe_row_meta_change(
73+
origin: CollabOrigin,
74+
row_id: RowId,
75+
row_meta_map: &MapRef,
76+
change_tx: RowChangeSender,
77+
) {
78+
let is_document_empty_key = meta_id_from_row_id(&row_id, RowMetaKey::IsDocumentEmpty);
79+
row_meta_map.observe_deep_with("meta-change", move |txn, events| {
80+
let txn_origin = CollabOrigin::from(txn);
81+
let is_local_change = txn_origin == origin;
82+
for event in events.iter() {
83+
if let Event::Map(map_event) = event {
84+
for (key, entry_change) in map_event.keys(txn).iter() {
85+
if key.deref() != is_document_empty_key {
86+
continue;
87+
}
88+
if matches!(
89+
entry_change,
90+
EntryChange::Inserted(_) | EntryChange::Updated(_, _) | EntryChange::Removed(_)
91+
) {
92+
let _ = change_tx.send(RowChange::DidUpdateRowMeta {
93+
row_id,
94+
is_local_change,
95+
});
96+
break;
97+
}
98+
}
99+
}
100+
}
101+
});
102+
}
103+
66104
fn handle_map_event(
67105
row_id: &RowId,
68106
change_tx: &RowChangeSender,
@@ -477,4 +515,38 @@ mod tests {
477515
other => panic!("unexpected row change: {:?}", other),
478516
}
479517
}
518+
519+
#[tokio::test]
520+
async fn row_observer_emits_row_meta_changes() {
521+
let doc = Doc::new();
522+
let row_meta_map: MapRef = doc.get_or_insert_map("row_meta");
523+
let row_id = Uuid::new_v4();
524+
let (origin, _) = local_and_remote_origins();
525+
526+
let (change_tx, mut change_rx) = broadcast::channel(256);
527+
subscribe_row_meta_change(origin.clone(), row_id, &row_meta_map, change_tx);
528+
529+
let is_document_empty_key = meta_id_from_row_id(&row_id, RowMetaKey::IsDocumentEmpty);
530+
{
531+
let mut txn = doc.transact_mut_with(origin.clone());
532+
row_meta_map.insert(&mut txn, is_document_empty_key, false);
533+
}
534+
535+
let change = loop {
536+
let change = recv_with_timeout(&mut change_rx).await;
537+
if matches!(change, RowChange::DidUpdateRowMeta { .. }) {
538+
break change;
539+
}
540+
};
541+
match change {
542+
RowChange::DidUpdateRowMeta {
543+
row_id: changed_row_id,
544+
is_local_change,
545+
} => {
546+
assert_eq!(changed_row_id, row_id);
547+
assert!(is_local_change);
548+
},
549+
other => panic!("unexpected row change: {:?}", other),
550+
}
551+
}
480552
}

0 commit comments

Comments
 (0)