lib.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #![allow(unused_doc_comments)]
  2. use std::sync::Weak;
  3. use std::time::Duration;
  4. use std::{fmt, sync::Arc};
  5. use tokio::sync::RwLock;
  6. use collab_integrate::collab_builder::{AppFlowyCollabBuilder, CollabSource};
  7. use flowy_database2::DatabaseManager;
  8. use flowy_document2::manager::DocumentManager;
  9. use flowy_folder2::manager::FolderManager;
  10. use flowy_sqlite::kv::StorePreferences;
  11. use flowy_storage::FileStorageService;
  12. use flowy_task::{TaskDispatcher, TaskRunner};
  13. use flowy_user::event_map::UserCloudServiceProvider;
  14. use flowy_user::manager::{UserManager, UserSessionConfig};
  15. use lib_dispatch::prelude::*;
  16. use lib_dispatch::runtime::tokio_default_runtime;
  17. use module::make_plugins;
  18. pub use module::*;
  19. use crate::deps_resolve::*;
  20. use crate::integrate::collab_interact::CollabInteractImpl;
  21. use crate::integrate::log::{create_log_filter, init_log};
  22. use crate::integrate::server::{current_server_provider, ServerProvider, ServerType};
  23. use crate::integrate::user::UserStatusCallbackImpl;
  24. mod deps_resolve;
  25. mod integrate;
  26. pub mod module;
  27. /// This name will be used as to identify the current [AppFlowyCore] instance.
  28. /// Don't change this.
  29. pub const DEFAULT_NAME: &str = "appflowy";
  30. #[derive(Clone)]
  31. pub struct AppFlowyCoreConfig {
  32. /// Different `AppFlowyCoreConfig` instance should have different name
  33. name: String,
  34. /// Panics if the `root` path is not existing
  35. pub storage_path: String,
  36. log_filter: String,
  37. }
  38. impl fmt::Debug for AppFlowyCoreConfig {
  39. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  40. f.debug_struct("AppFlowyCoreConfig")
  41. .field("storage_path", &self.storage_path)
  42. .finish()
  43. }
  44. }
  45. impl AppFlowyCoreConfig {
  46. pub fn new(root: &str, name: String) -> Self {
  47. AppFlowyCoreConfig {
  48. name,
  49. storage_path: root.to_owned(),
  50. log_filter: create_log_filter("info".to_owned(), vec![]),
  51. }
  52. }
  53. pub fn log_filter(mut self, level: &str, with_crates: Vec<String>) -> Self {
  54. self.log_filter = create_log_filter(level.to_owned(), with_crates);
  55. self
  56. }
  57. }
  58. #[derive(Clone)]
  59. pub struct AppFlowyCore {
  60. #[allow(dead_code)]
  61. pub config: AppFlowyCoreConfig,
  62. pub user_manager: Arc<UserManager>,
  63. pub document_manager: Arc<DocumentManager>,
  64. pub folder_manager: Arc<FolderManager>,
  65. pub database_manager: Arc<DatabaseManager>,
  66. pub event_dispatcher: Arc<AFPluginDispatcher>,
  67. pub server_provider: Arc<ServerProvider>,
  68. pub task_dispatcher: Arc<RwLock<TaskDispatcher>>,
  69. pub store_preference: Arc<StorePreferences>,
  70. }
  71. impl AppFlowyCore {
  72. pub fn new(config: AppFlowyCoreConfig) -> Self {
  73. /// The profiling can be used to tracing the performance of the application.
  74. /// Check out the [Link](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/backend/profiling)
  75. /// for more information.
  76. #[cfg(feature = "profiling")]
  77. console_subscriber::init();
  78. // Init the logger before anything else
  79. init_log(&config);
  80. // Init the key value database
  81. let store_preference = Arc::new(StorePreferences::new(&config.storage_path).unwrap());
  82. tracing::info!("🔥 {:?}", &config);
  83. let runtime = tokio_default_runtime().unwrap();
  84. let task_scheduler = TaskDispatcher::new(Duration::from_secs(2));
  85. let task_dispatcher = Arc::new(RwLock::new(task_scheduler));
  86. runtime.spawn(TaskRunner::run(task_dispatcher.clone()));
  87. let provider_type = current_server_provider(&store_preference);
  88. let server_provider = Arc::new(ServerProvider::new(
  89. config.clone(),
  90. provider_type,
  91. Arc::downgrade(&store_preference),
  92. ));
  93. let (
  94. user_manager,
  95. folder_manager,
  96. server_provider,
  97. database_manager,
  98. document_manager,
  99. collab_builder,
  100. ) = runtime.block_on(async {
  101. /// The shared collab builder is used to build the [Collab] instance. The plugins will be loaded
  102. /// on demand based on the [CollabPluginConfig].
  103. let collab_builder = Arc::new(AppFlowyCollabBuilder::new(server_provider.clone()));
  104. let user_manager = init_user_manager(
  105. &config,
  106. &store_preference,
  107. server_provider.clone(),
  108. Arc::downgrade(&collab_builder),
  109. );
  110. collab_builder
  111. .set_snapshot_persistence(Arc::new(SnapshotDBImpl(Arc::downgrade(&user_manager))));
  112. let database_manager = DatabaseDepsResolver::resolve(
  113. Arc::downgrade(&user_manager),
  114. task_dispatcher.clone(),
  115. collab_builder.clone(),
  116. server_provider.clone(),
  117. )
  118. .await;
  119. let document_manager = DocumentDepsResolver::resolve(
  120. Arc::downgrade(&user_manager),
  121. &database_manager,
  122. collab_builder.clone(),
  123. server_provider.clone(),
  124. Arc::downgrade(&(server_provider.clone() as Arc<dyn FileStorageService>)),
  125. );
  126. let folder_manager = FolderDepsResolver::resolve(
  127. Arc::downgrade(&user_manager),
  128. &document_manager,
  129. &database_manager,
  130. collab_builder.clone(),
  131. server_provider.clone(),
  132. )
  133. .await;
  134. (
  135. user_manager,
  136. folder_manager,
  137. server_provider,
  138. database_manager,
  139. document_manager,
  140. collab_builder,
  141. )
  142. });
  143. let user_status_callback = UserStatusCallbackImpl {
  144. collab_builder,
  145. folder_manager: folder_manager.clone(),
  146. database_manager: database_manager.clone(),
  147. document_manager: document_manager.clone(),
  148. server_provider: server_provider.clone(),
  149. config: config.clone(),
  150. };
  151. let collab_interact_impl = CollabInteractImpl {
  152. database_manager: Arc::downgrade(&database_manager),
  153. document_manager: Arc::downgrade(&document_manager),
  154. };
  155. let cloned_user_session = Arc::downgrade(&user_manager);
  156. runtime.block_on(async move {
  157. if let Some(user_session) = cloned_user_session.upgrade() {
  158. user_session
  159. .init(user_status_callback, collab_interact_impl)
  160. .await;
  161. }
  162. });
  163. let event_dispatcher = Arc::new(AFPluginDispatcher::construct(runtime, || {
  164. make_plugins(
  165. Arc::downgrade(&folder_manager),
  166. Arc::downgrade(&database_manager),
  167. Arc::downgrade(&user_manager),
  168. Arc::downgrade(&document_manager),
  169. )
  170. }));
  171. Self {
  172. config,
  173. user_manager,
  174. document_manager,
  175. folder_manager,
  176. database_manager,
  177. event_dispatcher,
  178. server_provider,
  179. task_dispatcher,
  180. store_preference,
  181. }
  182. }
  183. /// Only expose the dispatcher in test
  184. pub fn dispatcher(&self) -> Arc<AFPluginDispatcher> {
  185. self.event_dispatcher.clone()
  186. }
  187. }
  188. fn init_user_manager(
  189. config: &AppFlowyCoreConfig,
  190. storage_preference: &Arc<StorePreferences>,
  191. user_cloud_service_provider: Arc<dyn UserCloudServiceProvider>,
  192. collab_builder: Weak<AppFlowyCollabBuilder>,
  193. ) -> Arc<UserManager> {
  194. let user_config = UserSessionConfig::new(&config.name, &config.storage_path);
  195. UserManager::new(
  196. user_config,
  197. user_cloud_service_provider,
  198. storage_preference.clone(),
  199. collab_builder,
  200. )
  201. }
  202. impl From<ServerType> for CollabSource {
  203. fn from(server_type: ServerType) -> Self {
  204. match server_type {
  205. ServerType::Local => CollabSource::Local,
  206. ServerType::AFCloud => CollabSource::AFCloud,
  207. ServerType::Supabase => CollabSource::Supabase,
  208. }
  209. }
  210. }