You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2025/05/15 17:40:14 UTC

(opendal) branch main updated: RFC-6189: Remove Native Blocking (#6189)

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

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 866d39896 RFC-6189: Remove Native Blocking (#6189)
866d39896 is described below

commit 866d398963804baf4372395f20341d29ec416bc2
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Fri May 16 01:40:08 2025 +0800

    RFC-6189: Remove Native Blocking (#6189)
    
    * RFC: Remove Native Blocking
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
    
    * Update name
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
    
    * Assign number
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
    
    * Fix typo
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
    
    ---------
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
---
 core/src/docs/rfcs/6189_remove_native_blocking.md | 106 ++++++++++++++++++++++
 core/src/docs/rfcs/mod.rs                         |   4 +
 2 files changed, 110 insertions(+)

diff --git a/core/src/docs/rfcs/6189_remove_native_blocking.md b/core/src/docs/rfcs/6189_remove_native_blocking.md
new file mode 100644
index 000000000..8c4543477
--- /dev/null
+++ b/core/src/docs/rfcs/6189_remove_native_blocking.md
@@ -0,0 +1,106 @@
+- Proposal Name: `remove_native_blocking`
+- Start Date: 2025-05-15
+- RFC PR: [apache/opendal#6189](https://github.com/apache/opendal/pull/6189)
+- Tracking Issue: [apache/opendal#6190](https://github.com/apache/opendal/issues/6190)
+
+# Summary
+
+Remove native blocking support from OpenDAL and use `block_on` in the async runtime instead.
+
+# Motivation
+
+OpenDAL projects offer both native async and blocking support. This means we can provide true blocking functionality when services are capable of it. The advantage is that users who only require blocking operations can enjoy optimal performance. For example, `fs` offers native blocking support, allowing users to utilize `fs` without any additional overhead or performance loss compared to using `tokio_fs`.
+
+However, this approach has several drawbacks:
+
+- Huge maintenance burden: We need to maintain two versions of the same code, which is a significant overhead.
+- Increased complexity: The codebase becomes more complex, making it harder to understand and maintain.
+- API inconsistency: The API for blocking and async operations may differ, leading to confusion for users, for example, concurrent reading support is not available in blocking APIs.
+
+Apart from the above drawbacks, we also find that the following facts:
+
+- Only a few services have native blocking support, such as `fs`, `memory` and `moka`.
+- Only a few users are using `BlockingOperator` (based on [search results from github](https://github.com/search?q=opendal%3A%3ABlockingOperator&type=code))
+
+So I propose to remove the native blocking support from OpenDAL and use `block_on` in the async runtime instead. This will simplify the codebase, reduce maintenance overhead, and provide a more consistent API for users.
+
+# Guide-level explanation
+
+I plan to move `BlockingOperator` to the `opendal::blocking` module, which will offer a blocking interface for users. The `BlockingOperator` will utilize `block_on` within an async runtime to execute asynchronous operations in a blocking way.
+
+- `opendal::BlockingOperator` will become `opendal::blocking::Operator`
+- `opendal::BlockingReader` will become `opendal::blocking::Reader`
+- `opendal::BlockingWriter` will become `opendal::blocking::Writer`
+- `opendal::BlockingLister` will become `opendal::blocking::Lister`
+- `opendal::BlockingDeleter` will become `opendal::blocking::Deleter`
+
+The public API will remain unchanged. The only impacts for users are as follows:
+
+- `blocking::Operator` can no longer be used in an async context
+- An async runtime is now required to use the blocking APIs
+
+# Reference-level explanation
+
+I plan to remove all blocking APIs in `oio::Access`:
+
+```diff
+pub trait Access: Send + Sync + Debug + Unpin + 'static { 
+  ...
+
+  - fn blocking_create_dir(&self, path: &str, args: OpCreateDir) -> Result<RpCreateDir> {
+  -     self.as_ref().blocking_create_dir(path, args)
+  - }
+  - 
+  - fn blocking_stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
+  -     self.as_ref().blocking_stat(path, args)
+  - }
+  - 
+  - fn blocking_read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::BlockingReader)> {
+  -     self.as_ref().blocking_read(path, args)
+  - }
+  - 
+  - fn blocking_write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::BlockingWriter)> {
+  -     self.as_ref().blocking_write(path, args)
+  - }
+  - 
+  - fn blocking_delete(&self) -> Result<(RpDelete, Self::BlockingDeleter)> {
+  -     self.as_ref().blocking_delete()
+  - }
+  - 
+  - fn blocking_list(&self, path: &str, args: OpList) -> Result<(RpList, Self::BlockingLister)> {
+  -     self.as_ref().blocking_list(path, args)
+  - }
+  - 
+  - fn blocking_copy(&self, from: &str, to: &str, args: OpCopy) -> Result<RpCopy> {
+  -     self.as_ref().blocking_copy(from, to, args)
+  - }
+  - 
+  - fn blocking_rename(&self, from: &str, to: &str, args: OpRename) -> Result<RpRename> {
+  -     self.as_ref().blocking_rename(from, to, args)
+  - }
+}
+```
+
+Due to this change, we will remove all blocking implementations in services and layers. All existing public APIs that start with `Blocking` will be moved into the `blocking` module. For example, `opendal::BlockingOperator` will be relocated to `opendal::blocking::Operator`.
+
+# Drawbacks
+
+Users who rely on blocking APIs will need to adapt their code to use the new `blocking` module. Users might lost the performance benefits of using native blocking APIs, as they will now be using `block_on` in an async runtime.
+
+# Rationale and alternatives
+
+- We could keep the native blocking support, but this would increase the maintenance burden and complexity of the codebase.
+- We could provide a separate crate for blocking APIs, but this would lead to API inconsistency and confusion for users.
+
+# Prior art
+
+`reqwest` is using the same approach. It provides a blocking client in `reqwest::blocking` module, which is a wrapper around the async client. This allows users to use blocking APIs without the need for native blocking support.
+
+
+# Unresolved questions
+
+None
+
+# Future possibilities
+
+None
diff --git a/core/src/docs/rfcs/mod.rs b/core/src/docs/rfcs/mod.rs
index 778da9a40..def6caa71 100644
--- a/core/src/docs/rfcs/mod.rs
+++ b/core/src/docs/rfcs/mod.rs
@@ -264,3 +264,7 @@ pub mod rfc_5556_write_returns_metadata {}
 /// Read Returns Metadata
 #[doc = include_str!("5871_read_returns_metadata.md")]
 pub mod rfc_5871_read_returns_metadata {}
+
+/// Remove Native Blocking
+#[doc = include_str!("6189_remove_native_blocking.md")]
+pub mod rfc_6189_remove_native_blocking {}