2022-10-22 13:57:44 +00:00
use crate ::editor ::{ initial_document_content , AppFlowyDocumentEditor , DocumentRevisionCompress } ;
use crate ::entities ::{ DocumentVersionPB , EditParams } ;
use crate ::old_editor ::editor ::{ DeltaDocumentEditor , DeltaDocumentRevisionCompress } ;
2022-11-01 10:59:53 +00:00
use crate ::services ::rev_sqlite ::{ SQLiteDeltaDocumentRevisionPersistence , SQLiteDocumentRevisionPersistence } ;
2022-10-22 13:57:44 +00:00
use crate ::services ::DocumentPersistence ;
2022-10-20 03:35:11 +00:00
use crate ::{ errors ::FlowyError , DocumentCloudService } ;
2021-11-09 08:00:09 +00:00
use bytes ::Bytes ;
2022-11-08 03:32:07 +00:00
2022-03-19 08:52:28 +00:00
use flowy_database ::ConnectionPool ;
use flowy_error ::FlowyResult ;
2022-11-08 13:13:28 +00:00
use flowy_http_model ::util ::md5 ;
use flowy_http_model ::{ document ::DocumentIdPB , revision ::Revision , ws_data ::ServerRevisionWSData } ;
2022-06-09 12:58:56 +00:00
use flowy_revision ::{
2022-11-06 01:59:53 +00:00
RevisionCloudService , RevisionManager , RevisionPersistence , RevisionPersistenceConfiguration , RevisionWebSocket ,
SQLiteRevisionSnapshotPersistence ,
2022-06-09 12:58:56 +00:00
} ;
2022-10-22 13:57:44 +00:00
use flowy_sync ::client_document ::initial_delta_document_content ;
2021-12-13 05:55:44 +00:00
use lib_infra ::future ::FutureResult ;
2022-11-08 03:32:07 +00:00
use lib_infra ::ref_map ::{ RefCountHashMap , RefCountValue } ;
2022-10-20 03:35:11 +00:00
use lib_ws ::WSConnectState ;
use std ::any ::Any ;
2022-01-14 12:52:03 +00:00
use std ::{ convert ::TryInto , sync ::Arc } ;
2022-11-08 03:32:07 +00:00
use tokio ::sync ::RwLock ;
2021-07-23 06:37:18 +00:00
2022-10-13 15:29:37 +00:00
pub trait DocumentUser : Send + Sync {
2022-01-22 10:48:43 +00:00
fn user_dir ( & self ) -> Result < String , FlowyError > ;
fn user_id ( & self ) -> Result < String , FlowyError > ;
fn token ( & self ) -> Result < String , FlowyError > ;
2022-10-22 13:57:44 +00:00
}
pub trait DocumentDatabase : Send + Sync {
2022-01-22 10:48:43 +00:00
fn db_pool ( & self ) -> Result < Arc < ConnectionPool > , FlowyError > ;
}
2022-10-20 03:35:11 +00:00
pub trait DocumentEditor : Send + Sync {
2022-10-22 13:57:44 +00:00
/// Called when the document get closed
2022-10-20 03:35:11 +00:00
fn close ( & self ) ;
2022-10-22 13:57:44 +00:00
/// Exports the document content. The content is encoded in the corresponding
/// editor data format.
fn export ( & self ) -> FutureResult < String , FlowyError > ;
/// Duplicate the document inner data into String
fn duplicate ( & self ) -> FutureResult < String , FlowyError > ;
2022-10-20 03:35:11 +00:00
fn receive_ws_data ( & self , data : ServerRevisionWSData ) -> FutureResult < ( ) , FlowyError > ;
2022-10-22 13:57:44 +00:00
2022-10-20 03:35:11 +00:00
fn receive_ws_state ( & self , state : & WSConnectState ) ;
2022-10-22 13:57:44 +00:00
/// Receives the local operations made by the user input. The operations are encoded
/// in binary format.
fn compose_local_operations ( & self , data : Bytes ) -> FutureResult < ( ) , FlowyError > ;
2022-10-20 03:35:11 +00:00
/// Returns the `Any` reference that can be used to downcast back to the original,
/// concrete type.
///
/// The indirection through `as_any` is because using `downcast_ref`
/// on `Box<A>` *directly* only lets us downcast back to `&A` again. You can take a look at [this](https://stackoverflow.com/questions/33687447/how-to-get-a-reference-to-a-concrete-type-from-a-trait-object)
/// for more information.
///
///
fn as_any ( & self ) -> & dyn Any ;
}
#[ derive(Clone, Debug) ]
pub struct DocumentConfig {
2022-10-22 13:57:44 +00:00
pub version : DocumentVersionPB ,
}
impl std ::default ::Default for DocumentConfig {
fn default ( ) -> Self {
Self {
version : DocumentVersionPB ::V1 ,
}
}
2022-10-20 03:35:11 +00:00
}
2022-10-13 15:29:37 +00:00
pub struct DocumentManager {
cloud_service : Arc < dyn DocumentCloudService > ,
2022-02-18 15:04:55 +00:00
rev_web_socket : Arc < dyn RevisionWebSocket > ,
2022-11-08 03:32:07 +00:00
editor_map : Arc < RwLock < RefCountHashMap < RefCountDocumentHandler > > > ,
2022-10-13 15:29:37 +00:00
user : Arc < dyn DocumentUser > ,
2022-10-22 13:57:44 +00:00
persistence : Arc < DocumentPersistence > ,
#[ allow(dead_code) ]
2022-10-20 03:35:11 +00:00
config : DocumentConfig ,
2021-07-23 06:37:18 +00:00
}
2022-10-13 15:29:37 +00:00
impl DocumentManager {
2022-01-14 12:52:03 +00:00
pub fn new (
2022-10-13 15:29:37 +00:00
cloud_service : Arc < dyn DocumentCloudService > ,
document_user : Arc < dyn DocumentUser > ,
2022-10-22 13:57:44 +00:00
database : Arc < dyn DocumentDatabase > ,
2022-02-18 15:04:55 +00:00
rev_web_socket : Arc < dyn RevisionWebSocket > ,
2022-10-20 03:35:11 +00:00
config : DocumentConfig ,
2021-12-25 13:44:45 +00:00
) -> Self {
2021-12-17 16:23:26 +00:00
Self {
2022-01-10 15:45:59 +00:00
cloud_service ,
2022-02-18 15:04:55 +00:00
rev_web_socket ,
2022-11-08 03:32:07 +00:00
editor_map : Arc ::new ( RwLock ::new ( RefCountHashMap ::new ( ) ) ) ,
2022-10-13 15:29:37 +00:00
user : document_user ,
2022-10-22 13:57:44 +00:00
persistence : Arc ::new ( DocumentPersistence ::new ( database ) ) ,
2022-10-20 03:35:11 +00:00
config ,
2021-12-17 16:23:26 +00:00
}
2021-07-23 06:37:18 +00:00
}
2022-10-22 13:57:44 +00:00
/// Called immediately after the application launched with the user sign in/sign up.
#[ tracing::instrument(level = " trace " , skip_all, err) ]
pub async fn initialize ( & self , user_id : & str ) -> FlowyResult < ( ) > {
let _ = self . persistence . initialize ( user_id ) ? ;
2022-03-10 09:14:10 +00:00
listen_ws_state_changed ( self . rev_web_socket . clone ( ) , self . editor_map . clone ( ) ) ;
2022-10-22 13:57:44 +00:00
Ok ( ( ) )
}
2021-12-25 13:44:45 +00:00
2022-10-22 13:57:44 +00:00
pub async fn initialize_with_new_user ( & self , _user_id : & str , _token : & str ) -> FlowyResult < ( ) > {
2021-10-05 06:37:45 +00:00
Ok ( ( ) )
}
2022-10-22 13:57:44 +00:00
#[ tracing::instrument(level = " trace " , skip_all, fields(document_id), err) ]
2022-10-20 03:35:11 +00:00
pub async fn open_document_editor < T : AsRef < str > > (
& self ,
2022-10-22 13:57:44 +00:00
document_id : T ,
2022-10-20 03:35:11 +00:00
) -> Result < Arc < dyn DocumentEditor > , FlowyError > {
2022-10-22 13:57:44 +00:00
let document_id = document_id . as_ref ( ) ;
tracing ::Span ::current ( ) . record ( " document_id " , & document_id ) ;
self . init_document_editor ( document_id ) . await
2021-09-09 07:43:05 +00:00
}
2022-09-13 12:23:56 +00:00
#[ tracing::instrument(level = " trace " , skip(self, editor_id), fields(editor_id), err) ]
2022-11-08 03:32:07 +00:00
pub async fn close_document_editor < T : AsRef < str > > ( & self , editor_id : T ) -> Result < ( ) , FlowyError > {
2022-09-13 12:23:56 +00:00
let editor_id = editor_id . as_ref ( ) ;
tracing ::Span ::current ( ) . record ( " editor_id " , & editor_id ) ;
2022-11-08 03:32:07 +00:00
self . editor_map . write ( ) . await . remove ( editor_id ) ;
2021-09-22 15:21:44 +00:00
Ok ( ( ) )
}
2022-09-13 12:23:56 +00:00
pub async fn apply_edit ( & self , params : EditParams ) -> FlowyResult < ( ) > {
2022-10-13 15:29:37 +00:00
let editor = self . get_document_editor ( & params . doc_id ) . await ? ;
2022-10-20 03:35:11 +00:00
let _ = editor . compose_local_operations ( Bytes ::from ( params . operations ) ) . await ? ;
2022-09-13 12:23:56 +00:00
Ok ( ( ) )
}
2022-11-02 02:21:10 +00:00
pub async fn create_document < T : AsRef < str > > ( & self , doc_id : T , revisions : Vec < Revision > ) -> FlowyResult < ( ) > {
2022-10-13 15:29:37 +00:00
let doc_id = doc_id . as_ref ( ) . to_owned ( ) ;
2022-10-22 13:57:44 +00:00
let db_pool = self . persistence . database . db_pool ( ) ? ;
2022-10-13 15:29:37 +00:00
// Maybe we could save the document to disk without creating the RevisionManager
2022-10-22 13:57:44 +00:00
let rev_manager = self . make_rev_manager ( & doc_id , db_pool ) ? ;
2022-01-14 07:23:21 +00:00
let _ = rev_manager . reset_object ( revisions ) . await ? ;
2022-01-01 06:23:58 +00:00
Ok ( ( ) )
}
2022-02-18 15:04:55 +00:00
pub async fn receive_ws_data ( & self , data : Bytes ) {
2022-01-20 15:51:11 +00:00
let result : Result < ServerRevisionWSData , protobuf ::ProtobufError > = data . try_into ( ) ;
match result {
2022-11-08 03:32:07 +00:00
Ok ( data ) = > match self . editor_map . read ( ) . await . get ( & data . object_id ) {
2022-01-21 13:41:24 +00:00
None = > tracing ::error! ( " Can't find any source handler for {:?}-{:?} " , data . object_id , data . ty ) ,
2022-11-08 03:32:07 +00:00
Some ( handler ) = > match handler . 0. receive_ws_data ( data ) . await {
2022-01-24 09:35:58 +00:00
Ok ( _ ) = > { }
2022-01-20 15:51:11 +00:00
Err ( e ) = > tracing ::error! ( " {} " , e ) ,
} ,
} ,
Err ( e ) = > {
tracing ::error! ( " Document ws data parser failed: {:?} " , e ) ;
2022-01-24 09:35:58 +00:00
}
2022-01-14 12:52:03 +00:00
}
}
2022-10-20 03:35:11 +00:00
pub fn initial_document_content ( & self ) -> String {
2022-10-22 13:57:44 +00:00
match self . config . version {
DocumentVersionPB ::V0 = > initial_delta_document_content ( ) ,
DocumentVersionPB ::V1 = > initial_document_content ( ) ,
2022-10-20 03:35:11 +00:00
}
}
2022-01-14 12:52:03 +00:00
}
2022-10-13 15:29:37 +00:00
impl DocumentManager {
/// Returns the `DocumentEditor`
///
/// # Arguments
///
/// * `doc_id`: the id of the document
///
/// returns: Result<Arc<DocumentEditor>, FlowyError>
///
2022-10-20 03:35:11 +00:00
async fn get_document_editor ( & self , doc_id : & str ) -> FlowyResult < Arc < dyn DocumentEditor > > {
2022-11-08 03:32:07 +00:00
match self . editor_map . read ( ) . await . get ( doc_id ) {
2022-10-22 13:57:44 +00:00
None = > {
//
tracing ::warn! ( " Should call init_document_editor first " ) ;
self . init_document_editor ( doc_id ) . await
}
2022-11-08 03:32:07 +00:00
Some ( handler ) = > Ok ( handler . 0. clone ( ) ) ,
2022-01-01 06:23:58 +00:00
}
}
2021-07-23 06:37:18 +00:00
2022-10-13 15:29:37 +00:00
/// Initializes a document editor with the doc_id
///
/// # Arguments
///
/// * `doc_id`: the id of the document
2022-11-07 07:27:31 +00:00
/// * `pool`: sqlite connection pool
2022-10-13 15:29:37 +00:00
///
/// returns: Result<Arc<DocumentEditor>, FlowyError>
///
2022-10-20 03:35:11 +00:00
#[ tracing::instrument(level = " trace " , skip(self), err) ]
pub async fn init_document_editor ( & self , doc_id : & str ) -> Result < Arc < dyn DocumentEditor > , FlowyError > {
2022-10-22 13:57:44 +00:00
let pool = self . persistence . database . db_pool ( ) ? ;
2022-03-10 09:14:10 +00:00
let user = self . user . clone ( ) ;
let token = self . user . token ( ) ? ;
2022-10-13 15:29:37 +00:00
let cloud_service = Arc ::new ( DocumentRevisionCloudService {
2021-12-17 16:23:26 +00:00
token ,
2022-01-10 15:45:59 +00:00
server : self . cloud_service . clone ( ) ,
2021-12-17 16:23:26 +00:00
} ) ;
2022-10-20 03:35:11 +00:00
2022-10-22 13:57:44 +00:00
match self . config . version {
DocumentVersionPB ::V0 = > {
let rev_manager = self . make_delta_document_rev_manager ( doc_id , pool . clone ( ) ) ? ;
let editor : Arc < dyn DocumentEditor > = Arc ::new (
DeltaDocumentEditor ::new ( doc_id , user , rev_manager , self . rev_web_socket . clone ( ) , cloud_service )
. await ? ,
) ;
2022-11-08 03:32:07 +00:00
self . editor_map
. write ( )
. await
. insert ( doc_id . to_string ( ) , RefCountDocumentHandler ( editor . clone ( ) ) ) ;
2022-10-22 13:57:44 +00:00
Ok ( editor )
}
DocumentVersionPB ::V1 = > {
let rev_manager = self . make_document_rev_manager ( doc_id , pool . clone ( ) ) ? ;
let editor : Arc < dyn DocumentEditor > =
Arc ::new ( AppFlowyDocumentEditor ::new ( doc_id , user , rev_manager , cloud_service ) . await ? ) ;
2022-11-08 03:32:07 +00:00
self . editor_map
. write ( )
. await
. insert ( doc_id . to_string ( ) , RefCountDocumentHandler ( editor . clone ( ) ) ) ;
2022-10-22 13:57:44 +00:00
Ok ( editor )
}
}
}
2022-11-01 10:59:53 +00:00
fn make_rev_manager (
& self ,
doc_id : & str ,
pool : Arc < ConnectionPool > ,
) -> Result < RevisionManager < Arc < ConnectionPool > > , FlowyError > {
2022-10-22 13:57:44 +00:00
match self . config . version {
DocumentVersionPB ::V0 = > self . make_delta_document_rev_manager ( doc_id , pool ) ,
DocumentVersionPB ::V1 = > self . make_document_rev_manager ( doc_id , pool ) ,
}
2021-12-08 13:51:06 +00:00
}
2022-10-13 15:29:37 +00:00
fn make_document_rev_manager (
2022-09-13 12:23:56 +00:00
& self ,
doc_id : & str ,
pool : Arc < ConnectionPool > ,
2022-11-01 10:59:53 +00:00
) -> Result < RevisionManager < Arc < ConnectionPool > > , FlowyError > {
2022-03-10 09:14:10 +00:00
let user_id = self . user . user_id ( ) ? ;
2022-10-13 15:29:37 +00:00
let disk_cache = SQLiteDocumentRevisionPersistence ::new ( & user_id , pool . clone ( ) ) ;
2022-11-08 03:32:07 +00:00
let configuration = RevisionPersistenceConfiguration ::new ( 100 , true ) ;
2022-11-06 01:59:53 +00:00
let rev_persistence = RevisionPersistence ::new ( & user_id , doc_id , disk_cache , configuration ) ;
2022-07-20 06:07:54 +00:00
// let history_persistence = SQLiteRevisionHistoryPersistence::new(doc_id, pool.clone());
2022-06-10 14:27:19 +00:00
let snapshot_persistence = SQLiteRevisionSnapshotPersistence ::new ( doc_id , pool ) ;
2022-10-22 13:57:44 +00:00
Ok ( RevisionManager ::new (
& user_id ,
doc_id ,
rev_persistence ,
DocumentRevisionCompress ( ) ,
// history_persistence,
snapshot_persistence ,
) )
}
2022-06-09 12:58:56 +00:00
2022-10-22 13:57:44 +00:00
fn make_delta_document_rev_manager (
& self ,
doc_id : & str ,
pool : Arc < ConnectionPool > ,
2022-11-01 10:59:53 +00:00
) -> Result < RevisionManager < Arc < ConnectionPool > > , FlowyError > {
2022-10-22 13:57:44 +00:00
let user_id = self . user . user_id ( ) ? ;
let disk_cache = SQLiteDeltaDocumentRevisionPersistence ::new ( & user_id , pool . clone ( ) ) ;
2022-11-08 03:32:07 +00:00
let configuration = RevisionPersistenceConfiguration ::new ( 100 , true ) ;
2022-11-06 01:59:53 +00:00
let rev_persistence = RevisionPersistence ::new ( & user_id , doc_id , disk_cache , configuration ) ;
2022-10-22 13:57:44 +00:00
// let history_persistence = SQLiteRevisionHistoryPersistence::new(doc_id, pool.clone());
let snapshot_persistence = SQLiteRevisionSnapshotPersistence ::new ( doc_id , pool ) ;
2022-06-09 12:58:56 +00:00
Ok ( RevisionManager ::new (
& user_id ,
doc_id ,
rev_persistence ,
2022-10-22 13:57:44 +00:00
DeltaDocumentRevisionCompress ( ) ,
2022-07-20 06:07:54 +00:00
// history_persistence,
2022-06-10 14:27:19 +00:00
snapshot_persistence ,
2022-06-09 12:58:56 +00:00
) )
2021-07-23 06:37:18 +00:00
}
2021-09-21 07:07:07 +00:00
}
2021-09-26 08:39:57 +00:00
2022-10-13 15:29:37 +00:00
struct DocumentRevisionCloudService {
2021-10-02 09:19:54 +00:00
token : String ,
2022-10-13 15:29:37 +00:00
server : Arc < dyn DocumentCloudService > ,
2021-10-02 09:19:54 +00:00
}
2022-10-13 15:29:37 +00:00
impl RevisionCloudService for DocumentRevisionCloudService {
2022-01-23 14:33:47 +00:00
#[ tracing::instrument(level = " trace " , skip(self)) ]
2022-02-24 12:36:24 +00:00
fn fetch_object ( & self , user_id : & str , object_id : & str ) -> FutureResult < Vec < Revision > , FlowyError > {
2022-10-13 15:29:37 +00:00
let params : DocumentIdPB = object_id . to_string ( ) . into ( ) ;
2021-10-02 09:19:54 +00:00
let server = self . server . clone ( ) ;
let token = self . token . clone ( ) ;
2021-12-13 05:55:44 +00:00
FutureResult ::new ( async move {
2022-10-13 15:29:37 +00:00
match server . fetch_document ( & token , params ) . await ? {
2021-12-14 10:04:51 +00:00
None = > Err ( FlowyError ::record_not_found ( ) . context ( " Remote doesn't have this document " ) ) ,
2022-10-13 15:29:37 +00:00
Some ( payload ) = > {
2022-11-08 13:13:28 +00:00
let bytes = Bytes ::from ( payload . data . clone ( ) ) ;
2022-10-13 15:29:37 +00:00
let doc_md5 = md5 ( & bytes ) ;
2022-11-02 09:15:27 +00:00
let revision = Revision ::new ( & payload . doc_id , payload . base_rev_id , payload . rev_id , bytes , doc_md5 ) ;
2022-01-14 07:23:21 +00:00
Ok ( vec! [ revision ] )
2022-01-24 09:35:58 +00:00
}
2021-10-02 09:19:54 +00:00
}
} )
}
}
2022-11-08 03:32:07 +00:00
#[ derive(Clone) ]
struct RefCountDocumentHandler ( Arc < dyn DocumentEditor > ) ;
2021-12-10 03:05:23 +00:00
2022-11-08 03:32:07 +00:00
impl RefCountValue for RefCountDocumentHandler {
fn did_remove ( & self ) {
self . 0. close ( ) ;
2021-12-10 03:05:23 +00:00
}
2022-11-08 03:32:07 +00:00
}
2021-12-10 03:05:23 +00:00
2022-11-08 03:32:07 +00:00
impl std ::ops ::Deref for RefCountDocumentHandler {
type Target = Arc < dyn DocumentEditor > ;
2021-12-10 03:05:23 +00:00
2022-11-08 03:32:07 +00:00
fn deref ( & self ) -> & Self ::Target {
& self . 0
2021-12-10 03:05:23 +00:00
}
2021-09-26 08:39:57 +00:00
}
2021-12-10 03:05:23 +00:00
2022-02-25 14:27:44 +00:00
#[ tracing::instrument(level = " trace " , skip(web_socket, handlers)) ]
2022-11-08 03:32:07 +00:00
fn listen_ws_state_changed (
web_socket : Arc < dyn RevisionWebSocket > ,
handlers : Arc < RwLock < RefCountHashMap < RefCountDocumentHandler > > > ,
) {
2021-12-25 13:44:45 +00:00
tokio ::spawn ( async move {
2022-01-24 08:27:40 +00:00
let mut notify = web_socket . subscribe_state_changed ( ) . await ;
while let Ok ( state ) = notify . recv ( ) . await {
2022-11-08 03:32:07 +00:00
handlers . read ( ) . await . values ( ) . iter ( ) . for_each ( | handler | {
2022-02-25 14:27:44 +00:00
handler . receive_ws_state ( & state ) ;
} )
2021-12-25 13:44:45 +00:00
}
} ) ;
}