opendal 0.1.8 → 0.1.9
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/.gitignore +0 -1
- data/Cargo.lock +3448 -0
- data/Cargo.toml +1 -1
- data/DEPENDENCIES.rust.tsv +31 -31
- data/README.md +4 -1
- data/Rakefile +0 -7
- data/core/CHANGELOG.md +80 -0
- data/core/Cargo.lock +495 -599
- data/core/Cargo.toml +98 -95
- data/core/DEPENDENCIES.rust.tsv +319 -324
- data/core/NOTICE +5 -0
- data/core/README.md +11 -6
- data/core/benches/vs_fs/Cargo.toml +1 -1
- data/core/benches/vs_s3/Cargo.toml +1 -1
- data/core/core/Cargo.toml +2 -2
- data/core/core/LICENSE +201 -0
- data/core/core/NOTICE +5 -0
- data/core/core/README.md +93 -0
- data/core/core/src/blocking/delete.rs +2 -2
- data/core/core/src/blocking/list.rs +2 -1
- data/core/core/src/blocking/operator.rs +10 -5
- data/core/core/src/blocking/read/std_bytes_iterator.rs +2 -1
- data/core/core/src/blocking/read/std_reader.rs +2 -1
- data/core/core/src/blocking/write/std_writer.rs +1 -1
- data/core/core/src/docs/performance/http_optimization.md +9 -1
- data/core/core/src/docs/rfcs/7749_http_transporter.md +9 -5
- data/core/core/src/layers/mod.rs +6 -1
- data/core/core/src/lib.rs +2 -137
- data/core/core/src/raw/accessor.rs +23 -21
- data/core/core/src/raw/oio/buf/queue_buf.rs +4 -2
- data/core/core/src/raw/oio/write/block_write.rs +3 -2
- data/core/core/src/raw/operation.rs +5 -5
- data/core/core/src/raw/ops.rs +85 -63
- data/core/core/src/raw/std_io_util.rs +33 -1
- data/core/core/src/services/memory/backend.rs +0 -1
- data/core/core/src/services/memory/mod.rs +6 -2
- data/core/core/src/services/mod.rs +8 -2
- data/core/core/src/types/buffer.rs +4 -4
- data/core/core/src/types/builder.rs +15 -17
- data/core/core/src/types/copy.rs +3 -3
- data/core/core/src/types/entry.rs +3 -1
- data/core/core/src/types/error.rs +16 -11
- data/core/core/src/types/execute/executors/mod.rs +3 -3
- data/core/core/src/types/http_transport/mod.rs +6 -0
- data/core/core/src/types/list.rs +5 -6
- data/core/core/src/types/operator/info.rs +6 -4
- data/core/core/src/types/operator/mod.rs +1 -1
- data/core/core/src/types/operator/operator.rs +42 -8
- data/core/core/src/types/operator/operator_futures.rs +36 -38
- data/core/core/src/types/operator/registry.rs +73 -14
- data/core/core/src/types/options.rs +48 -42
- data/core/core/src/types/read/reader.rs +2 -1
- data/core/core/src/types/write/writer.rs +2 -1
- data/core/http-transports/reqwest/Cargo.toml +2 -1
- data/core/http-transports/reqwest/LICENSE +201 -0
- data/core/http-transports/reqwest/NOTICE +5 -0
- data/core/http-transports/reqwest/README.md +37 -9
- data/core/http-transports/reqwest/src/lib.rs +30 -51
- data/core/layers/async-backtrace/Cargo.toml +3 -2
- data/core/layers/async-backtrace/LICENSE +201 -0
- data/core/layers/async-backtrace/NOTICE +5 -0
- data/core/layers/async-backtrace/README.md +48 -0
- data/core/layers/async-backtrace/src/lib.rs +5 -5
- data/core/layers/await-tree/Cargo.toml +3 -2
- data/core/layers/await-tree/LICENSE +201 -0
- data/core/layers/await-tree/NOTICE +5 -0
- data/core/layers/await-tree/README.md +48 -0
- data/core/layers/await-tree/src/lib.rs +5 -6
- data/core/layers/capability-check/Cargo.toml +3 -2
- data/core/layers/capability-check/LICENSE +201 -0
- data/core/layers/capability-check/NOTICE +5 -0
- data/core/layers/capability-check/README.md +48 -0
- data/core/layers/capability-check/src/lib.rs +7 -8
- data/core/layers/chaos/Cargo.toml +3 -2
- data/core/layers/chaos/LICENSE +201 -0
- data/core/layers/chaos/NOTICE +5 -0
- data/core/layers/chaos/README.md +47 -0
- data/core/layers/chaos/src/lib.rs +6 -7
- data/core/layers/concurrent-limit/Cargo.toml +3 -2
- data/core/layers/concurrent-limit/LICENSE +201 -0
- data/core/layers/concurrent-limit/NOTICE +5 -0
- data/core/layers/concurrent-limit/README.md +48 -0
- data/core/layers/concurrent-limit/src/lib.rs +8 -14
- data/core/layers/dtrace/Cargo.toml +3 -2
- data/core/layers/dtrace/LICENSE +201 -0
- data/core/layers/dtrace/NOTICE +5 -0
- data/core/layers/dtrace/README.md +52 -0
- data/core/layers/dtrace/src/lib.rs +5 -5
- data/core/layers/fastmetrics/Cargo.toml +4 -3
- data/core/layers/fastmetrics/LICENSE +201 -0
- data/core/layers/fastmetrics/NOTICE +5 -0
- data/core/layers/fastmetrics/README.md +47 -0
- data/core/layers/fastmetrics/src/lib.rs +4 -4
- data/core/layers/fastrace/Cargo.toml +3 -2
- data/core/layers/fastrace/LICENSE +201 -0
- data/core/layers/fastrace/NOTICE +5 -0
- data/core/layers/fastrace/README.md +47 -0
- data/core/layers/fastrace/src/lib.rs +5 -5
- data/core/layers/foyer/Cargo.toml +3 -2
- data/core/layers/foyer/LICENSE +201 -0
- data/core/layers/foyer/NOTICE +5 -0
- data/core/layers/foyer/README.md +47 -0
- data/core/layers/foyer/src/deleter.rs +1 -0
- data/core/layers/foyer/src/lib.rs +27 -10
- data/core/layers/foyer/src/writer.rs +1 -0
- data/core/layers/hotpath/Cargo.toml +4 -3
- data/core/layers/hotpath/LICENSE +201 -0
- data/core/layers/hotpath/NOTICE +5 -0
- data/core/layers/hotpath/README.md +47 -0
- data/core/layers/hotpath/src/lib.rs +4 -4
- data/core/layers/immutable-index/Cargo.toml +3 -2
- data/core/layers/immutable-index/LICENSE +201 -0
- data/core/layers/immutable-index/NOTICE +5 -0
- data/core/layers/immutable-index/README.md +48 -0
- data/core/layers/immutable-index/src/lib.rs +3 -4
- data/core/layers/logging/Cargo.toml +3 -2
- data/core/layers/logging/LICENSE +201 -0
- data/core/layers/logging/NOTICE +5 -0
- data/core/layers/logging/README.md +47 -0
- data/core/layers/logging/src/lib.rs +11 -11
- data/core/layers/metrics/Cargo.toml +4 -3
- data/core/layers/metrics/LICENSE +201 -0
- data/core/layers/metrics/NOTICE +5 -0
- data/core/layers/metrics/README.md +47 -0
- data/core/layers/metrics/src/lib.rs +6 -6
- data/core/layers/mime-guess/Cargo.toml +3 -2
- data/core/layers/mime-guess/LICENSE +201 -0
- data/core/layers/mime-guess/NOTICE +5 -0
- data/core/layers/mime-guess/README.md +47 -0
- data/core/layers/mime-guess/src/lib.rs +13 -17
- data/core/layers/observe-metrics-common/Cargo.toml +2 -1
- data/core/layers/observe-metrics-common/LICENSE +201 -0
- data/core/layers/observe-metrics-common/NOTICE +5 -0
- data/core/layers/observe-metrics-common/README.md +27 -0
- data/core/layers/observe-metrics-common/src/lib.rs +15 -9
- data/core/layers/otelmetrics/Cargo.toml +4 -3
- data/core/layers/otelmetrics/LICENSE +201 -0
- data/core/layers/otelmetrics/NOTICE +5 -0
- data/core/layers/otelmetrics/README.md +47 -0
- data/core/layers/otelmetrics/src/lib.rs +4 -4
- data/core/layers/oteltrace/Cargo.toml +3 -2
- data/core/layers/oteltrace/LICENSE +201 -0
- data/core/layers/oteltrace/NOTICE +5 -0
- data/core/layers/oteltrace/README.md +48 -0
- data/core/layers/oteltrace/src/lib.rs +13 -4
- data/core/layers/prometheus/Cargo.toml +4 -3
- data/core/layers/prometheus/LICENSE +201 -0
- data/core/layers/prometheus/NOTICE +5 -0
- data/core/layers/prometheus/README.md +47 -0
- data/core/layers/prometheus/src/lib.rs +4 -4
- data/core/layers/prometheus-client/Cargo.toml +4 -3
- data/core/layers/prometheus-client/LICENSE +201 -0
- data/core/layers/prometheus-client/NOTICE +5 -0
- data/core/layers/prometheus-client/README.md +48 -0
- data/core/layers/prometheus-client/src/lib.rs +4 -4
- data/core/layers/retry/Cargo.toml +5 -4
- data/core/layers/retry/LICENSE +201 -0
- data/core/layers/retry/NOTICE +5 -0
- data/core/layers/retry/README.md +50 -0
- data/core/layers/retry/src/lib.rs +6 -7
- data/core/layers/route/Cargo.toml +4 -3
- data/core/layers/route/LICENSE +201 -0
- data/core/layers/route/NOTICE +5 -0
- data/core/layers/route/README.md +58 -0
- data/core/layers/route/src/lib.rs +39 -9
- data/core/layers/tail-cut/Cargo.toml +3 -2
- data/core/layers/tail-cut/LICENSE +201 -0
- data/core/layers/tail-cut/NOTICE +5 -0
- data/core/layers/tail-cut/README.md +47 -0
- data/core/layers/tail-cut/src/lib.rs +7 -9
- data/core/layers/throttle/Cargo.toml +3 -2
- data/core/layers/throttle/LICENSE +201 -0
- data/core/layers/throttle/NOTICE +5 -0
- data/core/layers/throttle/README.md +47 -0
- data/core/layers/throttle/src/lib.rs +5 -7
- data/core/layers/timeout/Cargo.toml +4 -3
- data/core/layers/timeout/LICENSE +201 -0
- data/core/layers/timeout/NOTICE +5 -0
- data/core/layers/timeout/README.md +50 -0
- data/core/layers/timeout/src/lib.rs +9 -10
- data/core/layers/tracing/Cargo.toml +3 -2
- data/core/layers/tracing/LICENSE +201 -0
- data/core/layers/tracing/NOTICE +5 -0
- data/core/layers/tracing/README.md +47 -0
- data/core/layers/tracing/src/lib.rs +4 -4
- data/core/services/aliyun-drive/Cargo.toml +2 -1
- data/core/services/aliyun-drive/LICENSE +201 -0
- data/core/services/aliyun-drive/NOTICE +5 -0
- data/core/services/aliyun-drive/README.md +56 -0
- data/core/services/aliyun-drive/src/backend.rs +2 -2
- data/core/services/aliyun-drive/src/docs.md +7 -9
- data/core/services/aliyun-drive/src/lib.rs +12 -2
- data/core/services/aliyun-drive/src/lister.rs +2 -2
- data/core/services/alluxio/Cargo.toml +2 -1
- data/core/services/alluxio/LICENSE +201 -0
- data/core/services/alluxio/NOTICE +5 -0
- data/core/services/alluxio/README.md +56 -0
- data/core/services/alluxio/src/backend.rs +3 -3
- data/core/services/alluxio/src/docs.md +7 -5
- data/core/services/alluxio/src/lib.rs +12 -2
- data/core/services/azblob/Cargo.toml +6 -5
- data/core/services/azblob/LICENSE +201 -0
- data/core/services/azblob/NOTICE +5 -0
- data/core/services/azblob/README.md +56 -0
- data/core/services/azblob/src/backend.rs +3 -3
- data/core/services/azblob/src/core.rs +3 -3
- data/core/services/azblob/src/docs.md +7 -9
- data/core/services/azblob/src/lib.rs +14 -2
- data/core/services/azdls/Cargo.toml +6 -5
- data/core/services/azdls/LICENSE +201 -0
- data/core/services/azdls/NOTICE +5 -0
- data/core/services/azdls/README.md +56 -0
- data/core/services/azdls/src/backend.rs +3 -3
- data/core/services/azdls/src/docs.md +7 -8
- data/core/services/azdls/src/lib.rs +12 -2
- data/core/services/azdls/src/lister.rs +1 -1
- data/core/services/azfile/Cargo.toml +6 -5
- data/core/services/azfile/LICENSE +201 -0
- data/core/services/azfile/NOTICE +5 -0
- data/core/services/azfile/README.md +56 -0
- data/core/services/azfile/src/backend.rs +2 -2
- data/core/services/azfile/src/docs.md +7 -8
- data/core/services/azfile/src/lib.rs +12 -2
- data/core/services/azure-common/Cargo.toml +2 -1
- data/core/services/azure-common/LICENSE +201 -0
- data/core/services/azure-common/NOTICE +5 -0
- data/core/services/azure-common/README.md +26 -0
- data/core/services/azure-common/src/lib.rs +2 -5
- data/core/services/b2/Cargo.toml +2 -1
- data/core/services/b2/LICENSE +201 -0
- data/core/services/b2/NOTICE +5 -0
- data/core/services/b2/README.md +56 -0
- data/core/services/b2/src/backend.rs +4 -4
- data/core/services/b2/src/docs.md +7 -8
- data/core/services/b2/src/lib.rs +9 -3
- data/core/services/cacache/Cargo.toml +2 -1
- data/core/services/cacache/LICENSE +201 -0
- data/core/services/cacache/NOTICE +5 -0
- data/core/services/cacache/README.md +56 -0
- data/core/services/cacache/src/backend.rs +0 -1
- data/core/services/cacache/src/docs.md +7 -4
- data/core/services/cacache/src/lib.rs +9 -4
- data/core/services/cloudflare-kv/Cargo.toml +2 -1
- data/core/services/cloudflare-kv/LICENSE +201 -0
- data/core/services/cloudflare-kv/NOTICE +5 -0
- data/core/services/cloudflare-kv/README.md +56 -0
- data/core/services/cloudflare-kv/src/backend.rs +0 -2
- data/core/services/cloudflare-kv/src/docs.md +7 -5
- data/core/services/cloudflare-kv/src/lib.rs +9 -3
- data/core/services/compfs/Cargo.toml +2 -1
- data/core/services/compfs/LICENSE +201 -0
- data/core/services/compfs/NOTICE +5 -0
- data/core/services/compfs/README.md +58 -0
- data/core/services/compfs/src/lib.rs +9 -3
- data/core/services/cos/Cargo.toml +5 -4
- data/core/services/cos/LICENSE +201 -0
- data/core/services/cos/NOTICE +5 -0
- data/core/services/cos/README.md +56 -0
- data/core/services/cos/src/backend.rs +4 -4
- data/core/services/cos/src/docs.md +7 -9
- data/core/services/cos/src/lib.rs +12 -2
- data/core/services/d1/Cargo.toml +2 -1
- data/core/services/d1/LICENSE +201 -0
- data/core/services/d1/NOTICE +5 -0
- data/core/services/d1/README.md +56 -0
- data/core/services/d1/src/docs.md +7 -8
- data/core/services/d1/src/lib.rs +9 -3
- data/core/services/dashmap/Cargo.toml +2 -1
- data/core/services/dashmap/LICENSE +201 -0
- data/core/services/dashmap/NOTICE +5 -0
- data/core/services/dashmap/README.md +56 -0
- data/core/services/dashmap/src/backend.rs +1 -2
- data/core/services/dashmap/src/docs.md +7 -4
- data/core/services/dashmap/src/lib.rs +9 -4
- data/core/services/dbfs/Cargo.toml +2 -1
- data/core/services/dbfs/LICENSE +201 -0
- data/core/services/dbfs/NOTICE +5 -0
- data/core/services/dbfs/README.md +56 -0
- data/core/services/dbfs/src/backend.rs +2 -2
- data/core/services/dbfs/src/core.rs +1 -1
- data/core/services/dbfs/src/docs.md +7 -6
- data/core/services/dbfs/src/lib.rs +9 -4
- data/core/services/dbfs/src/lister.rs +1 -1
- data/core/services/dropbox/Cargo.toml +2 -1
- data/core/services/dropbox/LICENSE +201 -0
- data/core/services/dropbox/NOTICE +5 -0
- data/core/services/dropbox/README.md +56 -0
- data/core/services/dropbox/src/docs.md +7 -4
- data/core/services/dropbox/src/lib.rs +9 -4
- data/core/services/etcd/Cargo.toml +2 -1
- data/core/services/etcd/LICENSE +201 -0
- data/core/services/etcd/NOTICE +5 -0
- data/core/services/etcd/README.md +56 -0
- data/core/services/etcd/src/docs.md +7 -10
- data/core/services/etcd/src/lib.rs +9 -4
- data/core/services/foundationdb/Cargo.toml +2 -1
- data/core/services/foundationdb/LICENSE +201 -0
- data/core/services/foundationdb/NOTICE +5 -0
- data/core/services/foundationdb/README.md +56 -0
- data/core/services/foundationdb/src/docs.md +7 -5
- data/core/services/foundationdb/src/lib.rs +9 -4
- data/core/services/foyer/Cargo.toml +4 -3
- data/core/services/foyer/LICENSE +201 -0
- data/core/services/foyer/NOTICE +5 -0
- data/core/services/foyer/README.md +57 -0
- data/core/services/foyer/src/backend.rs +1 -1
- data/core/services/foyer/src/docs.md +12 -1
- data/core/services/foyer/src/lib.rs +9 -11
- data/core/services/fs/Cargo.toml +2 -1
- data/core/services/fs/LICENSE +201 -0
- data/core/services/fs/NOTICE +5 -0
- data/core/services/fs/README.md +56 -0
- data/core/services/fs/src/backend.rs +1 -1
- data/core/services/fs/src/docs.md +7 -5
- data/core/services/fs/src/lib.rs +9 -3
- data/core/services/ftp/Cargo.toml +2 -1
- data/core/services/ftp/LICENSE +201 -0
- data/core/services/ftp/NOTICE +5 -0
- data/core/services/ftp/README.md +56 -0
- data/core/services/ftp/src/backend.rs +1 -1
- data/core/services/ftp/src/docs.md +7 -7
- data/core/services/ftp/src/lib.rs +12 -2
- data/core/services/ftp/src/lister.rs +1 -1
- data/core/services/gcs/Cargo.toml +5 -4
- data/core/services/gcs/LICENSE +201 -0
- data/core/services/gcs/NOTICE +5 -0
- data/core/services/gcs/README.md +56 -0
- data/core/services/gcs/src/core.rs +55 -1
- data/core/services/gcs/src/docs.md +7 -13
- data/core/services/gcs/src/lib.rs +9 -3
- data/core/services/gcs/src/writer.rs +5 -12
- data/core/services/gdrive/Cargo.toml +2 -1
- data/core/services/gdrive/LICENSE +201 -0
- data/core/services/gdrive/NOTICE +5 -0
- data/core/services/gdrive/README.md +56 -0
- data/core/services/gdrive/src/docs.md +8 -5
- data/core/services/gdrive/src/lib.rs +12 -2
- data/core/services/gdrive/src/lister.rs +6 -6
- data/core/services/ghac/Cargo.toml +5 -4
- data/core/services/ghac/LICENSE +201 -0
- data/core/services/ghac/NOTICE +5 -0
- data/core/services/ghac/README.md +56 -0
- data/core/services/ghac/src/docs.md +7 -4
- data/core/services/ghac/src/lib.rs +12 -2
- data/core/services/github/Cargo.toml +2 -1
- data/core/services/github/LICENSE +201 -0
- data/core/services/github/NOTICE +5 -0
- data/core/services/github/README.md +56 -0
- data/core/services/github/src/backend.rs +4 -4
- data/core/services/github/src/docs.md +7 -8
- data/core/services/github/src/lib.rs +12 -2
- data/core/services/goosefs/Cargo.toml +4 -3
- data/core/services/goosefs/LICENSE +201 -0
- data/core/services/goosefs/NOTICE +5 -0
- data/core/services/goosefs/README.md +56 -0
- data/core/services/goosefs/src/backend.rs +31 -12
- data/core/services/goosefs/src/config.rs +1 -1
- data/core/services/goosefs/src/core.rs +72 -25
- data/core/services/goosefs/src/docs.md +10 -10
- data/core/services/goosefs/src/lib.rs +12 -2
- data/core/services/goosefs/src/writer.rs +24 -20
- data/core/services/goosefs/tests/safe_conditional_put.rs +199 -0
- data/core/services/gridfs/Cargo.toml +2 -1
- data/core/services/gridfs/LICENSE +201 -0
- data/core/services/gridfs/NOTICE +5 -0
- data/core/services/gridfs/README.md +56 -0
- data/core/services/gridfs/src/docs.md +7 -6
- data/core/services/gridfs/src/lib.rs +9 -4
- data/core/services/hdfs/Cargo.toml +2 -1
- data/core/services/hdfs/LICENSE +201 -0
- data/core/services/hdfs/NOTICE +5 -0
- data/core/services/hdfs/README.md +58 -0
- data/core/services/hdfs/src/backend.rs +1 -1
- data/core/services/hdfs/src/docs.md +9 -9
- data/core/services/hdfs/src/lib.rs +12 -2
- data/core/services/hdfs-native/Cargo.toml +3 -2
- data/core/services/hdfs-native/LICENSE +201 -0
- data/core/services/hdfs-native/NOTICE +5 -0
- data/core/services/hdfs-native/README.md +56 -0
- data/core/services/hdfs-native/src/backend.rs +3 -2
- data/core/services/hdfs-native/src/docs.md +7 -4
- data/core/services/hdfs-native/src/lib.rs +12 -2
- data/core/services/hdfs-native/src/writer.rs +1 -1
- data/core/services/hf/Cargo.toml +3 -2
- data/core/services/hf/LICENSE +201 -0
- data/core/services/hf/NOTICE +5 -0
- data/core/services/hf/README.md +56 -0
- data/core/services/hf/src/backend.rs +11 -9
- data/core/services/hf/src/config.rs +1 -1
- data/core/services/hf/src/core.rs +12 -12
- data/core/services/hf/src/docs.md +11 -12
- data/core/services/hf/src/lib.rs +13 -3
- data/core/services/hf/src/lister.rs +1 -1
- data/core/services/http/Cargo.toml +4 -3
- data/core/services/http/LICENSE +201 -0
- data/core/services/http/NOTICE +5 -0
- data/core/services/http/README.md +56 -0
- data/core/services/http/src/backend.rs +1 -1
- data/core/services/http/src/docs.md +7 -5
- data/core/services/http/src/lib.rs +10 -4
- data/core/services/ipfs/Cargo.toml +2 -1
- data/core/services/ipfs/LICENSE +201 -0
- data/core/services/ipfs/NOTICE +5 -0
- data/core/services/ipfs/README.md +56 -0
- data/core/services/ipfs/src/backend.rs +2 -2
- data/core/services/ipfs/src/docs.md +7 -5
- data/core/services/ipfs/src/lib.rs +9 -3
- data/core/services/ipmfs/Cargo.toml +2 -1
- data/core/services/ipmfs/LICENSE +201 -0
- data/core/services/ipmfs/NOTICE +5 -0
- data/core/services/ipmfs/README.md +56 -0
- data/core/services/ipmfs/src/docs.md +10 -1
- data/core/services/ipmfs/src/lib.rs +12 -2
- data/core/services/ipmfs/src/lister.rs +2 -2
- data/core/services/koofr/Cargo.toml +2 -1
- data/core/services/koofr/LICENSE +201 -0
- data/core/services/koofr/NOTICE +5 -0
- data/core/services/koofr/README.md +56 -0
- data/core/services/koofr/src/backend.rs +4 -4
- data/core/services/koofr/src/docs.md +7 -7
- data/core/services/koofr/src/lib.rs +12 -2
- data/core/services/lakefs/Cargo.toml +2 -1
- data/core/services/lakefs/LICENSE +201 -0
- data/core/services/lakefs/NOTICE +5 -0
- data/core/services/lakefs/README.md +56 -0
- data/core/services/lakefs/src/backend.rs +5 -5
- data/core/services/lakefs/src/docs.md +7 -9
- data/core/services/lakefs/src/lib.rs +9 -4
- data/core/services/lakefs/src/lister.rs +1 -1
- data/core/services/memcached/Cargo.toml +3 -2
- data/core/services/memcached/LICENSE +201 -0
- data/core/services/memcached/NOTICE +5 -0
- data/core/services/memcached/README.md +56 -0
- data/core/services/memcached/src/docs.md +7 -8
- data/core/services/memcached/src/lib.rs +9 -4
- data/core/services/mini_moka/Cargo.toml +2 -1
- data/core/services/mini_moka/LICENSE +201 -0
- data/core/services/mini_moka/NOTICE +5 -0
- data/core/services/mini_moka/README.md +56 -0
- data/core/services/mini_moka/src/backend.rs +1 -1
- data/core/services/mini_moka/src/docs.md +10 -1
- data/core/services/mini_moka/src/lib.rs +9 -4
- data/core/services/moka/Cargo.toml +2 -1
- data/core/services/moka/LICENSE +201 -0
- data/core/services/moka/NOTICE +5 -0
- data/core/services/moka/README.md +56 -0
- data/core/services/moka/src/backend.rs +1 -2
- data/core/services/moka/src/docs.md +7 -7
- data/core/services/moka/src/lib.rs +9 -3
- data/core/services/mongodb/Cargo.toml +2 -1
- data/core/services/mongodb/LICENSE +201 -0
- data/core/services/mongodb/NOTICE +5 -0
- data/core/services/mongodb/README.md +56 -0
- data/core/services/mongodb/src/docs.md +7 -7
- data/core/services/mongodb/src/lib.rs +12 -2
- data/core/services/monoiofs/Cargo.toml +2 -1
- data/core/services/monoiofs/LICENSE +201 -0
- data/core/services/monoiofs/NOTICE +5 -0
- data/core/services/monoiofs/README.md +58 -0
- data/core/services/monoiofs/src/docs.md +7 -4
- data/core/services/monoiofs/src/lib.rs +9 -4
- data/core/services/mysql/Cargo.toml +2 -1
- data/core/services/mysql/LICENSE +201 -0
- data/core/services/mysql/NOTICE +5 -0
- data/core/services/mysql/README.md +56 -0
- data/core/services/mysql/src/docs.md +7 -6
- data/core/services/mysql/src/lib.rs +12 -2
- data/core/services/obs/Cargo.toml +5 -4
- data/core/services/obs/LICENSE +201 -0
- data/core/services/obs/NOTICE +5 -0
- data/core/services/obs/README.md +56 -0
- data/core/services/obs/src/backend.rs +4 -4
- data/core/services/obs/src/docs.md +7 -9
- data/core/services/obs/src/lib.rs +12 -2
- data/core/services/onedrive/Cargo.toml +2 -1
- data/core/services/onedrive/LICENSE +201 -0
- data/core/services/onedrive/NOTICE +5 -0
- data/core/services/onedrive/README.md +56 -0
- data/core/services/onedrive/src/docs.md +10 -10
- data/core/services/onedrive/src/lib.rs +9 -3
- data/core/services/opfs/Cargo.toml +4 -1
- data/core/services/opfs/LICENSE +201 -0
- data/core/services/opfs/NOTICE +5 -0
- data/core/services/opfs/README.md +63 -0
- data/core/services/opfs/src/core.rs +2 -0
- data/core/services/opfs/src/docs.md +7 -1
- data/core/services/opfs/src/lib.rs +11 -2
- data/core/services/oss/Cargo.toml +5 -4
- data/core/services/oss/LICENSE +201 -0
- data/core/services/oss/NOTICE +5 -0
- data/core/services/oss/README.md +56 -0
- data/core/services/oss/src/backend.rs +4 -4
- data/core/services/oss/src/docs.md +10 -22
- data/core/services/oss/src/lib.rs +9 -3
- data/core/services/pcloud/Cargo.toml +2 -1
- data/core/services/pcloud/LICENSE +201 -0
- data/core/services/pcloud/NOTICE +5 -0
- data/core/services/pcloud/README.md +56 -0
- data/core/services/pcloud/src/backend.rs +3 -3
- data/core/services/pcloud/src/docs.md +7 -7
- data/core/services/pcloud/src/lib.rs +9 -3
- data/core/services/persy/Cargo.toml +2 -1
- data/core/services/persy/LICENSE +201 -0
- data/core/services/persy/NOTICE +5 -0
- data/core/services/persy/README.md +56 -0
- data/core/services/persy/src/backend.rs +0 -1
- data/core/services/persy/src/docs.md +7 -6
- data/core/services/persy/src/lib.rs +9 -3
- data/core/services/postgresql/Cargo.toml +2 -1
- data/core/services/postgresql/LICENSE +201 -0
- data/core/services/postgresql/NOTICE +5 -0
- data/core/services/postgresql/README.md +56 -0
- data/core/services/postgresql/src/docs.md +7 -6
- data/core/services/postgresql/src/lib.rs +12 -2
- data/core/services/redb/Cargo.toml +2 -1
- data/core/services/redb/LICENSE +201 -0
- data/core/services/redb/NOTICE +5 -0
- data/core/services/redb/README.md +56 -0
- data/core/services/redb/src/backend.rs +0 -1
- data/core/services/redb/src/docs.md +7 -5
- data/core/services/redb/src/lib.rs +9 -3
- data/core/services/redis/Cargo.toml +2 -1
- data/core/services/redis/LICENSE +201 -0
- data/core/services/redis/NOTICE +5 -0
- data/core/services/redis/README.md +56 -0
- data/core/services/redis/src/docs.md +7 -9
- data/core/services/redis/src/lib.rs +9 -4
- data/core/services/rocksdb/Cargo.toml +2 -1
- data/core/services/rocksdb/LICENSE +201 -0
- data/core/services/rocksdb/NOTICE +5 -0
- data/core/services/rocksdb/README.md +56 -0
- data/core/services/rocksdb/src/backend.rs +0 -1
- data/core/services/rocksdb/src/docs.md +7 -5
- data/core/services/rocksdb/src/lib.rs +12 -2
- data/core/services/s3/Cargo.toml +5 -4
- data/core/services/s3/LICENSE +201 -0
- data/core/services/s3/NOTICE +5 -0
- data/core/services/s3/README.md +56 -0
- data/core/services/s3/src/backend.rs +60 -7
- data/core/services/s3/src/compatible_services.md +10 -2
- data/core/services/s3/src/core.rs +16 -8
- data/core/services/s3/src/docs.md +7 -28
- data/core/services/s3/src/lib.rs +9 -3
- data/core/services/seafile/Cargo.toml +2 -1
- data/core/services/seafile/LICENSE +201 -0
- data/core/services/seafile/NOTICE +5 -0
- data/core/services/seafile/README.md +56 -0
- data/core/services/seafile/src/backend.rs +3 -3
- data/core/services/seafile/src/docs.md +7 -8
- data/core/services/seafile/src/lib.rs +12 -2
- data/core/services/sftp/Cargo.toml +2 -1
- data/core/services/sftp/LICENSE +201 -0
- data/core/services/sftp/NOTICE +5 -0
- data/core/services/sftp/README.md +56 -0
- data/core/services/sftp/src/backend.rs +2 -2
- data/core/services/sftp/src/docs.md +7 -9
- data/core/services/sftp/src/lib.rs +9 -4
- data/core/services/sled/Cargo.toml +2 -1
- data/core/services/sled/LICENSE +201 -0
- data/core/services/sled/NOTICE +5 -0
- data/core/services/sled/README.md +56 -0
- data/core/services/sled/src/backend.rs +0 -1
- data/core/services/sled/src/docs.md +7 -4
- data/core/services/sled/src/lib.rs +12 -2
- data/core/services/sqlite/Cargo.toml +2 -1
- data/core/services/sqlite/LICENSE +201 -0
- data/core/services/sqlite/NOTICE +5 -0
- data/core/services/sqlite/README.md +56 -0
- data/core/services/sqlite/src/backend.rs +0 -1
- data/core/services/sqlite/src/docs.md +7 -6
- data/core/services/sqlite/src/lib.rs +12 -2
- data/core/services/surrealdb/Cargo.toml +2 -1
- data/core/services/surrealdb/LICENSE +201 -0
- data/core/services/surrealdb/NOTICE +5 -0
- data/core/services/surrealdb/README.md +56 -0
- data/core/services/surrealdb/src/docs.md +8 -10
- data/core/services/surrealdb/src/lib.rs +9 -3
- data/core/services/swift/Cargo.toml +2 -1
- data/core/services/swift/LICENSE +201 -0
- data/core/services/swift/NOTICE +5 -0
- data/core/services/swift/README.md +56 -0
- data/core/services/swift/src/backend.rs +2 -2
- data/core/services/swift/src/core.rs +24 -24
- data/core/services/swift/src/deleter.rs +1 -1
- data/core/services/swift/src/docs.md +7 -6
- data/core/services/swift/src/lib.rs +9 -4
- data/core/services/swift/src/writer.rs +1 -1
- data/core/services/tikv/Cargo.toml +2 -1
- data/core/services/tikv/LICENSE +201 -0
- data/core/services/tikv/NOTICE +5 -0
- data/core/services/tikv/README.md +56 -0
- data/core/services/tikv/src/backend.rs +1 -1
- data/core/services/tikv/src/docs.md +7 -8
- data/core/services/tikv/src/lib.rs +12 -2
- data/core/services/tos/Cargo.toml +5 -4
- data/core/services/tos/LICENSE +201 -0
- data/core/services/tos/NOTICE +5 -0
- data/core/services/tos/README.md +56 -0
- data/core/services/tos/src/docs.md +7 -10
- data/core/services/tos/src/lib.rs +9 -3
- data/core/services/upyun/Cargo.toml +2 -1
- data/core/services/upyun/LICENSE +201 -0
- data/core/services/upyun/NOTICE +5 -0
- data/core/services/upyun/README.md +56 -0
- data/core/services/upyun/src/backend.rs +3 -3
- data/core/services/upyun/src/docs.md +7 -7
- data/core/services/upyun/src/lib.rs +9 -4
- data/core/services/vercel-artifacts/Cargo.toml +2 -1
- data/core/services/vercel-artifacts/LICENSE +201 -0
- data/core/services/vercel-artifacts/NOTICE +5 -0
- data/core/services/vercel-artifacts/README.md +56 -0
- data/core/services/vercel-artifacts/src/docs.md +7 -7
- data/core/services/vercel-artifacts/src/lib.rs +11 -3
- data/core/services/vercel-blob/Cargo.toml +2 -1
- data/core/services/vercel-blob/LICENSE +201 -0
- data/core/services/vercel-blob/NOTICE +5 -0
- data/core/services/vercel-blob/README.md +56 -0
- data/core/services/vercel-blob/src/backend.rs +2 -2
- data/core/services/vercel-blob/src/docs.md +7 -5
- data/core/services/vercel-blob/src/lib.rs +12 -2
- data/core/services/webdav/Cargo.toml +2 -1
- data/core/services/webdav/LICENSE +201 -0
- data/core/services/webdav/NOTICE +5 -0
- data/core/services/webdav/README.md +56 -0
- data/core/services/webdav/src/backend.rs +1 -1
- data/core/services/webdav/src/docs.md +7 -7
- data/core/services/webdav/src/lib.rs +12 -2
- data/core/services/webhdfs/Cargo.toml +2 -1
- data/core/services/webhdfs/LICENSE +201 -0
- data/core/services/webhdfs/NOTICE +5 -0
- data/core/services/webhdfs/README.md +56 -0
- data/core/services/webhdfs/src/docs.md +11 -9
- data/core/services/webhdfs/src/lib.rs +12 -2
- data/core/services/yandex-disk/Cargo.toml +2 -1
- data/core/services/yandex-disk/LICENSE +201 -0
- data/core/services/yandex-disk/NOTICE +5 -0
- data/core/services/yandex-disk/README.md +56 -0
- data/core/services/yandex-disk/src/backend.rs +2 -2
- data/core/services/yandex-disk/src/docs.md +7 -5
- data/core/services/yandex-disk/src/lib.rs +9 -3
- data/core/src/lib.rs +30 -4
- data/core/testkit/Cargo.toml +5 -4
- data/core/testkit/LICENSE +201 -0
- data/core/testkit/NOTICE +5 -0
- data/core/testkit/README.md +25 -0
- data/core/testkit/src/lib.rs +4 -2
- data/core/testkit/src/read.rs +12 -13
- data/core/testkit/src/write.rs +12 -13
- data/core/tests/behavior/async_list.rs +2 -2
- data/core/tests/behavior/async_presign.rs +4 -4
- data/core/tests/behavior/async_stat.rs +1 -1
- data/core/tests/behavior/async_write.rs +1 -1
- data/core/users.md +2 -0
- data/opendal.gemspec +5 -1
- metadata +283 -2
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Apache OpenDAL™ GooseFS Service
|
|
2
|
+
|
|
3
|
+
`opendal-service-goosefs` provides access to GooseFS through its native gRPC API for
|
|
4
|
+
applications built with Apache OpenDAL™.
|
|
5
|
+
|
|
6
|
+
## Use through `opendal`
|
|
7
|
+
|
|
8
|
+
Applications should normally enable this service through the `opendal` facade with the
|
|
9
|
+
`services-goosefs` feature:
|
|
10
|
+
|
|
11
|
+
```shell
|
|
12
|
+
cargo add opendal --features services-goosefs
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The service is available as `opendal::services::GooseFs`. Configure the
|
|
16
|
+
service builder, then pass it to `opendal::Operator::new`.
|
|
17
|
+
|
|
18
|
+
## Use with `opendal-core`
|
|
19
|
+
|
|
20
|
+
Add the split crates directly:
|
|
21
|
+
|
|
22
|
+
```shell
|
|
23
|
+
cargo add opendal-core opendal-service-goosefs
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Pass a configured service builder to `Operator::new`:
|
|
27
|
+
|
|
28
|
+
```rust
|
|
29
|
+
use opendal_core::{Operator, OperatorRegistry, Result};
|
|
30
|
+
use opendal_service_goosefs::{register_goosefs_service, GooseFs};
|
|
31
|
+
|
|
32
|
+
fn build_operator(builder: GooseFs) -> Result<Operator> {
|
|
33
|
+
Operator::new(builder)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fn register_for_uri() {
|
|
37
|
+
register_goosefs_service(OperatorRegistry::get());
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`register_for_uri` is only needed for scheme-driven construction through
|
|
42
|
+
`Operator::from_uri` or `Operator::via_iter`.
|
|
43
|
+
|
|
44
|
+
Services that send HTTP requests also require an HTTP transport in
|
|
45
|
+
`OperationContext`. See the
|
|
46
|
+
[`opendal-core` composition example](https://crates.io/crates/opendal-core).
|
|
47
|
+
|
|
48
|
+
## Documentation
|
|
49
|
+
|
|
50
|
+
- [Service configuration and examples](https://opendal.apache.org/services/goosefs)
|
|
51
|
+
- [Rust API documentation](https://docs.rs/opendal-service-goosefs)
|
|
52
|
+
- [Apache OpenDAL documentation](https://opendal.apache.org/docs/)
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
Licensed under the Apache License, Version 2.0.
|
|
@@ -67,9 +67,10 @@ impl GoosefsBuilder {
|
|
|
67
67
|
/// When provided here it **overrides** any address discovered from
|
|
68
68
|
/// `goosefs-site.properties` or `GOOSEFS_MASTER_ADDR`. When left unset
|
|
69
69
|
/// the builder falls back to the SDK's auto-discovery chain
|
|
70
|
-
/// (defaults → properties → env) — see
|
|
71
|
-
/// `docs/CLIENT_CONFIGURATION.md`
|
|
72
|
-
/// `ConfigInvalid` only if **no** source
|
|
70
|
+
/// (defaults → properties → env) — see
|
|
71
|
+
/// [goosefs-sdk `docs/CLIENT_CONFIGURATION.md`](https://github.com/Tencent/tencent-goosefs-rust-sdk/blob/main/docs/CLIENT_CONFIGURATION.md)
|
|
72
|
+
/// §1. `build()` fails with `ConfigInvalid` only if **no** source
|
|
73
|
+
/// supplies a master address.
|
|
73
74
|
pub fn master_addr(mut self, addr: &str) -> Self {
|
|
74
75
|
if !addr.is_empty() {
|
|
75
76
|
self.config.master_addr = Some(addr.to_string());
|
|
@@ -128,16 +129,17 @@ impl Builder for GoosefsBuilder {
|
|
|
128
129
|
|
|
129
130
|
/// Build the backend and return a GoosefsBackend.
|
|
130
131
|
fn build(self) -> Result<impl Service> {
|
|
131
|
-
debug!("GoosefsBuilder::build started: {:?}",
|
|
132
|
+
debug!("GoosefsBuilder::build started: {:?}", self);
|
|
132
133
|
|
|
133
134
|
let root = normalize_root(&self.config.root.clone().unwrap_or_default());
|
|
134
|
-
debug!("GoosefsBuilder use root {}",
|
|
135
|
+
debug!("GoosefsBuilder use root {}", root);
|
|
135
136
|
|
|
136
137
|
// ── Step 1: establish the base SDK config ─────────────────────────────
|
|
137
138
|
//
|
|
138
139
|
// We follow the same priority chain that `FileSystemContext::connect`
|
|
139
140
|
// (and its `ConfigRefresher`) uses — see
|
|
140
|
-
//
|
|
141
|
+
// https://github.com/Tencent/tencent-goosefs-rust-sdk/blob/main/docs/CLIENT_CONFIGURATION.md
|
|
142
|
+
// §1 "Configuration Loading Priority":
|
|
141
143
|
//
|
|
142
144
|
// defaults < goosefs-site.properties < GOOSEFS_* env vars
|
|
143
145
|
//
|
|
@@ -210,7 +212,7 @@ impl Builder for GoosefsBuilder {
|
|
|
210
212
|
}
|
|
211
213
|
debug!(
|
|
212
214
|
"GoosefsBuilder use master_addr {} (addrs={:?})",
|
|
213
|
-
|
|
215
|
+
goosefs_config.master_addr, goosefs_config.master_addrs
|
|
214
216
|
);
|
|
215
217
|
|
|
216
218
|
if let Some(block_size) = self.config.block_size {
|
|
@@ -274,14 +276,16 @@ impl Builder for GoosefsBuilder {
|
|
|
274
276
|
read: true,
|
|
275
277
|
write: true,
|
|
276
278
|
write_can_multi: true,
|
|
277
|
-
//
|
|
278
|
-
//
|
|
279
|
-
//
|
|
279
|
+
// Authoritative Create: write-via-temp then
|
|
280
|
+
// GoosefsCore::rename(..., if_not_exists=true), backed by Master
|
|
281
|
+
// no-replace rename. Not CreateFile on the final path
|
|
282
|
+
// (writes go to .opendal.tmp.*).
|
|
280
283
|
write_with_if_not_exists: true,
|
|
281
284
|
create_dir: true,
|
|
282
285
|
delete: true,
|
|
283
286
|
list: true,
|
|
284
287
|
rename: true,
|
|
288
|
+
rename_with_if_not_exists: true,
|
|
285
289
|
shared: true,
|
|
286
290
|
..Default::default()
|
|
287
291
|
},
|
|
@@ -385,9 +389,9 @@ impl Service for GoosefsBackend {
|
|
|
385
389
|
_ctx: &OperationContext,
|
|
386
390
|
from: &str,
|
|
387
391
|
to: &str,
|
|
388
|
-
|
|
392
|
+
args: OpRename,
|
|
389
393
|
) -> Result<RpRename> {
|
|
390
|
-
self.core.rename(from, to).await?;
|
|
394
|
+
self.core.rename(from, to, args.if_not_exists()).await?;
|
|
391
395
|
Ok(RpRename::default())
|
|
392
396
|
}
|
|
393
397
|
|
|
@@ -444,4 +448,19 @@ mod tests {
|
|
|
444
448
|
"unexpected error message: {err}"
|
|
445
449
|
);
|
|
446
450
|
}
|
|
451
|
+
|
|
452
|
+
#[test]
|
|
453
|
+
fn test_capability_rename_with_if_not_exists() {
|
|
454
|
+
let backend = GoosefsBuilder::default()
|
|
455
|
+
.root("/data")
|
|
456
|
+
.master_addr("127.0.0.1:9200")
|
|
457
|
+
.build()
|
|
458
|
+
.expect("build");
|
|
459
|
+
let cap = backend.capability();
|
|
460
|
+
assert!(cap.write_with_if_not_exists);
|
|
461
|
+
assert!(
|
|
462
|
+
cap.rename_with_if_not_exists,
|
|
463
|
+
"rename_with_if_not_exists must be declared for Create publish"
|
|
464
|
+
);
|
|
465
|
+
}
|
|
447
466
|
}
|
|
@@ -45,7 +45,7 @@ pub struct GoosefsConfig {
|
|
|
45
45
|
/// `PollingMasterInquireClient` to discover the Primary Master automatically.
|
|
46
46
|
///
|
|
47
47
|
/// Resolution precedence at `build()` time (highest → lowest), following
|
|
48
|
-
///
|
|
48
|
+
/// [goosefs-sdk `docs/CLIENT_CONFIGURATION.md`](https://github.com/Tencent/tencent-goosefs-rust-sdk/blob/main/docs/CLIENT_CONFIGURATION.md) §1:
|
|
49
49
|
/// 1. This field (when set on the builder / OpenDAL config map)
|
|
50
50
|
/// 2. `GOOSEFS_MASTER_ADDR` environment variable
|
|
51
51
|
/// 3. `goosefs.master.rpc.addresses` / `goosefs.master.hostname` in
|
|
@@ -231,7 +231,9 @@ impl GoosefsCore {
|
|
|
231
231
|
|
|
232
232
|
pub async fn delete(&self, path: &str) -> Result<()> {
|
|
233
233
|
let full = self.full_path(path);
|
|
234
|
-
let
|
|
234
|
+
let ctx = self.ctx().await?;
|
|
235
|
+
let master = ctx.acquire_master();
|
|
236
|
+
ctx.invalidate_file_info(&full);
|
|
235
237
|
match master.delete(&full, false).await {
|
|
236
238
|
Ok(()) => Ok(()),
|
|
237
239
|
Err(e) => {
|
|
@@ -245,29 +247,37 @@ impl GoosefsCore {
|
|
|
245
247
|
}
|
|
246
248
|
}
|
|
247
249
|
|
|
248
|
-
|
|
250
|
+
/// Rename `from` → `to`.
|
|
251
|
+
///
|
|
252
|
+
/// When `if_not_exists` is true this is the authoritative publish step for
|
|
253
|
+
/// `write_with_if_not_exists` (Lance `PutMode::Create`). Conflict detection
|
|
254
|
+
/// is GooseFS Master no-replace rename
|
|
255
|
+
/// (`DefaultFileSystemMaster.renameInternal` → `FileAlreadyExistsException`
|
|
256
|
+
/// → gRPC ALREADY_EXISTS), reached via `MasterClient::rename`. Not a prior
|
|
257
|
+
/// `get_status`. Destination must never be deleted when `if_not_exists` is
|
|
258
|
+
/// true.
|
|
259
|
+
///
|
|
260
|
+
/// Mirror HDFS / Alluxio semantics so GooseFS passes OpenDAL's behavior
|
|
261
|
+
/// contract for rename:
|
|
262
|
+
///
|
|
263
|
+
/// 1. Destination parent directory is created on demand.
|
|
264
|
+
/// 2. If the destination exists as a file and `if_not_exists` is false,
|
|
265
|
+
/// overwrite by deleting it first. Never delete when `if_not_exists`
|
|
266
|
+
/// is true (that would destroy Master no-replace and re-introduce
|
|
267
|
+
/// TOCTOU overwrite).
|
|
268
|
+
/// 3. If the destination exists as a directory, surface `IsADirectory`.
|
|
269
|
+
///
|
|
270
|
+
/// Source NotFound is reported by the underlying `rename` RPC, so we
|
|
271
|
+
/// don't pre-stat the source.
|
|
272
|
+
pub async fn rename(&self, from: &str, to: &str, if_not_exists: bool) -> Result<()> {
|
|
249
273
|
let src = self.full_path(from);
|
|
250
274
|
let dst = self.full_path(to);
|
|
251
|
-
let
|
|
275
|
+
let ctx = self.ctx().await?;
|
|
276
|
+
let master = ctx.acquire_master();
|
|
277
|
+
|
|
278
|
+
ctx.invalidate_file_info(&src);
|
|
279
|
+
ctx.invalidate_file_info(&dst);
|
|
252
280
|
|
|
253
|
-
// Mirror HDFS / Alluxio semantics so GooseFS passes OpenDAL's
|
|
254
|
-
// behavior contract for rename (see `rename_test.go::testRenameNested`
|
|
255
|
-
// and `testRenameOverwrite`):
|
|
256
|
-
//
|
|
257
|
-
// 1. Destination parent directory is created on demand
|
|
258
|
-
// (`testRenameNested` writes to `<uuid>/<uuid>/<uuid>` without
|
|
259
|
-
// mkdir'ing intermediate levels first; S3-style backends treat
|
|
260
|
-
// this as implicit, fs-style backends must emulate it).
|
|
261
|
-
// 2. If the destination exists as a file, overwrite by deleting
|
|
262
|
-
// it first (`testRenameOverwrite`). GooseFS `rename` itself
|
|
263
|
-
// would otherwise return AlreadyExists.
|
|
264
|
-
// 3. If the destination exists as a directory, surface
|
|
265
|
-
// IsADirectory — matches the error code the behavior tests
|
|
266
|
-
// assert in `testRenameTargetDir`.
|
|
267
|
-
//
|
|
268
|
-
// Source NotFound is reported by the underlying `rename` RPC
|
|
269
|
-
// (`testRenameNonExistingSource` expects `NotFound`), so we don't
|
|
270
|
-
// pre-stat the source.
|
|
271
281
|
match master.get_status(&dst).await {
|
|
272
282
|
Ok(info) => {
|
|
273
283
|
if info.folder.unwrap_or(false) {
|
|
@@ -279,9 +289,19 @@ impl GoosefsCore {
|
|
|
279
289
|
.with_context("from", from)
|
|
280
290
|
.with_context("to", to));
|
|
281
291
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
292
|
+
if if_not_exists {
|
|
293
|
+
// Fast-path only. Authoritative race check is master.rename
|
|
294
|
+
// below (AlreadyExists → ConditionNotMatch).
|
|
295
|
+
return Err(Error::new(
|
|
296
|
+
ErrorKind::ConditionNotMatch,
|
|
297
|
+
"target path already exists while if_not_exists is set",
|
|
298
|
+
)
|
|
299
|
+
.with_context("service", super::GOOSEFS_SCHEME)
|
|
300
|
+
.with_context("from", from)
|
|
301
|
+
.with_context("to", to));
|
|
302
|
+
}
|
|
303
|
+
// Overwrite path ONLY. Master rename rejects existing dst;
|
|
304
|
+
// delete first so overwrite can proceed.
|
|
285
305
|
master.delete(&dst, false).await.map_err(parse_error)?;
|
|
286
306
|
}
|
|
287
307
|
Err(goosefs_sdk::error::Error::NotFound { .. }) => {
|
|
@@ -299,7 +319,29 @@ impl GoosefsCore {
|
|
|
299
319
|
Err(e) => return Err(parse_error(e)),
|
|
300
320
|
}
|
|
301
321
|
|
|
302
|
-
master.rename(&src, &dst).await
|
|
322
|
+
match master.rename(&src, &dst).await {
|
|
323
|
+
Ok(()) => {
|
|
324
|
+
// Same inode id moved (Master RenameEntry.setId(srcInode.getId()))
|
|
325
|
+
// — not a fresh inode. Drop any cached FileInfo so a reader
|
|
326
|
+
// opening `dst` immediately after sees current metadata.
|
|
327
|
+
ctx.invalidate_file_info(&src);
|
|
328
|
+
ctx.invalidate_file_info(&dst);
|
|
329
|
+
Ok(())
|
|
330
|
+
}
|
|
331
|
+
// Authoritative TOCTOU close: concurrent winner published between
|
|
332
|
+
// get_status and this RPC. Master FileAlreadyExistsException →
|
|
333
|
+
// gRPC ALREADY_EXISTS → SDK Error::AlreadyExists.
|
|
334
|
+
Err(goosefs_sdk::error::Error::AlreadyExists { .. }) if if_not_exists => {
|
|
335
|
+
Err(Error::new(
|
|
336
|
+
ErrorKind::ConditionNotMatch,
|
|
337
|
+
"target path already exists while if_not_exists is set",
|
|
338
|
+
)
|
|
339
|
+
.with_context("service", super::GOOSEFS_SCHEME)
|
|
340
|
+
.with_context("from", from)
|
|
341
|
+
.with_context("to", to))
|
|
342
|
+
}
|
|
343
|
+
Err(e) => Err(parse_error(e)),
|
|
344
|
+
}
|
|
303
345
|
}
|
|
304
346
|
|
|
305
347
|
// ── Data I/O Operations ──────────────────────────────────
|
|
@@ -477,6 +519,11 @@ impl GoosefsCore {
|
|
|
477
519
|
{
|
|
478
520
|
metadata.set_last_modified(ts);
|
|
479
521
|
}
|
|
522
|
+
// GooseFS Master rename preserves the same inode id; use it as etag
|
|
523
|
+
// for cache keys / checkout short-circuit (not commit conflict detection).
|
|
524
|
+
if let Some(fid) = info.file_id {
|
|
525
|
+
metadata.set_etag(&fid.to_string());
|
|
526
|
+
}
|
|
480
527
|
metadata
|
|
481
528
|
}
|
|
482
529
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## Capabilities
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Depending on its configuration and the backing system, this service can expose:
|
|
4
4
|
|
|
5
5
|
- [x] create_dir
|
|
6
6
|
- [x] stat
|
|
@@ -10,8 +10,12 @@ This service can be used to:
|
|
|
10
10
|
- [x] list
|
|
11
11
|
- [ ] copy
|
|
12
12
|
- [x] rename
|
|
13
|
+
- [x] rename (if_not_exists)
|
|
13
14
|
- [ ] presign
|
|
14
15
|
|
|
16
|
+
Inspect the effective capability set with [`opendal_core::Operator::info`] and
|
|
17
|
+
[`opendal_core::OperatorInfo::capability`] after building an operator.
|
|
18
|
+
|
|
15
19
|
## Notes
|
|
16
20
|
|
|
17
21
|
GooseFS service uses native gRPC protocol (not REST API like Alluxio),
|
|
@@ -23,18 +27,14 @@ Features:
|
|
|
23
27
|
- **Block-level I/O**: Data reads/writes go through block-level gRPC bidirectional streaming.
|
|
24
28
|
- **Consistent hash routing**: Worker selection uses consistent hashing on block IDs.
|
|
25
29
|
- **All WriteTypes**: Supports MUST_CACHE, CACHE_THROUGH, THROUGH, and ASYNC_THROUGH.
|
|
30
|
+
- **Conditional Create**: `write_with_if_not_exists` publishes via Master no-replace
|
|
31
|
+
rename (`rename_with_if_not_exists`); destination is never deleted on the Create path.
|
|
26
32
|
|
|
27
33
|
## Configuration
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- `chunk_size`: Chunk size for streaming RPCs (default: 1 MiB)
|
|
33
|
-
- `write_type`: Default write type (`must_cache`, `cache_through`, `through`, `async_through`)
|
|
34
|
-
- `auth_type`: Authentication type (`nosasl`, `simple`). Default: `simple`
|
|
35
|
-
- `auth_username`: Authentication username for SIMPLE mode. Default: current OS user
|
|
36
|
-
|
|
37
|
-
You can refer to [`GoosefsBuilder`]'s docs for more information
|
|
35
|
+
Use [`crate::GoosefsConfig`] for serializable configuration and this builder's
|
|
36
|
+
methods for direct construction. The field and method documentation defines
|
|
37
|
+
accepted values, defaults, and environment interaction.
|
|
38
38
|
|
|
39
39
|
## Example
|
|
40
40
|
|
|
@@ -15,10 +15,20 @@
|
|
|
15
15
|
// specific language governing permissions and limitations
|
|
16
16
|
// under the License.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
#![doc = include_str!("../README.md")]
|
|
19
|
+
#![cfg_attr(docsrs, feature(doc_cfg))]
|
|
20
|
+
#![cfg_attr(docsrs, doc(auto_cfg))]
|
|
21
|
+
#![deny(missing_docs)]
|
|
22
|
+
|
|
23
|
+
/// URI scheme used for service registration and scheme-driven construction.
|
|
19
24
|
pub const GOOSEFS_SCHEME: &str = "goosefs";
|
|
20
25
|
|
|
21
|
-
/// Register this service
|
|
26
|
+
/// Register this service's URI scheme or schemes with an operator registry.
|
|
27
|
+
///
|
|
28
|
+
/// Registration enables scheme-driven construction through
|
|
29
|
+
/// [`opendal_core::Operator::from_uri`] and
|
|
30
|
+
/// [`opendal_core::Operator::via_iter`]. Direct construction through
|
|
31
|
+
/// [`opendal_core::Operator::new`] does not require registration.
|
|
22
32
|
pub fn register_goosefs_service(registry: &opendal_core::OperatorRegistry) {
|
|
23
33
|
registry.register::<GooseFs>(GOOSEFS_SCHEME);
|
|
24
34
|
}
|
|
@@ -150,12 +150,10 @@ impl GoosefsWriter {
|
|
|
150
150
|
/// path, and cache both.
|
|
151
151
|
async fn ensure_writer(&mut self) -> Result<&mut ClientWriter> {
|
|
152
152
|
if self.writer.is_none() {
|
|
153
|
-
// Fast-path
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
// handles the race where a concurrent writer publishes
|
|
158
|
-
// the target between here and finalize.
|
|
153
|
+
// Fast-path only. Authority is GoosefsCore::rename(..., if_not_exists=true)
|
|
154
|
+
// → Master no-replace rename (DefaultFileSystemMaster →
|
|
155
|
+
// FileAlreadyExistsException → gRPC ALREADY_EXISTS → ConditionNotMatch).
|
|
156
|
+
// Not this get_status.
|
|
159
157
|
if self.op.if_not_exists() && self.core.get_status(&self.path).await.is_ok() {
|
|
160
158
|
return Err(Error::new(
|
|
161
159
|
ErrorKind::ConditionNotMatch,
|
|
@@ -186,8 +184,8 @@ impl GoosefsWriter {
|
|
|
186
184
|
return Ok(());
|
|
187
185
|
};
|
|
188
186
|
|
|
189
|
-
//
|
|
190
|
-
//
|
|
187
|
+
// Optional fast-path (optimization, not authority). Safe to keep:
|
|
188
|
+
// a miss here is closed by rename(..., if_not_exists) below.
|
|
191
189
|
if self.op.if_not_exists() && self.core.get_status(&self.path).await.is_ok() {
|
|
192
190
|
// Undo our staged temp before surfacing the error.
|
|
193
191
|
let _ = self.core.delete(&tmp).await;
|
|
@@ -197,16 +195,13 @@ impl GoosefsWriter {
|
|
|
197
195
|
));
|
|
198
196
|
}
|
|
199
197
|
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
match self.core.rename(&tmp, &self.path).await {
|
|
198
|
+
// Authority: pass OpWrite.if_not_exists into core.rename.
|
|
199
|
+
// Overwrite delete lives only inside core.rename when if_not_exists=false.
|
|
200
|
+
match self
|
|
201
|
+
.core
|
|
202
|
+
.rename(&tmp, &self.path, self.op.if_not_exists())
|
|
203
|
+
.await
|
|
204
|
+
{
|
|
210
205
|
Ok(()) => Ok(()),
|
|
211
206
|
Err(e) => {
|
|
212
207
|
// Rename failed — sweep the temp so we don't leak a
|
|
@@ -248,8 +243,13 @@ impl oio::Write for GoosefsWriter {
|
|
|
248
243
|
}
|
|
249
244
|
return Err(e);
|
|
250
245
|
}
|
|
246
|
+
// Capture file_id before rename; Master rename keeps the same inode id.
|
|
247
|
+
let mut meta = Metadata::default();
|
|
248
|
+
if let Some(fid) = writer.file_info().file_id {
|
|
249
|
+
meta.set_etag(&fid.to_string());
|
|
250
|
+
}
|
|
251
251
|
self.finalize_rename().await?;
|
|
252
|
-
return Ok(
|
|
252
|
+
return Ok(meta);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
// Zero-write path: the caller closed without ever calling
|
|
@@ -271,9 +271,13 @@ impl oio::Write for GoosefsWriter {
|
|
|
271
271
|
let _ = self.core.delete(&tmp).await;
|
|
272
272
|
return Err(e);
|
|
273
273
|
}
|
|
274
|
+
let mut meta = Metadata::default();
|
|
275
|
+
if let Some(fid) = w.file_info().file_id {
|
|
276
|
+
meta.set_etag(&fid.to_string());
|
|
277
|
+
}
|
|
274
278
|
self.tmp_path = Some(tmp);
|
|
275
279
|
self.finalize_rename().await?;
|
|
276
|
-
Ok(
|
|
280
|
+
Ok(meta)
|
|
277
281
|
}
|
|
278
282
|
|
|
279
283
|
async fn abort(&mut self) -> Result<()> {
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// Licensed to the Apache Software Foundation (ASF) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The ASF licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
//! Acceptance tests for GooseFS safe Create / conditional rename (doc §8.8).
|
|
19
|
+
//!
|
|
20
|
+
//! Requires a live GooseFS master. Skip unless `OPENDAL_GOOSEFS_MASTER_ADDR`
|
|
21
|
+
//! is set (same env the behavior CI fixture exports).
|
|
22
|
+
|
|
23
|
+
use std::sync::Arc;
|
|
24
|
+
|
|
25
|
+
use opendal::ErrorKind;
|
|
26
|
+
use opendal::Operator;
|
|
27
|
+
use opendal::services::GooseFs;
|
|
28
|
+
|
|
29
|
+
fn maybe_operator() -> Option<Operator> {
|
|
30
|
+
let master = std::env::var("OPENDAL_GOOSEFS_MASTER_ADDR").ok()?;
|
|
31
|
+
if master.trim().is_empty() {
|
|
32
|
+
return None;
|
|
33
|
+
}
|
|
34
|
+
let root = std::env::var("OPENDAL_GOOSEFS_ROOT").unwrap_or_else(|_| "/".to_string());
|
|
35
|
+
let write_type =
|
|
36
|
+
std::env::var("OPENDAL_GOOSEFS_WRITE_TYPE").unwrap_or_else(|_| "must_cache".to_string());
|
|
37
|
+
|
|
38
|
+
let builder = GooseFs::default()
|
|
39
|
+
.root(&root)
|
|
40
|
+
.master_addr(&master)
|
|
41
|
+
.write_type(&write_type);
|
|
42
|
+
Some(Operator::new(builder).expect("build GooseFS operator"))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fn unique(prefix: &str) -> String {
|
|
46
|
+
format!(
|
|
47
|
+
"{prefix}-{}-{}",
|
|
48
|
+
std::process::id(),
|
|
49
|
+
std::time::SystemTime::now()
|
|
50
|
+
.duration_since(std::time::UNIX_EPOCH)
|
|
51
|
+
.unwrap()
|
|
52
|
+
.as_nanos()
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#[tokio::test]
|
|
57
|
+
async fn capability_declares_rename_with_if_not_exists() {
|
|
58
|
+
let Some(op) = maybe_operator() else {
|
|
59
|
+
eprintln!("skip: OPENDAL_GOOSEFS_MASTER_ADDR unset");
|
|
60
|
+
return;
|
|
61
|
+
};
|
|
62
|
+
let cap = op.info().capability();
|
|
63
|
+
assert!(cap.write_with_if_not_exists);
|
|
64
|
+
assert!(cap.rename_with_if_not_exists);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// T0 / T4: conditional rename against an existing dst → ConditionNotMatch;
|
|
68
|
+
/// destination content is unchanged (Master no-replace).
|
|
69
|
+
#[tokio::test]
|
|
70
|
+
async fn rename_if_not_exists_rejects_existing_dst() {
|
|
71
|
+
let Some(op) = maybe_operator() else {
|
|
72
|
+
eprintln!("skip: OPENDAL_GOOSEFS_MASTER_ADDR unset");
|
|
73
|
+
return;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
let src = unique("t0-src");
|
|
77
|
+
let dst = unique("t0-dst");
|
|
78
|
+
op.write(&src, "from-src").await.expect("write src");
|
|
79
|
+
op.write(&dst, "dst-original").await.expect("write dst");
|
|
80
|
+
|
|
81
|
+
let err = op
|
|
82
|
+
.rename_with(&src, &dst)
|
|
83
|
+
.if_not_exists(true)
|
|
84
|
+
.await
|
|
85
|
+
.expect_err("rename must fail when dst exists");
|
|
86
|
+
assert_eq!(err.kind(), ErrorKind::ConditionNotMatch);
|
|
87
|
+
|
|
88
|
+
let dst_after = op.read(&dst).await.expect("read dst").to_bytes();
|
|
89
|
+
assert_eq!(&dst_after[..], b"dst-original");
|
|
90
|
+
|
|
91
|
+
let _ = op.delete(&src).await;
|
|
92
|
+
let _ = op.delete(&dst).await;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// T3: serial second Create (write_with if_not_exists) must fail.
|
|
96
|
+
#[tokio::test]
|
|
97
|
+
async fn write_if_not_exists_serial_conflict() {
|
|
98
|
+
let Some(op) = maybe_operator() else {
|
|
99
|
+
eprintln!("skip: OPENDAL_GOOSEFS_MASTER_ADDR unset");
|
|
100
|
+
return;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
let path = unique("t3-create");
|
|
104
|
+
op.write_with(&path, "winner")
|
|
105
|
+
.if_not_exists(true)
|
|
106
|
+
.await
|
|
107
|
+
.expect("first Create succeeds");
|
|
108
|
+
|
|
109
|
+
let err = op
|
|
110
|
+
.write_with(&path, "loser")
|
|
111
|
+
.if_not_exists(true)
|
|
112
|
+
.await
|
|
113
|
+
.expect_err("second Create must fail");
|
|
114
|
+
assert_eq!(err.kind(), ErrorKind::ConditionNotMatch);
|
|
115
|
+
|
|
116
|
+
let body = op.read(&path).await.expect("read").to_bytes();
|
|
117
|
+
assert_eq!(&body[..], b"winner");
|
|
118
|
+
|
|
119
|
+
let meta = op.stat(&path).await.expect("stat");
|
|
120
|
+
assert!(
|
|
121
|
+
meta.etag().is_some(),
|
|
122
|
+
"P1 etag (file_id) should be present after write"
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
let _ = op.delete(&path).await;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// T5: overwrite (if_not_exists=false) still replaces an existing file.
|
|
129
|
+
#[tokio::test]
|
|
130
|
+
async fn overwrite_rename_still_works() {
|
|
131
|
+
let Some(op) = maybe_operator() else {
|
|
132
|
+
eprintln!("skip: OPENDAL_GOOSEFS_MASTER_ADDR unset");
|
|
133
|
+
return;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
let src = unique("t5-src");
|
|
137
|
+
let dst = unique("t5-dst");
|
|
138
|
+
op.write(&src, "new-content").await.expect("write src");
|
|
139
|
+
op.write(&dst, "old-content").await.expect("write dst");
|
|
140
|
+
|
|
141
|
+
op.rename(&src, &dst).await.expect("overwrite rename");
|
|
142
|
+
|
|
143
|
+
let body = op.read(&dst).await.expect("read dst").to_bytes();
|
|
144
|
+
assert_eq!(&body[..], b"new-content");
|
|
145
|
+
|
|
146
|
+
let _ = op.delete(&dst).await;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/// T1: concurrent Create on the same path — exactly one wins; content is winner's.
|
|
150
|
+
#[tokio::test]
|
|
151
|
+
async fn concurrent_write_if_not_exists_exactly_one_wins() {
|
|
152
|
+
let Some(op) = maybe_operator() else {
|
|
153
|
+
eprintln!("skip: OPENDAL_GOOSEFS_MASTER_ADDR unset");
|
|
154
|
+
return;
|
|
155
|
+
};
|
|
156
|
+
let op = Arc::new(op);
|
|
157
|
+
let path = unique("t1-concurrent");
|
|
158
|
+
|
|
159
|
+
let rounds = 8u32;
|
|
160
|
+
for round in 0..rounds {
|
|
161
|
+
let p = format!("{path}-r{round}");
|
|
162
|
+
let op_a = op.clone();
|
|
163
|
+
let op_b = op.clone();
|
|
164
|
+
let path_a = p.clone();
|
|
165
|
+
let path_b = p.clone();
|
|
166
|
+
|
|
167
|
+
let (ra, rb) = tokio::join!(
|
|
168
|
+
async move {
|
|
169
|
+
op_a.write_with(&path_a, "A")
|
|
170
|
+
.if_not_exists(true)
|
|
171
|
+
.await
|
|
172
|
+
.map(|_| "A")
|
|
173
|
+
},
|
|
174
|
+
async move {
|
|
175
|
+
op_b.write_with(&path_b, "B")
|
|
176
|
+
.if_not_exists(true)
|
|
177
|
+
.await
|
|
178
|
+
.map(|_| "B")
|
|
179
|
+
},
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
match (&ra, &rb) {
|
|
183
|
+
(Ok(w), Err(e)) => {
|
|
184
|
+
assert_eq!(e.kind(), ErrorKind::ConditionNotMatch);
|
|
185
|
+
let body = op.read(&p).await.expect("read").to_bytes();
|
|
186
|
+
assert_eq!(&body[..], w.as_bytes());
|
|
187
|
+
}
|
|
188
|
+
(Err(e), Ok(w)) => {
|
|
189
|
+
assert_eq!(e.kind(), ErrorKind::ConditionNotMatch);
|
|
190
|
+
let body = op.read(&p).await.expect("read").to_bytes();
|
|
191
|
+
assert_eq!(&body[..], w.as_bytes());
|
|
192
|
+
}
|
|
193
|
+
(Ok(_), Ok(_)) => panic!("both concurrent Creates succeeded for {p}"),
|
|
194
|
+
(Err(ea), Err(eb)) => panic!("both concurrent Creates failed for {p}: {ea:?} / {eb:?}"),
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
let _ = op.delete(&p).await;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
[package]
|
|
19
19
|
description = "Apache OpenDAL GridFS service implementation"
|
|
20
20
|
name = "opendal-service-gridfs"
|
|
21
|
+
readme = "README.md"
|
|
21
22
|
|
|
22
23
|
authors = { workspace = true }
|
|
23
24
|
edition = { workspace = true }
|
|
@@ -34,7 +35,7 @@ all-features = true
|
|
|
34
35
|
futures = { workspace = true }
|
|
35
36
|
mea = { workspace = true }
|
|
36
37
|
mongodb = "3.3.0"
|
|
37
|
-
opendal-core = { path = "../../core", version = "0.58.
|
|
38
|
+
opendal-core = { path = "../../core", version = "0.58.1", default-features = false }
|
|
38
39
|
serde = { workspace = true, features = ["derive"] }
|
|
39
40
|
|
|
40
41
|
[dev-dependencies]
|