Turning calendars into Arc<Mutex>
This commit is contained in:
parent
d07a2b9493
commit
060f33b4bd
8 changed files with 199 additions and 91 deletions
37
src/cache.rs
37
src/cache.rs
|
@ -6,6 +6,7 @@ use std::error::Error;
|
|||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use async_trait::async_trait;
|
||||
|
@ -28,7 +29,7 @@ pub struct Cache {
|
|||
|
||||
#[derive(Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct CachedData {
|
||||
calendars: HashMap<CalendarId, CachedCalendar>,
|
||||
calendars: HashMap<CalendarId, Arc<Mutex<CachedCalendar>>>,
|
||||
last_sync: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
|
@ -81,8 +82,9 @@ impl Cache {
|
|||
}
|
||||
|
||||
|
||||
pub fn add_calendar(&mut self, calendar: CachedCalendar) {
|
||||
self.data.calendars.insert(calendar.id().clone(), calendar);
|
||||
pub fn add_calendar(&mut self, calendar: Arc<Mutex<CachedCalendar>>) {
|
||||
let id = calendar.lock().unwrap().id().clone();
|
||||
self.data.calendars.insert(id, calendar);
|
||||
}
|
||||
|
||||
/// Compares two Caches to check they have the same current content
|
||||
|
@ -97,8 +99,9 @@ impl Cache {
|
|||
}
|
||||
|
||||
for (id, cal_l) in calendars_l {
|
||||
let cal_r = match calendars_r.get(id) {
|
||||
Some(c) => c,
|
||||
let cal_l = cal_l.lock().unwrap();
|
||||
let cal_r = match calendars_r.get(&id) {
|
||||
Some(c) => c.lock().unwrap(),
|
||||
None => return Err("should not happen, we've just tested keys are the same".into()),
|
||||
};
|
||||
|
||||
|
@ -138,23 +141,15 @@ where
|
|||
|
||||
#[async_trait]
|
||||
impl CalDavSource<CachedCalendar> for Cache {
|
||||
async fn get_calendars(&self) -> Result<&HashMap<CalendarId, CachedCalendar>, Box<dyn Error>> {
|
||||
Ok(&self.data.calendars)
|
||||
async fn get_calendars(&self) -> Result<HashMap<CalendarId, Arc<Mutex<CachedCalendar>>>, Box<dyn Error>> {
|
||||
Ok(self.data.calendars.iter()
|
||||
.map(|(id, cal)| (id.clone(), cal.clone()))
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
async fn get_calendars_mut(&mut self) -> Result<HashMap<CalendarId, &mut CachedCalendar>, Box<dyn Error>> {
|
||||
let mut hm = HashMap::new();
|
||||
for (id, val) in self.data.calendars.iter_mut() {
|
||||
hm.insert(id.clone(), val);
|
||||
}
|
||||
Ok(hm)
|
||||
}
|
||||
|
||||
async fn get_calendar(&self, id: CalendarId) -> Option<&CachedCalendar> {
|
||||
self.data.calendars.get(&id)
|
||||
}
|
||||
async fn get_calendar_mut(&mut self, id: CalendarId) -> Option<&mut CachedCalendar> {
|
||||
self.data.calendars.get_mut(&id)
|
||||
async fn get_calendar(&self, id: CalendarId) -> Option<Arc<Mutex<CachedCalendar>>> {
|
||||
self.data.calendars.get(&id).map(|arc| arc.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +179,7 @@ mod tests {
|
|||
let cal1 = CachedCalendar::new("shopping list".to_string(),
|
||||
Url::parse("https://caldav.com/shopping").unwrap(),
|
||||
SupportedComponents::TODO);
|
||||
cache.add_calendar(cal1);
|
||||
cache.add_calendar(Arc::new(Mutex::new(cal1)));
|
||||
|
||||
cache.save_to_file();
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub mod cached_calendar;
|
||||
pub mod remote_calendar;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::error::Error;
|
||||
|
|
|
@ -1,21 +1,39 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::error::Error;
|
||||
|
||||
use url::Url;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
use crate::traits::PartialCalendar;
|
||||
use crate::calendar::SupportedComponents;
|
||||
use crate::calendar::CalendarId;
|
||||
use crate::item::ItemId;
|
||||
use crate::item::Item;
|
||||
|
||||
/// A CalDAV calendar created by a [`Client`](crate::client::Client).
|
||||
#[derive(Clone)]
|
||||
pub struct RemoteCalendar {
|
||||
name: String,
|
||||
url: Url,
|
||||
supported_components: SupportedComponents
|
||||
}
|
||||
|
||||
impl PartialCalendar for RemoteCalendar {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
impl RemoteCalendar {
|
||||
pub fn new(name: String, url: Url, supported_components: SupportedComponents) -> Self {
|
||||
Self {
|
||||
name, url, supported_components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialCalendar for RemoteCalendar {
|
||||
fn name(&self) -> &str { &self.name }
|
||||
fn id(&self) -> &CalendarId { &self.url }
|
||||
fn supported_components(&self) -> crate::calendar::SupportedComponents {
|
||||
self.supported_components
|
||||
}
|
||||
|
||||
/// Returns the items that have been last-modified after `since`
|
||||
fn get_items_modified_since(&self, since: Option<DateTime<Utc>>, filter: Option<crate::calendar::SearchFilter>)
|
||||
-> HashMap<ItemId, &Item>
|
||||
{
|
||||
|
@ -23,16 +41,28 @@ impl PartialCalendar for RemoteCalendar {
|
|||
HashMap::new()
|
||||
}
|
||||
|
||||
/// Get the IDs of all current items in this calendar
|
||||
fn get_item_ids(&mut self) -> HashSet<ItemId> {
|
||||
log::error!("Not implemented");
|
||||
HashSet::new()
|
||||
}
|
||||
|
||||
/// Returns a particular item
|
||||
fn get_item_by_id_mut(&mut self, id: &ItemId) -> Option<&mut Item> {
|
||||
log::error!("Not implemented");
|
||||
None
|
||||
}
|
||||
|
||||
/// Add an item into this calendar
|
||||
fn add_item(&mut self, item: Item) {
|
||||
log::error!("Not implemented");
|
||||
}
|
||||
|
||||
fn delete_item(&mut self, item_id: &ItemId) {
|
||||
/// Remove an item from this calendar
|
||||
fn delete_item(&mut self, item_id: &ItemId) -> Result<(), Box<dyn Error>> {
|
||||
log::error!("Not implemented");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
161
src/client.rs
161
src/client.rs
|
@ -3,15 +3,18 @@
|
|||
use std::error::Error;
|
||||
use std::convert::TryFrom;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use reqwest::Method;
|
||||
use reqwest::header::CONTENT_TYPE;
|
||||
use minidom::Element;
|
||||
use url::Url;
|
||||
|
||||
use crate::utils::{find_elem, find_elems};
|
||||
use crate::calendar::cached_calendar::CachedCalendar;
|
||||
use crate::calendar::remote_calendar::RemoteCalendar;
|
||||
use crate::calendar::CalendarId;
|
||||
use crate::traits::CalDavSource;
|
||||
use crate::traits::PartialCalendar;
|
||||
|
||||
|
||||
|
@ -71,9 +74,17 @@ pub struct Client {
|
|||
username: String,
|
||||
password: String,
|
||||
|
||||
/// The interior mutable part of a Client.
|
||||
/// This data may be retrieved once and then cached
|
||||
cached_replies: Mutex<CachedReplies>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
struct CachedReplies {
|
||||
principal: Option<Url>,
|
||||
calendar_home_set: Option<Url>,
|
||||
calendars: Option<HashMap<CalendarId, CachedCalendar>>,
|
||||
calendars: Option<HashMap<CalendarId, Arc<Mutex<RemoteCalendar>>>>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
|
@ -85,9 +96,7 @@ impl Client {
|
|||
url,
|
||||
username: username.to_string(),
|
||||
password: password.to_string(),
|
||||
principal: None,
|
||||
calendar_home_set: None,
|
||||
calendars: None,
|
||||
cached_replies: Mutex::new(CachedReplies::default()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -111,33 +120,30 @@ impl Client {
|
|||
let text = self.sub_request(url, body, 0).await?;
|
||||
|
||||
let mut current_element: &Element = &text.parse().unwrap();
|
||||
items.iter()
|
||||
.map(|item| {
|
||||
for item in items {
|
||||
current_element = find_elem(¤t_element, item).unwrap();
|
||||
})
|
||||
.collect::<()>();
|
||||
|
||||
}
|
||||
Ok(current_element.text())
|
||||
}
|
||||
|
||||
/// Return the Principal URL, or fetch it from server if not known yet
|
||||
async fn get_principal(&mut self) -> Result<Url, Box<dyn Error>> {
|
||||
if let Some(p) = &self.principal {
|
||||
async fn get_principal(&self) -> Result<Url, Box<dyn Error>> {
|
||||
if let Some(p) = &self.cached_replies.lock().unwrap().principal {
|
||||
return Ok(p.clone());
|
||||
}
|
||||
|
||||
let href = self.sub_request_and_process(&self.url, DAVCLIENT_BODY.into(), &["current-user-principal", "href"]).await?;
|
||||
let mut principal_url = self.url.clone();
|
||||
principal_url.set_path(&href);
|
||||
self.principal = Some(principal_url.clone());
|
||||
self.cached_replies.lock().unwrap().principal = Some(principal_url.clone());
|
||||
log::debug!("Principal URL is {}", href);
|
||||
|
||||
return Ok(principal_url);
|
||||
}
|
||||
|
||||
/// Return the Homeset URL, or fetch it from server if not known yet
|
||||
async fn get_cal_home_set(&mut self) -> Result<Url, Box<dyn Error>> {
|
||||
if let Some(h) = &self.calendar_home_set {
|
||||
async fn get_cal_home_set(&self) -> Result<Url, Box<dyn Error>> {
|
||||
if let Some(h) = &self.cached_replies.lock().unwrap().calendar_home_set {
|
||||
return Ok(h.clone());
|
||||
}
|
||||
let principal_url = self.get_principal().await?;
|
||||
|
@ -145,16 +151,88 @@ impl Client {
|
|||
let href = self.sub_request_and_process(&principal_url, HOMESET_BODY.into(), &["calendar-home-set", "href"]).await?;
|
||||
let mut chs_url = self.url.clone();
|
||||
chs_url.set_path(&href);
|
||||
self.calendar_home_set = Some(chs_url.clone());
|
||||
self.cached_replies.lock().unwrap().calendar_home_set = Some(chs_url.clone());
|
||||
log::debug!("Calendar home set URL is {:?}", chs_url.path());
|
||||
|
||||
Ok(chs_url)
|
||||
}
|
||||
|
||||
async fn populate_calendars(&self) -> Result<(), Box<dyn Error>> {
|
||||
let cal_home_set = self.get_cal_home_set().await?;
|
||||
|
||||
let text = self.sub_request(&cal_home_set, CAL_BODY.into(), 1).await?;
|
||||
|
||||
let root: Element = text.parse().unwrap();
|
||||
let reps = find_elems(&root, "response");
|
||||
let mut calendars = HashMap::new();
|
||||
for rep in reps {
|
||||
let display_name = find_elem(rep, "displayname").map(|e| e.text()).unwrap_or("<no name>".to_string());
|
||||
log::debug!("Considering calendar {}", display_name);
|
||||
|
||||
// We filter out non-calendar items
|
||||
let resource_types = match find_elem(rep, "resourcetype") {
|
||||
None => continue,
|
||||
Some(rt) => rt,
|
||||
};
|
||||
let mut found_calendar_type = false;
|
||||
for resource_type in resource_types.children() {
|
||||
if resource_type.name() == "calendar" {
|
||||
found_calendar_type = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if found_calendar_type == false {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We filter out the root calendar collection, that has an empty supported-calendar-component-set
|
||||
let el_supported_comps = match find_elem(rep, "supported-calendar-component-set") {
|
||||
None => continue,
|
||||
Some(comps) => comps,
|
||||
};
|
||||
if el_supported_comps.children().count() == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let calendar_href = match find_elem(rep, "href") {
|
||||
None => {
|
||||
log::warn!("Calendar {} has no URL! Ignoring it.", display_name);
|
||||
continue;
|
||||
},
|
||||
Some(h) => h.text(),
|
||||
};
|
||||
|
||||
let mut this_calendar_url = self.url.clone();
|
||||
this_calendar_url.set_path(&calendar_href);
|
||||
|
||||
let supported_components = match crate::calendar::SupportedComponents::try_from(el_supported_comps.clone()) {
|
||||
Err(err) => {
|
||||
log::warn!("Calendar {} has invalid supported components ({})! Ignoring it.", display_name, err);
|
||||
continue;
|
||||
},
|
||||
Ok(sc) => sc,
|
||||
};
|
||||
let this_calendar = RemoteCalendar::new(display_name, this_calendar_url, supported_components);
|
||||
log::info!("Found calendar {}", this_calendar.name());
|
||||
calendars.insert(this_calendar.id().clone(), Arc::new(Mutex::new(this_calendar)));
|
||||
}
|
||||
|
||||
let mut replies = self.cached_replies.lock().unwrap();
|
||||
replies.calendars = Some(calendars);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CalDavSource<RemoteCalendar> for Client {
|
||||
/// Return the list of calendars, or fetch from server if not known yet
|
||||
pub async fn get_calendars(&mut self) -> Result<HashMap<CalendarId, CachedCalendar>, Box<dyn Error>> {
|
||||
if let Some(c) = &self.calendars {
|
||||
return Ok(c.clone());
|
||||
/*
|
||||
async fn get_calendars(&self) -> Result<&HashMap<CalendarId, RemoteCalendar>, Box<dyn Error>> {
|
||||
let mut replies = self.cached_replies.lock().unwrap();
|
||||
|
||||
if let Some(c) = &replies.calendars {
|
||||
return Ok(c);
|
||||
}
|
||||
let cal_home_set = self.get_cal_home_set().await?;
|
||||
|
||||
|
@ -210,37 +288,36 @@ impl Client {
|
|||
},
|
||||
Ok(sc) => sc,
|
||||
};
|
||||
let this_calendar = CachedCalendar::new(display_name, this_calendar_url, supported_components);
|
||||
let this_calendar = RemoteCalendar::new(display_name, this_calendar_url, supported_components);
|
||||
log::info!("Found calendar {}", this_calendar.name());
|
||||
calendars.insert(this_calendar.id().clone(), this_calendar);
|
||||
}
|
||||
|
||||
self.calendars = Some(calendars.clone());
|
||||
Ok(calendars)
|
||||
replies.calendars = Some(calendars);
|
||||
Ok(&calendars)
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
async fn get_calendars(&self) -> Result<HashMap<CalendarId, Arc<Mutex<RemoteCalendar>>>, Box<dyn Error>> {
|
||||
self.populate_calendars().await?;
|
||||
|
||||
match &self.cached_replies.lock().unwrap().calendars {
|
||||
Some(cals) => {
|
||||
return Ok(cals.clone())
|
||||
},
|
||||
None => return Err("No calendars available".into())
|
||||
};
|
||||
}
|
||||
|
||||
pub async fn get_tasks(&mut self, calendar: &CalendarId) -> Result<(), Box<dyn Error>> {
|
||||
let method = Method::from_bytes(b"REPORT")
|
||||
.expect("cannot create REPORT method.");
|
||||
|
||||
let res = reqwest::Client::new()
|
||||
.request(method, calendar.as_str())
|
||||
.header("Depth", 1)
|
||||
.header(CONTENT_TYPE, "application/xml")
|
||||
.basic_auth(self.username.clone(), Some(self.password.clone()))
|
||||
.body(TASKS_BODY)
|
||||
.send()
|
||||
.await?;
|
||||
let text = res.text().await?;
|
||||
|
||||
let el: Element = text.parse().unwrap();
|
||||
let responses = find_elems(&el, "response");
|
||||
|
||||
for _response in responses {
|
||||
println!("(a response)\n");
|
||||
async fn get_calendar(&self, id: CalendarId) -> Option<Arc<Mutex<RemoteCalendar>>> {
|
||||
self.cached_replies.lock().unwrap()
|
||||
.calendars
|
||||
.as_ref()
|
||||
.and_then(|cals| cals.get(&id))
|
||||
.map(|cal| cal.clone())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,16 +63,19 @@ where
|
|||
pub async fn sync(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let last_sync = self.local.get_last_sync();
|
||||
log::info!("Starting a sync. Last sync was at {:?}", last_sync);
|
||||
let cals_server = self.server.get_calendars_mut().await?;
|
||||
let cals_server = self.server.get_calendars().await?;
|
||||
|
||||
for (id, cal_server) in cals_server {
|
||||
let cal_local = match self.local.get_calendar_mut(id).await {
|
||||
for (id, mut cal_server) in cals_server {
|
||||
let mut cal_server = cal_server.lock().unwrap();
|
||||
|
||||
let cal_local = match self.local.get_calendar(id).await {
|
||||
None => {
|
||||
log::error!("TODO: implement here");
|
||||
continue;
|
||||
},
|
||||
Some(cal) => cal,
|
||||
};
|
||||
let mut cal_local = cal_local.lock().unwrap();
|
||||
|
||||
// Pull remote changes from the server
|
||||
let mut tasks_id_to_remove_from_local = match last_sync {
|
||||
|
@ -93,7 +96,7 @@ where
|
|||
tasks_to_add_to_local.push((*new_item).clone());
|
||||
}
|
||||
// Even in case of conflicts, "the server always wins", so it is safe to remove tasks from the local cache as soon as now
|
||||
remove_from_calendar(&tasks_id_to_remove_from_local, cal_local);
|
||||
remove_from_calendar(&tasks_id_to_remove_from_local, &mut *cal_local);
|
||||
|
||||
|
||||
|
||||
|
@ -121,9 +124,9 @@ where
|
|||
tasks_to_add_to_server.push((*new_item).clone());
|
||||
}
|
||||
|
||||
remove_from_calendar(&tasks_id_to_remove_from_server, cal_server);
|
||||
move_to_calendar(&mut tasks_to_add_to_local, cal_local);
|
||||
move_to_calendar(&mut tasks_to_add_to_server, cal_server);
|
||||
remove_from_calendar(&tasks_id_to_remove_from_server, &mut *cal_server);
|
||||
move_to_calendar(&mut tasks_to_add_to_local, &mut *cal_local);
|
||||
move_to_calendar(&mut tasks_to_add_to_server, &mut *cal_server);
|
||||
}
|
||||
|
||||
self.local.update_last_sync(None);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::error::Error;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
@ -12,16 +13,9 @@ use crate::calendar::CalendarId;
|
|||
pub trait CalDavSource<T: PartialCalendar> {
|
||||
/// Returns the current calendars that this source contains
|
||||
/// This function may trigger an update (that can be a long process, or that can even fail, e.g. in case of a remote server)
|
||||
async fn get_calendars(&self) -> Result<&HashMap<CalendarId, T>, Box<dyn Error>>;
|
||||
/// Returns the current calendars that this source contains
|
||||
/// This function may trigger an update (that can be a long process, or that can even fail, e.g. in case of a remote server)
|
||||
async fn get_calendars_mut(&mut self) -> Result<HashMap<CalendarId, &mut T>, Box<dyn Error>>;
|
||||
|
||||
async fn get_calendars(&self) -> Result<HashMap<CalendarId, Arc<Mutex<T>>>, Box<dyn Error>>;
|
||||
/// Returns the calendar matching the ID
|
||||
async fn get_calendar(&self, id: CalendarId) -> Option<&T>;
|
||||
/// Returns the calendar matching the ID
|
||||
async fn get_calendar_mut(&mut self, id: CalendarId) -> Option<&mut T>;
|
||||
|
||||
async fn get_calendar(&self, id: CalendarId) -> Option<Arc<Mutex<T>>>;
|
||||
}
|
||||
|
||||
pub trait SyncSlave {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
///! Some utility functions
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use minidom::Element;
|
||||
|
||||
|
@ -56,10 +57,13 @@ pub fn print_xml(element: &Element) {
|
|||
}
|
||||
|
||||
/// A debug utility that pretty-prints calendars
|
||||
pub fn print_calendar_list<C: CompleteCalendar>(cals: &HashMap<CalendarId, C>) {
|
||||
pub fn print_calendar_list<C>(cals: &HashMap<CalendarId, Arc<Mutex<C>>>)
|
||||
where
|
||||
C: CompleteCalendar,
|
||||
{
|
||||
for (id, cal) in cals {
|
||||
println!("CAL {}", id);
|
||||
for (_, item) in cal.get_items() {
|
||||
for (_, item) in cal.lock().unwrap().get_items() {
|
||||
let task = item.unwrap_task();
|
||||
let completion = if task.completed() {"✓"} else {" "};
|
||||
println!(" {} {}\t{}", completion, task.name(), task.id());
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use chrono::{Utc, TimeZone};
|
||||
use url::Url;
|
||||
|
@ -20,10 +21,11 @@ async fn test_regular_sync() {
|
|||
let mut provider = populate_test_provider().await;
|
||||
provider.sync().await.unwrap();
|
||||
|
||||
|
||||
let cals_server = provider.server().get_calendars().await.unwrap();
|
||||
my_tasks::utils::print_calendar_list(&cals_server);
|
||||
let cals_local = provider.local().get_calendars().await.unwrap();
|
||||
my_tasks::utils::print_calendar_list(cals_local);
|
||||
my_tasks::utils::print_calendar_list(cals_server);
|
||||
my_tasks::utils::print_calendar_list(&cals_local);
|
||||
|
||||
assert!(provider.server().has_same_contents_than(provider.local()).await.unwrap());
|
||||
|
||||
|
@ -94,12 +96,13 @@ async fn populate_test_provider() -> Provider<Cache, CachedCalendar, Cache, Cach
|
|||
calendar.add_item(task_l);
|
||||
calendar.add_item(task_m);
|
||||
|
||||
server.add_calendar(calendar.clone());
|
||||
local.add_calendar(calendar.clone());
|
||||
server.add_calendar(Arc::new(Mutex::new(calendar.clone())));
|
||||
local.add_calendar(Arc::new(Mutex::new(calendar.clone())));
|
||||
|
||||
// Step 2
|
||||
// Edit the server calendar
|
||||
let cal_server = server.get_calendar_mut(cal_id.clone()).await.unwrap();
|
||||
let cal_server = server.get_calendar(cal_id.clone()).await.unwrap();
|
||||
let mut cal_server = cal_server.lock().unwrap();
|
||||
|
||||
cal_server.delete_item(&task_b_id);
|
||||
|
||||
|
@ -126,7 +129,8 @@ async fn populate_test_provider() -> Provider<Cache, CachedCalendar, Cache, Cach
|
|||
|
||||
// Step 3
|
||||
// Edit the local calendar
|
||||
let cal_local = local.get_calendar_mut(cal_id).await.unwrap();
|
||||
let cal_local = local.get_calendar(cal_id).await.unwrap();
|
||||
let mut cal_local = cal_local.lock().unwrap();
|
||||
|
||||
cal_local.delete_item(&task_c_id);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue