diff --git a/frontend/rust-lib/event-integration-test/src/document/document_event.rs b/frontend/rust-lib/event-integration-test/src/document/document_event.rs index 8595ac056b..fbd80349b9 100644 --- a/frontend/rust-lib/event-integration-test/src/document/document_event.rs +++ b/frontend/rust-lib/event-integration-test/src/document/document_event.rs @@ -49,6 +49,19 @@ impl DocumentEventTest { guard.encode_collab().unwrap() } + pub async fn get_encoded_collab(&self, doc_id: &str) -> EncodedCollabPB { + let core = &self.event_test; + let payload = OpenDocumentPayloadPB { + document_id: doc_id.to_string(), + }; + EventBuilder::new(core.clone()) + .event(DocumentEvent::GetDocEncodedCollab) + .payload(payload) + .async_send() + .await + .parse::() + } + pub async fn create_document(&self) -> ViewPB { let core = &self.event_test; let current_workspace = core.get_current_workspace().await; diff --git a/frontend/rust-lib/event-integration-test/src/document_event.rs b/frontend/rust-lib/event-integration-test/src/document_event.rs index 8374bc9de3..214cad4ca3 100644 --- a/frontend/rust-lib/event-integration-test/src/document_event.rs +++ b/frontend/rust-lib/event-integration-test/src/document_event.rs @@ -64,6 +64,7 @@ impl EventIntegrationTest { view } + pub async fn open_document(&self, doc_id: String) -> OpenDocumentData { let payload = OpenDocumentPayloadPB { document_id: doc_id.clone(), diff --git a/frontend/rust-lib/event-integration-test/tests/document/local_test/edit_test.rs b/frontend/rust-lib/event-integration-test/tests/document/local_test/edit_test.rs index cfcefeb506..199c1b43c2 100644 --- a/frontend/rust-lib/event-integration-test/tests/document/local_test/edit_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/document/local_test/edit_test.rs @@ -19,6 +19,16 @@ async fn get_document_event_test() { assert!(document_data.blocks.len() > 1); } +#[tokio::test] +async fn get_encoded_collab_event_test() { + let test = DocumentEventTest::new().await; + let view = test.create_document().await; + let doc_id = view.id.clone(); + let encoded_v1 = test.get_encoded_collab(&doc_id).await; + assert!(!encoded_v1.doc_state.is_empty()); + assert!(!encoded_v1.state_vector.is_empty()); +} + #[tokio::test] async fn apply_document_event_test() { let test = DocumentEventTest::new().await; diff --git a/frontend/rust-lib/flowy-document/src/entities.rs b/frontend/rust-lib/flowy-document/src/entities.rs index 079d07cb0a..406300e2a2 100644 --- a/frontend/rust-lib/flowy-document/src/entities.rs +++ b/frontend/rust-lib/flowy-document/src/entities.rs @@ -16,6 +16,14 @@ use validator::Validate; use crate::parse::{NotEmptyStr, NotEmptyVec}; +#[derive(Default, ProtoBuf)] +pub struct EncodedCollabPB { + #[pb(index = 1)] + pub state_vector: Vec, + #[pb(index = 2)] + pub doc_state: Vec, +} + #[derive(Default, ProtoBuf)] pub struct OpenDocumentPayloadPB { #[pb(index = 1)] diff --git a/frontend/rust-lib/flowy-document/src/event_handler.rs b/frontend/rust-lib/flowy-document/src/event_handler.rs index 2eabbf639a..580ba85587 100644 --- a/frontend/rust-lib/flowy-document/src/event_handler.rs +++ b/frontend/rust-lib/flowy-document/src/event_handler.rs @@ -33,6 +33,22 @@ fn upgrade_document( Ok(manager) } +// Handler for getting the document state +#[instrument(level = "debug", skip_all, err)] +pub(crate) async fn get_encode_collab_handler( + data: AFPluginData, + manager: AFPluginState>, +) -> DataResult { + let manager = upgrade_document(manager)?; + let params: OpenDocumentParams = data.into_inner().try_into()?; + let doc_id = params.document_id; + let state = manager.encode_collab(&doc_id).await?; + data_result_ok(EncodedCollabPB { + state_vector: Vec::from(state.state_vector), + doc_state: Vec::from(state.doc_state), + }) +} + // Handler for creating a new document pub(crate) async fn create_document_handler( data: AFPluginData, diff --git a/frontend/rust-lib/flowy-document/src/event_map.rs b/frontend/rust-lib/flowy-document/src/event_map.rs index 1e11db6356..a6ce6959d9 100644 --- a/frontend/rust-lib/flowy-document/src/event_map.rs +++ b/frontend/rust-lib/flowy-document/src/event_map.rs @@ -18,6 +18,10 @@ pub fn init(document_manager: Weak) -> AFPlugin { .event(DocumentEvent::CloseDocument, close_document_handler) .event(DocumentEvent::ApplyAction, apply_action_handler) .event(DocumentEvent::GetDocumentData, get_document_data_handler) + .event( + DocumentEvent::GetDocEncodedCollab, + get_encode_collab_handler, + ) .event( DocumentEvent::ConvertDataToDocument, convert_data_to_document, @@ -126,4 +130,7 @@ pub enum DocumentEvent { #[event(input = "UpdateDocumentAwarenessStatePB")] SetAwarenessState = 18, + + #[event(input = "OpenDocumentPayloadPB", output = "EncodedCollabPB")] + GetDocEncodedCollab = 19, } diff --git a/frontend/rust-lib/flowy-document/src/manager.rs b/frontend/rust-lib/flowy-document/src/manager.rs index 5511a61725..37f59755f2 100644 --- a/frontend/rust-lib/flowy-document/src/manager.rs +++ b/frontend/rust-lib/flowy-document/src/manager.rs @@ -12,6 +12,7 @@ use collab_document::document_awareness::DocumentAwarenessUser; use collab_document::document_data::default_document_data; use collab_entity::CollabType; use collab_plugins::CollabKVDB; +use collab_plugins::local_storage::kv::PersistenceError; use dashmap::DashMap; use lib_infra::util::timestamp; use tracing::trace; @@ -74,6 +75,19 @@ impl DocumentManager { } } + /// In order to support the requirement of automatically publishing sub-documents in publishing requirements, + /// we need to read binary data from disk instead of reading from the open document. + pub async fn encode_collab(&self, doc_id: &str) -> FlowyResult { + let doc_state = DataSource::Disk; + let uid = self.user_service.user_id()?; + let collab = self + .collab_for_document(uid, doc_id, doc_state, false) + .await?; + + let collab = collab.lock(); + collab.encode_collab_v1(|_| Ok::<(), PersistenceError>(())).map_err(internal_error) + } + pub async fn initialize(&self, _uid: i64) -> FlowyResult<()> { trace!("initialize document manager"); self.documents.clear();