[provider] More logs + fixed syncing bugs

This commit is contained in:
daladim 2021-03-28 19:42:07 +02:00
parent 479011755e
commit 9a23081cda
2 changed files with 50 additions and 8 deletions

View file

@ -68,6 +68,7 @@ where
let mut cal_local = cal_local.lock().unwrap();
// Step 1 - find the differences
log::debug!("* Finding the differences to sync...");
let mut local_del = HashSet::new();
let mut remote_del = HashSet::new();
let mut local_changes = HashSet::new();
@ -78,13 +79,15 @@ where
let remote_items = cal_remote.get_item_version_tags().await?;
let mut local_items_to_handle = cal_local.get_item_ids().await?;
for (id, remote_tag) in remote_items {
log::trace!("* Considering remote item {}...", id);
match cal_local.get_item_by_id(&id).await {
None => {
// This was created on the remote
log::debug!("* {} is a remote addition", id);
remote_additions.insert(id);
},
Some(local_item) => {
if local_items_to_handle.remove(&id) == true {
if local_items_to_handle.remove(&id) == false {
log::error!("Inconsistent state: missing task {} from the local tasks", id);
}
@ -96,24 +99,29 @@ where
SyncStatus::Synced(local_tag) => {
if &remote_tag != local_tag {
// This has been modified on the remote
log::debug!("* {} is a remote change", id);
remote_changes.insert(id);
}
},
SyncStatus::LocallyModified(local_tag) => {
if &remote_tag == local_tag {
// This has been changed locally
log::debug!("* {} is a local change", id);
local_changes.insert(id);
} else {
log::info!("Conflict: task {} has been modified in both sources. Using the remote version.", id);
log::debug!("* {} is considered a remote change", id);
remote_changes.insert(id);
}
},
SyncStatus::LocallyDeleted(local_tag) => {
if &remote_tag == local_tag {
// This has been locally deleted
log::debug!("* {} is a local deletion", id);
local_del.insert(id);
} else {
log::info!("Conflict: task {} has been locally deleted and remotely modified. Reverting to the remote version.", id);
log::debug!("* {} is a considered a remote change", id);
remote_changes.insert(id);
}
},
@ -124,6 +132,7 @@ where
// Also iterate on the local tasks that are not on the remote
for id in local_items_to_handle {
log::trace!("# Considering local item {}...", id);
let local_item = match cal_local.get_item_by_id(&id).await {
None => {
log::error!("Inconsistent state: missing task {} from the local tasks", id);
@ -134,33 +143,52 @@ where
match local_item.sync_status() {
SyncStatus::Synced(_) => {
// This item has been removed from the remote
log::debug!("# {} is a deletion from the server", id);
remote_del.insert(id);
},
SyncStatus::NotSynced => {
// This item has just been locally created
log::debug!("# {} has been locally created", id);
local_additions.insert(id);
},
variant @ _=> {
log::error!("Inconsistent state: unexpected variant {:?}", variant);
SyncStatus::LocallyDeleted(_) => {
// This item has been deleted from both sources
log::debug!("# {} has been deleted from both sources", id);
remote_del.insert(id);
},
SyncStatus::LocallyModified(_) => {
log::info!("Conflict: item {} has been deleted from the server and locally modified. Deleting the local copy", id);
remote_del.insert(id);
},
}
}
}
// Step 2 - commit changes
for id_del in local_del {
if let Err(err) = cal_remote.delete_item(&id_del).await {
log::debug!("> Pushing local deletion {} to the server", id_del);
match cal_remote.delete_item(&id_del).await {
Err(err) => {
log::warn!("Unable to delete remote item {}: {}", id_del, err);
},
Ok(()) => {
// Change the local copy from "marked to deletion" to "actually deleted"
if let Err(err) = cal_local.immediately_delete_item(&id_del).await {
log::error!("Unable to permanently delete local item {}: {}", id_del, err);
}
},
}
}
for id_del in remote_del {
log::debug!("> Applying remote deletion {} locally", id_del);
if let Err(err) = cal_local.immediately_delete_item(&id_del).await {
log::warn!("Unable to delete local item {}: {}", id_del, err);
}
}
for id_add in remote_additions {
log::debug!("> Applying remote addition {} locally", id_add);
match cal_remote.get_item_by_id(&id_add).await {
None => {
log::error!("Inconsistency: new item {} has vanished from the remote end", id_add);
@ -175,13 +203,14 @@ where
}
for id_change in remote_changes {
log::debug!("> Applying remote change {} locally", id_change);
match cal_remote.get_item_by_id(&id_change).await {
None => {
log::error!("Inconsistency: modified item {} has vanished from the remote end", id_change);
continue;
},
Some(item) => {
if let Err(err) = cal_local.delete_item(&id_change).await {
if let Err(err) = cal_local.immediately_delete_item(&id_change).await {
log::error!("Unable to delete item {} from local calendar: {}", id_change, err);
}
if let Err(err) = cal_local.add_item(item.clone()).await {
@ -193,6 +222,7 @@ where
for id_add in local_additions {
log::debug!("> Pushing local addition {} to the server", id_add);
match cal_local.get_item_by_id(&id_add).await {
None => {
log::error!("Inconsistency: created item {} has been marked for upload but is locally missing", id_add);
@ -207,6 +237,7 @@ where
}
for id_change in local_changes {
log::debug!("> Pushing local change {} to the server", id_change);
match cal_local.get_item_by_id(&id_change).await {
None => {
log::error!("Inconsistency: modified item {} has been marked for upload but is locally missing", id_change);

View file

@ -8,6 +8,7 @@ use minidom::Element;
use crate::traits::CompleteCalendar;
use crate::calendar::CalendarId;
use crate::Item;
use crate::item::SyncStatus;
/// Walks an XML tree and returns every element that has the given name
pub fn find_elems<S: AsRef<str>>(root: &Element, searched_name: S) -> Vec<&Element> {
@ -79,8 +80,18 @@ where
pub fn print_task(item: &Item) {
match item {
Item::Task(task) => {
let completion = if task.completed() {""} else {" "};
println!(" {} {}\t{}", completion, task.name(), task.id());
let mut status = String::new();
if task.completed() {
status += "";
} else {
status += " ";
}
match task.sync_status() {
SyncStatus::LocallyModified(_) => { status += "~"; },
SyncStatus::LocallyDeleted(_) => { status += "x"; },
_ => (),
}
println!(" {} {}\t{}", status, task.name(), task.id());
},
_ => return,
}