Added get_items_by_url, to fetch multiple items at once

This commit is contained in:
daladim 2021-12-24 00:11:18 +01:00
parent f7110c254f
commit a973146366
3 changed files with 56 additions and 0 deletions

View file

@ -326,6 +326,14 @@ impl DavCalendar for CachedCalendar {
Ok(self.items.get(url).cloned()) Ok(self.items.get(url).cloned())
} }
async fn get_items_by_url(&self, urls: &[Url]) -> Result<Vec<Option<Item>>, Box<dyn Error>> {
let mut v = Vec::new();
for url in urls {
v.push(DavCalendar::get_item_by_url(self, url).await?);
}
Ok(v)
}
async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box<dyn Error>> { async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box<dyn Error>> {
#[cfg(feature = "local_calendar_mocks_remote_calendars")] #[cfg(feature = "local_calendar_mocks_remote_calendars")]
self.mock_behaviour.as_ref().map_or(Ok(()), |b| b.lock().unwrap().can_delete_item())?; self.mock_behaviour.as_ref().map_or(Ok(()), |b| b.lock().unwrap().can_delete_item())?;

View file

@ -14,6 +14,7 @@ use crate::item::Item;
use crate::item::VersionTag; use crate::item::VersionTag;
use crate::item::SyncStatus; use crate::item::SyncStatus;
use crate::resource::Resource; use crate::resource::Resource;
use crate::utils::find_elem;
static TASKS_BODY: &str = r#" static TASKS_BODY: &str = r#"
<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav"> <c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
@ -28,6 +29,15 @@ static TASKS_BODY: &str = r#"
</c:calendar-query> </c:calendar-query>
"#; "#;
static MULTIGET_BODY_PREFIX: &str = r#"
<c:calendar-multiget xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
<d:prop>
<c:calendar-data />
</d:prop>
"#;
static MULTIGET_BODY_SUFFIX: &str = r#"
</c:calendar-multiget>
"#;
@ -191,6 +201,40 @@ impl DavCalendar for RemoteCalendar {
Ok(Some(item)) Ok(Some(item))
} }
async fn get_items_by_url(&self, urls: &[Url]) -> Result<Vec<Option<Item>>, Box<dyn Error>> {
// Build the request body
let mut hrefs = String::new();
for url in urls {
hrefs.push_str(&format!(" <d:href>{}</d:href>\n", url.path()));
}
let body = format!("{}{}{}", MULTIGET_BODY_PREFIX, hrefs, MULTIGET_BODY_SUFFIX);
// Send the request
let xml_replies = crate::client::sub_request_and_extract_elems(&self.resource, "REPORT", body, "response").await?;
// This is supposed to be cached
let version_tags = self.get_item_version_tags().await?;
// Parse the results
let mut results = Vec::new();
for xml_reply in xml_replies {
let href = find_elem(&xml_reply, "href").ok_or("Missing HREF")?.text();
let mut url = self.resource.url().clone();
url.set_path(&href);
let ical_data = find_elem(&xml_reply, "calendar-data").ok_or("Missing calendar-data")?.text();
let vt = match version_tags.get(&url) {
None => return Err(format!("Inconsistent data: {} has no version tag", url).into()),
Some(vt) => vt,
};
let item = crate::ical::parse(&ical_data, url.clone(), SyncStatus::Synced(vt.clone()))?;
results.push(Some(item));
}
Ok(results)
}
async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box<dyn Error>> { async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box<dyn Error>> {
let del_response = reqwest::Client::new() let del_response = reqwest::Client::new()
.delete(item_url.clone()) .delete(item_url.clone())

View file

@ -83,6 +83,10 @@ pub trait DavCalendar : BaseCalendar {
/// Returns a particular item /// Returns a particular item
async fn get_item_by_url(&self, url: &Url) -> Result<Option<Item>, Box<dyn Error>>; async fn get_item_by_url(&self, url: &Url) -> Result<Option<Item>, Box<dyn Error>>;
/// Returns a set of items.
/// This is usually faster than calling multiple consecutive [`get_item_by_url`], since it only issues one HTTP request.
async fn get_items_by_url(&self, urls: &[Url]) -> Result<Vec<Option<Item>>, Box<dyn Error>>;
/// Delete an item /// Delete an item
async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box<dyn Error>>; async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box<dyn Error>>;