opendal 0.1.6.pre.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.standard.yml +20 -0
- data/.tool-versions +1 -0
- data/.yardopts +1 -0
- data/Cargo.toml +65 -0
- data/DEPENDENCIES.md +9 -0
- data/DEPENDENCIES.rust.tsv +277 -0
- data/Gemfile +35 -0
- data/README.md +159 -0
- data/Rakefile +149 -0
- data/build.rs +22 -0
- data/core/CHANGELOG.md +4929 -0
- data/core/CONTRIBUTING.md +61 -0
- data/core/Cargo.lock +10259 -0
- data/core/Cargo.toml +437 -0
- data/core/DEPENDENCIES.md +3 -0
- data/core/DEPENDENCIES.rust.tsv +185 -0
- data/core/LICENSE +201 -0
- data/core/README.md +228 -0
- data/core/benches/README.md +18 -0
- data/core/benches/ops/README.md +26 -0
- data/core/benches/ops/main.rs +25 -0
- data/core/benches/ops/read.rs +100 -0
- data/core/benches/ops/utils.rs +59 -0
- data/core/benches/ops/write.rs +106 -0
- data/core/benches/types/README.md +9 -0
- data/core/benches/types/buffer.rs +114 -0
- data/core/benches/types/main.rs +23 -0
- data/core/benches/types/tasks.rs +64 -0
- data/core/benches/vs_fs/Cargo.toml +32 -0
- data/core/benches/vs_fs/README.md +35 -0
- data/core/benches/vs_fs/src/main.rs +83 -0
- data/core/benches/vs_s3/Cargo.toml +38 -0
- data/core/benches/vs_s3/README.md +55 -0
- data/core/benches/vs_s3/src/main.rs +123 -0
- data/core/edge/README.md +3 -0
- data/core/edge/file_write_on_full_disk/Cargo.toml +31 -0
- data/core/edge/file_write_on_full_disk/README.md +14 -0
- data/core/edge/file_write_on_full_disk/src/main.rs +43 -0
- data/core/edge/s3_aws_assume_role_with_web_identity/Cargo.toml +30 -0
- data/core/edge/s3_aws_assume_role_with_web_identity/README.md +18 -0
- data/core/edge/s3_aws_assume_role_with_web_identity/src/main.rs +34 -0
- data/core/edge/s3_read_on_wasm/.gitignore +3 -0
- data/core/edge/s3_read_on_wasm/Cargo.toml +38 -0
- data/core/edge/s3_read_on_wasm/README.md +42 -0
- data/core/edge/s3_read_on_wasm/src/lib.rs +60 -0
- data/core/edge/s3_read_on_wasm/webdriver.json +15 -0
- data/core/examples/README.md +23 -0
- data/core/examples/basic/Cargo.toml +29 -0
- data/core/examples/basic/README.md +15 -0
- data/core/examples/basic/src/main.rs +51 -0
- data/core/examples/concurrent-upload/Cargo.toml +29 -0
- data/core/examples/concurrent-upload/README.md +15 -0
- data/core/examples/concurrent-upload/src/main.rs +68 -0
- data/core/examples/multipart-upload/Cargo.toml +29 -0
- data/core/examples/multipart-upload/README.md +15 -0
- data/core/examples/multipart-upload/src/main.rs +56 -0
- data/core/fuzz/.gitignore +5 -0
- data/core/fuzz/Cargo.toml +92 -0
- data/core/fuzz/README.md +68 -0
- data/core/fuzz/fuzz_reader.rs +102 -0
- data/core/fuzz/fuzz_writer.rs +123 -0
- data/core/src/blocking/delete.rs +74 -0
- data/core/src/blocking/list.rs +71 -0
- data/core/src/blocking/mod.rs +33 -0
- data/core/src/blocking/operator.rs +729 -0
- data/core/src/blocking/read/buffer_iterator.rs +66 -0
- data/core/src/blocking/read/mod.rs +27 -0
- data/core/src/blocking/read/reader.rs +124 -0
- data/core/src/blocking/read/std_bytes_iterator.rs +69 -0
- data/core/src/blocking/read/std_reader.rs +95 -0
- data/core/src/blocking/write/mod.rs +22 -0
- data/core/src/blocking/write/std_writer.rs +82 -0
- data/core/src/blocking/write/writer.rs +109 -0
- data/core/src/docs/comparisons/mod.rs +30 -0
- data/core/src/docs/comparisons/vs_object_store.md +183 -0
- data/core/src/docs/concepts.rs +135 -0
- data/core/src/docs/internals/accessor.rs +306 -0
- data/core/src/docs/internals/layer.rs +42 -0
- data/core/src/docs/internals/mod.rs +62 -0
- data/core/src/docs/mod.rs +43 -0
- data/core/src/docs/performance/concurrent_write.md +101 -0
- data/core/src/docs/performance/http_optimization.md +124 -0
- data/core/src/docs/performance/mod.rs +32 -0
- data/core/src/docs/rfcs/0000_example.md +74 -0
- data/core/src/docs/rfcs/0000_foyer_integration.md +111 -0
- data/core/src/docs/rfcs/0041_object_native_api.md +185 -0
- data/core/src/docs/rfcs/0044_error_handle.md +198 -0
- data/core/src/docs/rfcs/0057_auto_region.md +160 -0
- data/core/src/docs/rfcs/0069_object_stream.md +145 -0
- data/core/src/docs/rfcs/0090_limited_reader.md +155 -0
- data/core/src/docs/rfcs/0112_path_normalization.md +79 -0
- data/core/src/docs/rfcs/0191_async_streaming_io.md +328 -0
- data/core/src/docs/rfcs/0203_remove_credential.md +96 -0
- data/core/src/docs/rfcs/0221_create_dir.md +89 -0
- data/core/src/docs/rfcs/0247_retryable_error.md +87 -0
- data/core/src/docs/rfcs/0293_object_id.md +67 -0
- data/core/src/docs/rfcs/0337_dir_entry.md +191 -0
- data/core/src/docs/rfcs/0409_accessor_capabilities.md +67 -0
- data/core/src/docs/rfcs/0413_presign.md +154 -0
- data/core/src/docs/rfcs/0423_command_line_interface.md +268 -0
- data/core/src/docs/rfcs/0429_init_from_iter.md +107 -0
- data/core/src/docs/rfcs/0438_multipart.md +163 -0
- data/core/src/docs/rfcs/0443_gateway.md +73 -0
- data/core/src/docs/rfcs/0501_new_builder.md +111 -0
- data/core/src/docs/rfcs/0554_write_refactor.md +96 -0
- data/core/src/docs/rfcs/0561_list_metadata_reuse.md +210 -0
- data/core/src/docs/rfcs/0599_blocking_api.md +157 -0
- data/core/src/docs/rfcs/0623_redis_service.md +300 -0
- data/core/src/docs/rfcs/0627_split_capabilities.md +89 -0
- data/core/src/docs/rfcs/0661_path_in_accessor.md +126 -0
- data/core/src/docs/rfcs/0793_generic_kv_services.md +209 -0
- data/core/src/docs/rfcs/0926_object_reader.md +93 -0
- data/core/src/docs/rfcs/0977_refactor_error.md +151 -0
- data/core/src/docs/rfcs/1085_object_handler.md +73 -0
- data/core/src/docs/rfcs/1391_object_metadataer.md +110 -0
- data/core/src/docs/rfcs/1398_query_based_metadata.md +125 -0
- data/core/src/docs/rfcs/1420_object_writer.md +147 -0
- data/core/src/docs/rfcs/1477_remove_object_concept.md +159 -0
- data/core/src/docs/rfcs/1735_operation_extension.md +117 -0
- data/core/src/docs/rfcs/2083_writer_sink_api.md +106 -0
- data/core/src/docs/rfcs/2133_append_api.md +88 -0
- data/core/src/docs/rfcs/2299_chain_based_operator_api.md +99 -0
- data/core/src/docs/rfcs/2602_object_versioning.md +138 -0
- data/core/src/docs/rfcs/2758_merge_append_into_write.md +79 -0
- data/core/src/docs/rfcs/2774_lister_api.md +66 -0
- data/core/src/docs/rfcs/2779_list_with_metakey.md +143 -0
- data/core/src/docs/rfcs/2852_native_capability.md +58 -0
- data/core/src/docs/rfcs/2884_merge_range_read_into_read.md +80 -0
- data/core/src/docs/rfcs/3017_remove_write_copy_from.md +94 -0
- data/core/src/docs/rfcs/3197_config.md +237 -0
- data/core/src/docs/rfcs/3232_align_list_api.md +69 -0
- data/core/src/docs/rfcs/3243_list_prefix.md +128 -0
- data/core/src/docs/rfcs/3356_lazy_reader.md +111 -0
- data/core/src/docs/rfcs/3526_list_recursive.md +59 -0
- data/core/src/docs/rfcs/3574_concurrent_stat_in_list.md +80 -0
- data/core/src/docs/rfcs/3734_buffered_reader.md +64 -0
- data/core/src/docs/rfcs/3898_concurrent_writer.md +66 -0
- data/core/src/docs/rfcs/3911_deleter_api.md +165 -0
- data/core/src/docs/rfcs/4382_range_based_read.md +213 -0
- data/core/src/docs/rfcs/4638_executor.md +215 -0
- data/core/src/docs/rfcs/5314_remove_metakey.md +120 -0
- data/core/src/docs/rfcs/5444_operator_from_uri.md +162 -0
- data/core/src/docs/rfcs/5479_context.md +140 -0
- data/core/src/docs/rfcs/5485_conditional_reader.md +112 -0
- data/core/src/docs/rfcs/5495_list_with_deleted.md +81 -0
- data/core/src/docs/rfcs/5556_write_returns_metadata.md +121 -0
- data/core/src/docs/rfcs/5871_read_returns_metadata.md +112 -0
- data/core/src/docs/rfcs/6189_remove_native_blocking.md +106 -0
- data/core/src/docs/rfcs/6209_glob_support.md +132 -0
- data/core/src/docs/rfcs/6213_options_api.md +142 -0
- data/core/src/docs/rfcs/README.md +62 -0
- data/core/src/docs/rfcs/mod.rs +278 -0
- data/core/src/docs/upgrade.md +1556 -0
- data/core/src/layers/async_backtrace.rs +174 -0
- data/core/src/layers/await_tree.rs +202 -0
- data/core/src/layers/capability_check.rs +239 -0
- data/core/src/layers/chaos.rs +170 -0
- data/core/src/layers/complete.rs +385 -0
- data/core/src/layers/concurrent_limit.rs +322 -0
- data/core/src/layers/correctness_check.rs +440 -0
- data/core/src/layers/dtrace.rs +294 -0
- data/core/src/layers/error_context.rs +310 -0
- data/core/src/layers/fastmetrics.rs +525 -0
- data/core/src/layers/fastrace.rs +271 -0
- data/core/src/layers/http_client.rs +206 -0
- data/core/src/layers/immutable_index.rs +408 -0
- data/core/src/layers/logging.rs +842 -0
- data/core/src/layers/metrics.rs +182 -0
- data/core/src/layers/mime_guess.rs +199 -0
- data/core/src/layers/mod.rs +130 -0
- data/core/src/layers/observe/metrics.rs +936 -0
- data/core/src/layers/observe/mod.rs +93 -0
- data/core/src/layers/otelmetrics.rs +496 -0
- data/core/src/layers/oteltrace.rs +203 -0
- data/core/src/layers/prometheus.rs +686 -0
- data/core/src/layers/prometheus_client.rs +519 -0
- data/core/src/layers/retry.rs +933 -0
- data/core/src/layers/throttle.rs +204 -0
- data/core/src/layers/timeout.rs +513 -0
- data/core/src/layers/tracing.rs +349 -0
- data/core/src/layers/type_eraser.rs +91 -0
- data/core/src/lib.rs +204 -0
- data/core/src/raw/accessor.rs +856 -0
- data/core/src/raw/adapters/kv/api.rs +164 -0
- data/core/src/raw/adapters/kv/backend.rs +253 -0
- data/core/src/raw/adapters/kv/mod.rs +31 -0
- data/core/src/raw/adapters/mod.rs +50 -0
- data/core/src/raw/adapters/typed_kv/api.rs +171 -0
- data/core/src/raw/adapters/typed_kv/backend.rs +279 -0
- data/core/src/raw/adapters/typed_kv/mod.rs +29 -0
- data/core/src/raw/atomic_util.rs +57 -0
- data/core/src/raw/azure.rs +570 -0
- data/core/src/raw/chrono_util.rs +109 -0
- data/core/src/raw/enum_utils.rs +201 -0
- data/core/src/raw/futures_util.rs +470 -0
- data/core/src/raw/http_util/body.rs +144 -0
- data/core/src/raw/http_util/bytes_content_range.rs +239 -0
- data/core/src/raw/http_util/bytes_range.rs +260 -0
- data/core/src/raw/http_util/client.rs +276 -0
- data/core/src/raw/http_util/error.rs +68 -0
- data/core/src/raw/http_util/header.rs +356 -0
- data/core/src/raw/http_util/mod.rs +78 -0
- data/core/src/raw/http_util/multipart.rs +1180 -0
- data/core/src/raw/http_util/uri.rs +190 -0
- data/core/src/raw/layer.rs +295 -0
- data/core/src/raw/mod.rs +101 -0
- data/core/src/raw/oio/buf/flex_buf.rs +118 -0
- data/core/src/raw/oio/buf/mod.rs +25 -0
- data/core/src/raw/oio/buf/pooled_buf.rs +126 -0
- data/core/src/raw/oio/buf/queue_buf.rs +117 -0
- data/core/src/raw/oio/delete/api.rs +102 -0
- data/core/src/raw/oio/delete/batch_delete.rs +127 -0
- data/core/src/raw/oio/delete/mod.rs +30 -0
- data/core/src/raw/oio/delete/one_shot_delete.rs +79 -0
- data/core/src/raw/oio/entry.rs +89 -0
- data/core/src/raw/oio/list/api.rs +69 -0
- data/core/src/raw/oio/list/flat_list.rs +137 -0
- data/core/src/raw/oio/list/hierarchy_list.rs +135 -0
- data/core/src/raw/oio/list/mod.rs +35 -0
- data/core/src/raw/oio/list/page_list.rs +105 -0
- data/core/src/raw/oio/list/prefix_list.rs +64 -0
- data/core/src/raw/oio/mod.rs +40 -0
- data/core/src/raw/oio/read/api.rs +119 -0
- data/core/src/raw/oio/read/mod.rs +21 -0
- data/core/src/raw/oio/write/api.rs +103 -0
- data/core/src/raw/oio/write/append_write.rs +111 -0
- data/core/src/raw/oio/write/block_write.rs +405 -0
- data/core/src/raw/oio/write/mod.rs +42 -0
- data/core/src/raw/oio/write/multipart_write.rs +518 -0
- data/core/src/raw/oio/write/one_shot_write.rs +77 -0
- data/core/src/raw/oio/write/position_write.rs +284 -0
- data/core/src/raw/operation.rs +88 -0
- data/core/src/raw/ops.rs +917 -0
- data/core/src/raw/path.rs +451 -0
- data/core/src/raw/path_cache.rs +244 -0
- data/core/src/raw/rps.rs +249 -0
- data/core/src/raw/serde_util.rs +423 -0
- data/core/src/raw/std_io_util.rs +65 -0
- data/core/src/raw/tests/mod.rs +30 -0
- data/core/src/raw/tests/read.rs +116 -0
- data/core/src/raw/tests/utils.rs +80 -0
- data/core/src/raw/tests/write.rs +79 -0
- data/core/src/raw/tokio_util.rs +24 -0
- data/core/src/raw/version.rs +19 -0
- data/core/src/services/aliyun_drive/backend.rs +421 -0
- data/core/src/services/aliyun_drive/config.rs +72 -0
- data/core/src/services/aliyun_drive/core.rs +651 -0
- data/core/src/services/aliyun_drive/delete.rs +51 -0
- data/core/src/services/aliyun_drive/docs.md +61 -0
- data/core/src/services/aliyun_drive/error.rs +56 -0
- data/core/src/services/aliyun_drive/lister.rs +134 -0
- data/core/src/services/aliyun_drive/mod.rs +39 -0
- data/core/src/services/aliyun_drive/writer.rs +114 -0
- data/core/src/services/alluxio/backend.rs +257 -0
- data/core/src/services/alluxio/config.rs +50 -0
- data/core/src/services/alluxio/core.rs +367 -0
- data/core/src/services/alluxio/delete.rs +38 -0
- data/core/src/services/alluxio/docs.md +45 -0
- data/core/src/services/alluxio/error.rs +99 -0
- data/core/src/services/alluxio/lister.rs +73 -0
- data/core/src/services/alluxio/mod.rs +39 -0
- data/core/src/services/alluxio/writer.rs +74 -0
- data/core/src/services/azblob/backend.rs +594 -0
- data/core/src/services/azblob/config.rs +220 -0
- data/core/src/services/azblob/core.rs +937 -0
- data/core/src/services/azblob/delete.rs +108 -0
- data/core/src/services/azblob/docs.md +77 -0
- data/core/src/services/azblob/error.rs +164 -0
- data/core/src/services/azblob/lister.rs +107 -0
- data/core/src/services/azblob/mod.rs +38 -0
- data/core/src/services/azblob/writer.rs +177 -0
- data/core/src/services/azdls/backend.rs +435 -0
- data/core/src/services/azdls/config.rs +89 -0
- data/core/src/services/azdls/core.rs +388 -0
- data/core/src/services/azdls/delete.rs +48 -0
- data/core/src/services/azdls/docs.md +73 -0
- data/core/src/services/azdls/error.rs +107 -0
- data/core/src/services/azdls/lister.rs +165 -0
- data/core/src/services/azdls/mod.rs +38 -0
- data/core/src/services/azdls/writer.rs +129 -0
- data/core/src/services/azfile/backend.rs +373 -0
- data/core/src/services/azfile/config.rs +61 -0
- data/core/src/services/azfile/core.rs +435 -0
- data/core/src/services/azfile/delete.rs +51 -0
- data/core/src/services/azfile/docs.md +65 -0
- data/core/src/services/azfile/error.rs +108 -0
- data/core/src/services/azfile/lister.rs +217 -0
- data/core/src/services/azfile/mod.rs +39 -0
- data/core/src/services/azfile/writer.rs +92 -0
- data/core/src/services/b2/backend.rs +434 -0
- data/core/src/services/b2/config.rs +64 -0
- data/core/src/services/b2/core.rs +742 -0
- data/core/src/services/b2/delete.rs +56 -0
- data/core/src/services/b2/docs.md +54 -0
- data/core/src/services/b2/error.rs +132 -0
- data/core/src/services/b2/lister.rs +110 -0
- data/core/src/services/b2/mod.rs +39 -0
- data/core/src/services/b2/writer.rs +189 -0
- data/core/src/services/cacache/backend.rs +160 -0
- data/core/src/services/cacache/config.rs +28 -0
- data/core/src/services/cacache/core.rs +96 -0
- data/core/src/services/cacache/delete.rs +39 -0
- data/core/src/services/cacache/docs.md +38 -0
- data/core/src/services/cacache/mod.rs +34 -0
- data/core/src/services/cacache/writer.rs +61 -0
- data/core/src/services/cloudflare_kv/backend.rs +513 -0
- data/core/src/services/cloudflare_kv/config.rs +55 -0
- data/core/src/services/cloudflare_kv/core.rs +168 -0
- data/core/src/services/cloudflare_kv/delete.rs +119 -0
- data/core/src/services/cloudflare_kv/docs.md +21 -0
- data/core/src/services/cloudflare_kv/error.rs +79 -0
- data/core/src/services/cloudflare_kv/lister.rs +170 -0
- data/core/src/services/cloudflare_kv/mod.rs +39 -0
- data/core/src/services/cloudflare_kv/model.rs +76 -0
- data/core/src/services/cloudflare_kv/writer.rs +68 -0
- data/core/src/services/compfs/backend.rs +290 -0
- data/core/src/services/compfs/config.rs +30 -0
- data/core/src/services/compfs/core.rs +159 -0
- data/core/src/services/compfs/delete.rs +53 -0
- data/core/src/services/compfs/lister.rs +98 -0
- data/core/src/services/compfs/mod.rs +38 -0
- data/core/src/services/compfs/reader.rs +79 -0
- data/core/src/services/compfs/writer.rs +90 -0
- data/core/src/services/cos/backend.rs +442 -0
- data/core/src/services/cos/config.rs +54 -0
- data/core/src/services/cos/core.rs +761 -0
- data/core/src/services/cos/delete.rs +48 -0
- data/core/src/services/cos/docs.md +55 -0
- data/core/src/services/cos/error.rs +105 -0
- data/core/src/services/cos/lister.rs +237 -0
- data/core/src/services/cos/mod.rs +39 -0
- data/core/src/services/cos/writer.rs +234 -0
- data/core/src/services/d1/backend.rs +330 -0
- data/core/src/services/d1/config.rs +55 -0
- data/core/src/services/d1/docs.md +48 -0
- data/core/src/services/d1/error.rs +79 -0
- data/core/src/services/d1/mod.rs +29 -0
- data/core/src/services/d1/model.rs +125 -0
- data/core/src/services/dashmap/backend.rs +203 -0
- data/core/src/services/dashmap/config.rs +37 -0
- data/core/src/services/dashmap/core.rs +61 -0
- data/core/src/services/dashmap/delete.rs +40 -0
- data/core/src/services/dashmap/docs.md +38 -0
- data/core/src/services/dashmap/lister.rs +63 -0
- data/core/src/services/dashmap/mod.rs +36 -0
- data/core/src/services/dashmap/writer.rs +87 -0
- data/core/src/services/dbfs/backend.rs +258 -0
- data/core/src/services/dbfs/config.rs +48 -0
- data/core/src/services/dbfs/core.rs +191 -0
- data/core/src/services/dbfs/delete.rs +49 -0
- data/core/src/services/dbfs/docs.md +57 -0
- data/core/src/services/dbfs/error.rs +74 -0
- data/core/src/services/dbfs/lister.rs +96 -0
- data/core/src/services/dbfs/mod.rs +38 -0
- data/core/src/services/dbfs/writer.rs +64 -0
- data/core/src/services/dropbox/backend.rs +187 -0
- data/core/src/services/dropbox/builder.rs +222 -0
- data/core/src/services/dropbox/config.rs +47 -0
- data/core/src/services/dropbox/core.rs +496 -0
- data/core/src/services/dropbox/delete.rs +54 -0
- data/core/src/services/dropbox/docs.md +64 -0
- data/core/src/services/dropbox/error.rs +85 -0
- data/core/src/services/dropbox/lister.rs +117 -0
- data/core/src/services/dropbox/mod.rs +40 -0
- data/core/src/services/dropbox/writer.rs +51 -0
- data/core/src/services/etcd/backend.rs +345 -0
- data/core/src/services/etcd/config.rs +86 -0
- data/core/src/services/etcd/core.rs +143 -0
- data/core/src/services/etcd/deleter.rs +41 -0
- data/core/src/services/etcd/docs.md +45 -0
- data/core/src/services/etcd/error.rs +26 -0
- data/core/src/services/etcd/lister.rs +79 -0
- data/core/src/services/etcd/mod.rs +36 -0
- data/core/src/services/etcd/writer.rs +61 -0
- data/core/src/services/foundationdb/backend.rs +171 -0
- data/core/src/services/foundationdb/config.rs +45 -0
- data/core/src/services/foundationdb/docs.md +42 -0
- data/core/src/services/foundationdb/mod.rs +24 -0
- data/core/src/services/fs/backend.rs +299 -0
- data/core/src/services/fs/config.rs +33 -0
- data/core/src/services/fs/core.rs +227 -0
- data/core/src/services/fs/delete.rs +53 -0
- data/core/src/services/fs/docs.md +49 -0
- data/core/src/services/fs/error.rs +31 -0
- data/core/src/services/fs/lister.rs +81 -0
- data/core/src/services/fs/mod.rs +40 -0
- data/core/src/services/fs/reader.rs +83 -0
- data/core/src/services/fs/writer.rs +212 -0
- data/core/src/services/ftp/backend.rs +388 -0
- data/core/src/services/ftp/config.rs +46 -0
- data/core/src/services/ftp/core.rs +136 -0
- data/core/src/services/ftp/delete.rs +62 -0
- data/core/src/services/ftp/docs.md +42 -0
- data/core/src/services/ftp/err.rs +47 -0
- data/core/src/services/ftp/lister.rs +72 -0
- data/core/src/services/ftp/mod.rs +41 -0
- data/core/src/services/ftp/reader.rs +84 -0
- data/core/src/services/ftp/writer.rs +122 -0
- data/core/src/services/gcs/backend.rs +499 -0
- data/core/src/services/gcs/config.rs +168 -0
- data/core/src/services/gcs/core.rs +1079 -0
- data/core/src/services/gcs/delete.rs +98 -0
- data/core/src/services/gcs/docs.md +76 -0
- data/core/src/services/gcs/error.rs +122 -0
- data/core/src/services/gcs/lister.rs +136 -0
- data/core/src/services/gcs/mod.rs +40 -0
- data/core/src/services/gcs/uri.rs +75 -0
- data/core/src/services/gcs/writer.rs +163 -0
- data/core/src/services/gdrive/backend.rs +176 -0
- data/core/src/services/gdrive/builder.rs +228 -0
- data/core/src/services/gdrive/config.rs +47 -0
- data/core/src/services/gdrive/core.rs +499 -0
- data/core/src/services/gdrive/delete.rs +57 -0
- data/core/src/services/gdrive/docs.md +65 -0
- data/core/src/services/gdrive/error.rs +80 -0
- data/core/src/services/gdrive/lister.rs +110 -0
- data/core/src/services/gdrive/mod.rs +40 -0
- data/core/src/services/gdrive/writer.rs +77 -0
- data/core/src/services/ghac/backend.rs +285 -0
- data/core/src/services/ghac/config.rs +36 -0
- data/core/src/services/ghac/core.rs +459 -0
- data/core/src/services/ghac/docs.md +84 -0
- data/core/src/services/ghac/error.rs +52 -0
- data/core/src/services/ghac/mod.rs +35 -0
- data/core/src/services/ghac/writer.rs +201 -0
- data/core/src/services/github/backend.rs +285 -0
- data/core/src/services/github/config.rs +59 -0
- data/core/src/services/github/core.rs +351 -0
- data/core/src/services/github/delete.rs +41 -0
- data/core/src/services/github/docs.md +52 -0
- data/core/src/services/github/error.rs +101 -0
- data/core/src/services/github/lister.rs +112 -0
- data/core/src/services/github/mod.rs +38 -0
- data/core/src/services/github/writer.rs +51 -0
- data/core/src/services/gridfs/backend.rs +166 -0
- data/core/src/services/gridfs/config.rs +50 -0
- data/core/src/services/gridfs/core.rs +154 -0
- data/core/src/services/gridfs/docs.md +46 -0
- data/core/src/services/gridfs/mod.rs +26 -0
- data/core/src/services/hdfs/backend.rs +413 -0
- data/core/src/services/hdfs/config.rs +59 -0
- data/core/src/services/hdfs/delete.rs +62 -0
- data/core/src/services/hdfs/docs.md +140 -0
- data/core/src/services/hdfs/lister.rs +70 -0
- data/core/src/services/hdfs/mod.rs +36 -0
- data/core/src/services/hdfs/reader.rs +79 -0
- data/core/src/services/hdfs/writer.rs +104 -0
- data/core/src/services/hdfs_native/backend.rs +340 -0
- data/core/src/services/hdfs_native/config.rs +45 -0
- data/core/src/services/hdfs_native/delete.rs +47 -0
- data/core/src/services/hdfs_native/docs.md +35 -0
- data/core/src/services/hdfs_native/error.rs +59 -0
- data/core/src/services/hdfs_native/lister.rs +85 -0
- data/core/src/services/hdfs_native/mod.rs +39 -0
- data/core/src/services/hdfs_native/reader.rs +62 -0
- data/core/src/services/hdfs_native/writer.rs +61 -0
- data/core/src/services/http/backend.rs +291 -0
- data/core/src/services/http/config.rs +49 -0
- data/core/src/services/http/core.rs +125 -0
- data/core/src/services/http/docs.md +45 -0
- data/core/src/services/http/error.rs +53 -0
- data/core/src/services/http/mod.rs +32 -0
- data/core/src/services/huggingface/backend.rs +289 -0
- data/core/src/services/huggingface/config.rs +75 -0
- data/core/src/services/huggingface/core.rs +406 -0
- data/core/src/services/huggingface/docs.md +61 -0
- data/core/src/services/huggingface/error.rs +93 -0
- data/core/src/services/huggingface/lister.rs +91 -0
- data/core/src/services/huggingface/mod.rs +34 -0
- data/core/src/services/ipfs/backend.rs +257 -0
- data/core/src/services/ipfs/config.rs +32 -0
- data/core/src/services/ipfs/core.rs +239 -0
- data/core/src/services/ipfs/docs.md +45 -0
- data/core/src/services/ipfs/error.rs +52 -0
- data/core/src/services/ipfs/ipld.rs +162 -0
- data/core/src/services/ipfs/mod.rs +34 -0
- data/core/src/services/ipmfs/backend.rs +147 -0
- data/core/src/services/ipmfs/builder.rs +166 -0
- data/core/src/services/ipmfs/config.rs +32 -0
- data/core/src/services/ipmfs/core.rs +142 -0
- data/core/src/services/ipmfs/delete.rs +48 -0
- data/core/src/services/ipmfs/docs.md +14 -0
- data/core/src/services/ipmfs/error.rs +83 -0
- data/core/src/services/ipmfs/lister.rs +135 -0
- data/core/src/services/ipmfs/mod.rs +40 -0
- data/core/src/services/ipmfs/writer.rs +49 -0
- data/core/src/services/koofr/backend.rs +361 -0
- data/core/src/services/koofr/config.rs +50 -0
- data/core/src/services/koofr/core.rs +458 -0
- data/core/src/services/koofr/delete.rs +50 -0
- data/core/src/services/koofr/docs.md +51 -0
- data/core/src/services/koofr/error.rs +72 -0
- data/core/src/services/koofr/lister.rs +88 -0
- data/core/src/services/koofr/mod.rs +38 -0
- data/core/src/services/koofr/writer.rs +53 -0
- data/core/src/services/lakefs/backend.rs +309 -0
- data/core/src/services/lakefs/config.rs +81 -0
- data/core/src/services/lakefs/core.rs +261 -0
- data/core/src/services/lakefs/delete.rs +54 -0
- data/core/src/services/lakefs/docs.md +62 -0
- data/core/src/services/lakefs/error.rs +93 -0
- data/core/src/services/lakefs/lister.rs +120 -0
- data/core/src/services/lakefs/mod.rs +38 -0
- data/core/src/services/lakefs/writer.rs +50 -0
- data/core/src/services/memcached/backend.rs +284 -0
- data/core/src/services/memcached/binary.rs +289 -0
- data/core/src/services/memcached/config.rs +43 -0
- data/core/src/services/memcached/docs.md +47 -0
- data/core/src/services/memcached/mod.rs +27 -0
- data/core/src/services/memory/backend.rs +205 -0
- data/core/src/services/memory/config.rs +30 -0
- data/core/src/services/memory/core.rs +80 -0
- data/core/src/services/memory/delete.rs +42 -0
- data/core/src/services/memory/docs.md +36 -0
- data/core/src/services/memory/lister.rs +56 -0
- data/core/src/services/memory/mod.rs +36 -0
- data/core/src/services/memory/writer.rs +85 -0
- data/core/src/services/mini_moka/backend.rs +260 -0
- data/core/src/services/mini_moka/config.rs +56 -0
- data/core/src/services/mini_moka/core.rs +52 -0
- data/core/src/services/mini_moka/delete.rs +42 -0
- data/core/src/services/mini_moka/docs.md +19 -0
- data/core/src/services/mini_moka/lister.rs +68 -0
- data/core/src/services/mini_moka/mod.rs +36 -0
- data/core/src/services/mini_moka/writer.rs +84 -0
- data/core/src/services/mod.rs +206 -0
- data/core/src/services/moka/backend.rs +326 -0
- data/core/src/services/moka/config.rs +59 -0
- data/core/src/services/moka/core.rs +62 -0
- data/core/src/services/moka/delete.rs +42 -0
- data/core/src/services/moka/docs.md +42 -0
- data/core/src/services/moka/lister.rs +65 -0
- data/core/src/services/moka/mod.rs +41 -0
- data/core/src/services/moka/writer.rs +83 -0
- data/core/src/services/mongodb/backend.rs +291 -0
- data/core/src/services/mongodb/config.rs +54 -0
- data/core/src/services/mongodb/docs.md +49 -0
- data/core/src/services/mongodb/mod.rs +24 -0
- data/core/src/services/monoiofs/backend.rs +238 -0
- data/core/src/services/monoiofs/config.rs +34 -0
- data/core/src/services/monoiofs/core.rs +313 -0
- data/core/src/services/monoiofs/delete.rs +64 -0
- data/core/src/services/monoiofs/docs.md +46 -0
- data/core/src/services/monoiofs/mod.rs +36 -0
- data/core/src/services/monoiofs/reader.rs +147 -0
- data/core/src/services/monoiofs/writer.rs +189 -0
- data/core/src/services/mysql/backend.rs +256 -0
- data/core/src/services/mysql/config.rs +66 -0
- data/core/src/services/mysql/docs.md +47 -0
- data/core/src/services/mysql/mod.rs +24 -0
- data/core/src/services/obs/backend.rs +442 -0
- data/core/src/services/obs/config.rs +53 -0
- data/core/src/services/obs/core.rs +608 -0
- data/core/src/services/obs/delete.rs +48 -0
- data/core/src/services/obs/docs.md +54 -0
- data/core/src/services/obs/error.rs +106 -0
- data/core/src/services/obs/lister.rs +101 -0
- data/core/src/services/obs/mod.rs +38 -0
- data/core/src/services/obs/writer.rs +235 -0
- data/core/src/services/onedrive/backend.rs +127 -0
- data/core/src/services/onedrive/builder.rs +236 -0
- data/core/src/services/onedrive/config.rs +49 -0
- data/core/src/services/onedrive/core.rs +691 -0
- data/core/src/services/onedrive/delete.rs +47 -0
- data/core/src/services/onedrive/docs.md +115 -0
- data/core/src/services/onedrive/error.rs +61 -0
- data/core/src/services/onedrive/graph_model.rs +425 -0
- data/core/src/services/onedrive/lister.rs +150 -0
- data/core/src/services/onedrive/mod.rs +42 -0
- data/core/src/services/onedrive/writer.rs +168 -0
- data/core/src/services/opfs/backend.rs +50 -0
- data/core/src/services/opfs/config.rs +25 -0
- data/core/src/services/opfs/core.rs +74 -0
- data/core/src/services/opfs/docs.md +18 -0
- data/core/src/services/opfs/error.rs +27 -0
- data/core/src/services/opfs/mod.rs +30 -0
- data/core/src/services/opfs/utils.rs +70 -0
- data/core/src/services/oss/backend.rs +734 -0
- data/core/src/services/oss/config.rs +113 -0
- data/core/src/services/oss/core.rs +1088 -0
- data/core/src/services/oss/delete.rs +109 -0
- data/core/src/services/oss/docs.md +74 -0
- data/core/src/services/oss/error.rs +109 -0
- data/core/src/services/oss/lister.rs +256 -0
- data/core/src/services/oss/mod.rs +38 -0
- data/core/src/services/oss/writer.rs +228 -0
- data/core/src/services/pcloud/backend.rs +358 -0
- data/core/src/services/pcloud/config.rs +51 -0
- data/core/src/services/pcloud/core.rs +461 -0
- data/core/src/services/pcloud/delete.rs +66 -0
- data/core/src/services/pcloud/docs.md +51 -0
- data/core/src/services/pcloud/error.rs +88 -0
- data/core/src/services/pcloud/lister.rs +95 -0
- data/core/src/services/pcloud/mod.rs +38 -0
- data/core/src/services/pcloud/writer.rs +66 -0
- data/core/src/services/persy/backend.rs +226 -0
- data/core/src/services/persy/config.rs +32 -0
- data/core/src/services/persy/docs.md +43 -0
- data/core/src/services/persy/mod.rs +24 -0
- data/core/src/services/postgresql/backend.rs +258 -0
- data/core/src/services/postgresql/config.rs +66 -0
- data/core/src/services/postgresql/docs.md +47 -0
- data/core/src/services/postgresql/mod.rs +24 -0
- data/core/src/services/redb/backend.rs +280 -0
- data/core/src/services/redb/config.rs +34 -0
- data/core/src/services/redb/docs.md +41 -0
- data/core/src/services/redb/mod.rs +24 -0
- data/core/src/services/redis/backend.rs +442 -0
- data/core/src/services/redis/config.rs +79 -0
- data/core/src/services/redis/core.rs +209 -0
- data/core/src/services/redis/delete.rs +40 -0
- data/core/src/services/redis/docs.md +43 -0
- data/core/src/services/redis/mod.rs +34 -0
- data/core/src/services/redis/writer.rs +57 -0
- data/core/src/services/rocksdb/backend.rs +159 -0
- data/core/src/services/rocksdb/config.rs +34 -0
- data/core/src/services/rocksdb/docs.md +54 -0
- data/core/src/services/rocksdb/mod.rs +24 -0
- data/core/src/services/s3/backend.rs +1293 -0
- data/core/src/services/s3/compatible_services.md +126 -0
- data/core/src/services/s3/config.rs +327 -0
- data/core/src/services/s3/core.rs +1741 -0
- data/core/src/services/s3/delete.rs +109 -0
- data/core/src/services/s3/docs.md +244 -0
- data/core/src/services/s3/error.rs +171 -0
- data/core/src/services/s3/lister.rs +405 -0
- data/core/src/services/s3/mod.rs +38 -0
- data/core/src/services/s3/writer.rs +262 -0
- data/core/src/services/seafile/backend.rs +297 -0
- data/core/src/services/seafile/config.rs +56 -0
- data/core/src/services/seafile/core.rs +475 -0
- data/core/src/services/seafile/delete.rs +40 -0
- data/core/src/services/seafile/docs.md +54 -0
- data/core/src/services/seafile/error.rs +86 -0
- data/core/src/services/seafile/lister.rs +83 -0
- data/core/src/services/seafile/mod.rs +38 -0
- data/core/src/services/seafile/writer.rs +55 -0
- data/core/src/services/sftp/backend.rs +397 -0
- data/core/src/services/sftp/config.rs +50 -0
- data/core/src/services/sftp/core.rs +154 -0
- data/core/src/services/sftp/delete.rs +55 -0
- data/core/src/services/sftp/docs.md +49 -0
- data/core/src/services/sftp/error.rs +57 -0
- data/core/src/services/sftp/lister.rs +88 -0
- data/core/src/services/sftp/mod.rs +42 -0
- data/core/src/services/sftp/reader.rs +78 -0
- data/core/src/services/sftp/utils.rs +51 -0
- data/core/src/services/sftp/writer.rs +67 -0
- data/core/src/services/sled/backend.rs +194 -0
- data/core/src/services/sled/config.rs +45 -0
- data/core/src/services/sled/docs.md +39 -0
- data/core/src/services/sled/mod.rs +24 -0
- data/core/src/services/sqlite/backend.rs +326 -0
- data/core/src/services/sqlite/config.rs +70 -0
- data/core/src/services/sqlite/docs.md +46 -0
- data/core/src/services/sqlite/mod.rs +24 -0
- data/core/src/services/surrealdb/backend.rs +365 -0
- data/core/src/services/surrealdb/config.rs +64 -0
- data/core/src/services/surrealdb/docs.md +54 -0
- data/core/src/services/surrealdb/mod.rs +24 -0
- data/core/src/services/swift/backend.rs +275 -0
- data/core/src/services/swift/compatible_services.md +53 -0
- data/core/src/services/swift/config.rs +53 -0
- data/core/src/services/swift/core.rs +310 -0
- data/core/src/services/swift/delete.rs +49 -0
- data/core/src/services/swift/docs.md +52 -0
- data/core/src/services/swift/error.rs +90 -0
- data/core/src/services/swift/lister.rs +119 -0
- data/core/src/services/swift/mod.rs +38 -0
- data/core/src/services/swift/writer.rs +53 -0
- data/core/src/services/tikv/backend.rs +237 -0
- data/core/src/services/tikv/config.rs +52 -0
- data/core/src/services/tikv/docs.md +43 -0
- data/core/src/services/tikv/mod.rs +24 -0
- data/core/src/services/upyun/backend.rs +317 -0
- data/core/src/services/upyun/config.rs +51 -0
- data/core/src/services/upyun/core.rs +521 -0
- data/core/src/services/upyun/delete.rs +50 -0
- data/core/src/services/upyun/docs.md +51 -0
- data/core/src/services/upyun/error.rs +97 -0
- data/core/src/services/upyun/lister.rs +101 -0
- data/core/src/services/upyun/mod.rs +38 -0
- data/core/src/services/upyun/writer.rs +127 -0
- data/core/src/services/vercel_artifacts/backend.rs +99 -0
- data/core/src/services/vercel_artifacts/builder.rs +117 -0
- data/core/src/services/vercel_artifacts/config.rs +39 -0
- data/core/src/services/vercel_artifacts/core.rs +112 -0
- data/core/src/services/vercel_artifacts/docs.md +40 -0
- data/core/src/services/vercel_artifacts/error.rs +50 -0
- data/core/src/services/vercel_artifacts/mod.rs +36 -0
- data/core/src/services/vercel_artifacts/writer.rs +58 -0
- data/core/src/services/vercel_blob/backend.rs +251 -0
- data/core/src/services/vercel_blob/config.rs +45 -0
- data/core/src/services/vercel_blob/core.rs +449 -0
- data/core/src/services/vercel_blob/delete.rs +38 -0
- data/core/src/services/vercel_blob/docs.md +45 -0
- data/core/src/services/vercel_blob/error.rs +110 -0
- data/core/src/services/vercel_blob/lister.rs +69 -0
- data/core/src/services/vercel_blob/mod.rs +38 -0
- data/core/src/services/vercel_blob/writer.rs +143 -0
- data/core/src/services/webdav/backend.rs +318 -0
- data/core/src/services/webdav/config.rs +53 -0
- data/core/src/services/webdav/core.rs +859 -0
- data/core/src/services/webdav/delete.rs +47 -0
- data/core/src/services/webdav/docs.md +49 -0
- data/core/src/services/webdav/error.rs +53 -0
- data/core/src/services/webdav/lister.rs +106 -0
- data/core/src/services/webdav/mod.rs +38 -0
- data/core/src/services/webdav/writer.rs +56 -0
- data/core/src/services/webhdfs/backend.rs +376 -0
- data/core/src/services/webhdfs/config.rs +52 -0
- data/core/src/services/webhdfs/core.rs +398 -0
- data/core/src/services/webhdfs/delete.rs +46 -0
- data/core/src/services/webhdfs/docs.md +90 -0
- data/core/src/services/webhdfs/error.rs +126 -0
- data/core/src/services/webhdfs/lister.rs +130 -0
- data/core/src/services/webhdfs/message.rs +249 -0
- data/core/src/services/webhdfs/mod.rs +41 -0
- data/core/src/services/webhdfs/writer.rs +177 -0
- data/core/src/services/yandex_disk/backend.rs +267 -0
- data/core/src/services/yandex_disk/config.rs +45 -0
- data/core/src/services/yandex_disk/core.rs +340 -0
- data/core/src/services/yandex_disk/delete.rs +54 -0
- data/core/src/services/yandex_disk/docs.md +45 -0
- data/core/src/services/yandex_disk/error.rs +104 -0
- data/core/src/services/yandex_disk/lister.rs +113 -0
- data/core/src/services/yandex_disk/mod.rs +38 -0
- data/core/src/services/yandex_disk/writer.rs +52 -0
- data/core/src/types/buffer.rs +991 -0
- data/core/src/types/builder.rs +152 -0
- data/core/src/types/capability.rs +209 -0
- data/core/src/types/context/mod.rs +22 -0
- data/core/src/types/context/read.rs +231 -0
- data/core/src/types/context/write.rs +441 -0
- data/core/src/types/delete/deleter.rs +220 -0
- data/core/src/types/delete/futures_delete_sink.rs +176 -0
- data/core/src/types/delete/input.rs +97 -0
- data/core/src/types/delete/mod.rs +26 -0
- data/core/src/types/entry.rs +69 -0
- data/core/src/types/error.rs +570 -0
- data/core/src/types/execute/api.rs +110 -0
- data/core/src/types/execute/executor.rs +96 -0
- data/core/src/types/execute/executors/mod.rs +27 -0
- data/core/src/types/execute/executors/tokio_executor.rs +60 -0
- data/core/src/types/execute/mod.rs +25 -0
- data/core/src/types/list.rs +137 -0
- data/core/src/types/metadata.rs +436 -0
- data/core/src/types/mod.rs +72 -0
- data/core/src/types/mode.rs +68 -0
- data/core/src/types/operator/builder.rs +535 -0
- data/core/src/types/operator/info.rs +63 -0
- data/core/src/types/operator/mod.rs +33 -0
- data/core/src/types/operator/operator.rs +2236 -0
- data/core/src/types/operator/operator_futures.rs +1430 -0
- data/core/src/types/operator/registry.rs +129 -0
- data/core/src/types/options.rs +548 -0
- data/core/src/types/read/buffer_stream.rs +273 -0
- data/core/src/types/read/futures_async_reader.rs +289 -0
- data/core/src/types/read/futures_bytes_stream.rs +157 -0
- data/core/src/types/read/mod.rs +29 -0
- data/core/src/types/read/reader.rs +604 -0
- data/core/src/types/scheme.rs +475 -0
- data/core/src/types/write/buffer_sink.rs +188 -0
- data/core/src/types/write/futures_async_writer.rs +136 -0
- data/core/src/types/write/futures_bytes_sink.rs +103 -0
- data/core/src/types/write/mod.rs +26 -0
- data/core/src/types/write/writer.rs +411 -0
- data/core/tests/behavior/README.md +77 -0
- data/core/tests/behavior/async_copy.rs +314 -0
- data/core/tests/behavior/async_create_dir.rs +53 -0
- data/core/tests/behavior/async_delete.rs +354 -0
- data/core/tests/behavior/async_list.rs +739 -0
- data/core/tests/behavior/async_presign.rs +175 -0
- data/core/tests/behavior/async_read.rs +871 -0
- data/core/tests/behavior/async_rename.rs +210 -0
- data/core/tests/behavior/async_stat.rs +628 -0
- data/core/tests/behavior/async_write.rs +819 -0
- data/core/tests/behavior/main.rs +78 -0
- data/core/tests/behavior/utils.rs +187 -0
- data/core/tests/data/normal_dir/.gitkeep +0 -0
- data/core/tests/data/normal_file.txt +1041 -0
- data/core/tests/data/special_dir !@#$%^&()_+-=;',/.gitkeep +0 -0
- data/core/tests/data/special_file !@#$%^&()_+-=;',.txt +1041 -0
- data/core/users.md +13 -0
- data/extconf.rb +24 -0
- data/lib/opendal.rb +25 -0
- data/lib/opendal_ruby/entry.rb +35 -0
- data/lib/opendal_ruby/io.rb +70 -0
- data/lib/opendal_ruby/metadata.rb +44 -0
- data/lib/opendal_ruby/operator.rb +29 -0
- data/lib/opendal_ruby/operator_info.rb +26 -0
- data/src/capability.rs +146 -0
- data/src/io.rs +464 -0
- data/src/lib.rs +63 -0
- data/src/lister.rs +141 -0
- data/src/metadata.rs +111 -0
- data/src/middlewares.rs +174 -0
- data/src/operator.rs +310 -0
- data/src/operator_info.rs +83 -0
- data/test/blocking_op_test.rb +112 -0
- data/test/capability_test.rb +42 -0
- data/test/io_test.rb +172 -0
- data/test/lister_test.rb +77 -0
- data/test/metadata_test.rb +78 -0
- data/test/middlewares_test.rb +46 -0
- data/test/operator_info_test.rb +35 -0
- data/test/test_helper.rb +36 -0
- metadata +857 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
- Proposal Name: `range_based_read`
|
|
2
|
+
- Start Date: 2024-03-20
|
|
3
|
+
- RFC PR: [apache/opendal#4382](https://github.com/apache/opendal/pull/4382)
|
|
4
|
+
- Tracking Issue: [apache/opendal#4383](https://github.com/apache/opendal/issues/4383)
|
|
5
|
+
|
|
6
|
+
# Summary
|
|
7
|
+
|
|
8
|
+
Convert `oio::Read` into a stateless, range-based reading pattern.
|
|
9
|
+
|
|
10
|
+
# Motivation
|
|
11
|
+
|
|
12
|
+
The current `oio::Read` API is stateful:
|
|
13
|
+
|
|
14
|
+
```rust
|
|
15
|
+
pub trait Read: Unpin + Send + Sync {
|
|
16
|
+
fn read(&mut self, limit: usize) -> impl Future<Output = Result<Bytes>> + Send;
|
|
17
|
+
fn seek(&mut self, pos: io::SeekFrom) -> impl Future<Output = Result<u64>> + Send;
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Users use `read` to retrieve data from storage and can use `seek` to navigate to specific positions. OpenDAL manages the underlying state. This design is good for users from `std::io::Read`, `futures::AsyncRead` and `tokio::io::AsyncRead`.
|
|
22
|
+
|
|
23
|
+
OpenDAL also provides `range` option at the `Operator` level for users to read a specific range of data. The most common usage will be like:
|
|
24
|
+
|
|
25
|
+
```rust
|
|
26
|
+
let r: Reader = op.reader_with(path).range(1024..2048).await?;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
However, after observing our users, we found that:
|
|
30
|
+
|
|
31
|
+
- `AsyncSeek` in `Reader` is prone to misuse.
|
|
32
|
+
- `Reader` does not support concurrent reading.
|
|
33
|
+
- `Reader` can't adopt Completion-based IO
|
|
34
|
+
|
|
35
|
+
## Misuse of `AsyncSeek`
|
|
36
|
+
|
|
37
|
+
When designing `Reader`, I expected users to check the `read_can_seek` capability to determine if the underlying storage services natively support `seek`. However, many users are unaware of this and directly use `seek`, leading to suboptimal performance.
|
|
38
|
+
|
|
39
|
+
For example, `s3` storage does not support `seek` natively. When users call `seek`, opendal will drop current reader and sending a new request. This behavior is hidden from users and can lead to unexpected performance issues like [What's going on in my parquet stream](https://github.com/apache/opendal/issues/3725).
|
|
40
|
+
|
|
41
|
+
## Lack of concurrent reading
|
|
42
|
+
|
|
43
|
+
`oio::Read` complicates supporting concurrent reading. Users must implement a feature similar to merge IO, as discussed in [support merge io read api by settings](https://github.com/apache/opendal/issues/3675).
|
|
44
|
+
|
|
45
|
+
There is no way for opendal to support this feature.
|
|
46
|
+
|
|
47
|
+
## Can't adopt Completion-based IO
|
|
48
|
+
|
|
49
|
+
Completion-based IO requires take the buffer's owner ship. But API that take `&mut [u8]` can't do that.
|
|
50
|
+
|
|
51
|
+
# Guide-level explanation
|
|
52
|
+
|
|
53
|
+
So I propose to convert `Reader` into a stateless, range-based reading pattern.
|
|
54
|
+
|
|
55
|
+
We will remove the following `impl` from `Reader`:
|
|
56
|
+
|
|
57
|
+
- `futures::AsyncRead`
|
|
58
|
+
- `futures::AsyncSeek`
|
|
59
|
+
- `futures::Stream`
|
|
60
|
+
- `tokio::AsyncRead`
|
|
61
|
+
- `tokio::AsyncSeek`
|
|
62
|
+
|
|
63
|
+
We will add the following new APIs to `Reader`:
|
|
64
|
+
|
|
65
|
+
```rust
|
|
66
|
+
impl Reader {
|
|
67
|
+
/// Read data from the storage at the specified offset.
|
|
68
|
+
pub async fn read(&self, buf: &mut impl BufMut, offset: u64, limit: usize) -> Result<usize>;
|
|
69
|
+
|
|
70
|
+
/// Read data from the storage at the specified range.
|
|
71
|
+
pub async fn read_range(
|
|
72
|
+
&self,
|
|
73
|
+
buf: &mut impl BufMut,
|
|
74
|
+
range: impl RangeBounds<u64>,
|
|
75
|
+
) -> Result<usize>;
|
|
76
|
+
|
|
77
|
+
/// Read all data from the storage into given buf.
|
|
78
|
+
pub async fn read_to_end(&self, buf: &mut impl BufMut) -> Result<usize>;
|
|
79
|
+
|
|
80
|
+
/// Copy data from the storage into given writer.
|
|
81
|
+
pub async fn copy(&mut self, write_into: &mut impl futures::AsyncWrite) -> Result<u64>;
|
|
82
|
+
|
|
83
|
+
/// Sink date from the storage into given sink.
|
|
84
|
+
pub async fn sink<S, T>(&mut self, sink_from: &mut S) -> Result<u64>
|
|
85
|
+
where
|
|
86
|
+
S: futures::Sink<T, Error = Error>,
|
|
87
|
+
T: Into<Bytes>,
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Apart from `Reader`'s own API, we will also provide convert to existing IO APIs like:
|
|
92
|
+
|
|
93
|
+
```rust
|
|
94
|
+
impl Reader {
|
|
95
|
+
/// Convert Reader into `futures::AsyncRead`
|
|
96
|
+
pub fn into_futures_io_async_read(self, range: Range<u64>) -> FuturesIoAsyncReader;
|
|
97
|
+
|
|
98
|
+
/// Convert Reader into `futures::Stream`
|
|
99
|
+
pub fn into_futures_bytes_stream(self, range: Range<u64>) -> FuturesBytesStream;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
After this change, users will be able to use `Reader` to read data from storage in a stateless, range-based pattern. Users can also convert `Reader` into `futures::AsyncRead`, `futures::AsyncSeek` and `futures::Stream` as needed.
|
|
104
|
+
|
|
105
|
+
# Reference-level explanation
|
|
106
|
+
|
|
107
|
+
The new raw API will be:
|
|
108
|
+
|
|
109
|
+
```rust
|
|
110
|
+
pub trait Read: Unpin + Send + Sync {
|
|
111
|
+
fn read_at(
|
|
112
|
+
&self,
|
|
113
|
+
offset: u64,
|
|
114
|
+
limit: usize,
|
|
115
|
+
) -> impl Future<Output = Result<oio::Buffer>> + Send;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The API is similar to [`ReadAt`](https://doc.rust-lang.org/std/fs/struct.File.html#method.read_at), but with following changes:
|
|
120
|
+
|
|
121
|
+
```diff
|
|
122
|
+
- async fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>
|
|
123
|
+
+ async fn read_at(&self, offset: u64, limit: usize) -> Result<oio::Buffer>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- opendal chooses to use `oio::Buffer` instead of `&mut [u8]` to avoid lifetime issues.
|
|
127
|
+
- opendal chooses to return `oio::Buffer` to let services itself manage the buffer.
|
|
128
|
+
|
|
129
|
+
For example, http based storage services like `s3` is a stream that generating data on the fly.
|
|
130
|
+
|
|
131
|
+
# Drawbacks
|
|
132
|
+
|
|
133
|
+
## Breaking changes to `Reader`
|
|
134
|
+
|
|
135
|
+
This change will break the existing `Reader` API. Users will need to update their code to use the new `Reader` API.
|
|
136
|
+
|
|
137
|
+
Users wishing to migrate to the new range-based API will need to update their code. Those who simply want to use `futures::AsyncRead` can instead utilize `Reader::into_futures_read`.
|
|
138
|
+
|
|
139
|
+
# Rationale and alternatives
|
|
140
|
+
|
|
141
|
+
None.
|
|
142
|
+
|
|
143
|
+
# Prior art
|
|
144
|
+
|
|
145
|
+
## `object_store`'s API design
|
|
146
|
+
|
|
147
|
+
Current API design inspired from `object_store`'s `ObjectStore` a lot:
|
|
148
|
+
|
|
149
|
+
```rust
|
|
150
|
+
#[async_trait]
|
|
151
|
+
pub trait ObjectStore: std::fmt::Display + Send + Sync + Debug + 'static {
|
|
152
|
+
/// Return the bytes that are stored at the specified location.
|
|
153
|
+
async fn get(&self, location: &Path) -> Result<GetResult> {
|
|
154
|
+
self.get_opts(location, GetOptions::default()).await
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/// Perform a get request with options
|
|
158
|
+
async fn get_opts(&self, location: &Path, options: GetOptions) -> Result<GetResult>;
|
|
159
|
+
|
|
160
|
+
/// Return the bytes that are stored at the specified location
|
|
161
|
+
/// in the given byte range.
|
|
162
|
+
///
|
|
163
|
+
/// See [`GetRange::Bounded`] for more details on how `range` gets interpreted
|
|
164
|
+
async fn get_range(&self, location: &Path, range: Range<usize>) -> Result<Bytes> {
|
|
165
|
+
let options = GetOptions {
|
|
166
|
+
range: Some(range.into()),
|
|
167
|
+
..Default::default()
|
|
168
|
+
};
|
|
169
|
+
self.get_opts(location, options).await?.bytes().await
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/// Return the bytes that are stored at the specified location
|
|
173
|
+
/// in the given byte ranges
|
|
174
|
+
async fn get_ranges(&self, location: &Path, ranges: &[Range<usize>]) -> Result<Vec<Bytes>> {
|
|
175
|
+
coalesce_ranges(
|
|
176
|
+
ranges,
|
|
177
|
+
|range| self.get_range(location, range),
|
|
178
|
+
OBJECT_STORE_COALESCE_DEFAULT,
|
|
179
|
+
)
|
|
180
|
+
.await
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
We can add support that similar to `get_ranges` in the future.
|
|
186
|
+
|
|
187
|
+
OpenDAL opts to return a `Reader` rather than directly implementing `read` to allow for optimization with storage services like `fs` to reduce the extra `open` syscall.
|
|
188
|
+
|
|
189
|
+
# Unresolved questions
|
|
190
|
+
|
|
191
|
+
## Buffer
|
|
192
|
+
|
|
193
|
+
After switching to range-based reading, we can no longer keep a buffer within the reader. As of writing this proposal, users should use `into_async_buf_read` instead.
|
|
194
|
+
|
|
195
|
+
# Future possibilities
|
|
196
|
+
|
|
197
|
+
## Read Ranges
|
|
198
|
+
|
|
199
|
+
We can implement `read_ranges` support in the future. This will allow users to read multiple ranges of data in less requests.
|
|
200
|
+
|
|
201
|
+
## Native `read_at` for fs and hdfs
|
|
202
|
+
|
|
203
|
+
We can reduce unnecessary `open` and `seek` syscalls by using the `read_at` API across different platforms.
|
|
204
|
+
|
|
205
|
+
## Auto Range Read
|
|
206
|
+
|
|
207
|
+
We can implement [Auto ranged read support](https://github.com/apache/opendal/issues/1105) like AWS S3 Crt Client. For examples, split the range into multiple ranges and read them concurrently.
|
|
208
|
+
|
|
209
|
+
Services can define the preferred io size as default, and users can override it. For example, s3 can use `8 MiB` as preferred io size, while fs can use `4 KiB` instead.
|
|
210
|
+
|
|
211
|
+
## Completion-based IO
|
|
212
|
+
|
|
213
|
+
`oio::Read` is designed with Completion-based IO in mind. We can add IOCP/io_uring support in the future.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
- Proposal Name: `executor`
|
|
2
|
+
- Start Date: 2024-05-23
|
|
3
|
+
- RFC PR: [apache/opendal#4638](https://github.com/apache/opendal/pull/4638)
|
|
4
|
+
- Tracking Issue: [apache/opendal#4639](https://github.com/apache/opendal/issues/4639)
|
|
5
|
+
|
|
6
|
+
# Summary
|
|
7
|
+
|
|
8
|
+
Add executor in opendal to allow running tasks concurrently in background.
|
|
9
|
+
|
|
10
|
+
# Motivation
|
|
11
|
+
|
|
12
|
+
OpenDAL offers top-tier support for concurrent execution, allowing tasks to run simultaneously in the background. Users can easily enable concurrent file read/write operations with just one line of code:
|
|
13
|
+
|
|
14
|
+
```diff
|
|
15
|
+
let mut w = op
|
|
16
|
+
.writer_with(path)
|
|
17
|
+
.chunk(8 * 1024 * 1024) // 8 MiB per chunk
|
|
18
|
+
+ .concurrent(16) // 16 concurrent tasks
|
|
19
|
+
.await?;
|
|
20
|
+
|
|
21
|
+
w.write(bs).await?;
|
|
22
|
+
w.write(bs).await?; // The submitted tasks only be executed while user calling `write`.
|
|
23
|
+
...
|
|
24
|
+
sleep(Duration::from_secs(10)).await; // The submitted tasks make no progress during `sleep`.
|
|
25
|
+
...
|
|
26
|
+
w.close().await?;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
However, the execution of those tasks relies on users continuously calling `write`. They cannot run tasks concurrently in the background. (I explained the technical details in the `Rationale and alternatives` section.)
|
|
30
|
+
|
|
31
|
+
This can result in the following issues:
|
|
32
|
+
|
|
33
|
+
- Task latency may increase as tasks are not executed until the task queue is full.
|
|
34
|
+
- Memory usage may be high because all chunks must be held in memory until the task is completed.
|
|
35
|
+
|
|
36
|
+
I propose introducing an executor abstraction in OpenDAL to enable concurrent background task execution. The executor will automatically manage the tasks in the background without requiring users to drive the progress manually.
|
|
37
|
+
|
|
38
|
+
# Guide-level explanation
|
|
39
|
+
|
|
40
|
+
OpenDAL will add a new `Executor` struct to manage concurrent tasks.
|
|
41
|
+
|
|
42
|
+
```rust
|
|
43
|
+
pub struct Executor {
|
|
44
|
+
...
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
pub struct Task {
|
|
48
|
+
...
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
impl Executor {
|
|
52
|
+
/// Create a new tokio based executor.
|
|
53
|
+
pub fn new() -> Self { ... }
|
|
54
|
+
|
|
55
|
+
/// Create a new executor with given execute impl.
|
|
56
|
+
pub fn with(exec: Arc<dyn Execute>) -> Self { ... }
|
|
57
|
+
|
|
58
|
+
/// Run given future in background immediately.
|
|
59
|
+
pub fn execute<F>(&self, f: F) -> Task<F::Output>
|
|
60
|
+
where
|
|
61
|
+
F: Future + Send + 'static,
|
|
62
|
+
{
|
|
63
|
+
...
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The `Executor` uses the `tokio` runtime by default but users can also provide their own runtime by:
|
|
69
|
+
|
|
70
|
+
```rust
|
|
71
|
+
pub trait Execute {
|
|
72
|
+
fn execute(&self, f: BoxedFuture<()>) -> Result<()>;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Users can set executor in `OpWrite` / `OpRead` to enable concurrent background task execution:
|
|
77
|
+
|
|
78
|
+
```rust
|
|
79
|
+
+ let exec = Executor::new();
|
|
80
|
+
let w = op
|
|
81
|
+
.writer_with(path)
|
|
82
|
+
.chunk(8 * 1024 * 1024) // 8 MiB per chunk
|
|
83
|
+
.concurrent(16) // 16 concurrent tasks
|
|
84
|
+
+ .executor(exec) // Use specified executor
|
|
85
|
+
.await?;
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Specifying an executor every time is cumbersome. Users can also set a global executor for given operator:
|
|
89
|
+
|
|
90
|
+
```rust
|
|
91
|
+
+ let exec = Executor::new();
|
|
92
|
+
+ let op = op.with_default_executor(exec);
|
|
93
|
+
|
|
94
|
+
let w = op
|
|
95
|
+
.writer_with(path)
|
|
96
|
+
.chunk(8 * 1024 * 1024) // 8 MiB per chunk
|
|
97
|
+
.concurrent(16) // 16 concurrent tasks
|
|
98
|
+
.await?;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
# Reference-level explanation
|
|
102
|
+
|
|
103
|
+
As mentioned in the `Guide-level explanation`, the `Executor` struct will manage concurrent tasks in the background. `Executor` will be powered by trait `Execute` to support different underlying runtimes. To make trait `Execute` object safe, we only accept `BoxedFuture<()>` as input. `Executor` will handle the future output and return the result to the caller.
|
|
104
|
+
|
|
105
|
+
Operations that supporting concurrent execution will add a new field:
|
|
106
|
+
|
|
107
|
+
```rust
|
|
108
|
+
pub struct OpXxx {
|
|
109
|
+
...
|
|
110
|
+
executor: Option<Executor>,
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Operator will add a new field to store the default executor:
|
|
115
|
+
|
|
116
|
+
```rust
|
|
117
|
+
pub struct Operator {
|
|
118
|
+
...
|
|
119
|
+
default_executor: Option<Executor>,
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The `Task` spawned by `Executor` will be a future that can be awaited to fetch the result:
|
|
124
|
+
|
|
125
|
+
```rust
|
|
126
|
+
let res = task.await;
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The task will be executed immediately after calling `execute`. Users can also cancel the task by dropping the `Task` object. Users don't need to poll those `Task` object to make progress.
|
|
130
|
+
|
|
131
|
+
# Drawbacks
|
|
132
|
+
|
|
133
|
+
## Complexity
|
|
134
|
+
|
|
135
|
+
To support concurrent execution, we need to introduce:
|
|
136
|
+
|
|
137
|
+
- a new `Executor` struct
|
|
138
|
+
- a new `Task` struct
|
|
139
|
+
- a new `Execute` trait
|
|
140
|
+
|
|
141
|
+
This may increase the complexity of the codebase.
|
|
142
|
+
|
|
143
|
+
# Rationale and alternatives
|
|
144
|
+
|
|
145
|
+
## Why introducing so many new abstractions?
|
|
146
|
+
|
|
147
|
+
We need to introduce new abstractions to support concurrent execution across different runtimes. Unfortunately, this is the current reality of async rust.
|
|
148
|
+
|
|
149
|
+
Supporting just one or two runtimes by adding features is much easier. Supporting only Tokio is extremely simple, requiring about 10 lines of changes. However, this violates our vision of free data access.
|
|
150
|
+
|
|
151
|
+
Firstly, we don't want to force our users to use Tokio. We aim to support all runtimes, including async-std, smol, and others.
|
|
152
|
+
|
|
153
|
+
Secondly, OpenDAL should be capable of running in any environment, including embedded systems. We don’t want to restrict our users to a specific runtime.
|
|
154
|
+
|
|
155
|
+
Finally, users may have their own preferences for observability and performance in their runtime. We intend to accommodate these needs effortlessly.
|
|
156
|
+
|
|
157
|
+
## Why `ConcurrentFutures` doesn't work?
|
|
158
|
+
|
|
159
|
+
`ConcurrentFutures` is a `Vec<impl Future>`, users need to keep calling `poll_next` to make progress. This is not suitable for our use case. We need a way to run tasks in the background without user intervention.
|
|
160
|
+
|
|
161
|
+
> I've heard that futures will wake up when they're ready, and it's the runtime's job to poll them, right?
|
|
162
|
+
|
|
163
|
+
No, it's partially correct. The runtime will wake up the future when it's ready, but it's the user's job to poll the future. The runtime will not poll the future automatically unless it's managed by the runtime.
|
|
164
|
+
|
|
165
|
+
For tokio, that means all futures provided by tokio, like `tokio::time::Sleep`, will be polled by tokio runtime. However, if you create a future by yourself, you need to poll it manually.
|
|
166
|
+
|
|
167
|
+
I have an example to explain this:
|
|
168
|
+
|
|
169
|
+
*Try it at [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=628e67adef90128151e175d22c87808e)*
|
|
170
|
+
|
|
171
|
+
```rust
|
|
172
|
+
use futures::stream::FuturesUnordered;
|
|
173
|
+
use futures::StreamExt;
|
|
174
|
+
use std::time::Duration;
|
|
175
|
+
use tokio::time::{sleep, Instant};
|
|
176
|
+
|
|
177
|
+
#[tokio::main]
|
|
178
|
+
async fn main() {
|
|
179
|
+
let now = Instant::now();
|
|
180
|
+
let mut cf = FuturesUnordered::new();
|
|
181
|
+
|
|
182
|
+
// cf.push(Box::pin(sleep(Duration::from_secs(3))));
|
|
183
|
+
cf.push(Box::pin(async move {
|
|
184
|
+
sleep(Duration::from_secs(3)).await;
|
|
185
|
+
println!("async task finished at {}s", now.elapsed().as_secs_f64());
|
|
186
|
+
}));
|
|
187
|
+
sleep(Duration::from_secs(4)).await;
|
|
188
|
+
println!("outer sleep finished at {}s", now.elapsed().as_secs_f64());
|
|
189
|
+
|
|
190
|
+
let _: Vec<()> = cf.collect().await;
|
|
191
|
+
println!("consumed: {}s", now.elapsed().as_secs_f64())
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
# Prior art
|
|
196
|
+
|
|
197
|
+
None.
|
|
198
|
+
|
|
199
|
+
# Unresolved questions
|
|
200
|
+
|
|
201
|
+
None.
|
|
202
|
+
|
|
203
|
+
# Future possibilities
|
|
204
|
+
|
|
205
|
+
## Blocking Executor
|
|
206
|
+
|
|
207
|
+
This proposal mainly focuses on async tasks. However, we can also consider adding blocking support to `Executor`. Users can use concurrent tasks in blocking context too:
|
|
208
|
+
|
|
209
|
+
```rust
|
|
210
|
+
let w = op
|
|
211
|
+
.writer_with(path)
|
|
212
|
+
.chunk(8 * 1024 * 1024) // 8 MiB per chunk
|
|
213
|
+
+ .concurrent(16) // 16 concurrent tasks
|
|
214
|
+
.do()?;
|
|
215
|
+
```
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
- Proposal Name: `remove_metakey`
|
|
2
|
+
- Start Date: 2024-11-12
|
|
3
|
+
- RFC PR: [apache/opendal#5313](https://github.com/apache/opendal/pull/5313)
|
|
4
|
+
- Tracking Issue: [apache/opendal#5314](https://github.com/apache/opendal/issues/5314)
|
|
5
|
+
|
|
6
|
+
# Summary
|
|
7
|
+
|
|
8
|
+
Remove the `Metakey` concept from OpenDAL and replace it with a simpler and more predictable metadata handling mechanism.
|
|
9
|
+
|
|
10
|
+
# Motivation
|
|
11
|
+
|
|
12
|
+
The current `Metakey` design has several issues:
|
|
13
|
+
|
|
14
|
+
1. Performance Impact: Users often initiate costly operations unintentionally, such as using `Metakey::Full`, which results in extra stat calls
|
|
15
|
+
2. Usability Issues: Users often try to access metadata that hasn't been explicitly requested
|
|
16
|
+
3. API Confusion: There's a conflict between `Metakey::Version` and the new `version(bool)` parameter
|
|
17
|
+
4. Implementation Complexity: Service developers struggle to implement `Metakey` correctly
|
|
18
|
+
|
|
19
|
+
The goal is a simpler, more intuitive API that prevents common mistakes and improves performance as standard.
|
|
20
|
+
|
|
21
|
+
# Guide-level explanation
|
|
22
|
+
|
|
23
|
+
Instead of using `Metakey` to specify which metadata fields to fetch, services will now declare their metadata capabilities upfront through a new `MetadataCapability` struct:
|
|
24
|
+
|
|
25
|
+
```rust
|
|
26
|
+
let entries = op.list("path").await?;
|
|
27
|
+
for entry in entries {
|
|
28
|
+
if op.metadata_capability().content_type {
|
|
29
|
+
println!("Content-Type: {}", entry.metadata().content_type());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If users need additional metadata not provided by `list`:
|
|
35
|
+
|
|
36
|
+
```rust
|
|
37
|
+
let entries = op.list("path").await?;
|
|
38
|
+
for entry in entries {
|
|
39
|
+
let mut meta = entry.metadata();
|
|
40
|
+
if !op.metadata_capability().etag {
|
|
41
|
+
meta = op.stat(&entry.path()).await?;
|
|
42
|
+
}
|
|
43
|
+
println!("Content-Type: {}", meta.etag());
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For existing OpenDAL users, the main changes are:
|
|
48
|
+
|
|
49
|
+
- Remove all `metakey()` calls from their code
|
|
50
|
+
- Use `metadata_capability()` to check available metadata
|
|
51
|
+
- Explicitly call `stat()` when needed
|
|
52
|
+
|
|
53
|
+
# Reference-level explanation
|
|
54
|
+
|
|
55
|
+
The implementation involves:
|
|
56
|
+
|
|
57
|
+
1. Remove the `Metakey` enum
|
|
58
|
+
2. Add new `MetadataCapability` struct:
|
|
59
|
+
```rust
|
|
60
|
+
pub struct MetadataCapability {
|
|
61
|
+
pub content_length: bool,
|
|
62
|
+
pub content_type: bool,
|
|
63
|
+
pub last_modified: bool,
|
|
64
|
+
pub etag: bool,
|
|
65
|
+
pub mode: bool,
|
|
66
|
+
pub version: bool,
|
|
67
|
+
...
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. Add method to Operator to query capabilities:
|
|
72
|
+
```rust
|
|
73
|
+
impl Operator {
|
|
74
|
+
pub fn metadata_capability(&self) -> MetadataCapability;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
4. Modify list operation to avoid implicit stat calls
|
|
79
|
+
5. Update all service implementations to declare their metadata capabilities
|
|
80
|
+
|
|
81
|
+
Each service implementation will need to:
|
|
82
|
+
- Remove `Metakey` handling logic
|
|
83
|
+
- Implement `metadata_capability()` to accurately indicate the metadata provided by default
|
|
84
|
+
- Ensure list operations return metadata that's always available without extra API calls
|
|
85
|
+
|
|
86
|
+
# Drawbacks
|
|
87
|
+
|
|
88
|
+
- Breaking change for existing users
|
|
89
|
+
- Loss of fine-grained control over metadata fetching
|
|
90
|
+
- Potential increased API calls if users need multiple metadata fields
|
|
91
|
+
|
|
92
|
+
# Rationale and alternatives
|
|
93
|
+
|
|
94
|
+
This design is superior because:
|
|
95
|
+
- Prevents performance pitfalls by default
|
|
96
|
+
- Makes metadata availability explicitly
|
|
97
|
+
- Simplifies service implementation
|
|
98
|
+
- Provides clearer mental model
|
|
99
|
+
|
|
100
|
+
Alternatives considered:
|
|
101
|
+
1. Keep `Metakey` but make it more restrictive
|
|
102
|
+
2. Add warnings for potentially costly operations
|
|
103
|
+
3. Make stat calls async/lazy
|
|
104
|
+
|
|
105
|
+
Not making this change would continue the current issues of performance problems and API misuse.
|
|
106
|
+
|
|
107
|
+
# Prior art
|
|
108
|
+
|
|
109
|
+
None
|
|
110
|
+
|
|
111
|
+
# Unresolved questions
|
|
112
|
+
|
|
113
|
+
None
|
|
114
|
+
|
|
115
|
+
# Future possibilities
|
|
116
|
+
|
|
117
|
+
- Add metadata prefetching optimization
|
|
118
|
+
- Add metadata caching layer
|
|
119
|
+
- Support for custom metadata fields
|
|
120
|
+
- Automated capability detection
|