|
@@ -1,3 +1,4 @@
|
|
|
|
+use crate::services::retry::GetRowDataRetryAction;
|
|
use bytes::Bytes;
|
|
use bytes::Bytes;
|
|
use flowy_client_sync::client_database::{GridBlockRevisionChangeset, GridBlockRevisionPad};
|
|
use flowy_client_sync::client_database::{GridBlockRevisionChangeset, GridBlockRevisionPad};
|
|
use flowy_client_sync::make_operations_from_revisions;
|
|
use flowy_client_sync::make_operations_from_revisions;
|
|
@@ -8,11 +9,14 @@ use flowy_revision::{
|
|
use flowy_sqlite::ConnectionPool;
|
|
use flowy_sqlite::ConnectionPool;
|
|
use grid_model::{CellRevision, DatabaseBlockRevision, RowChangeset, RowRevision};
|
|
use grid_model::{CellRevision, DatabaseBlockRevision, RowChangeset, RowRevision};
|
|
use lib_infra::future::FutureResult;
|
|
use lib_infra::future::FutureResult;
|
|
|
|
+use lib_infra::retry::spawn_retry;
|
|
use lib_ot::core::EmptyAttributes;
|
|
use lib_ot::core::EmptyAttributes;
|
|
|
|
+use parking_lot::RwLock;
|
|
use revision_model::Revision;
|
|
use revision_model::Revision;
|
|
use std::borrow::Cow;
|
|
use std::borrow::Cow;
|
|
use std::sync::Arc;
|
|
use std::sync::Arc;
|
|
-use tokio::sync::RwLock;
|
|
|
|
|
|
+use std::time::Duration;
|
|
|
|
+// use tokio::sync::RwLock;
|
|
|
|
|
|
pub struct DatabaseBlockRevisionEditor {
|
|
pub struct DatabaseBlockRevisionEditor {
|
|
#[allow(dead_code)]
|
|
#[allow(dead_code)]
|
|
@@ -53,7 +57,7 @@ impl DatabaseBlockRevisionEditor {
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn duplicate_block(&self, duplicated_block_id: &str) -> DatabaseBlockRevision {
|
|
pub async fn duplicate_block(&self, duplicated_block_id: &str) -> DatabaseBlockRevision {
|
|
- self.pad.read().await.duplicate_data(duplicated_block_id).await
|
|
|
|
|
|
+ self.pad.read().duplicate_data(duplicated_block_id)
|
|
}
|
|
}
|
|
|
|
|
|
/// Create a row after the the with prev_row_id. If prev_row_id is None, the row will be appended to the list
|
|
/// Create a row after the the with prev_row_id. If prev_row_id is None, the row will be appended to the list
|
|
@@ -108,20 +112,30 @@ impl DatabaseBlockRevisionEditor {
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn index_of_row(&self, row_id: &str) -> Option<usize> {
|
|
pub async fn index_of_row(&self, row_id: &str) -> Option<usize> {
|
|
- self.pad.read().await.index_of_row(row_id)
|
|
|
|
|
|
+ self.pad.read().index_of_row(row_id)
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn number_of_rows(&self) -> i32 {
|
|
pub async fn number_of_rows(&self) -> i32 {
|
|
- self.pad.read().await.rows.len() as i32
|
|
|
|
|
|
+ self.pad.read().rows.len() as i32
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn get_row_rev(&self, row_id: &str) -> FlowyResult<Option<(usize, Arc<RowRevision>)>> {
|
|
pub async fn get_row_rev(&self, row_id: &str) -> FlowyResult<Option<(usize, Arc<RowRevision>)>> {
|
|
- if self.pad.try_read().is_err() {
|
|
|
|
- tracing::error!("Required grid block read lock failed");
|
|
|
|
- Ok(None)
|
|
|
|
|
|
+ let duration = Duration::from_millis(300);
|
|
|
|
+ if let Some(pad) = self.pad.try_read_for(duration) {
|
|
|
|
+ Ok(pad.get_row_rev(row_id))
|
|
} else {
|
|
} else {
|
|
- let row_rev = self.pad.read().await.get_row_rev(row_id);
|
|
|
|
- Ok(row_rev)
|
|
|
|
|
|
+ tracing::error!("Required grid block read lock failed, retrying");
|
|
|
|
+ let retry = GetRowDataRetryAction {
|
|
|
|
+ row_id: row_id.to_owned(),
|
|
|
|
+ pad: self.pad.clone(),
|
|
|
|
+ };
|
|
|
|
+ match spawn_retry(3, 300, retry).await {
|
|
|
|
+ Ok(value) => Ok(value),
|
|
|
|
+ Err(err) => {
|
|
|
|
+ tracing::error!("Read row revision failed with: {}", err);
|
|
|
|
+ Ok(None)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -129,7 +143,7 @@ impl DatabaseBlockRevisionEditor {
|
|
where
|
|
where
|
|
T: AsRef<str> + ToOwned + ?Sized,
|
|
T: AsRef<str> + ToOwned + ?Sized,
|
|
{
|
|
{
|
|
- let row_revs = self.pad.read().await.get_row_revs(row_ids)?;
|
|
|
|
|
|
+ let row_revs = self.pad.read().get_row_revs(row_ids)?;
|
|
Ok(row_revs)
|
|
Ok(row_revs)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -138,7 +152,7 @@ impl DatabaseBlockRevisionEditor {
|
|
field_id: &str,
|
|
field_id: &str,
|
|
row_ids: Option<Vec<Cow<'_, String>>>,
|
|
row_ids: Option<Vec<Cow<'_, String>>>,
|
|
) -> FlowyResult<Vec<CellRevision>> {
|
|
) -> FlowyResult<Vec<CellRevision>> {
|
|
- let cell_revs = self.pad.read().await.get_cell_revs(field_id, row_ids)?;
|
|
|
|
|
|
+ let cell_revs = self.pad.read().get_cell_revs(field_id, row_ids)?;
|
|
Ok(cell_revs)
|
|
Ok(cell_revs)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -146,11 +160,11 @@ impl DatabaseBlockRevisionEditor {
|
|
where
|
|
where
|
|
F: for<'a> FnOnce(&'a mut GridBlockRevisionPad) -> FlowyResult<Option<GridBlockRevisionChangeset>>,
|
|
F: for<'a> FnOnce(&'a mut GridBlockRevisionPad) -> FlowyResult<Option<GridBlockRevisionChangeset>>,
|
|
{
|
|
{
|
|
- let mut write_guard = self.pad.write().await;
|
|
|
|
- match f(&mut write_guard)? {
|
|
|
|
|
|
+ let changeset = f(&mut self.pad.write())?;
|
|
|
|
+ match changeset {
|
|
None => {}
|
|
None => {}
|
|
- Some(change) => {
|
|
|
|
- self.apply_change(change).await?;
|
|
|
|
|
|
+ Some(changeset) => {
|
|
|
|
+ self.apply_change(changeset).await?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
Ok(())
|