view_controller.rs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. use crate::{
  2. entities::view::{CreateViewParams, UpdateViewParams, View},
  3. errors::WorkspaceError,
  4. module::WorkspaceDatabase,
  5. observable::notify,
  6. services::{helper::spawn, server::Server},
  7. sql_tables::view::{ViewTable, ViewTableChangeset, ViewTableSql},
  8. };
  9. use crate::{
  10. entities::view::{DeleteViewParams, QueryViewParams, RepeatedView},
  11. module::WorkspaceUser,
  12. observable::WorkspaceObservable,
  13. };
  14. use flowy_database::SqliteConnection;
  15. use flowy_document::{
  16. entities::doc::{CreateDocParams, Doc, DocChangeset, QueryDocParams},
  17. module::FlowyDocument,
  18. };
  19. use std::sync::Arc;
  20. pub(crate) struct ViewController {
  21. user: Arc<dyn WorkspaceUser>,
  22. sql: Arc<ViewTableSql>,
  23. server: Server,
  24. database: Arc<dyn WorkspaceDatabase>,
  25. document: Arc<FlowyDocument>,
  26. }
  27. impl ViewController {
  28. pub(crate) fn new(
  29. user: Arc<dyn WorkspaceUser>,
  30. database: Arc<dyn WorkspaceDatabase>,
  31. server: Server,
  32. document: Arc<FlowyDocument>,
  33. ) -> Self {
  34. let sql = Arc::new(ViewTableSql {});
  35. Self {
  36. user,
  37. sql,
  38. server,
  39. database,
  40. document,
  41. }
  42. }
  43. pub(crate) async fn create_view(&self, params: CreateViewParams) -> Result<View, WorkspaceError> {
  44. let view = self.create_view_on_server(params.clone()).await?;
  45. let conn = &*self.database.db_connection()?;
  46. // TODO: rollback anything created before if failed?
  47. conn.immediate_transaction::<_, WorkspaceError, _>(|| {
  48. let _ = self.save_view(view.clone(), conn)?;
  49. self.document.create(CreateDocParams::new(&view.id, params.data), conn)?;
  50. let repeated_view = self.read_local_views_belong_to(&view.belong_to_id, conn)?;
  51. notify(&view.belong_to_id, WorkspaceObservable::AppCreateView)
  52. .payload(repeated_view)
  53. .send();
  54. Ok(())
  55. })?;
  56. Ok(view)
  57. }
  58. pub(crate) fn save_view(&self, view: View, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
  59. let view_table = ViewTable::new(view);
  60. let _ = self.sql.create_view(view_table, conn)?;
  61. Ok(())
  62. }
  63. pub(crate) async fn read_view(&self, params: QueryViewParams) -> Result<View, WorkspaceError> {
  64. let conn = self.database.db_connection()?;
  65. let view_table = self.sql.read_view(&params.view_id, Some(params.is_trash), &*conn)?;
  66. let view: View = view_table.into();
  67. let _ = self.read_view_on_server(params);
  68. Ok(view)
  69. }
  70. #[tracing::instrument(level = "debug", skip(self), err)]
  71. pub(crate) async fn open_view(&self, params: QueryDocParams) -> Result<Doc, WorkspaceError> {
  72. let doc = self.document.open(params, self.database.db_pool()?).await?;
  73. Ok(doc)
  74. }
  75. pub(crate) async fn delete_view(&self, params: DeleteViewParams) -> Result<(), WorkspaceError> {
  76. let conn = &*self.database.db_connection()?;
  77. let _ = self.delete_view_on_server(&params.view_id);
  78. conn.immediate_transaction::<_, WorkspaceError, _>(|| {
  79. let view_table = self.sql.delete_view(&params.view_id, conn)?;
  80. let _ = self.document.delete(params.into(), conn)?;
  81. let repeated_view = self.read_local_views_belong_to(&view_table.belong_to_id, conn)?;
  82. notify(&view_table.belong_to_id, WorkspaceObservable::AppDeleteView)
  83. .payload(repeated_view)
  84. .send();
  85. Ok(())
  86. })?;
  87. Ok(())
  88. }
  89. // belong_to_id will be the app_id or view_id.
  90. #[tracing::instrument(level = "debug", skip(self), err)]
  91. pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result<RepeatedView, WorkspaceError> {
  92. // TODO: read from server
  93. let conn = self.database.db_connection()?;
  94. let repeated_view = self.read_local_views_belong_to(belong_to_id, &*conn)?;
  95. Ok(repeated_view)
  96. }
  97. pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> {
  98. let conn = &*self.database.db_connection()?;
  99. let changeset = ViewTableChangeset::new(params.clone());
  100. let view_id = changeset.id.clone();
  101. conn.immediate_transaction::<_, WorkspaceError, _>(|| {
  102. let _ = self.sql.update_view(changeset, conn)?;
  103. let view: View = self.sql.read_view(&view_id, None, conn)?.into();
  104. notify(&view_id, WorkspaceObservable::ViewUpdated).payload(view).send();
  105. Ok(())
  106. })?;
  107. let _ = self.update_view_on_server(params);
  108. Ok(())
  109. }
  110. pub(crate) async fn apply_changeset(&self, params: DocChangeset) -> Result<Doc, WorkspaceError> {
  111. let pool = self.database.db_pool()?;
  112. let doc = self.document.apply_changeset(params, pool).await?;
  113. Ok(doc)
  114. }
  115. }
  116. impl ViewController {
  117. #[tracing::instrument(skip(self), err)]
  118. async fn create_view_on_server(&self, params: CreateViewParams) -> Result<View, WorkspaceError> {
  119. let token = self.user.token()?;
  120. let view = self.server.create_view(&token, params).await?;
  121. Ok(view)
  122. }
  123. #[tracing::instrument(skip(self), err)]
  124. fn update_view_on_server(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> {
  125. let token = self.user.token()?;
  126. let server = self.server.clone();
  127. spawn(async move {
  128. match server.update_view(&token, params).await {
  129. Ok(_) => {},
  130. Err(e) => {
  131. // TODO: retry?
  132. log::error!("Update view failed: {:?}", e);
  133. },
  134. }
  135. });
  136. Ok(())
  137. }
  138. #[tracing::instrument(skip(self), err)]
  139. fn delete_view_on_server(&self, view_id: &str) -> Result<(), WorkspaceError> {
  140. let token = self.user.token()?;
  141. let server = self.server.clone();
  142. let params = DeleteViewParams {
  143. view_id: view_id.to_string(),
  144. };
  145. spawn(async move {
  146. match server.delete_view(&token, params).await {
  147. Ok(_) => {},
  148. Err(e) => {
  149. // TODO: retry?
  150. log::error!("Delete view failed: {:?}", e);
  151. },
  152. }
  153. });
  154. Ok(())
  155. }
  156. #[tracing::instrument(skip(self), err)]
  157. fn read_view_on_server(&self, params: QueryViewParams) -> Result<(), WorkspaceError> {
  158. let token = self.user.token()?;
  159. let server = self.server.clone();
  160. spawn(async move {
  161. match server.read_view(&token, params).await {
  162. Ok(_) => {},
  163. Err(e) => {
  164. // TODO: retry?
  165. log::error!("Read view failed: {:?}", e);
  166. },
  167. }
  168. });
  169. Ok(())
  170. }
  171. // belong_to_id will be the app_id or view_id.
  172. fn read_local_views_belong_to(&self, belong_to_id: &str, conn: &SqliteConnection) -> Result<RepeatedView, WorkspaceError> {
  173. let views = self
  174. .sql
  175. .read_views_belong_to(belong_to_id, conn)?
  176. .into_iter()
  177. .map(|view_table| view_table.into())
  178. .collect::<Vec<View>>();
  179. Ok(RepeatedView { items: views })
  180. }
  181. }