From 1175ed8eac6a9b7a8c4909e9acacd6cb9e4db695 Mon Sep 17 00:00:00 2001 From: aawsome <37850842+aawsome@users.noreply.github.com> Date: Sun, 24 Nov 2024 10:34:50 +0100 Subject: [PATCH] fix(commands): Use spawn_blocking in webdav when calling rustic_core (#1365) (after reverting #1361) solves the webdav problem reported in #1181 Co-authored-by: simonsan <14062932+simonsan@users.noreply.github.com> --- src/commands/webdav/webdavfs.rs | 81 +++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/src/commands/webdav/webdavfs.rs b/src/commands/webdav/webdavfs.rs index 0c3ebb545..ae5f02a7c 100644 --- a/src/commands/webdav/webdavfs.rs +++ b/src/commands/webdav/webdavfs.rs @@ -16,12 +16,12 @@ use dav_server::{ }, }; use futures::FutureExt; - use rustic_core::{ repofile::Node, vfs::{FilePolicy, OpenFile, Vfs}, IndexedFull, Repository, }; +use tokio::task::spawn_blocking; fn now() -> SystemTime { static NOW: OnceLock = OnceLock::new(); @@ -55,7 +55,7 @@ pub struct WebDavFS { inner: Arc>, } -impl WebDavFS { +impl WebDavFS { /// Create a new [`WebDavFS`] instance. /// /// # Arguments @@ -94,11 +94,17 @@ impl WebDavFS { /// The [`Node`] at the specified path /// /// [`Tree`]: crate::repofile::Tree - fn node_from_path(&self, path: &DavPath) -> Result { - self.inner - .vfs - .node_from_path(&self.inner.repo, &path.as_pathbuf()) - .map_err(|_| FsError::GeneralFailure) + async fn node_from_path(&self, path: &DavPath) -> Result { + let inner = self.inner.clone(); + let path = path.as_pathbuf(); + spawn_blocking(move || { + inner + .vfs + .node_from_path(&inner.repo, &path) + .map_err(|_| FsError::GeneralFailure) + }) + .await + .map_err(|_| FsError::GeneralFailure)? } /// Get a list of [`Node`]s from the specified directory path. @@ -116,11 +122,17 @@ impl WebDavFS { /// The list of [`Node`]s at the specified path /// /// [`Tree`]: crate::repofile::Tree - fn dir_entries_from_path(&self, path: &DavPath) -> Result, FsError> { - self.inner - .vfs - .dir_entries_from_path(&self.inner.repo, &path.as_pathbuf()) - .map_err(|_| FsError::GeneralFailure) + async fn dir_entries_from_path(&self, path: &DavPath) -> Result, FsError> { + let inner = self.inner.clone(); + let path = path.as_pathbuf(); + spawn_blocking(move || { + inner + .vfs + .dir_entries_from_path(&inner.repo, &path) + .map_err(|_| FsError::GeneralFailure) + }) + .await + .map_err(|_| FsError::GeneralFailure)? } } @@ -141,7 +153,7 @@ impl(&'a self, davpath: &'a DavPath) -> FsFuture<'_, Box> { async move { - let node = self.node_from_path(davpath)?; + let node = self.node_from_path(davpath).await?; let meta: Box = Box::new(DavFsMetaData(node)); Ok(meta) } @@ -154,7 +166,7 @@ impl FsFuture<'_, FsStream>> { async move { - let entries = self.dir_entries_from_path(davpath)?; + let entries = self.dir_entries_from_path(davpath).await?; let entry_iter = entries.into_iter().map(|e| { let entry: Box = Box::new(DavFsDirEntry(e)); Ok(entry) @@ -180,19 +192,25 @@ impl = Box::new(DavFsFile { node, - open, + open: Arc::new(open), fs: self.inner.clone(), seek: 0, }); @@ -239,7 +257,7 @@ struct DavFsFile { node: Node, /// The [`OpenFile`] for this file - open: OpenFile, + open: Arc, /// The [`DavFsInner`] this file belongs to fs: Arc>, @@ -254,7 +272,9 @@ impl Debug for DavFsFile { } } -impl DavFile for DavFsFile { +impl DavFile + for DavFsFile +{ fn metadata(&mut self) -> FsFuture<'_, Box> { async move { let meta: Box = Box::new(DavFsMetaData(self.node.clone())); @@ -272,12 +292,17 @@ impl DavFile for D } fn read_bytes(&mut self, count: usize) -> FsFuture<'_, Bytes> { + let fs = self.fs.clone(); + let seek = self.seek; + let open = self.open.clone(); async move { - let data = self - .fs - .repo - .read_file_at(&self.open, self.seek, count) - .map_err(|_err| FsError::GeneralFailure)?; + let data = spawn_blocking(move || { + fs.repo + .read_file_at(&open, seek, count) + .map_err(|_err| FsError::GeneralFailure) + }) + .await + .map_err(|_| FsError::GeneralFailure)??; self.seek += data.len(); Ok(data) }