2 changed files with 132 additions and 124 deletions
@ -1,114 +1,96 @@ |
|||||||
//! This modules abstracts data sources and merges them in a single virtual one
|
//! This modules abstracts data sources and merges them in a single virtual one
|
||||||
|
|
||||||
use std::error::Error; |
use std::error::Error; |
||||||
|
|
||||||
use chrono::{DateTime, Utc}; |
use chrono::{DateTime, Utc}; |
||||||
|
|
||||||
use crate::traits::CalDavSource; |
use crate::traits::CalDavSource; |
||||||
use crate::Calendar; |
use crate::Calendar; |
||||||
use crate::Task; |
use crate::Task; |
||||||
use crate::task::TaskId; |
use crate::task::TaskId; |
||||||
|
|
||||||
|
|
||||||
pub struct Provider<S, L> |
pub struct Provider<S, L> |
||||||
where |
where |
||||||
S: CalDavSource, |
S: CalDavSource, |
||||||
L: CalDavSource, |
L: CalDavSource, |
||||||
{ |
{ |
||||||
/// The remote server
|
/// The remote server
|
||||||
server: S, |
server: S, |
||||||
/// The local cache
|
/// The local cache
|
||||||
local: L, |
local: L, |
||||||
|
|
||||||
/// The last time the provider successfully synchronized both sources
|
/// The last time the provider successfully synchronized both sources
|
||||||
last_sync: DateTime<Utc>, |
last_sync: DateTime<Utc>, |
||||||
} |
} |
||||||
|
|
||||||
impl<S,L> Provider<S, L> |
impl<S,L> Provider<S, L> |
||||||
where |
where |
||||||
S: CalDavSource, |
S: CalDavSource, |
||||||
L: CalDavSource, |
L: CalDavSource, |
||||||
{ |
{ |
||||||
/// Create a provider that will merge both sources
|
/// Create a provider that will merge both sources
|
||||||
pub fn new(server: S, local: L, last_sync: DateTime<Utc>) -> Self { |
pub fn new(server: S, local: L, last_sync: DateTime<Utc>) -> Self { |
||||||
Self { server, local, last_sync } |
Self { server, local, last_sync } |
||||||
} |
} |
||||||
|
|
||||||
pub fn server(&self) -> &S { &self.server } |
pub fn server(&self) -> &S { &self.server } |
||||||
pub fn local(&self) -> &L { &self.local } |
pub fn local(&self) -> &L { &self.local } |
||||||
|
|
||||||
pub async fn sync(&mut self) -> Result<(), Box<dyn Error>> { |
pub async fn sync(&mut self) -> Result<(), Box<dyn Error>> { |
||||||
self.pull_items_from_server().await?; |
let cals_server = self.server.get_calendars_mut().await?; |
||||||
self.resolve_conflicts().await; |
|
||||||
self.push_items_to_server().await; |
for cal_server in cals_server { |
||||||
|
let cal_local = match self.local.get_calendar_mut(cal_server.url().clone()).await { |
||||||
// what to do with errors? Return Err directly? Go ahead as far as we can?
|
None => { |
||||||
Ok(()) |
log::error!("TODO: implement here"); |
||||||
} |
continue; |
||||||
|
}, |
||||||
pub async fn pull_items_from_server(&mut self) -> Result<(), Box<dyn Error>> { |
Some(cal) => cal, |
||||||
let cals_server = self.server.get_calendars_mut().await?; |
}; |
||||||
|
|
||||||
for cal_server in cals_server { |
let server_mod = cal_server.get_tasks_modified_since(Some(self.last_sync), None); |
||||||
let cal_local = match self.local.get_calendar_mut(cal_server.url().clone()).await { |
let local_mod = cal_local.get_tasks_modified_since(Some(self.last_sync), None); |
||||||
None => { |
|
||||||
log::error!("TODO: implement here"); |
let mut tasks_to_add_to_local = Vec::new(); |
||||||
continue; |
let mut tasks_id_to_remove_from_local = Vec::new(); |
||||||
}, |
for (new_id, new_item) in &server_mod { |
||||||
Some(cal) => cal, |
if server_mod.contains_key(new_id) { |
||||||
}; |
log::warn!("Conflict for task {} ({}). Using the server version.", new_item.name(), new_id); |
||||||
|
tasks_id_to_remove_from_local.push(new_id.clone()); |
||||||
let server_mod = cal_server.get_tasks_modified_since(Some(self.last_sync), None); |
} |
||||||
let local_mod = cal_local.get_tasks_modified_since(Some(self.last_sync), None); |
tasks_to_add_to_local.push((*new_item).clone()); |
||||||
|
} |
||||||
let mut tasks_to_add_to_local = Vec::new(); |
|
||||||
let mut tasks_id_to_remove_from_local = Vec::new(); |
let mut tasks_to_add_to_server = Vec::new(); |
||||||
for (new_id, new_item) in &server_mod { |
for (new_id, new_item) in &local_mod { |
||||||
if server_mod.contains_key(new_id) { |
if server_mod.contains_key(new_id) { |
||||||
log::warn!("Conflict for task {} ({}). Using the server version.", new_item.name(), new_id); |
log::warn!("Conflict for task {} ({}). Using the server version.", new_item.name(), new_id); |
||||||
tasks_id_to_remove_from_local.push(new_id.clone()); |
continue; |
||||||
} |
} |
||||||
tasks_to_add_to_local.push((*new_item).clone()); |
tasks_to_add_to_server.push((*new_item).clone()); |
||||||
} |
} |
||||||
|
|
||||||
let mut tasks_to_add_to_server = Vec::new(); |
remove_from_calendar(&tasks_id_to_remove_from_local, cal_local); |
||||||
for (new_id, new_item) in &local_mod { |
move_to_calendar(&mut tasks_to_add_to_local, cal_local); |
||||||
if server_mod.contains_key(new_id) { |
move_to_calendar(&mut tasks_to_add_to_server, cal_server); |
||||||
log::warn!("Conflict for task {} ({}). Using the server version.", new_item.name(), new_id); |
} |
||||||
continue; |
|
||||||
} |
Ok(()) |
||||||
tasks_to_add_to_server.push((*new_item).clone()); |
} |
||||||
} |
} |
||||||
|
|
||||||
remove_from_calendar(&tasks_id_to_remove_from_local, cal_local); |
|
||||||
move_to_calendar(&mut tasks_to_add_to_local, cal_local); |
fn move_to_calendar(tasks: &mut Vec<Task>, calendar: &mut Calendar) { |
||||||
move_to_calendar(&mut tasks_to_add_to_server, cal_server); |
while tasks.len() > 0 { |
||||||
} |
let task = tasks.remove(0); |
||||||
|
calendar.add_task(task); |
||||||
Ok(()) |
} |
||||||
} |
} |
||||||
|
|
||||||
pub async fn resolve_conflicts(&mut self) { |
fn remove_from_calendar(ids: &Vec<TaskId>, calendar: &mut Calendar) { |
||||||
log::error!("We should do something here"); |
for id in ids { |
||||||
} |
log::info!(" Removing {:?} from local calendar", id); |
||||||
|
calendar.delete_task(id); |
||||||
pub async fn push_items_to_server(&mut self) { |
} |
||||||
|
} |
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
fn move_to_calendar(tasks: &mut Vec<Task>, calendar: &mut Calendar) { |
|
||||||
while tasks.len() > 0 { |
|
||||||
let task = tasks.remove(0); |
|
||||||
calendar.add_task(task); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fn remove_from_calendar(ids: &Vec<TaskId>, calendar: &mut Calendar) { |
|
||||||
for id in ids { |
|
||||||
log::info!(" Removing {:?} from local calendar", id); |
|
||||||
calendar.delete_task(id); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|||||||
Loading…
Reference in new issue