This is an automated email from the ASF dual-hosted git repository. xuanwo pushed a commit to branch new-idea in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
commit ba345beccca513cb0e580f93048f58306579ff1c Author: Xuanwo <[email protected]> AuthorDate: Tue May 23 20:50:07 2023 +0800 rfc: Add chain based operator API Signed-off-by: Xuanwo <[email protected]> --- .../src/docs/rfcs/0000_chain_based_operator_api.md | 99 ++++++++++++++++++++++ core/src/docs/rfcs/mod.rs | 3 + 2 files changed, 102 insertions(+) diff --git a/core/src/docs/rfcs/0000_chain_based_operator_api.md b/core/src/docs/rfcs/0000_chain_based_operator_api.md new file mode 100644 index 00000000..35d6818e --- /dev/null +++ b/core/src/docs/rfcs/0000_chain_based_operator_api.md @@ -0,0 +1,99 @@ +- Proposal Name: `chain_based_operator_api` +- Start Date: 2023-05-23 +- RFC PR: [apache/incubator-opendal#0000](https://github.com/apache/incubator-opendal/pull/0000) +- Tracking Issue: [apache/incubator-opendal#0000](https://github.com/apache/incubator-opendal/issues/0000) + +# Summary + +Add chain based Operator API to replace `OpXxx`. + +# Motivation + +OpenDAL provides `xxx_with` API for users to add more options for requests: + +```rust +let bs = op.read_with("path/to/file", OpRead::new().with_range(0..=1024)).await?; +``` + +However, the API's usability is hindered as users are required to create a new `OpXxx` struct. The API call can be excessively verbose: + +```rust +let bs = op.read_with( + "path/to/file", + OpRead::new() + .with_range(0..=1024) + .with_if_match("<etag>") + .with_if_none_match("<etag>") + .with_override_cache_control("<cache_control>") + .with_override_content_disposition("<content_disposition>") + ).await?; +``` + + +# Guide-level explanation + +In this proposal, I plan to introduce chain based `Operator` API to make them more firendly to use: + +```rust +let bs = op.read_with("path/to/file") + .range(0..=1024) + .if_match("<etag>") + .if_none_match("<etag>") + .override_cache_control("<cache_control>") + .override_content_disposition("<content_disposition>") + .await?; +``` + +By eliminating the usage of `OpXxx`, our users can write code that is more readable. + +# Reference-level explanation + +To implement chain based API, we will change `read_with` as following: + +```diff +- pub async fn read_with(&self, path: &str, args: OpRead) -> Result<Vec<u8>> ++ pub fn read_with(&self, path: &str) -> FutureRead +``` + +`FutureRead` will implement `Future<Output=Result<Vec<u8>>>`, so that users can still call `read_with` like the following: + +```rust +let bs = op.read_with("path/to/file").await?; +``` + +For blocking operations, we will change `read_with` as following: + +```diff +- pub fn read_with(&self, path: &str, args: OpRead) -> Result<Vec<u8>> ++ pub fn read_with(&self, path: &str) -> FunctionRead +``` + +`FunctionRead` will implement `call(self) -> Result<Vec<u8>>`, so that users can call `read_with` like the following: + +```rust +let bs = op.read_with("path/to/file").call()?; +``` + +After this change, all `OpXxx` will be moved as raw API. + +# Drawbacks + +None + +# Rationale and alternatives + +None + +# Prior art + +None + +# Unresolved questions + +None + +# Future possibilities + +## Change API after fn_traits stablized + +After [fn_traits](https://github.com/rust-lang/rust/issues/29625) get stablized, we will implement `FnOnce` for `FunctionXxx` instead of `call`. diff --git a/core/src/docs/rfcs/mod.rs b/core/src/docs/rfcs/mod.rs index a27593b0..b73ac282 100644 --- a/core/src/docs/rfcs/mod.rs +++ b/core/src/docs/rfcs/mod.rs @@ -139,3 +139,6 @@ pub mod rfc_2083_writer_sink_api {} #[doc = include_str!("2133_append_api.md")] pub mod rfc_2133_append_api {} + +#[doc = include_str!("0000_chain_based_operator_api.md")] +pub mod rfc_0000_chain_based_operator_api {}
