opendal 0.1.9 → 0.1.11
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 +4 -4
- data/Cargo.lock +89 -56
- data/Cargo.toml +1 -1
- data/DEPENDENCIES.rust.tsv +55 -41
- data/LICENSE +201 -0
- data/LICENSE-MPL-2.0.txt +373 -0
- data/NOTICE +5 -0
- data/core/CHANGELOG.md +175 -0
- data/core/Cargo.lock +225 -298
- data/core/Cargo.toml +100 -94
- data/core/DEPENDENCIES.rust.tsv +44 -73
- data/core/benches/metadata/README.md +21 -0
- data/core/benches/metadata/main.rs +541 -0
- data/core/benches/vs_fs/Cargo.toml +1 -1
- data/core/benches/vs_s3/Cargo.toml +1 -1
- data/core/core/Cargo.toml +7 -2
- data/core/core/src/blocking/delete.rs +5 -1
- data/core/core/src/blocking/operator.rs +12 -0
- data/core/core/src/blocking/read/std_reader.rs +25 -0
- data/core/core/src/docs/concepts.rs +70 -94
- data/core/core/src/docs/internals/accessor.rs +62 -293
- data/core/core/src/docs/internals/layer.rs +43 -59
- data/core/core/src/docs/internals/mod.rs +21 -23
- data/core/core/src/docs/mod.rs +10 -6
- data/core/core/src/docs/performance/concurrent_write.md +92 -55
- data/core/core/src/docs/performance/http_optimization.md +120 -104
- data/core/core/src/docs/performance/mod.rs +8 -6
- data/core/core/src/docs/rfcs/5485_conditional_reader.md +4 -0
- data/core/core/src/docs/rfcs/7182_restore_api.md +139 -557
- data/core/core/src/docs/rfcs/7945_limited_read.md +210 -0
- data/core/core/src/docs/rfcs/7948_s3_provider_presets.md +254 -0
- data/core/core/src/docs/rfcs/8109_writer_copy_from.md +330 -0
- data/core/core/src/docs/rfcs/8145_conflict_error_kind.md +210 -0
- data/core/core/src/docs/rfcs/8147_write_if_not_changed.md +233 -0
- data/core/core/src/docs/rfcs/8188_compose_api.md +292 -0
- data/core/core/src/docs/rfcs/8194_compact_metadata_and_operation_args.md +444 -0
- data/core/core/src/docs/rfcs/README.md +14 -3
- data/core/core/src/docs/rfcs/mod.rs +46 -22
- data/core/core/src/docs/specs/README.md +34 -0
- data/core/core/src/docs/specs/conditional-operations.md +156 -0
- data/core/core/src/docs/specs/metadata.md +63 -0
- data/core/core/src/docs/specs/mod.rs +26 -0
- data/core/core/src/docs/upgrade.md +114 -1
- data/core/core/src/layers/capability_override.rs +15 -2
- data/core/core/src/layers/complete.rs +347 -43
- data/core/core/src/layers/correctness_check.rs +718 -51
- data/core/core/src/layers/error_context.rs +76 -2
- data/core/core/src/layers/simulate.rs +91 -28
- data/core/core/src/lib.rs +1 -0
- data/core/core/src/raw/accessor.rs +91 -15
- data/core/core/src/raw/enum_utils.rs +7 -0
- data/core/core/src/raw/http_util/header.rs +22 -17
- data/core/core/src/raw/oio/compose/api.rs +92 -0
- data/core/core/src/raw/oio/compose/mod.rs +19 -0
- data/core/core/src/raw/oio/copy/api.rs +3 -3
- data/core/core/src/raw/oio/copy/block_copy.rs +32 -4
- data/core/core/src/raw/oio/copy/multipart_copy.rs +36 -7
- data/core/core/src/raw/oio/entry.rs +48 -22
- data/core/core/src/raw/oio/list/flat_list.rs +1 -1
- data/core/core/src/raw/oio/list/hierarchy_list.rs +3 -2
- data/core/core/src/raw/oio/mod.rs +3 -0
- data/core/core/src/raw/oio/read/position_read.rs +1 -1
- data/core/core/src/raw/oio/write/api.rs +40 -0
- data/core/core/src/raw/oio/write/append_write.rs +4 -4
- data/core/core/src/raw/oio/write/block_write.rs +2 -2
- data/core/core/src/raw/oio/write/multipart_write.rs +181 -48
- data/core/core/src/raw/oio/write/position_write.rs +1 -1
- data/core/core/src/raw/operation.rs +6 -0
- data/core/core/src/raw/ops.rs +1191 -456
- data/core/core/src/raw/rps.rs +11 -0
- data/core/core/src/raw/time.rs +14 -3
- data/core/core/src/services/memory/backend.rs +5 -10
- data/core/core/src/services/memory/lister.rs +4 -4
- data/core/core/src/services/memory/writer.rs +7 -6
- data/core/core/src/types/buffer.rs +102 -12
- data/core/core/src/types/bytes_range.rs +20 -1
- data/core/core/src/types/capability.rs +65 -0
- data/core/core/src/types/compact.rs +329 -0
- data/core/core/src/types/compose/composer.rs +183 -0
- data/core/core/src/types/compose/input.rs +57 -0
- data/core/core/src/types/compose/mod.rs +23 -0
- data/core/core/src/types/context/read.rs +16 -11
- data/core/core/src/types/context/write.rs +150 -2
- data/core/core/src/types/copy.rs +5 -3
- data/core/core/src/types/delete/deleter.rs +20 -12
- data/core/core/src/types/delete/input.rs +22 -64
- data/core/core/src/types/delete/mod.rs +0 -1
- data/core/core/src/types/entry.rs +8 -14
- data/core/core/src/types/error.rs +28 -11
- data/core/core/src/types/metadata.rs +709 -322
- data/core/core/src/types/mod.rs +9 -1
- data/core/core/src/types/operator/operator.rs +278 -29
- data/core/core/src/types/operator/operator_futures.rs +466 -105
- data/core/core/src/types/options.rs +631 -158
- data/core/core/src/types/read/futures_async_reader.rs +663 -50
- data/core/core/src/types/read/reader.rs +23 -5
- data/core/core/src/types/write/futures_async_writer.rs +27 -0
- data/core/core/src/types/write/writer.rs +47 -5
- data/core/http-transports/reqwest/Cargo.toml +1 -1
- data/core/layers/async-backtrace/Cargo.toml +2 -2
- data/core/layers/async-backtrace/src/lib.rs +21 -2
- data/core/layers/await-tree/Cargo.toml +2 -2
- data/core/layers/await-tree/src/lib.rs +25 -2
- data/core/layers/capability-check/Cargo.toml +2 -2
- data/core/layers/capability-check/src/lib.rs +98 -10
- data/core/layers/chaos/Cargo.toml +2 -2
- data/core/layers/chaos/src/lib.rs +18 -3
- data/core/layers/concurrent-limit/Cargo.toml +3 -3
- data/core/layers/concurrent-limit/src/lib.rs +53 -13
- data/core/layers/dtrace/Cargo.toml +2 -2
- data/core/layers/dtrace/src/lib.rs +29 -2
- data/core/layers/fastmetrics/Cargo.toml +3 -3
- data/core/layers/fastrace/Cargo.toml +2 -2
- data/core/layers/fastrace/src/lib.rs +28 -2
- data/core/layers/foyer/Cargo.toml +2 -2
- data/core/layers/foyer/src/full.rs +16 -19
- data/core/layers/foyer/src/lib.rs +67 -14
- data/core/layers/hotpath/Cargo.toml +2 -2
- data/core/layers/hotpath/src/lib.rs +20 -2
- data/core/layers/immutable-index/Cargo.toml +2 -2
- data/core/layers/immutable-index/src/lib.rs +48 -24
- data/core/layers/logging/Cargo.toml +2 -2
- data/core/layers/logging/src/lib.rs +46 -2
- data/core/layers/metrics/Cargo.toml +3 -3
- data/core/layers/mime-guess/Cargo.toml +2 -2
- data/core/layers/mime-guess/src/lib.rs +31 -4
- data/core/layers/observe-metrics-common/Cargo.toml +2 -2
- data/core/layers/observe-metrics-common/src/lib.rs +55 -2
- data/core/layers/otelmetrics/Cargo.toml +3 -3
- data/core/layers/oteltrace/Cargo.toml +2 -2
- data/core/layers/oteltrace/src/lib.rs +27 -2
- data/core/layers/prometheus/Cargo.toml +3 -3
- data/core/layers/prometheus-client/Cargo.toml +3 -3
- data/core/layers/retry/Cargo.toml +4 -4
- data/core/layers/retry/src/lib.rs +76 -19
- data/core/layers/route/Cargo.toml +3 -3
- data/core/layers/route/src/lib.rs +34 -7
- data/core/layers/tail-cut/Cargo.toml +2 -2
- data/core/layers/tail-cut/src/lib.rs +28 -2
- data/core/layers/throttle/Cargo.toml +2 -2
- data/core/layers/throttle/src/lib.rs +19 -2
- data/core/layers/timeout/Cargo.toml +3 -3
- data/core/layers/timeout/src/lib.rs +38 -13
- data/core/layers/tracing/Cargo.toml +2 -2
- data/core/layers/tracing/src/lib.rs +24 -3
- data/core/services/aliyun-drive/Cargo.toml +2 -2
- data/core/services/aliyun-drive/src/backend.rs +34 -24
- data/core/services/aliyun-drive/src/core.rs +143 -54
- data/core/services/aliyun-drive/src/lister.rs +19 -18
- data/core/services/aliyun-drive/src/reader.rs +4 -1
- data/core/services/aliyun-drive/src/writer.rs +3 -3
- data/core/services/alluxio/Cargo.toml +1 -1
- data/core/services/alluxio/src/backend.rs +1 -1
- data/core/services/alluxio/src/core.rs +113 -94
- data/core/services/alluxio/src/reader.rs +7 -3
- data/core/services/alluxio/src/writer.rs +2 -2
- data/core/services/azblob/Cargo.toml +2 -2
- data/core/services/azblob/src/backend.rs +17 -9
- data/core/services/azblob/src/copier.rs +41 -15
- data/core/services/azblob/src/core.rs +372 -135
- data/core/services/azblob/src/deleter.rs +41 -18
- data/core/services/azblob/src/lister.rs +16 -10
- data/core/services/azblob/src/reader.rs +4 -1
- data/core/services/azblob/src/writer.rs +48 -15
- data/core/services/azdls/Cargo.toml +3 -3
- data/core/services/azdls/src/backend.rs +45 -15
- data/core/services/azdls/src/config.rs +4 -1
- data/core/services/azdls/src/core.rs +276 -87
- data/core/services/azdls/src/deleter.rs +13 -4
- data/core/services/azdls/src/lister.rs +18 -12
- data/core/services/azdls/src/reader.rs +6 -2
- data/core/services/azdls/src/writer.rs +44 -23
- data/core/services/azfile/Cargo.toml +2 -2
- data/core/services/azfile/src/backend.rs +24 -8
- data/core/services/azfile/src/core.rs +195 -77
- data/core/services/azfile/src/deleter.rs +8 -1
- data/core/services/azfile/src/lister.rs +20 -14
- data/core/services/azfile/src/reader.rs +5 -2
- data/core/services/azfile/src/writer.rs +27 -15
- data/core/services/azure-common/Cargo.toml +1 -1
- data/core/services/b2/Cargo.toml +2 -2
- data/core/services/b2/src/backend.rs +30 -11
- data/core/services/b2/src/core.rs +134 -120
- data/core/services/b2/src/deleter.rs +1 -1
- data/core/services/b2/src/lister.rs +5 -2
- data/core/services/b2/src/reader.rs +5 -2
- data/core/services/b2/src/writer.rs +29 -12
- data/core/services/cacache/Cargo.toml +1 -1
- data/core/services/cacache/src/backend.rs +4 -5
- data/core/services/cacache/src/reader.rs +4 -1
- data/core/services/cacache/src/writer.rs +6 -2
- data/core/services/cloudflare-kv/Cargo.toml +1 -1
- data/core/services/cloudflare-kv/src/backend.rs +26 -15
- data/core/services/cloudflare-kv/src/config.rs +13 -2
- data/core/services/cloudflare-kv/src/core.rs +62 -56
- data/core/services/cloudflare-kv/src/deleter.rs +12 -3
- data/core/services/cloudflare-kv/src/lister.rs +66 -17
- data/core/services/cloudflare-kv/src/reader.rs +14 -9
- data/core/services/cloudflare-kv/src/writer.rs +10 -7
- data/core/services/compfs/Cargo.toml +1 -1
- data/core/services/compfs/src/backend.rs +11 -7
- data/core/services/compfs/src/lister.rs +7 -7
- data/core/services/compfs/src/writer.rs +1 -1
- data/core/services/cos/Cargo.toml +1 -1
- data/core/services/cos/src/backend.rs +129 -16
- data/core/services/cos/src/core.rs +198 -80
- data/core/services/cos/src/deleter.rs +4 -1
- data/core/services/cos/src/lister.rs +42 -27
- data/core/services/cos/src/reader.rs +6 -2
- data/core/services/cos/src/writer.rs +45 -21
- data/core/services/d1/Cargo.toml +1 -1
- data/core/services/d1/src/backend.rs +6 -5
- data/core/services/d1/src/core.rs +79 -63
- data/core/services/d1/src/reader.rs +4 -1
- data/core/services/d1/src/writer.rs +6 -2
- data/core/services/dashmap/Cargo.toml +1 -1
- data/core/services/dashmap/src/backend.rs +2 -2
- data/core/services/dashmap/src/reader.rs +4 -1
- data/core/services/dashmap/src/writer.rs +11 -8
- data/core/services/dbfs/Cargo.toml +1 -1
- data/core/services/dbfs/src/backend.rs +21 -15
- data/core/services/dbfs/src/core.rs +65 -60
- data/core/services/dbfs/src/deleter.rs +4 -1
- data/core/services/dbfs/src/lister.rs +10 -10
- data/core/services/dbfs/src/writer.rs +6 -3
- data/core/services/dropbox/Cargo.toml +2 -2
- data/core/services/dropbox/src/backend.rs +30 -23
- data/core/services/dropbox/src/core.rs +65 -63
- data/core/services/dropbox/src/deleter.rs +1 -1
- data/core/services/dropbox/src/lister.rs +17 -8
- data/core/services/dropbox/src/reader.rs +4 -1
- data/core/services/dropbox/src/writer.rs +13 -10
- data/core/services/etcd/Cargo.toml +1 -1
- data/core/services/etcd/src/backend.rs +8 -5
- data/core/services/etcd/src/core.rs +5 -11
- data/core/services/etcd/src/lister.rs +6 -1
- data/core/services/etcd/src/reader.rs +4 -1
- data/core/services/etcd/src/writer.rs +6 -3
- data/core/services/foundationdb/Cargo.toml +1 -1
- data/core/services/foundationdb/src/backend.rs +6 -5
- data/core/services/foundationdb/src/reader.rs +4 -1
- data/core/services/foundationdb/src/writer.rs +6 -2
- data/core/services/foyer/Cargo.toml +3 -3
- data/core/services/foyer/src/backend.rs +6 -5
- data/core/services/foyer/src/reader.rs +4 -1
- data/core/services/foyer/src/writer.rs +6 -2
- data/core/services/fs/Cargo.toml +1 -1
- data/core/services/fs/src/backend.rs +4 -3
- data/core/services/fs/src/core.rs +44 -26
- data/core/services/fs/src/lister.rs +9 -6
- data/core/services/fs/src/writer.rs +20 -13
- data/core/services/ftp/Cargo.toml +4 -6
- data/core/services/ftp/src/backend.rs +9 -5
- data/core/services/ftp/src/core.rs +9 -7
- data/core/services/ftp/src/lister.rs +7 -8
- data/core/services/ftp/src/reader.rs +3 -3
- data/core/services/ftp/src/writer.rs +3 -3
- data/core/services/gcs/Cargo.toml +4 -2
- data/core/services/gcs/src/backend.rs +53 -7
- data/core/services/gcs/src/composer.rs +705 -0
- data/core/services/gcs/src/copier.rs +14 -4
- data/core/services/gcs/src/core.rs +828 -124
- data/core/services/gcs/src/deleter.rs +33 -18
- data/core/services/gcs/src/lib.rs +1 -0
- data/core/services/gcs/src/lister.rs +21 -12
- data/core/services/gcs/src/reader.rs +12 -5
- data/core/services/gcs/src/writer.rs +632 -10
- data/core/services/gcs-grpc/Cargo.toml +58 -0
- data/core/services/gcs-grpc/README.md +19 -0
- data/core/services/gcs-grpc/proto/README.md +23 -0
- data/core/services/gcs-grpc/proto/google/storage/v2/storage.proto +171 -0
- data/core/services/gcs-grpc/proto/upstream-descriptor.bin +0 -0
- data/core/services/gcs-grpc/src/backend.rs +449 -0
- data/core/services/gcs-grpc/src/config.rs +116 -0
- data/core/services/gcs-grpc/src/copier.rs +98 -0
- data/core/services/gcs-grpc/src/core.rs +298 -0
- data/core/services/gcs-grpc/src/deleter.rs +65 -0
- data/core/services/gcs-grpc/src/docs.md +19 -0
- data/core/services/gcs-grpc/src/generated/google.storage.v2.rs +541 -0
- data/core/services/gcs-grpc/src/generated/mod.rs +24 -0
- data/core/services/gcs-grpc/src/lib.rs +43 -0
- data/core/services/gcs-grpc/src/lister.rs +125 -0
- data/core/services/gcs-grpc/src/reader.rs +140 -0
- data/core/services/gcs-grpc/src/writer.rs +780 -0
- data/core/services/gdrive/Cargo.toml +2 -2
- data/core/services/gdrive/src/backend.rs +123 -69
- data/core/services/gdrive/src/core.rs +87 -69
- data/core/services/gdrive/src/deleter.rs +8 -2
- data/core/services/gdrive/src/lister.rs +38 -26
- data/core/services/gdrive/src/path_index.rs +2 -2
- data/core/services/gdrive/src/reader.rs +9 -3
- data/core/services/gdrive/src/writer.rs +13 -7
- data/core/services/ghac/Cargo.toml +2 -2
- data/core/services/ghac/src/backend.rs +5 -2
- data/core/services/ghac/src/core.rs +59 -37
- data/core/services/ghac/src/reader.rs +5 -2
- data/core/services/ghac/src/writer.rs +16 -6
- data/core/services/github/Cargo.toml +1 -1
- data/core/services/github/src/backend.rs +16 -8
- data/core/services/github/src/core.rs +88 -76
- data/core/services/github/src/lister.rs +17 -15
- data/core/services/github/src/reader.rs +5 -2
- data/core/services/github/src/writer.rs +12 -6
- data/core/services/goosefs/Cargo.toml +2 -2
- data/core/services/goosefs/src/backend.rs +2 -2
- data/core/services/goosefs/src/core.rs +291 -208
- data/core/services/goosefs/src/docs.md +3 -0
- data/core/services/goosefs/src/lister.rs +2 -3
- data/core/services/goosefs/src/reader.rs +7 -3
- data/core/services/goosefs/src/writer.rs +21 -10
- data/core/services/goosefs/tests/safe_conditional_put.rs +37 -0
- data/core/services/gridfs/Cargo.toml +2 -2
- data/core/services/gridfs/src/backend.rs +12 -8
- data/core/services/gridfs/src/core.rs +1 -1
- data/core/services/gridfs/src/reader.rs +4 -1
- data/core/services/gridfs/src/writer.rs +6 -2
- data/core/services/hdfs/Cargo.toml +1 -1
- data/core/services/hdfs/src/backend.rs +1 -1
- data/core/services/hdfs/src/core.rs +7 -4
- data/core/services/hdfs/src/lister.rs +7 -9
- data/core/services/hdfs/src/writer.rs +5 -1
- data/core/services/hdfs-native/Cargo.toml +1 -1
- data/core/services/hdfs-native/src/backend.rs +1 -1
- data/core/services/hdfs-native/src/core.rs +44 -50
- data/core/services/hdfs-native/src/lister.rs +8 -10
- data/core/services/hdfs-native/src/writer.rs +5 -1
- data/core/services/hf/Cargo.toml +4 -3
- data/core/services/hf/src/backend.rs +4 -3
- data/core/services/hf/src/core.rs +907 -153
- data/core/services/hf/src/lister.rs +16 -6
- data/core/services/hf/src/reader.rs +377 -57
- data/core/services/hf/src/writer.rs +6 -2
- data/core/services/http/Cargo.toml +3 -3
- data/core/services/http/src/backend.rs +8 -6
- data/core/services/http/src/core.rs +57 -35
- data/core/services/http/src/reader.rs +5 -2
- data/core/services/ipfs/Cargo.toml +1 -1
- data/core/services/ipfs/src/backend.rs +20 -9
- data/core/services/ipfs/src/core.rs +43 -34
- data/core/services/ipfs/src/reader.rs +5 -2
- data/core/services/ipmfs/Cargo.toml +1 -1
- data/core/services/ipmfs/src/backend.rs +17 -8
- data/core/services/ipmfs/src/core.rs +66 -60
- data/core/services/ipmfs/src/deleter.rs +5 -2
- data/core/services/ipmfs/src/lister.rs +15 -12
- data/core/services/ipmfs/src/reader.rs +5 -2
- data/core/services/ipmfs/src/writer.rs +6 -3
- data/core/services/koofr/Cargo.toml +2 -2
- data/core/services/koofr/src/backend.rs +46 -17
- data/core/services/koofr/src/core.rs +64 -48
- data/core/services/koofr/src/deleter.rs +4 -1
- data/core/services/koofr/src/lister.rs +11 -10
- data/core/services/koofr/src/reader.rs +5 -2
- data/core/services/koofr/src/writer.rs +13 -7
- data/core/services/lakefs/Cargo.toml +1 -1
- data/core/services/lakefs/src/backend.rs +25 -8
- data/core/services/lakefs/src/core.rs +79 -73
- data/core/services/lakefs/src/deleter.rs +4 -1
- data/core/services/lakefs/src/lister.rs +17 -14
- data/core/services/lakefs/src/reader.rs +5 -2
- data/core/services/lakefs/src/writer.rs +11 -10
- data/core/services/memcached/Cargo.toml +1 -1
- data/core/services/memcached/src/backend.rs +57 -7
- data/core/services/memcached/src/config.rs +13 -2
- data/core/services/memcached/src/core.rs +11 -1
- data/core/services/memcached/src/reader.rs +4 -1
- data/core/services/memcached/src/writer.rs +6 -2
- data/core/services/mini_moka/Cargo.toml +1 -1
- data/core/services/mini_moka/src/backend.rs +8 -8
- data/core/services/mini_moka/src/reader.rs +4 -1
- data/core/services/mini_moka/src/writer.rs +11 -7
- data/core/services/moka/Cargo.toml +1 -1
- data/core/services/moka/src/backend.rs +7 -7
- data/core/services/moka/src/reader.rs +4 -1
- data/core/services/moka/src/writer.rs +10 -6
- data/core/services/mongodb/Cargo.toml +2 -2
- data/core/services/mongodb/src/backend.rs +7 -6
- data/core/services/mongodb/src/core.rs +1 -1
- data/core/services/mongodb/src/reader.rs +4 -1
- data/core/services/mongodb/src/writer.rs +6 -2
- data/core/services/monoiofs/Cargo.toml +2 -2
- data/core/services/monoiofs/src/backend.rs +16 -10
- data/core/services/monoiofs/src/core.rs +8 -9
- data/core/services/monoiofs/src/reader.rs +8 -10
- data/core/services/monoiofs/src/writer.rs +19 -24
- data/core/services/mysql/Cargo.toml +2 -2
- data/core/services/mysql/src/backend.rs +7 -6
- data/core/services/mysql/src/core.rs +1 -1
- data/core/services/mysql/src/lister.rs +7 -3
- data/core/services/mysql/src/reader.rs +4 -1
- data/core/services/mysql/src/writer.rs +6 -2
- data/core/services/obs/Cargo.toml +1 -1
- data/core/services/obs/src/backend.rs +29 -11
- data/core/services/obs/src/core.rs +81 -82
- data/core/services/obs/src/deleter.rs +4 -1
- data/core/services/obs/src/lister.rs +12 -5
- data/core/services/obs/src/reader.rs +5 -2
- data/core/services/obs/src/writer.rs +40 -19
- data/core/services/onedrive/Cargo.toml +2 -2
- data/core/services/onedrive/src/backend.rs +30 -21
- data/core/services/onedrive/src/config.rs +2 -2
- data/core/services/onedrive/src/core.rs +191 -90
- data/core/services/onedrive/src/deleter.rs +5 -2
- data/core/services/onedrive/src/graph_model.rs +10 -51
- data/core/services/onedrive/src/lister.rs +60 -24
- data/core/services/onedrive/src/reader.rs +17 -2
- data/core/services/onedrive/src/writer.rs +26 -15
- data/core/services/opfs/Cargo.toml +1 -1
- data/core/services/opfs/src/backend.rs +6 -13
- data/core/services/opfs/src/core.rs +33 -37
- data/core/services/opfs/src/lister.rs +4 -4
- data/core/services/opfs/src/writer.rs +1 -3
- data/core/services/oss/Cargo.toml +1 -1
- data/core/services/oss/src/backend.rs +40 -8
- data/core/services/oss/src/core.rs +192 -92
- data/core/services/oss/src/deleter.rs +16 -6
- data/core/services/oss/src/lister.rs +43 -27
- data/core/services/oss/src/reader.rs +6 -2
- data/core/services/oss/src/writer.rs +40 -22
- data/core/services/pcloud/Cargo.toml +1 -1
- data/core/services/pcloud/src/backend.rs +40 -6
- data/core/services/pcloud/src/core.rs +80 -66
- data/core/services/pcloud/src/deleter.rs +8 -1
- data/core/services/pcloud/src/lister.rs +4 -1
- data/core/services/pcloud/src/reader.rs +5 -2
- data/core/services/pcloud/src/writer.rs +6 -3
- data/core/services/persy/Cargo.toml +1 -1
- data/core/services/persy/src/backend.rs +6 -5
- data/core/services/persy/src/core.rs +60 -15
- data/core/services/persy/src/reader.rs +4 -1
- data/core/services/persy/src/writer.rs +6 -2
- data/core/services/postgresql/Cargo.toml +2 -2
- data/core/services/postgresql/src/backend.rs +7 -6
- data/core/services/postgresql/src/core.rs +1 -1
- data/core/services/postgresql/src/reader.rs +4 -1
- data/core/services/postgresql/src/writer.rs +6 -2
- data/core/services/redb/Cargo.toml +1 -1
- data/core/services/redb/src/backend.rs +6 -5
- data/core/services/redb/src/reader.rs +4 -1
- data/core/services/redb/src/writer.rs +6 -2
- data/core/services/redis/Cargo.toml +1 -1
- data/core/services/redis/src/backend.rs +18 -8
- data/core/services/redis/src/config.rs +13 -2
- data/core/services/redis/src/reader.rs +8 -4
- data/core/services/redis/src/writer.rs +6 -2
- data/core/services/rocksdb/Cargo.toml +1 -1
- data/core/services/rocksdb/src/backend.rs +6 -5
- data/core/services/rocksdb/src/lister.rs +6 -5
- data/core/services/rocksdb/src/reader.rs +4 -1
- data/core/services/rocksdb/src/writer.rs +6 -2
- data/core/services/s3/Cargo.toml +5 -4
- data/core/services/s3/src/backend.rs +995 -39
- data/core/services/s3/src/compatible_services.md +57 -0
- data/core/services/s3/src/config.rs +16 -0
- data/core/services/s3/src/copier.rs +190 -55
- data/core/services/s3/src/core.rs +299 -190
- data/core/services/s3/src/deleter.rs +26 -7
- data/core/services/s3/src/docs.md +57 -0
- data/core/services/s3/src/lister.rs +55 -36
- data/core/services/s3/src/reader.rs +22 -2
- data/core/services/s3/src/writer.rs +154 -32
- data/core/services/seafile/Cargo.toml +2 -2
- data/core/services/seafile/src/backend.rs +3 -3
- data/core/services/seafile/src/core.rs +105 -79
- data/core/services/seafile/src/lister.rs +11 -8
- data/core/services/seafile/src/reader.rs +5 -2
- data/core/services/seafile/src/writer.rs +6 -3
- data/core/services/sftp/Cargo.toml +1 -1
- data/core/services/sftp/src/backend.rs +19 -4
- data/core/services/sftp/src/core.rs +51 -46
- data/core/services/sftp/src/lister.rs +4 -4
- data/core/services/sftp/src/writer.rs +1 -1
- data/core/services/sled/Cargo.toml +1 -1
- data/core/services/sled/src/backend.rs +6 -5
- data/core/services/sled/src/core.rs +28 -6
- data/core/services/sled/src/lister.rs +6 -5
- data/core/services/sled/src/reader.rs +4 -1
- data/core/services/sled/src/writer.rs +6 -2
- data/core/services/sqlite/Cargo.toml +2 -2
- data/core/services/sqlite/src/backend.rs +12 -7
- data/core/services/sqlite/src/core.rs +3 -3
- data/core/services/sqlite/src/reader.rs +4 -1
- data/core/services/sqlite/src/writer.rs +7 -3
- data/core/services/surrealdb/Cargo.toml +2 -2
- data/core/services/surrealdb/src/backend.rs +7 -6
- data/core/services/surrealdb/src/core.rs +1 -1
- data/core/services/surrealdb/src/reader.rs +4 -1
- data/core/services/surrealdb/src/writer.rs +6 -2
- data/core/services/swift/Cargo.toml +1 -1
- data/core/services/swift/src/backend.rs +38 -8
- data/core/services/swift/src/core.rs +63 -67
- data/core/services/swift/src/deleter.rs +8 -2
- data/core/services/swift/src/lister.rs +11 -8
- data/core/services/swift/src/reader.rs +5 -2
- data/core/services/swift/src/writer.rs +17 -8
- data/core/services/tikv/Cargo.toml +2 -2
- data/core/services/tikv/src/backend.rs +7 -6
- data/core/services/tikv/src/core.rs +31 -14
- data/core/services/tikv/src/reader.rs +4 -1
- data/core/services/tikv/src/writer.rs +6 -2
- data/core/services/tos/Cargo.toml +2 -2
- data/core/services/tos/src/backend.rs +45 -21
- data/core/services/tos/src/copier.rs +44 -17
- data/core/services/tos/src/core.rs +147 -117
- data/core/services/tos/src/deleter.rs +9 -3
- data/core/services/tos/src/docs.md +1 -1
- data/core/services/tos/src/lister.rs +43 -28
- data/core/services/tos/src/reader.rs +5 -2
- data/core/services/tos/src/writer.rs +37 -16
- data/core/services/upyun/Cargo.toml +1 -1
- data/core/services/upyun/src/backend.rs +30 -7
- data/core/services/upyun/src/core.rs +122 -87
- data/core/services/upyun/src/deleter.rs +4 -1
- data/core/services/upyun/src/lister.rs +10 -10
- data/core/services/upyun/src/reader.rs +5 -2
- data/core/services/upyun/src/writer.rs +19 -7
- data/core/services/vercel-artifacts/Cargo.toml +1 -1
- data/core/services/vercel-artifacts/src/backend.rs +6 -3
- data/core/services/vercel-artifacts/src/core.rs +32 -27
- data/core/services/vercel-artifacts/src/reader.rs +5 -2
- data/core/services/vercel-artifacts/src/writer.rs +6 -3
- data/core/services/vercel-blob/Cargo.toml +1 -1
- data/core/services/vercel-blob/src/backend.rs +23 -6
- data/core/services/vercel-blob/src/core.rs +92 -81
- data/core/services/vercel-blob/src/lister.rs +12 -3
- data/core/services/vercel-blob/src/reader.rs +5 -2
- data/core/services/vercel-blob/src/writer.rs +19 -7
- data/core/services/webdav/Cargo.toml +2 -2
- data/core/services/webdav/src/backend.rs +25 -5
- data/core/services/webdav/src/core.rs +116 -59
- data/core/services/webdav/src/deleter.rs +4 -1
- data/core/services/webdav/src/lister.rs +4 -1
- data/core/services/webdav/src/reader.rs +6 -2
- data/core/services/webdav/src/writer.rs +17 -7
- data/core/services/webhdfs/Cargo.toml +2 -2
- data/core/services/webhdfs/src/backend.rs +24 -11
- data/core/services/webhdfs/src/core.rs +99 -98
- data/core/services/webhdfs/src/deleter.rs +5 -2
- data/core/services/webhdfs/src/lister.rs +21 -9
- data/core/services/webhdfs/src/reader.rs +5 -2
- data/core/services/webhdfs/src/writer.rs +49 -14
- data/core/services/yandex-disk/Cargo.toml +1 -1
- data/core/services/yandex-disk/src/backend.rs +28 -6
- data/core/services/yandex-disk/src/core.rs +97 -79
- data/core/services/yandex-disk/src/deleter.rs +4 -1
- data/core/services/yandex-disk/src/lister.rs +25 -9
- data/core/services/yandex-disk/src/reader.rs +5 -2
- data/core/services/yandex-disk/src/writer.rs +6 -3
- data/core/src/lib.rs +5 -0
- data/core/testkit/Cargo.toml +4 -4
- data/core/testkit/src/utils.rs +53 -8
- data/core/tests/behavior/async_compose.rs +297 -0
- data/core/tests/behavior/async_copy.rs +162 -1
- data/core/tests/behavior/async_delete.rs +364 -3
- data/core/tests/behavior/async_read.rs +86 -0
- data/core/tests/behavior/async_restore.rs +162 -0
- data/core/tests/behavior/async_stat.rs +90 -0
- data/core/tests/behavior/async_write.rs +330 -2
- data/core/tests/behavior/main.rs +4 -0
- data/core/upgrade.md +114 -1
- data/src/capability.rs +0 -1
- data/src/io.rs +0 -1
- data/src/lister.rs +0 -1
- data/src/metadata.rs +0 -1
- data/src/operator_info.rs +0 -1
- metadata +44 -2
|
@@ -15,101 +15,104 @@
|
|
|
15
15
|
// specific language governing permissions and limitations
|
|
16
16
|
// under the License.
|
|
17
17
|
|
|
18
|
-
//! The core concepts of OpenDAL's
|
|
18
|
+
//! The core concepts of OpenDAL's Rust API.
|
|
19
19
|
//!
|
|
20
|
-
//! OpenDAL
|
|
20
|
+
//! OpenDAL gives applications one storage API across services. Rust
|
|
21
|
+
//! applications use four concepts: a service describes the storage backend, a
|
|
22
|
+
//! builder configures it, an operator exposes operations, and layers add
|
|
23
|
+
//! behavior around those operations.
|
|
21
24
|
//!
|
|
22
|
-
//!
|
|
25
|
+
//! For the language-independent model shared by every OpenDAL binding, see the
|
|
26
|
+
//! [OpenDAL concepts guide](https://opendal.apache.org/docs/concepts/).
|
|
23
27
|
//!
|
|
24
|
-
//!
|
|
25
|
-
//! - [`Operator`]: owns a service stack and exposes storage operations such as
|
|
26
|
-
//! `read`, `write`, and `list`.
|
|
27
|
-
//! - [`Layer`][crate::raw::Layer]: wraps an operator's service stack or runtime
|
|
28
|
-
//! resources to add behavior such as retry, timeout, tracing, and metrics.
|
|
28
|
+
//! # Service and builder
|
|
29
29
|
//!
|
|
30
|
-
//!
|
|
30
|
+
//! A **service** is a storage backend such as S3, Google Cloud Storage, a
|
|
31
|
+
//! local filesystem, or an in-memory store. Each service supports a different
|
|
32
|
+
//! set of operations and optional features.
|
|
31
33
|
//!
|
|
32
|
-
//!
|
|
33
|
-
//!
|
|
34
|
-
//!
|
|
35
|
-
//!
|
|
36
|
-
//! [`services::Memory`][crate::services::Memory].
|
|
34
|
+
//! A [`Builder`] collects one service's configuration and constructs its
|
|
35
|
+
//! implementation. The [`services`][crate::services] module exposes concrete
|
|
36
|
+
//! builders, while [`Operator::new`] turns a builder into a ready-to-use
|
|
37
|
+
//! operator.
|
|
37
38
|
//!
|
|
38
39
|
//! ```text
|
|
39
|
-
//!
|
|
40
|
-
//! │ Builder ├────────────►│ Service │
|
|
41
|
-
//! └─────────┘ └─────────┘
|
|
40
|
+
//! configuration -> builder -> service -> operator
|
|
42
41
|
//! ```
|
|
43
42
|
//!
|
|
44
43
|
//! ```no_run
|
|
44
|
+
//! # use opendal_core::Result;
|
|
45
|
+
//! use opendal_core::Operator;
|
|
45
46
|
//! use opendal_core::services::Memory;
|
|
46
47
|
//!
|
|
48
|
+
//! # fn test() -> Result<()> {
|
|
47
49
|
//! let builder = Memory::default();
|
|
50
|
+
//! let op = Operator::new(builder)?;
|
|
51
|
+
//! # let _ = op;
|
|
52
|
+
//! # Ok(())
|
|
53
|
+
//! # }
|
|
48
54
|
//! ```
|
|
49
55
|
//!
|
|
56
|
+
//! OpenDAL does not make every service support every operation. Applications
|
|
57
|
+
//! can inspect the operator's effective [`Capability`] before using an
|
|
58
|
+
//! optional operation or option.
|
|
59
|
+
//!
|
|
50
60
|
//! # Operator
|
|
51
61
|
//!
|
|
52
|
-
//! An [`Operator`] is the public handle for
|
|
62
|
+
//! An [`Operator`] is the public handle for one configured service and root.
|
|
63
|
+
//! It normalizes paths, validates options against effective capabilities, runs
|
|
64
|
+
//! the configured layers, and dispatches each operation to the service.
|
|
53
65
|
//!
|
|
54
|
-
//!
|
|
55
|
-
//!
|
|
56
|
-
//!
|
|
57
|
-
//!
|
|
58
|
-
//!
|
|
66
|
+
//! Operators are cheap to clone, contain no caller-visible lifetime or service
|
|
67
|
+
//! type parameter, and can be shared across threads. A clone refers to the
|
|
68
|
+
//! same composed service stack. Methods that add a layer or replace runtime
|
|
69
|
+
//! resources return a new operator; existing clones and in-flight operations
|
|
70
|
+
//! keep their current stack.
|
|
59
71
|
//!
|
|
60
|
-
//!
|
|
61
|
-
//! ┌─────────┐ Operator::new ┌────────────────────────────┐
|
|
62
|
-
//! │ Builder ├──────────────────►│ Operator │
|
|
63
|
-
//! └─────────┘ │ - base service │
|
|
64
|
-
//! │ - base OperationContext │
|
|
65
|
-
//! │ - layers │
|
|
66
|
-
//! │ - composed service/context │
|
|
67
|
-
//! └────────────────────────────┘
|
|
68
|
-
//! ```
|
|
72
|
+
//! # Operation
|
|
69
73
|
//!
|
|
70
|
-
//!
|
|
71
|
-
//! `
|
|
74
|
+
//! Operations are storage actions such as `read`, `write`, `stat`, `list`,
|
|
75
|
+
//! `delete`, `copy`, and `rename`. Convenience methods use default options,
|
|
76
|
+
//! while the corresponding `_with` methods expose operation-specific options.
|
|
72
77
|
//!
|
|
73
78
|
//! ```no_run
|
|
74
79
|
//! # use opendal_core::Result;
|
|
75
|
-
//! use opendal_core::services::Memory;
|
|
76
80
|
//! use opendal_core::Operator;
|
|
81
|
+
//! use opendal_core::services::Memory;
|
|
77
82
|
//!
|
|
78
|
-
//! # fn test() -> Result<()> {
|
|
79
|
-
//! let
|
|
80
|
-
//!
|
|
81
|
-
//! let
|
|
83
|
+
//! # async fn test() -> Result<()> {
|
|
84
|
+
//! let op = Operator::new(Memory::default())?;
|
|
85
|
+
//! let bs = op.read("abc").await?;
|
|
86
|
+
//! # let _ = bs;
|
|
82
87
|
//! # Ok(())
|
|
83
88
|
//! # }
|
|
84
89
|
//! ```
|
|
85
90
|
//!
|
|
86
|
-
//!
|
|
87
|
-
//!
|
|
88
|
-
//!
|
|
89
|
-
//!
|
|
90
|
-
//!
|
|
91
|
-
//!
|
|
92
|
-
//!
|
|
91
|
+
//! OpenDAL normalizes every path relative to the operator's root. `/`
|
|
92
|
+
//! represents the root, a trailing `/` represents a directory, and any other
|
|
93
|
+
//! normalized path represents a file. Operation documentation defines the
|
|
94
|
+
//! observable behavior and errors. [Specifications][super::specs] define
|
|
95
|
+
//! portable contracts that span multiple operations and services.
|
|
96
|
+
//!
|
|
97
|
+
//! # Layer and operation context
|
|
93
98
|
//!
|
|
94
|
-
//!
|
|
99
|
+
//! A [`Layer`][crate::raw::Layer] adds cross-cutting behavior such as retry,
|
|
100
|
+
//! timeout, tracing, or metrics. Layers form an ordered stack around a
|
|
101
|
+
//! service.
|
|
95
102
|
//!
|
|
96
|
-
//! [`OperationContext`] carries runtime resources
|
|
97
|
-
//!
|
|
98
|
-
//! Operation
|
|
99
|
-
//!
|
|
103
|
+
//! An [`OperationContext`] carries runtime resources such as the HTTP
|
|
104
|
+
//! transport and executor from the operator to the service.
|
|
105
|
+
//! Operation-specific values such as ranges, versions, conditions, and
|
|
106
|
+
//! concurrency remain in that operation's options.
|
|
100
107
|
//!
|
|
101
|
-
//!
|
|
102
|
-
//! [`Operator::
|
|
103
|
-
//!
|
|
104
|
-
//! service and context.
|
|
108
|
+
//! Adding a layer with [`Operator::layer`] or replacing the base context with
|
|
109
|
+
//! [`Operator::with_context`] rebuilds both the service stack and the composed
|
|
110
|
+
//! context from the same ordered layer list:
|
|
105
111
|
//!
|
|
106
112
|
//! ```text
|
|
107
|
-
//! base service
|
|
108
|
-
//!
|
|
109
|
-
//! base context
|
|
110
|
-
//! │ srv.read(&ctx, ...)
|
|
111
|
-
//! ▼
|
|
112
|
-
//! composed context
|
|
113
|
+
//! base service -----+ +-> composed service --+
|
|
114
|
+
//! +-> ordered layers --+ +-> operation
|
|
115
|
+
//! base context -----+ +-> composed context --+
|
|
113
116
|
//! ```
|
|
114
117
|
//!
|
|
115
118
|
//! ```no_run
|
|
@@ -129,40 +132,13 @@
|
|
|
129
132
|
//! # }
|
|
130
133
|
//! ```
|
|
131
134
|
//!
|
|
132
|
-
//!
|
|
133
|
-
//!
|
|
134
|
-
//! After creating an operator, use it to run operations on normalized paths.
|
|
135
|
-
//!
|
|
136
|
-
//! ```text
|
|
137
|
-
//! ┌──────────────┐
|
|
138
|
-
//! ┌────────►│ read("abc") │
|
|
139
|
-
//! │ └──────────────┘
|
|
140
|
-
//! ┌───────────┐ │
|
|
141
|
-
//! │ Operator │ │ ┌──────────────┐
|
|
142
|
-
//! │ ┌───────┐ ├────┼────────►│ write("def") │
|
|
143
|
-
//! │ │Service│ │ │ └──────────────┘
|
|
144
|
-
//! └─┴───────┴─┘ │
|
|
145
|
-
//! │ ┌──────────────┐
|
|
146
|
-
//! └────────►│ list("ghi/") │
|
|
147
|
-
//! └──────────────┘
|
|
148
|
-
//! ```
|
|
149
|
-
//!
|
|
150
|
-
//! We can read data with given path in this way:
|
|
151
|
-
//!
|
|
152
|
-
//! ```no_run
|
|
153
|
-
//! # use opendal_core::Result;
|
|
154
|
-
//! use opendal_core::services::Memory;
|
|
155
|
-
//! use opendal_core::Operator;
|
|
156
|
-
//!
|
|
157
|
-
//! # async fn test() -> Result<()> {
|
|
158
|
-
//! let builder = Memory::default();
|
|
159
|
-
//!
|
|
160
|
-
//! let op = Operator::new(builder)?;
|
|
161
|
-
//! let bs: Vec<u8> = op.read("abc").await?;
|
|
162
|
-
//! # Ok(())
|
|
163
|
-
//! # }
|
|
164
|
-
//! ```
|
|
135
|
+
//! Most applications only need the public [`Operator`] API. Service and layer
|
|
136
|
+
//! authors should continue with the [internals][super::internals] guide.
|
|
165
137
|
//!
|
|
166
138
|
//! [`Builder`]: crate::Builder
|
|
167
139
|
//! [`Operator`]: crate::Operator
|
|
140
|
+
//! [`Operator::new`]: crate::Operator::new
|
|
141
|
+
//! [`Operator::layer`]: crate::Operator::layer
|
|
142
|
+
//! [`Operator::with_context`]: crate::Operator::with_context
|
|
143
|
+
//! [`Capability`]: crate::Capability
|
|
168
144
|
//! [`OperationContext`]: crate::OperationContext
|
|
@@ -15,318 +15,87 @@
|
|
|
15
15
|
// specific language governing permissions and limitations
|
|
16
16
|
// under the License.
|
|
17
17
|
|
|
18
|
-
//!
|
|
18
|
+
//! Implementing a service.
|
|
19
19
|
//!
|
|
20
|
-
//! [`Service`]
|
|
21
|
-
//!
|
|
20
|
+
//! Every OpenDAL backend implements the raw [`Service`] trait. A service owns
|
|
21
|
+
//! protocol-specific request construction and response handling. The operator
|
|
22
|
+
//! owns path normalization, option validation, layer composition, and
|
|
23
|
+
//! dispatch.
|
|
22
24
|
//!
|
|
23
|
-
//!
|
|
25
|
+
//! Service crates live under `core/services/<name>/`. Their public builder and
|
|
26
|
+
//! configuration types construct a typed backend; the backend then implements
|
|
27
|
+
//! [`Service`].
|
|
24
28
|
//!
|
|
25
|
-
//!
|
|
29
|
+
//! # Service identity and capabilities
|
|
26
30
|
//!
|
|
27
|
-
//!
|
|
28
|
-
//!
|
|
29
|
-
//!
|
|
30
|
-
//! fn info(&self) -> ServiceInfo;
|
|
31
|
-
//! fn capability(&self) -> Capability;
|
|
31
|
+
//! [`Service::info`] returns immutable identity such as the scheme, root, and
|
|
32
|
+
//! namespace name. Runtime resources do not belong in [`ServiceInfo`];
|
|
33
|
+
//! services read them from [`OperationContext`].
|
|
32
34
|
//!
|
|
33
|
-
//!
|
|
34
|
-
//!
|
|
35
|
-
//!
|
|
36
|
-
//!
|
|
37
|
-
//! type Copier: oio::Copy;
|
|
35
|
+
//! [`Service::capability`] reports the behavior implemented by that service
|
|
36
|
+
//! stack. Set an operation or option capability only when the implementation
|
|
37
|
+
//! satisfies the corresponding public contract. Operators reject options whose
|
|
38
|
+
//! required capability is absent.
|
|
38
39
|
//!
|
|
39
|
-
//!
|
|
40
|
-
//! &self,
|
|
41
|
-
//! ctx: &OperationContext,
|
|
42
|
-
//! path: &str,
|
|
43
|
-
//! args: OpRead,
|
|
44
|
-
//! ) -> impl Future<Output = Result<Self::Reader>> + MaybeSend;
|
|
45
|
-
//! }
|
|
46
|
-
//! ```
|
|
47
|
-
//!
|
|
48
|
-
//! Let's go deep into [`Service`] line by line.
|
|
49
|
-
//!
|
|
50
|
-
//! ## Trait Bound
|
|
51
|
-
//!
|
|
52
|
-
//! First we will read the declaration of [`Service`] trait:
|
|
53
|
-
//!
|
|
54
|
-
//! ```ignore
|
|
55
|
-
//! pub trait Service: Send + Sync + Debug + Unpin + 'static {}
|
|
56
|
-
//! ```
|
|
57
|
-
//!
|
|
58
|
-
//! There are many trait boundings here. For now, [`Service`] requires the following bound:
|
|
59
|
-
//!
|
|
60
|
-
//! - [`Send`]: Allow user to send between threads without extra wrapper.
|
|
61
|
-
//! - [`Sync`]: Allow user to sync between threads without extra lock.
|
|
62
|
-
//! - [`Debug`][std::fmt::Debug]: Allow users to print underlying debug information of service.
|
|
63
|
-
//! - [`Unpin`]: Make sure `Service` can be safely moved after being pinned, so users don't need to `Pin<Box<A>>`.
|
|
64
|
-
//! - `'static`: Make sure `Service` is not a short-time reference, allow users to use `Service` in closures and futures without playing with lifetime.
|
|
65
|
-
//!
|
|
66
|
-
//! Implementer of `Service` should take care of the following things:
|
|
67
|
-
//!
|
|
68
|
-
//! - Implement `Debug` for backend, but don't leak credentials.
|
|
69
|
-
//! - Make sure the backend is `Send` and `Sync`, wrap the internal struct with `Arc<Mutex<T>>` if necessary.
|
|
70
|
-
//!
|
|
71
|
-
//! ## Associated Type
|
|
72
|
-
//!
|
|
73
|
-
//! The middle block of [`Service`] is our associated types. We require
|
|
74
|
-
//! implementers to specify concrete operation body types, avoiding extra
|
|
75
|
-
//! dynamic dispatch inside the backend and typed service wrappers.
|
|
76
|
-
//!
|
|
77
|
-
//! [`Service`] has five associated types so far:
|
|
78
|
-
//!
|
|
79
|
-
//! - `Reader`: reader returned by `read` operation.
|
|
80
|
-
//! - `Writer`: writer returned by `write` operation.
|
|
81
|
-
//! - `Lister`: lister returned by `list` operation.
|
|
82
|
-
//! - `Deleter`: deleter returned by `delete` operation.
|
|
83
|
-
//! - `Copier`: copier returned by `copy` operation.
|
|
84
|
-
//!
|
|
85
|
-
//! Backend implementers should take care of the following things:
|
|
86
|
-
//!
|
|
87
|
-
//! - Return concrete operation body types instead of dynamic trait objects like `oio::Reader`.
|
|
88
|
-
//! - Use `()` as the type if the operation is not supported.
|
|
89
|
-
//! - Implement every operation method; unsupported operations should return
|
|
90
|
-
//! [`ErrorKind::Unsupported`] explicitly.
|
|
91
|
-
//!
|
|
92
|
-
//! Runtime service wrappers that already receive a [`Servicer`] can forward the
|
|
93
|
-
//! erased `oio::*` body types, but the original backend should not erase itself.
|
|
94
|
-
//!
|
|
95
|
-
//! OpenDAL erases these associated types at the [`ServiceDyn`] boundary.
|
|
96
|
-
//! [`Servicer`] is `Arc<dyn ServiceDyn>` and is the handle used by
|
|
97
|
-
//! [`Operator`] and runtime layer composition. This keeps backend and typed
|
|
98
|
-
//! layer implementations concrete, while the composed operator stack can be
|
|
99
|
-
//! stored and cloned through one object-safe service handle.
|
|
100
|
-
//!
|
|
101
|
-
//! ## API Style
|
|
102
|
-
//!
|
|
103
|
-
//! Every API of [`Service`] follows the same style:
|
|
104
|
-
//!
|
|
105
|
-
//! - All APIs have a unique [`Operation`] and [`Capability`]
|
|
106
|
-
//! - All APIs are orthogonal and do not overlap with each other
|
|
107
|
-
//! - Most APIs accept [`OperationContext`], `path` and `OpXxx`, and returns `RpXxx` with concrete operation bodies.
|
|
108
|
-
//! - Most APIs have `async` and `blocking` variants, they share the same semantics but may have different underlying implementations.
|
|
109
|
-
//!
|
|
110
|
-
//! [`OperationContext`] carries operator resources composed by operator layers,
|
|
111
|
-
//! such as HTTP client and executor. Backend implementations should use this
|
|
112
|
-
//! context instead of storing mutable operator resources in [`ServiceInfo`].
|
|
113
|
-
//!
|
|
114
|
-
//! [`Service`] declares immutable identity facts via [`ServiceInfo`] and
|
|
115
|
-
//! operation capability via [`Service::capability`]:
|
|
116
|
-
//!
|
|
117
|
-
//! ```ignore
|
|
118
|
-
//! impl Service for MyBackend {
|
|
119
|
-
//! type Reader = MyReader;
|
|
120
|
-
//! type Writer = ();
|
|
121
|
-
//! type Lister = ();
|
|
122
|
-
//! type Deleter = ();
|
|
123
|
-
//! type Copier = ();
|
|
124
|
-
//!
|
|
125
|
-
//! fn info(&self) -> ServiceInfo {
|
|
126
|
-
//! ServiceInfo::new(MY_SCHEME, "/", "")
|
|
127
|
-
//! }
|
|
128
|
-
//!
|
|
129
|
-
//! fn capability(&self) -> Capability {
|
|
130
|
-
//! Capability {
|
|
131
|
-
//! read: true,
|
|
132
|
-
//! write: true,
|
|
133
|
-
//! ..Default::default()
|
|
134
|
-
//! }
|
|
135
|
-
//! }
|
|
136
|
-
//! }
|
|
137
|
-
//! ```
|
|
138
|
-
//!
|
|
139
|
-
//! Now that you have mastered [`Service`], let's go and implement our own backend!
|
|
140
|
-
//!
|
|
141
|
-
//! # Tutorial
|
|
40
|
+
//! # Operation body types
|
|
142
41
|
//!
|
|
143
|
-
//!
|
|
144
|
-
//! requests to a super-powered duck. Gagaga!
|
|
42
|
+
//! [`Service`] uses associated types for operation bodies:
|
|
145
43
|
//!
|
|
146
|
-
//!
|
|
147
|
-
//!
|
|
148
|
-
//!
|
|
149
|
-
//!
|
|
150
|
-
//!
|
|
151
|
-
//!
|
|
152
|
-
//! For example, we will use `s3` for AWS S3 Compatible Storage Service
|
|
153
|
-
//! instead of `aws` or `awss3`. This is because there are many storage
|
|
154
|
-
//! vendors that provide s3-like RESTful APIs, and our s3 service is
|
|
155
|
-
//! implemented to support all of them, not just AWS S3.
|
|
156
|
-
//!
|
|
157
|
-
//! Obviously, we can use `duck` as scheme, let's add a new constant string:
|
|
158
|
-
//!
|
|
159
|
-
//! ```ignore
|
|
160
|
-
//! pub const DUCK_SCHEME: &str = "duck";
|
|
44
|
+
//! ```text
|
|
45
|
+
//! type Reader: oio::Read;
|
|
46
|
+
//! type Writer: oio::Write;
|
|
47
|
+
//! type Lister: oio::List;
|
|
48
|
+
//! type Deleter: oio::Delete;
|
|
49
|
+
//! type Copier: oio::Copy;
|
|
161
50
|
//! ```
|
|
162
51
|
//!
|
|
163
|
-
//!
|
|
52
|
+
//! A backend returns concrete body types so its implementation and typed
|
|
53
|
+
//! wrappers do not pay for dynamic dispatch. Use `()` for an unsupported body
|
|
54
|
+
//! type and return [`ErrorKind::Unsupported`] from the corresponding operation
|
|
55
|
+
//! entry point.
|
|
164
56
|
//!
|
|
165
|
-
//!
|
|
166
|
-
//!
|
|
167
|
-
//!
|
|
57
|
+
//! OpenDAL erases these types once, at [`ServiceDyn`]. [`Servicer`] is
|
|
58
|
+
//! `Arc<dyn ServiceDyn>` and is the handle used by operators and runtime layer
|
|
59
|
+
//! composition. A wrapper that receives a [`Servicer`] may forward erased
|
|
60
|
+
//! `oio::*` bodies, but a backend should keep its own bodies concrete.
|
|
168
61
|
//!
|
|
169
|
-
//!
|
|
62
|
+
//! # Operation methods
|
|
170
63
|
//!
|
|
171
|
-
//!
|
|
172
|
-
//!
|
|
173
|
-
//!
|
|
64
|
+
//! Each operation method receives normalized paths, an [`OperationContext`],
|
|
65
|
+
//! and operation-specific arguments. The context supplies layer-composed
|
|
66
|
+
//! runtime resources such as the HTTP transport and executor. Options such as
|
|
67
|
+
//! ranges, versions, conditions, and concurrency remain in the operation
|
|
68
|
+
//! arguments.
|
|
174
69
|
//!
|
|
175
|
-
//!
|
|
176
|
-
//! ///
|
|
177
|
-
//! /// # Capabilities
|
|
178
|
-
//! ///
|
|
179
|
-
//! /// This service can be used to:
|
|
180
|
-
//! ///
|
|
181
|
-
//! /// - [x] read
|
|
182
|
-
//! /// - [ ] write
|
|
183
|
-
//! /// - [ ] list
|
|
184
|
-
//! /// - [ ] presign
|
|
185
|
-
//! ///
|
|
186
|
-
//! /// # Configuration
|
|
187
|
-
//! ///
|
|
188
|
-
//! /// - `root`: Set the work dir for backend.
|
|
189
|
-
//! ///
|
|
190
|
-
//! /// ## Via Builder
|
|
191
|
-
//! ///
|
|
192
|
-
//! /// ```no_run
|
|
193
|
-
//! /// use std::sync::Arc;
|
|
194
|
-
//! ///
|
|
195
|
-
//! /// use anyhow::Result;
|
|
196
|
-
//! /// use opendal_core::services::Duck;
|
|
197
|
-
//! /// use opendal_core::Operator;
|
|
198
|
-
//! ///
|
|
199
|
-
//! /// #[tokio::main]
|
|
200
|
-
//! /// async fn main() -> Result<()> {
|
|
201
|
-
//! /// // Create Duck backend builder.
|
|
202
|
-
//! /// let mut builder = DuckBuilder::default();
|
|
203
|
-
//! /// // Set the root for duck, all operations will happen under this root.
|
|
204
|
-
//! /// //
|
|
205
|
-
//! /// // NOTE: the root must be absolute path.
|
|
206
|
-
//! /// builder.root("/path/to/dir");
|
|
207
|
-
//! ///
|
|
208
|
-
//! /// let op: Operator = Operator::new(builder)?;
|
|
209
|
-
//! ///
|
|
210
|
-
//! /// Ok(())
|
|
211
|
-
//! /// }
|
|
212
|
-
//! /// ```
|
|
213
|
-
//! #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
|
214
|
-
//! #[serde(default)]
|
|
215
|
-
//! #[non_exhaustive]
|
|
216
|
-
//! pub struct DuckConfig {
|
|
217
|
-
//! pub root: Option<String>,
|
|
218
|
-
//! }
|
|
70
|
+
//! An implementation must:
|
|
219
71
|
//!
|
|
220
|
-
//!
|
|
221
|
-
//!
|
|
222
|
-
//!
|
|
223
|
-
//!
|
|
224
|
-
//!
|
|
225
|
-
//!
|
|
226
|
-
//!
|
|
72
|
+
//! - Map every advertised option to the native request without silently
|
|
73
|
+
//! dropping it.
|
|
74
|
+
//! - Preserve the operation's public success, error, and atomicity contract.
|
|
75
|
+
//! - Return structured OpenDAL errors with the correct [`ErrorKind`] and
|
|
76
|
+
//! useful context.
|
|
77
|
+
//! - Keep credentials and other secrets out of `Debug` output and errors.
|
|
78
|
+
//! - Forward cancellation and cleanup to protocol-specific readers, writers,
|
|
79
|
+
//! deleters, and copiers.
|
|
227
80
|
//!
|
|
228
|
-
//!
|
|
229
|
-
//! impl Configurator for DuckConfig {
|
|
230
|
-
//! type Builder = DuckBuilder;
|
|
231
|
-
//!
|
|
232
|
-
//! fn into_builder(self) -> Self::Builder {
|
|
233
|
-
//! DuckBuilder { config: self }
|
|
234
|
-
//! }
|
|
235
|
-
//! }
|
|
236
|
-
//! ```
|
|
81
|
+
//! # Adding or changing a service
|
|
237
82
|
//!
|
|
238
|
-
//!
|
|
239
|
-
//!
|
|
240
|
-
//!
|
|
241
|
-
//!
|
|
83
|
+
//! Keep configuration, request construction, operation bodies, and error
|
|
84
|
+
//! parsing at their existing service boundaries. Update the facade feature and
|
|
85
|
+
//! service registration when the service must be available through the
|
|
86
|
+
//! `opendal` crate.
|
|
242
87
|
//!
|
|
243
|
-
//!
|
|
244
|
-
//!
|
|
245
|
-
//!
|
|
246
|
-
//!
|
|
247
|
-
//! /// Set root of this backend.
|
|
248
|
-
//! ///
|
|
249
|
-
//! /// All operations will happen under this root.
|
|
250
|
-
//! pub fn root(&mut self, root: &str) -> &mut Self {
|
|
251
|
-
//! self.config.root = if root.is_empty() {
|
|
252
|
-
//! None
|
|
253
|
-
//! } else {
|
|
254
|
-
//! Some(root.to_string())
|
|
255
|
-
//! };
|
|
256
|
-
//!
|
|
257
|
-
//! self
|
|
258
|
-
//! }
|
|
259
|
-
//! }
|
|
260
|
-
//!
|
|
261
|
-
//! impl Builder for DuckBuilder {
|
|
262
|
-
//! type Config = DuckConfig;
|
|
263
|
-
//!
|
|
264
|
-
//! fn build(self) -> Result<impl Service> {
|
|
265
|
-
//! debug!("backend build started: {:?}", &self);
|
|
266
|
-
//!
|
|
267
|
-
//! let root = normalize_root(&self.config.root.clone().unwrap_or_default());
|
|
268
|
-
//! debug!("backend use root {}", &root);
|
|
269
|
-
//!
|
|
270
|
-
//! Ok(DuckBackend { root })
|
|
271
|
-
//! }
|
|
272
|
-
//! }
|
|
273
|
-
//! ```
|
|
274
|
-
//!
|
|
275
|
-
//! `DuckBuilder` is ready now, let's try to play with real ducks!
|
|
276
|
-
//!
|
|
277
|
-
//! ## Backend
|
|
278
|
-
//!
|
|
279
|
-
//! I'm sure you can see it already: `DuckBuilder` will build a
|
|
280
|
-
//! `DuckBackend` that implements [`Service`]. The backend is what we used
|
|
281
|
-
//! to communicate with the super-powered ducks!
|
|
282
|
-
//!
|
|
283
|
-
//! Let's keep adding more code under `backend.rs`:
|
|
284
|
-
//!
|
|
285
|
-
//! ```ignore
|
|
286
|
-
//! /// Duck storage service backend
|
|
287
|
-
//! #[derive(Clone, Debug)]
|
|
288
|
-
//! pub struct DuckBackend {
|
|
289
|
-
//! root: String,
|
|
290
|
-
//! }
|
|
291
|
-
//!
|
|
292
|
-
//! impl Service for DuckBackend {
|
|
293
|
-
//! type Reader = DuckReader;
|
|
294
|
-
//! type Writer = ();
|
|
295
|
-
//! type Lister = ();
|
|
296
|
-
//! type Deleter = ();
|
|
297
|
-
//! type Copier = ();
|
|
298
|
-
//!
|
|
299
|
-
//! fn info(&self) -> ServiceInfo {
|
|
300
|
-
//! ServiceInfo::new(DUCK_SCHEME, &self.root, "")
|
|
301
|
-
//! }
|
|
302
|
-
//!
|
|
303
|
-
//! fn capability(&self) -> Capability {
|
|
304
|
-
//! Capability {
|
|
305
|
-
//! read: true,
|
|
306
|
-
//! ..Default::default()
|
|
307
|
-
//! }
|
|
308
|
-
//! }
|
|
309
|
-
//!
|
|
310
|
-
//! fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
|
|
311
|
-
//! gagaga!()
|
|
312
|
-
//! }
|
|
313
|
-
//! }
|
|
314
|
-
//! ```
|
|
315
|
-
//!
|
|
316
|
-
//! Congratulations, we have implemented a [`Service`] that can talk to
|
|
317
|
-
//! Super Power Ducks!
|
|
318
|
-
//!
|
|
319
|
-
//! What!? There are no Super Power Ducks? So sad, but never mind, we have
|
|
320
|
-
//! really powerful storage services [here](https://github.com/apache/opendal/issues/5). Welcome to pick one to implement. I promise you won't
|
|
321
|
-
//! have to `gagaga!()` this time.
|
|
88
|
+
//! Before advertising new behavior, reproduce it against the actual service
|
|
89
|
+
//! and run the matching capability-gated behavior tests. Protocol
|
|
90
|
+
//! documentation, emulators, and fabricated responses can explain an
|
|
91
|
+
//! implementation, but they do not establish real-service conformance.
|
|
322
92
|
//!
|
|
323
93
|
//! [`Service`]: crate::raw::Service
|
|
94
|
+
//! [`Service::info`]: crate::raw::Service::info
|
|
95
|
+
//! [`Service::capability`]: crate::raw::Service::capability
|
|
96
|
+
//! [`ServiceInfo`]: crate::raw::ServiceInfo
|
|
324
97
|
//! [`ServiceDyn`]: crate::raw::ServiceDyn
|
|
325
98
|
//! [`Servicer`]: crate::raw::Servicer
|
|
326
|
-
//! [`
|
|
327
|
-
//! [`
|
|
328
|
-
//! [`
|
|
329
|
-
//! [`OperationContext`]: crate::raw::OperationContext
|
|
330
|
-
//! [`Operator`]: crate::Operator
|
|
331
|
-
//! [`Builder`]: crate::Builder
|
|
332
|
-
//! [`Configurator`]: crate::Configurator
|
|
99
|
+
//! [`OperationContext`]: crate::OperationContext
|
|
100
|
+
//! [`ErrorKind`]: crate::ErrorKind
|
|
101
|
+
//! [`ErrorKind::Unsupported`]: crate::ErrorKind::Unsupported
|