This is an automated email from the ASF dual-hosted git repository.

junouyang pushed a commit to branch feat/blockong-operator-range-read
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git

commit e208907aca34130480f4786896027d8e419b1857
Author: owl <[email protected]>
AuthorDate: Wed Aug 23 22:34:12 2023 +0800

    feat(types): add stat_with API for blocking operator
---
 core/src/types/operator/blocking_operator.rs  | 49 ++++++++++++++++++++++++---
 core/src/types/operator/operator_functions.rs | 31 +++++++++++++++++
 2 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/core/src/types/operator/blocking_operator.rs 
b/core/src/types/operator/blocking_operator.rs
index 6d4b102f2..28aa53bb6 100644
--- a/core/src/types/operator/blocking_operator.rs
+++ b/core/src/types/operator/blocking_operator.rs
@@ -137,12 +137,53 @@ impl BlockingOperator {
     /// # }
     /// ```
     pub fn stat(&self, path: &str) -> Result<Metadata> {
-        let path = normalize_path(path);
+        self.stat_with(path).call()
+    }
 
-        let rp = self.inner().blocking_stat(&path, OpStat::new())?;
-        let meta = rp.into_metadata();
+    /// Get current path's metadata **without cache** directly with extra 
options.
+    ///
+    /// # Notes
+    ///
+    /// Use `stat` if you:
+    ///
+    /// - Want to detect the outside changes of path.
+    /// - Don't want to read from cached metadata.
+    ///
+    /// You may want to use `metadata` if you are working with entries
+    /// returned by [`Lister`]. It's highly possible that metadata
+    /// you want has already been cached.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use anyhow::Result;
+    /// # use opendal::BlockingOperator;
+    /// use opendal::ErrorKind;
+    /// #
+    /// # #[tokio::main]
+    /// # async fn test(op: BlockingOperator) -> Result<()> {
+    /// if let Err(e) = op.stat_with("test").if_match("<etag>").call() {
+    ///     if e.kind() == ErrorKind::NotFound {
+    ///         println!("file not exist")
+    ///     }
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn stat_with(&self, path: &str) -> FunctionStat {
+        let path = normalize_path(path);
 
-        Ok(meta)
+        FunctionStat(OperatorFunction::new(
+            self.inner().clone(),
+            path,
+            OpStat::default(),
+            |inner, path, args| {
+                let rp = inner.blocking_stat(&path, args)?;
+                let meta = rp.into_metadata();
+        
+                Ok(meta)
+            },
+        ))
     }
 
     /// Check if this path exists or not.
diff --git a/core/src/types/operator/operator_functions.rs 
b/core/src/types/operator/operator_functions.rs
index 1000b7094..758a1cc2c 100644
--- a/core/src/types/operator/operator_functions.rs
+++ b/core/src/types/operator/operator_functions.rs
@@ -229,3 +229,34 @@ impl FunctionReader {
         self.0.call()
     }
 }
+
+/// Function that generated by [`BlockingOperator::stat_with`].
+///
+/// Users can add more options by public functions provided by this struct.
+pub struct FunctionStat(pub(crate) OperatorFunction<OpStat, Metadata>);
+
+impl FunctionStat {
+    /// Set the If-Match for this operation.
+    pub fn if_match(mut self, v: &str) -> Self {
+        self.0 = self.0.map_args(|args| args.with_if_match(v));
+        self
+    }
+
+    /// Set the If-None-Match for this operation.
+    pub fn if_none_match(mut self, v: &str) -> Self {
+        self.0 = self.0.map_args(|args| args.with_if_none_match(v));
+        self
+    }
+
+    /// Set the version for this operation.
+    pub fn version(mut self, v: &str) -> Self {
+        self.0 = self.0.map_args(|args| args.with_version(v));
+        self
+    }
+
+    /// Call the function to consume all the input and generate a
+    /// result.
+    pub fn call(self) -> Result<Metadata> {
+        self.0.call()
+    }
+}
\ No newline at end of file

Reply via email to