fix: migrate cloud document when the document content is not sync to … (#4108)

* fix: migrate cloud document when the document content is not sync to local

* chore: clippy
This commit is contained in:
Nathan.fooo 2023-12-06 09:14:02 -08:00 committed by GitHub
parent 4837d7f7fe
commit d86431dfbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 118 additions and 83 deletions

View File

@ -131,7 +131,7 @@ async fn hide_group_event_test() {
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups.len(), 4);
assert_eq!(groups[0].is_visible, false);
assert!(!groups[0].is_visible);
}
#[tokio::test]

View File

@ -4,7 +4,7 @@ use flowy_core::DEFAULT_NAME;
use crate::util::unzip_history_user_db;
#[tokio::test]
async fn migrate_historical_empty_document_test() {
async fn collab_db_restore_test() {
let (cleaner, user_db_path) = unzip_history_user_db(
"./tests/user/migration_test/history_user_db",
"038_collab_db_corrupt_restore",

View File

@ -220,7 +220,7 @@ impl TryInto<CreateFieldParams> for CreateFieldPayloadPB {
CreateFieldPosition::Before => {
let field_id = self
.target_field_id
.ok_or_else(|| ErrorCode::InvalidParams)?;
.ok_or(ErrorCode::InvalidParams)?;
let field_id = NotEmptyStr::parse(field_id)
.map_err(|_| ErrorCode::InvalidParams)?
.0;
@ -229,7 +229,7 @@ impl TryInto<CreateFieldParams> for CreateFieldPayloadPB {
CreateFieldPosition::After => {
let field_id = self
.target_field_id
.ok_or_else(|| ErrorCode::InvalidParams)?;
.ok_or(ErrorCode::InvalidParams)?;
let field_id = NotEmptyStr::parse(field_id)
.map_err(|_| ErrorCode::InvalidParams)?
.0;
@ -564,7 +564,7 @@ pub enum FieldType {
impl Display for FieldType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let value: i64 = self.clone().into();
let value: i64 = (*self).into();
f.write_fmt(format_args!("{}", value))
}
}
@ -577,13 +577,13 @@ impl AsRef<FieldType> for FieldType {
impl From<&FieldType> for FieldType {
fn from(field_type: &FieldType) -> Self {
field_type.clone()
*field_type
}
}
impl FieldType {
pub fn value(&self) -> i64 {
self.clone().into()
(*self).into()
}
pub fn default_name(&self) -> String {
@ -666,7 +666,7 @@ impl From<FieldType> for i64 {
impl From<&FieldType> for i64 {
fn from(ty: &FieldType) -> Self {
i64::from(ty.clone())
i64::from(*ty)
}
}

View File

@ -47,7 +47,7 @@ impl std::convert::From<&Filter> for FilterPB {
Self {
id: filter.id.clone(),
field_id: filter.field_id.clone(),
field_type: filter.field_type.clone(),
field_type: filter.field_type,
data: bytes.to_vec(),
}
}

View File

@ -25,7 +25,7 @@ impl std::convert::From<&Sort> for SortPB {
Self {
id: sort.id.clone(),
field_id: sort.field_id.clone(),
field_type: sort.field_type.clone(),
field_type: sort.field_type,
condition: sort.condition.into(),
}
}

View File

@ -25,7 +25,7 @@ impl TypeCellData {
pub fn from_field_type(field_type: &FieldType) -> TypeCellData {
Self {
cell_str: "".to_string(),
field_type: field_type.clone(),
field_type: *field_type,
}
}

View File

@ -346,7 +346,7 @@ impl DatabaseEditor {
}
let old_field_type = FieldType::from(field.field_type);
let old_type_option = field.get_any_type_option(old_field_type.clone());
let old_type_option = field.get_any_type_option(old_field_type);
let new_type_option = field
.get_any_type_option(new_field_type)
.unwrap_or_else(|| default_type_option_data_from_type(new_field_type));
@ -464,7 +464,7 @@ impl DatabaseEditor {
field.map(|field| {
let field_type = FieldType::from(field.field_type);
let type_option = field
.get_any_type_option(field_type.clone())
.get_any_type_option(field_type)
.unwrap_or_else(|| default_type_option_data_from_type(&field_type));
(field, type_option_to_pb(type_option, &field_type))
})
@ -1265,7 +1265,7 @@ impl DatabaseViewOperation for DatabaseViewOperationImpl {
let (_, field) = self.database.lock().create_field_with_mut(
view_id,
name.to_string(),
field_type.clone().into(),
field_type.into(),
&OrderObjectPosition::default(),
|field| {
field

View File

@ -139,7 +139,7 @@ impl DatabaseLayoutDepsResolver {
Field::new(
field_id,
"Date".to_string(),
field_type.clone().into(),
field_type.into(),
false,
)
.with_type_option_data(field_type, default_date_type_option.into())
@ -152,7 +152,7 @@ impl DatabaseLayoutDepsResolver {
Field::new(
field_id,
"Status".to_string(),
field_type.clone().into(),
field_type.into(),
false,
)
.with_type_option_data(field_type, default_select_type_option.into())

View File

@ -118,7 +118,7 @@ pub(crate) async fn get_cell_for_row(
Some(RowSingleCellData {
row_id: row_cell.row_id.clone(),
field_id: field.id.clone(),
field_type: field_type.clone(),
field_type,
cell_data,
})
}
@ -143,7 +143,7 @@ pub(crate) async fn get_cells_for_field(
RowSingleCellData {
row_id: row_cell.row_id.clone(),
field_id: field.id.clone(),
field_type: field_type.clone(),
field_type,
cell_data,
}
})

View File

@ -12,7 +12,7 @@ impl FieldBuilder {
let mut field = Field::new(
gen_field_id(),
"".to_string(),
field_type.clone().into(),
field_type.into(),
false,
);
field.width = 150;

View File

@ -12,7 +12,7 @@ mod tests {
fn checkout_box_description_test() {
let type_option = CheckboxTypeOption::default();
let field_type = FieldType::Checkbox;
let field_rev = FieldBuilder::from_field_type(field_type.clone()).build();
let field_rev = FieldBuilder::from_field_type(field_type).build();
// the checkout value will be checked if the value is "1", "true" or "yes"
assert_checkbox(&type_option, "1", CHECK, &field_type, &field_rev);

View File

@ -12,7 +12,7 @@ mod tests {
fn number_type_option_input_test() {
let type_option = NumberTypeOption::default();
let field_type = FieldType::Number;
let field = FieldBuilder::from_field_type(field_type.clone()).build();
let field = FieldBuilder::from_field_type(field_type).build();
// Input is empty String
assert_number(&type_option, "", "", &field_type, &field);
@ -31,7 +31,7 @@ mod tests {
let field_type = FieldType::Number;
let mut type_option = NumberTypeOption::new();
type_option.format = NumberFormat::USD;
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
let field = FieldBuilder::new(field_type, type_option.clone()).build();
assert_number(&type_option, "", "", &field_type, &field);
assert_number(&type_option, "abc", "", &field_type, &field);
@ -49,7 +49,7 @@ mod tests {
let field_type = FieldType::Number;
let mut type_option = NumberTypeOption::new();
type_option.format = NumberFormat::USD;
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
let field = FieldBuilder::new(field_type, type_option.clone()).build();
assert_number(
&type_option,
@ -71,7 +71,7 @@ mod tests {
let field_type = FieldType::Number;
let mut type_option = NumberTypeOption::new();
type_option.format = NumberFormat::USD;
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
let field = FieldBuilder::new(field_type, type_option.clone()).build();
assert_number(&type_option, "€0.2", "$0.2", &field_type, &field);
assert_number(&type_option, "-€0.2", "-$0.2", &field_type, &field);
@ -85,7 +85,7 @@ mod tests {
let field_type = FieldType::Number;
let mut type_option = NumberTypeOption::new();
type_option.format = NumberFormat::EUR;
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
let field = FieldBuilder::new(field_type, type_option.clone()).build();
assert_number(&type_option, "0.2", "€0,2", &field_type, &field);
assert_number(&type_option, "1000", "€1.000", &field_type, &field);

View File

@ -12,7 +12,7 @@ mod tests {
#[test]
fn date_type_to_text_type() {
let field_type = FieldType::DateTime;
let field = FieldBuilder::new(field_type.clone(), DateTypeOption::test()).build();
let field = FieldBuilder::new(field_type, DateTypeOption::test()).build();
assert_eq!(
stringify_cell_data(
@ -77,7 +77,7 @@ mod tests {
options: vec![done_option.clone()],
disable_color: false,
};
let field = FieldBuilder::new(field_type.clone(), single_select).build();
let field = FieldBuilder::new(field_type, single_select).build();
assert_eq!(
stringify_cell_data(
@ -107,7 +107,7 @@ mod tests {
let france_option_id = france.id;
let argentina_option_id = argentina.id;
let field_rev = FieldBuilder::new(field_type.clone(), multi_select).build();
let field_rev = FieldBuilder::new(field_type, multi_select).build();
assert_eq!(
stringify_cell_data(

View File

@ -272,7 +272,7 @@ pub fn default_type_option_data_from_type(field_type: &FieldType) -> TypeOptionD
FieldType::Number => NumberTypeOption::default().into(),
FieldType::DateTime => DateTypeOption::default().into(),
FieldType::LastEditedTime | FieldType::CreatedTime => TimestampTypeOption {
field_type: field_type.clone(),
field_type: *field_type,
date_format: DateFormat::Friendly,
time_format: TimeFormat::TwelveHour,
include_time: true,

View File

@ -78,7 +78,7 @@ struct CellDataCacheKey(u64);
impl CellDataCacheKey {
pub fn new(field_rev: &Field, decoded_field_type: FieldType, cell: &Cell) -> Self {
let mut hasher = DefaultHasher::new();
if let Some(type_option_data) = field_rev.get_any_type_option(&decoded_field_type) {
if let Some(type_option_data) = field_rev.get_any_type_option(decoded_field_type) {
type_option_data.hash(&mut hasher);
}
hasher.write(field_rev.id.as_bytes());
@ -141,7 +141,7 @@ where
decoded_field_type: &FieldType,
field: &Field,
) -> FlowyResult<<Self as TypeOption>::CellData> {
let key = CellDataCacheKey::new(field, decoded_field_type.clone(), cell);
let key = CellDataCacheKey::new(field, *decoded_field_type, cell);
if let Some(cell_data_cache) = self.cell_data_cache.as_ref() {
let read_guard = cell_data_cache.read();
if let Some(cell_data) = read_guard.get(key.as_ref()).cloned() {

View File

@ -117,7 +117,7 @@ impl std::convert::From<&Filter> for FilterType {
Self {
filter_id: filter.id.clone(),
field_id: filter.field_id.clone(),
field_type: filter.field_type.clone(),
field_type: filter.field_type,
}
}
}
@ -127,7 +127,7 @@ impl std::convert::From<&FilterPB> for FilterType {
Self {
filter_id: filter.id.clone(),
field_id: filter.field_id.clone(),
field_type: filter.field_type.clone(),
field_type: filter.field_type,
}
}
}

View File

@ -147,7 +147,7 @@ fn default_field(field_str: String, is_primary: bool) -> Field {
Field::new(
gen_field_id(),
field_str,
field_type.clone().into(),
field_type.into(),
is_primary,
)
.with_type_option_data(field_type, type_option_data)

View File

@ -240,7 +240,7 @@ fn cmp_row(
fields: &[Arc<Field>],
cell_data_cache: &CellCache,
) -> Ordering {
let field_type = sort.field_type.clone();
let field_type = sort.field_type;
match fields
.iter()
.find(|field_rev| field_rev.id == sort.field_id)

View File

@ -109,7 +109,7 @@ impl From<&Sort> for SortType {
Self {
sort_id: data.id.clone(),
field_id: data.field_id.clone(),
field_type: data.field_type.clone(),
field_type: data.field_type,
}
}
}

View File

@ -147,7 +147,7 @@ impl DatabaseEditorTest {
pub fn get_multi_select_type_option(&self, field_id: &str) -> Vec<SelectOption> {
let field_type = FieldType::MultiSelect;
let field = self.get_field(field_id, field_type.clone());
let field = self.get_field(field_id, field_type);
let type_option = field
.get_type_option::<MultiSelectTypeOption>(field_type)
.unwrap();
@ -156,7 +156,7 @@ impl DatabaseEditorTest {
pub fn get_single_select_type_option(&self, field_id: &str) -> SingleSelectTypeOption {
let field_type = FieldType::SingleSelect;
let field = self.get_field(field_id, field_type.clone());
let field = self.get_field(field_id, field_type);
field
.get_type_option::<SingleSelectTypeOption>(field_type)
.unwrap()
@ -165,7 +165,7 @@ impl DatabaseEditorTest {
#[allow(dead_code)]
pub fn get_checklist_type_option(&self, field_id: &str) -> ChecklistTypeOption {
let field_type = FieldType::Checklist;
let field = self.get_field(field_id, field_type.clone());
let field = self.get_field(field_id, field_type);
field
.get_type_option::<ChecklistTypeOption>(field_type)
.unwrap()
@ -174,7 +174,7 @@ impl DatabaseEditorTest {
#[allow(dead_code)]
pub fn get_checkbox_type_option(&self, field_id: &str) -> CheckboxTypeOption {
let field_type = FieldType::Checkbox;
let field = self.get_field(field_id, field_type.clone());
let field = self.get_field(field_id, field_type);
field
.get_type_option::<CheckboxTypeOption>(field_type)
.unwrap()

View File

@ -1,5 +1,6 @@
use collab_database::fields::Field;
use collab_database::views::OrderObjectPosition;
use flowy_database2::entities::{CreateFieldParams, FieldType};
use flowy_database2::services::field::{
type_option_to_pb, DateCellChangeset, DateFormat, DateTypeOption, FieldBuilder,
@ -9,7 +10,7 @@ use flowy_database2::services::field::{
pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, Field) {
let field_type = FieldType::RichText;
let type_option = RichTextTypeOption::default();
let text_field = FieldBuilder::new(field_type.clone(), type_option.clone())
let text_field = FieldBuilder::new(field_type, type_option.clone())
.name("Name")
.visibility(true)
.primary(true)
@ -31,7 +32,7 @@ pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, Field) {
let mut type_option = SingleSelectTypeOption::default();
type_option.options.push(SelectOption::new("Done"));
type_option.options.push(SelectOption::new("Progress"));
let single_select_field = FieldBuilder::new(field_type.clone(), type_option.clone())
let single_select_field = FieldBuilder::new(field_type, type_option.clone())
.name("Name")
.visibility(true)
.build();
@ -76,17 +77,15 @@ pub fn create_timestamp_field(grid_id: &str, field_type: FieldType) -> (CreateFi
date_format: DateFormat::US,
time_format: TimeFormat::TwentyFourHour,
include_time: true,
field_type: field_type.clone(),
field_type,
};
let field: Field = match field_type {
FieldType::LastEditedTime => {
FieldBuilder::new(field_type.clone(), timestamp_type_option.clone())
.name("Updated At")
.visibility(true)
.build()
},
FieldType::CreatedTime => FieldBuilder::new(field_type.clone(), timestamp_type_option.clone())
FieldType::LastEditedTime => FieldBuilder::new(field_type, timestamp_type_option.clone())
.name("Updated At")
.visibility(true)
.build(),
FieldType::CreatedTime => FieldBuilder::new(field_type, timestamp_type_option.clone())
.name("Created At")
.visibility(true)
.build(),

View File

@ -1,7 +1,5 @@
use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData};
use collab_database::views::{DatabaseLayout, DatabaseView, LayoutSetting, LayoutSettings};
use flowy_database2::services::field_settings::default_field_settings_for_fields;
use flowy_database2::services::setting::BoardLayoutSetting;
use strum::IntoEnumIterator;
use flowy_database2::entities::FieldType;
@ -10,6 +8,8 @@ use flowy_database2::services::field::{
DateFormat, DateTypeOption, FieldBuilder, MultiSelectTypeOption, SelectOption, SelectOptionColor,
SingleSelectTypeOption, TimeFormat, TimestampTypeOption,
};
use flowy_database2::services::field_settings::default_field_settings_for_fields;
use flowy_database2::services::setting::BoardLayoutSetting;
use crate::database::database_editor::TestRowBuilder;
use crate::database::mock_data::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, PLANNED, TWITTER};
@ -22,7 +22,7 @@ pub fn make_test_board() -> DatabaseData {
for field_type in FieldType::iter() {
match field_type {
FieldType::RichText => {
let text_field = FieldBuilder::from_field_type(field_type.clone())
let text_field = FieldBuilder::from_field_type(field_type)
.name("Name")
.visibility(true)
.primary(true)
@ -31,7 +31,7 @@ pub fn make_test_board() -> DatabaseData {
},
FieldType::Number => {
// Number
let number_field = FieldBuilder::from_field_type(field_type.clone())
let number_field = FieldBuilder::from_field_type(field_type)
.name("Price")
.visibility(true)
.build();
@ -45,7 +45,7 @@ pub fn make_test_board() -> DatabaseData {
timezone_id: "Etc/UTC".to_owned(),
};
let name = "Time";
let date_field = FieldBuilder::new(field_type.clone(), date_type_option)
let date_field = FieldBuilder::new(field_type, date_type_option)
.name(name)
.visibility(true)
.build();
@ -57,14 +57,14 @@ pub fn make_test_board() -> DatabaseData {
date_format: DateFormat::US,
time_format: TimeFormat::TwentyFourHour,
include_time: true,
field_type: field_type.clone(),
field_type,
};
let name = match field_type {
FieldType::LastEditedTime => "Last Modified",
FieldType::CreatedTime => "Created At",
_ => "",
};
let date_field = FieldBuilder::new(field_type.clone(), date_type_option)
let date_field = FieldBuilder::new(field_type, date_type_option)
.name(name)
.visibility(true)
.build();
@ -79,7 +79,7 @@ pub fn make_test_board() -> DatabaseData {
single_select_type_option
.options
.extend(vec![option1, option2, option3]);
let single_select_field = FieldBuilder::new(field_type.clone(), single_select_type_option)
let single_select_field = FieldBuilder::new(field_type, single_select_type_option)
.name("Status")
.visibility(true)
.build();
@ -92,7 +92,7 @@ pub fn make_test_board() -> DatabaseData {
let option3 = SelectOption::with_color(TWITTER, SelectOptionColor::Yellow);
let mut type_option = MultiSelectTypeOption::default();
type_option.options.extend(vec![option1, option2, option3]);
let multi_select_field = FieldBuilder::new(field_type.clone(), type_option)
let multi_select_field = FieldBuilder::new(field_type, type_option)
.name("Platform")
.visibility(true)
.build();
@ -100,7 +100,7 @@ pub fn make_test_board() -> DatabaseData {
},
FieldType::Checkbox => {
// Checkbox
let checkbox_field = FieldBuilder::from_field_type(field_type.clone())
let checkbox_field = FieldBuilder::from_field_type(field_type)
.name("is urgent")
.visibility(true)
.build();
@ -108,7 +108,7 @@ pub fn make_test_board() -> DatabaseData {
},
FieldType::URL => {
// URL
let url = FieldBuilder::from_field_type(field_type.clone())
let url = FieldBuilder::from_field_type(field_type)
.name("link")
.visibility(true)
.build();
@ -120,7 +120,7 @@ pub fn make_test_board() -> DatabaseData {
// let option3 = SelectOption::with_color(THIRD_THING, SelectOptionColor::Yellow);
let type_option = ChecklistTypeOption::default();
// type_option.options.extend(vec![option1, option2, option3]);
let checklist_field = FieldBuilder::new(field_type.clone(), type_option)
let checklist_field = FieldBuilder::new(field_type, type_option)
.name("TODO")
.visibility(true)
.build();

View File

@ -1,6 +1,5 @@
use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData};
use collab_database::views::{DatabaseLayout, DatabaseView};
use flowy_database2::services::field_settings::default_field_settings_for_fields;
use strum::IntoEnumIterator;
use flowy_database2::entities::FieldType;
@ -9,6 +8,7 @@ use flowy_database2::services::field::{
DateFormat, DateTypeOption, FieldBuilder, MultiSelectTypeOption, NumberFormat, NumberTypeOption,
SelectOption, SelectOptionColor, SingleSelectTypeOption, TimeFormat, TimestampTypeOption,
};
use flowy_database2::services::field_settings::default_field_settings_for_fields;
use crate::database::database_editor::TestRowBuilder;
use crate::database::mock_data::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, PLANNED, TWITTER};
@ -21,7 +21,7 @@ pub fn make_test_grid() -> DatabaseData {
for field_type in FieldType::iter() {
match field_type {
FieldType::RichText => {
let text_field = FieldBuilder::from_field_type(field_type.clone())
let text_field = FieldBuilder::from_field_type(field_type)
.name("Name")
.visibility(true)
.primary(true)
@ -33,7 +33,7 @@ pub fn make_test_grid() -> DatabaseData {
let mut type_option = NumberTypeOption::default();
type_option.set_format(NumberFormat::USD);
let number_field = FieldBuilder::new(field_type.clone(), type_option)
let number_field = FieldBuilder::new(field_type, type_option)
.name("Price")
.visibility(true)
.build();
@ -47,7 +47,7 @@ pub fn make_test_grid() -> DatabaseData {
timezone_id: "Etc/UTC".to_owned(),
};
let name = "Time";
let date_field = FieldBuilder::new(field_type.clone(), date_type_option)
let date_field = FieldBuilder::new(field_type, date_type_option)
.name(name)
.visibility(true)
.build();
@ -59,14 +59,14 @@ pub fn make_test_grid() -> DatabaseData {
date_format: DateFormat::US,
time_format: TimeFormat::TwentyFourHour,
include_time: true,
field_type: field_type.clone(),
field_type,
};
let name = match field_type {
FieldType::LastEditedTime => "Last Modified",
FieldType::CreatedTime => "Created At",
_ => "",
};
let timestamp_field = FieldBuilder::new(field_type.clone(), timestamp_type_option)
let timestamp_field = FieldBuilder::new(field_type, timestamp_type_option)
.name(name)
.visibility(true)
.build();
@ -81,7 +81,7 @@ pub fn make_test_grid() -> DatabaseData {
single_select_type_option
.options
.extend(vec![option1, option2, option3]);
let single_select_field = FieldBuilder::new(field_type.clone(), single_select_type_option)
let single_select_field = FieldBuilder::new(field_type, single_select_type_option)
.name("Status")
.visibility(true)
.build();
@ -94,7 +94,7 @@ pub fn make_test_grid() -> DatabaseData {
let option3 = SelectOption::with_color(TWITTER, SelectOptionColor::Yellow);
let mut type_option = MultiSelectTypeOption::default();
type_option.options.extend(vec![option1, option2, option3]);
let multi_select_field = FieldBuilder::new(field_type.clone(), type_option)
let multi_select_field = FieldBuilder::new(field_type, type_option)
.name("Platform")
.visibility(true)
.build();
@ -102,7 +102,7 @@ pub fn make_test_grid() -> DatabaseData {
},
FieldType::Checkbox => {
// Checkbox
let checkbox_field = FieldBuilder::from_field_type(field_type.clone())
let checkbox_field = FieldBuilder::from_field_type(field_type)
.name("is urgent")
.visibility(true)
.build();
@ -110,7 +110,7 @@ pub fn make_test_grid() -> DatabaseData {
},
FieldType::URL => {
// URL
let url = FieldBuilder::from_field_type(field_type.clone())
let url = FieldBuilder::from_field_type(field_type)
.name("link")
.visibility(true)
.build();
@ -122,7 +122,7 @@ pub fn make_test_grid() -> DatabaseData {
// let option3 = SelectOption::with_color(THIRD_THING, SelectOptionColor::Yellow);
let type_option = ChecklistTypeOption::default();
// type_option.options.extend(vec![option1, option2, option3]);
let checklist_field = FieldBuilder::new(field_type.clone(), type_option)
let checklist_field = FieldBuilder::new(field_type, type_option)
.name("TODO")
.visibility(true)
.build();
@ -274,7 +274,7 @@ pub fn make_no_date_test_grid() -> DatabaseData {
for field_type in FieldType::iter() {
match field_type {
FieldType::RichText => {
let text_field = FieldBuilder::from_field_type(field_type.clone())
let text_field = FieldBuilder::from_field_type(field_type)
.name("Name")
.visibility(true)
.primary(true)
@ -286,7 +286,7 @@ pub fn make_no_date_test_grid() -> DatabaseData {
let mut type_option = NumberTypeOption::default();
type_option.set_format(NumberFormat::USD);
let number_field = FieldBuilder::new(field_type.clone(), type_option)
let number_field = FieldBuilder::new(field_type, type_option)
.name("Price")
.visibility(true)
.build();

View File

@ -234,7 +234,8 @@ impl UserManager {
Box::new(HistoricalEmptyDocumentMigration),
Box::new(FavoriteV1AndWorkspaceArrayMigration),
];
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool).run(migrations)
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool)
.run(migrations, &current_authenticator)
{
Ok(applied_migrations) => {
if !applied_migrations.is_empty() {

View File

@ -9,6 +9,7 @@ use tracing::{event, instrument};
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
use flowy_error::{internal_error, FlowyError, FlowyResult};
use flowy_user_deps::entities::Authenticator;
use crate::migrations::migration::UserDataMigration;
use crate::migrations::util::load_collab;
@ -23,7 +24,18 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
}
#[instrument(name = "HistoricalEmptyDocumentMigration", skip_all, err)]
fn run(&self, session: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()> {
fn run(
&self,
session: &Session,
collab_db: &Arc<RocksCollabDB>,
authenticator: &Authenticator,
) -> FlowyResult<()> {
// - The `empty document` struct has already undergone refactoring prior to the launch of the AppFlowy cloud version.
// - Consequently, if a user is utilizing the AppFlowy cloud version, there is no need to perform any migration for the `empty document` struct.
// - This migration step is only necessary for users who are transitioning from a local version of AppFlowy to the cloud version.
if !matches!(authenticator, Authenticator::Local) {
return Ok(());
}
let write_txn = collab_db.write_txn();
let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom"));
let folder_collab = match load_collab(session.user_id, &write_txn, &session.user_workspace.id) {
@ -37,7 +49,7 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
// For historical reasons, the first level documents are empty. So migrate them by inserting
// the default document data.
for view in migration_views {
if let Err(_) = migrate_empty_document(&write_txn, &origin, &view, session.user_id) {
if migrate_empty_document(&write_txn, &origin, &view, session.user_id).is_err() {
event!(
tracing::Level::ERROR,
"Failed to migrate document {}",
@ -46,7 +58,6 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
}
}
event!(tracing::Level::INFO, "Save all migrated documents");
write_txn.commit_transaction().map_err(internal_error)?;
Ok(())
}
@ -62,6 +73,7 @@ where
W: YrsDocAction<'a>,
PersistenceError: From<W::Error>,
{
// If the document is not exist, we don't need to migrate it.
if load_collab(user_id, write_txn, &view.id).is_err() {
let collab = Arc::new(MutexCollab::new(origin.clone(), &view.id, vec![]));
let document = Document::create_with_data(collab, default_document_data())?;

View File

@ -7,6 +7,7 @@ use collab_integrate::RocksCollabDB;
use flowy_error::FlowyResult;
use flowy_sqlite::schema::user_data_migration_records;
use flowy_sqlite::ConnectionPool;
use flowy_user_deps::entities::Authenticator;
use crate::services::entities::Session;
@ -42,7 +43,11 @@ impl UserLocalDataMigration {
///
/// * `migrations` - A vector of boxed dynamic `UserDataMigration` objects representing the migrations to be applied.
///
pub fn run(self, migrations: Vec<Box<dyn UserDataMigration>>) -> FlowyResult<Vec<String>> {
pub fn run(
self,
migrations: Vec<Box<dyn UserDataMigration>>,
authenticator: &Authenticator,
) -> FlowyResult<Vec<String>> {
let mut applied_migrations = vec![];
let conn = self.sqlite_pool.get()?;
let record = get_all_records(&conn)?;
@ -54,7 +59,7 @@ impl UserLocalDataMigration {
{
let migration_name = migration.name().to_string();
if !duplicated_names.contains(&migration_name) {
migration.run(&self.session, &self.collab_db)?;
migration.run(&self.session, &self.collab_db, authenticator)?;
applied_migrations.push(migration.name().to_string());
save_record(&conn, &migration_name);
duplicated_names.push(migration_name);
@ -70,7 +75,12 @@ impl UserLocalDataMigration {
pub trait UserDataMigration {
/// Migration with the same name will be skipped
fn name(&self) -> &str;
fn run(&self, user: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()>;
fn run(
&self,
user: &Session,
collab_db: &Arc<RocksCollabDB>,
authenticator: &Authenticator,
) -> FlowyResult<()>;
}
fn save_record(conn: &SqliteConnection, migration_name: &str) {

View File

@ -5,6 +5,7 @@ use tracing::instrument;
use collab_integrate::{RocksCollabDB, YrsDocAction};
use flowy_error::{internal_error, FlowyResult};
use flowy_user_deps::entities::Authenticator;
use crate::migrations::migration::UserDataMigration;
use crate::migrations::util::load_collab;
@ -21,7 +22,19 @@ impl UserDataMigration for FavoriteV1AndWorkspaceArrayMigration {
}
#[instrument(name = "FavoriteV1AndWorkspaceArrayMigration", skip_all, err)]
fn run(&self, session: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()> {
fn run(
&self,
session: &Session,
collab_db: &Arc<RocksCollabDB>,
authenticator: &Authenticator,
) -> FlowyResult<()> {
// Note on `favorite` Struct Refactoring and Migration:
// - The `favorite` struct has already undergone refactoring prior to the launch of the AppFlowy cloud version.
// - Consequently, if a user is utilizing the AppFlowy cloud version, there is no need to perform any migration for the `favorite` struct.
// - This migration step is only necessary for users who are transitioning from a local version of AppFlowy to the cloud version.
if !matches!(authenticator, Authenticator::Local) {
return Ok(());
}
let write_txn = collab_db.write_txn();
if let Ok(collab) = load_collab(session.user_id, &write_txn, &session.user_workspace.id) {
let folder = Folder::open(session.user_id, collab, None)?;