opendal 0.1.14 → 0.1.16

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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +46 -36
  3. data/Cargo.toml +1 -1
  4. data/DEPENDENCIES.rust.tsv +25 -24
  5. data/core/CHANGELOG.md +9 -1
  6. data/core/Cargo.lock +363 -1184
  7. data/core/Cargo.toml +95 -95
  8. data/core/DEPENDENCIES.rust.tsv +13 -12
  9. data/core/benches/types/buffer.rs +61 -0
  10. data/core/benches/vs_fs/Cargo.toml +1 -1
  11. data/core/benches/vs_s3/Cargo.toml +1 -1
  12. data/core/core/CHANGELOG.md +9 -1
  13. data/core/core/src/raw/futures_util.rs +5 -0
  14. data/core/core/src/raw/oio/copy/block_copy.rs +1 -1
  15. data/core/core/src/raw/oio/copy/multipart_copy.rs +1 -1
  16. data/core/core/src/raw/oio/write/block_write.rs +1 -1
  17. data/core/core/src/raw/oio/write/multipart_write.rs +1 -1
  18. data/core/core/src/raw/oio/write/position_write.rs +41 -1
  19. data/core/core/src/types/buffer.rs +131 -0
  20. data/core/core/src/types/delete/deleter.rs +13 -0
  21. data/core/core/src/types/mod.rs +1 -0
  22. data/core/http-transports/reqwest/Cargo.toml +1 -1
  23. data/core/layers/async-backtrace/Cargo.toml +2 -2
  24. data/core/layers/await-tree/Cargo.toml +2 -2
  25. data/core/layers/capability-check/Cargo.toml +2 -2
  26. data/core/layers/chaos/Cargo.toml +2 -2
  27. data/core/layers/concurrent-limit/Cargo.toml +2 -2
  28. data/core/layers/dtrace/Cargo.toml +2 -2
  29. data/core/layers/fastmetrics/Cargo.toml +3 -3
  30. data/core/layers/fastrace/Cargo.toml +2 -2
  31. data/core/layers/foyer/Cargo.toml +2 -2
  32. data/core/layers/hotpath/Cargo.toml +2 -2
  33. data/core/layers/immutable-index/Cargo.toml +2 -2
  34. data/core/layers/logging/Cargo.toml +2 -2
  35. data/core/layers/metrics/Cargo.toml +3 -3
  36. data/core/layers/mime-guess/Cargo.toml +2 -2
  37. data/core/layers/observe-metrics-common/Cargo.toml +1 -1
  38. data/core/layers/otelmetrics/Cargo.toml +3 -3
  39. data/core/layers/oteltrace/Cargo.toml +2 -2
  40. data/core/layers/prometheus/Cargo.toml +3 -3
  41. data/core/layers/prometheus-client/Cargo.toml +3 -3
  42. data/core/layers/retry/Cargo.toml +4 -4
  43. data/core/layers/route/Cargo.toml +3 -3
  44. data/core/layers/tail-cut/Cargo.toml +2 -2
  45. data/core/layers/throttle/Cargo.toml +2 -2
  46. data/core/layers/timeout/Cargo.toml +3 -3
  47. data/core/layers/tracing/Cargo.toml +2 -2
  48. data/core/services/aliyun-drive/Cargo.toml +1 -1
  49. data/core/services/alluxio/Cargo.toml +1 -1
  50. data/core/services/azblob/Cargo.toml +2 -2
  51. data/core/services/azdls/Cargo.toml +2 -2
  52. data/core/services/azfile/Cargo.toml +2 -2
  53. data/core/services/azure-common/Cargo.toml +1 -1
  54. data/core/services/b2/Cargo.toml +1 -1
  55. data/core/services/cacache/Cargo.toml +1 -1
  56. data/core/services/cloudflare-kv/Cargo.toml +1 -1
  57. data/core/services/compfs/Cargo.toml +1 -1
  58. data/core/services/cos/Cargo.toml +1 -1
  59. data/core/services/d1/Cargo.toml +1 -1
  60. data/core/services/dashmap/Cargo.toml +1 -1
  61. data/core/services/dbfs/Cargo.toml +1 -1
  62. data/core/services/dropbox/Cargo.toml +1 -1
  63. data/core/services/etcd/Cargo.toml +1 -1
  64. data/core/services/foundationdb/Cargo.toml +1 -1
  65. data/core/services/foyer/Cargo.toml +3 -3
  66. data/core/services/fs/Cargo.toml +1 -1
  67. data/core/services/fs/src/core.rs +25 -7
  68. data/core/services/ftp/Cargo.toml +1 -1
  69. data/core/services/gcs/Cargo.toml +1 -1
  70. data/core/services/gcs-grpc/Cargo.toml +1 -1
  71. data/core/services/gdrive/Cargo.toml +1 -1
  72. data/core/services/ghac/Cargo.toml +2 -2
  73. data/core/services/github/Cargo.toml +1 -1
  74. data/core/services/goosefs/Cargo.toml +2 -2
  75. data/core/services/gridfs/Cargo.toml +1 -1
  76. data/core/services/hdfs/Cargo.toml +2 -2
  77. data/core/services/hdfs/src/backend.rs +15 -7
  78. data/core/services/hdfs/src/core.rs +55 -16
  79. data/core/services/hdfs/src/docs.md +9 -1
  80. data/core/services/hdfs-native/Cargo.toml +1 -1
  81. data/core/services/hf/Cargo.toml +3 -3
  82. data/core/services/http/Cargo.toml +3 -3
  83. data/core/services/http/src/core.rs +2 -1
  84. data/core/services/ipfs/Cargo.toml +1 -1
  85. data/core/services/ipmfs/Cargo.toml +1 -1
  86. data/core/services/koofr/Cargo.toml +1 -1
  87. data/core/services/lakefs/Cargo.toml +1 -1
  88. data/core/services/memcached/Cargo.toml +1 -1
  89. data/core/services/mini_moka/Cargo.toml +1 -1
  90. data/core/services/moka/Cargo.toml +1 -1
  91. data/core/services/mongodb/Cargo.toml +1 -1
  92. data/core/services/monoiofs/Cargo.toml +1 -1
  93. data/core/services/mysql/Cargo.toml +1 -1
  94. data/core/services/obs/Cargo.toml +1 -1
  95. data/core/services/onedrive/Cargo.toml +1 -1
  96. data/core/services/opfs/Cargo.toml +1 -1
  97. data/core/services/oss/Cargo.toml +1 -1
  98. data/core/services/oss/src/backend.rs +143 -2
  99. data/core/services/oss/src/docs.md +12 -0
  100. data/core/services/pcloud/Cargo.toml +1 -1
  101. data/core/services/persy/Cargo.toml +1 -1
  102. data/core/services/postgresql/Cargo.toml +1 -1
  103. data/core/services/redb/Cargo.toml +1 -1
  104. data/core/services/redis/Cargo.toml +1 -1
  105. data/core/services/rocksdb/Cargo.toml +1 -1
  106. data/core/services/s3/Cargo.toml +1 -1
  107. data/core/services/seafile/Cargo.toml +1 -1
  108. data/core/services/sftp/Cargo.toml +1 -1
  109. data/core/services/sled/Cargo.toml +1 -1
  110. data/core/services/sqlite/Cargo.toml +1 -1
  111. data/core/services/surrealdb/Cargo.toml +2 -2
  112. data/core/services/swift/Cargo.toml +1 -1
  113. data/core/services/tikv/Cargo.toml +1 -1
  114. data/core/services/tos/Cargo.toml +1 -1
  115. data/core/services/upyun/Cargo.toml +1 -1
  116. data/core/services/vercel-artifacts/Cargo.toml +1 -1
  117. data/core/services/vercel-blob/Cargo.toml +1 -1
  118. data/core/services/webdav/Cargo.toml +1 -1
  119. data/core/services/webdav/src/backend.rs +10 -21
  120. data/core/services/webdav/src/config.rs +5 -14
  121. data/core/services/webdav/src/core.rs +12 -15
  122. data/core/services/webhdfs/Cargo.toml +1 -1
  123. data/core/services/yandex-disk/Cargo.toml +1 -1
  124. data/core/testkit/Cargo.toml +4 -4
  125. metadata +2 -2
@@ -420,7 +420,7 @@ mod tests {
420
420
 
421
421
  #[cfg(unix)]
422
422
  #[tokio::test]
423
- async fn test_delete_iter_rejects_absolute_path_outside_root() {
423
+ async fn test_delete_iter_normalizes_absolute_path_under_root() {
424
424
  use opendal_core::Operator;
425
425
 
426
426
  let root_dir = tempfile::TempDir::new().unwrap();
@@ -429,16 +429,34 @@ mod tests {
429
429
  let outside = outside_dir.path().join("outside.txt");
430
430
  std::fs::write(&outside, b"content").unwrap();
431
431
 
432
+ let inside = root_dir.path().join(outside.strip_prefix("/").unwrap());
433
+ std::fs::create_dir_all(inside.parent().unwrap()).unwrap();
434
+ std::fs::write(&inside, b"content").unwrap();
435
+
432
436
  let op =
433
437
  Operator::new(crate::Fs::default().root(root_dir.path().to_str().unwrap())).unwrap();
434
438
 
435
- // `Deleter` takes the caller's key verbatim, so an absolute key reaches
436
- // `root_join` without `normalize_path` having stripped the leading `/`.
437
- let err = op
438
- .delete_iter([outside.to_str().unwrap().to_string()])
439
+ op.delete_iter([outside.to_str().unwrap().to_string()])
439
440
  .await
440
- .unwrap_err();
441
+ .unwrap();
442
+ assert!(!inside.exists());
443
+ assert_eq!(std::fs::read(&outside).unwrap(), b"content");
444
+ }
445
+
446
+ #[tokio::test]
447
+ async fn test_delete_iter_rejects_parent_path_outside_root() {
448
+ use opendal_core::Operator;
449
+
450
+ let temp_dir = tempfile::TempDir::new().unwrap();
451
+ let root = temp_dir.path().join("root");
452
+ std::fs::create_dir(&root).unwrap();
453
+
454
+ let outside = temp_dir.path().join("outside.txt");
455
+ std::fs::write(&outside, b"content").unwrap();
456
+
457
+ let op = Operator::new(crate::Fs::default().root(root.to_str().unwrap())).unwrap();
458
+ let err = op.delete_iter(["../outside.txt"]).await.unwrap_err();
441
459
  assert_eq!(err.kind(), ErrorKind::NotFound);
442
- assert!(outside.exists());
460
+ assert_eq!(std::fs::read(&outside).unwrap(), b"content");
443
461
  }
444
462
  }
@@ -36,7 +36,7 @@ asyncband = { workspace = true, features = ["pool"] }
36
36
  bytes = { workspace = true }
37
37
  http = { workspace = true }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
40
40
  rustls-native-certs = "0.8"
41
41
  serde = { workspace = true, features = ["derive"] }
42
42
  suppaftp = { version = "10.0.2", default-features = false, features = [
@@ -36,7 +36,7 @@ async-trait = "0.1"
36
36
  bytes = { workspace = true }
37
37
  http = { workspace = true }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false, features = [
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false, features = [
40
40
  "reqsign",
41
41
  ] }
42
42
  percent-encoding = "2.3"
@@ -36,7 +36,7 @@ bytes = { workspace = true }
36
36
  futures = { workspace = true, features = ["async-await", "std"] }
37
37
  http = { workspace = true }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false, features = [
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false, features = [
40
40
  "reqsign",
41
41
  ] }
42
42
  percent-encoding = "2"
@@ -32,7 +32,7 @@ version = { workspace = true }
32
32
  all-features = true
33
33
 
34
34
  [dependencies]
35
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
35
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
36
36
 
37
37
  asyncband = { workspace = true, features = ["mutex", "singleflight"] }
38
38
  bytes = { workspace = true }
@@ -36,8 +36,8 @@ bytes = { workspace = true }
36
36
  ghac = { version = "0.3.0", default-features = false }
37
37
  http = { workspace = true }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
40
- opendal-service-azblob = { path = "../azblob", version = "0.59.3", default-features = false }
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
40
+ opendal-service-azblob = { path = "../azblob", version = "0.59.5", default-features = false }
41
41
  prost = { version = "0.14.3", default-features = false }
42
42
  reqsign-azure-storage = { version = "3.1.1", default-features = false }
43
43
  reqsign-core = { version = "3.2.0", default-features = false }
@@ -36,7 +36,7 @@ base64 = { workspace = true }
36
36
  bytes = { workspace = true }
37
37
  http = { workspace = true }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
40
40
  serde = { workspace = true, features = ["derive"] }
41
41
  serde_json = { workspace = true }
42
42
 
@@ -45,11 +45,11 @@ asyncband = { workspace = true, features = ["rwlock"] }
45
45
  bytes = { workspace = true }
46
46
  goosefs-sdk = { version = "0.2.1", default-features = false }
47
47
  log = { workspace = true }
48
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
48
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
49
49
  serde = { workspace = true, features = ["derive"] }
50
50
 
51
51
  [dev-dependencies]
52
- opendal = { path = "../..", version = "0.59.3", features = [
52
+ opendal = { path = "../..", version = "0.59.5", features = [
53
53
  "services-goosefs",
54
54
  ] }
55
55
  tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
@@ -35,7 +35,7 @@ all-features = true
35
35
  asyncband = { workspace = true, features = ["once-cell"] }
36
36
  futures = { workspace = true }
37
37
  mongodb = "3.3.0"
38
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
38
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
39
39
  serde = { workspace = true, features = ["derive"] }
40
40
 
41
41
  [dev-dependencies]
@@ -32,11 +32,11 @@ version = { workspace = true }
32
32
  all-features = true
33
33
 
34
34
  [dependencies]
35
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
35
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
36
36
 
37
37
  bytes = { workspace = true }
38
38
  futures = { workspace = true }
39
- hdrs = { version = "0.3.2", features = ["async_file"] }
39
+ hdrs = { version = "0.3.3", features = ["async_file"] }
40
40
  log = { workspace = true }
41
41
  serde = { workspace = true, features = ["derive"] }
42
42
  tokio = { workspace = true, features = ["rt"] }
@@ -169,6 +169,8 @@ impl Builder for HdfsBuilder {
169
169
 
170
170
  list: true,
171
171
 
172
+ copy: true,
173
+
172
174
  rename: true,
173
175
  rename_with_if_not_exists: true,
174
176
 
@@ -195,7 +197,7 @@ impl Service for HdfsBackend {
195
197
  type Writer = HdfsLazyWriter;
196
198
  type Lister = Option<HdfsLister>;
197
199
  type Deleter = oio::OneShotDeleter<HdfsDeleter>;
198
- type Copier = ();
200
+ type Copier = oio::OneShotCopier;
199
201
  type Composer = ();
200
202
 
201
203
  fn info(&self) -> ServiceInfo {
@@ -258,14 +260,20 @@ impl Service for HdfsBackend {
258
260
  fn copy(
259
261
  &self,
260
262
  _ctx: &OperationContext,
261
- _from: &str,
262
- _to: &str,
263
+ from: &str,
264
+ to: &str,
263
265
  _args: OpCopy,
264
266
  ) -> Result<Self::Copier> {
265
- Err(Error::new(
266
- ErrorKind::Unsupported,
267
- "operation is not supported",
268
- ))
267
+ let core = self.core.clone();
268
+ let from = from.to_string();
269
+ let to = to.to_string();
270
+ // Recreate the future so retry layers can rerun the copy after a temporary error.
271
+ Ok(oio::OneShotCopier::new_with(move || {
272
+ let core = core.clone();
273
+ let from = from.clone();
274
+ let to = to.clone();
275
+ async move { core.hdfs_copy(&from, &to).await }
276
+ }))
269
277
  }
270
278
 
271
279
  async fn rename(
@@ -124,8 +124,7 @@ impl HdfsCore {
124
124
  });
125
125
 
126
126
  if !target_exists {
127
- let parent = get_parent(&target_path);
128
- self.client.create_dir(parent).map_err(new_std_io_error)?;
127
+ self.ensure_parent_dir(&target_path)?;
129
128
  }
130
129
  if !should_append {
131
130
  initial_size = 0;
@@ -175,20 +174,7 @@ impl HdfsCore {
175
174
  return Err(new_std_io_error(err));
176
175
  }
177
176
 
178
- let parent = std::path::PathBuf::from(&to_path)
179
- .parent()
180
- .ok_or_else(|| {
181
- Error::new(
182
- ErrorKind::Unexpected,
183
- "path should have parent but not, it must be malformed",
184
- )
185
- .with_context("to", &to_path)
186
- })?
187
- .to_path_buf();
188
-
189
- self.client
190
- .create_dir(&parent.to_string_lossy())
191
- .map_err(new_std_io_error)?;
177
+ self.ensure_parent_dir(&to_path)?;
192
178
  }
193
179
  Ok(metadata) => {
194
180
  if metadata.is_file() {
@@ -215,6 +201,59 @@ impl HdfsCore {
215
201
 
216
202
  Ok(())
217
203
  }
204
+
205
+ pub async fn hdfs_copy(&self, from: &str, to: &str) -> Result<Metadata> {
206
+ let from_path = build_rooted_abs_path(&self.root, from);
207
+ // OpenDAL copy is file-to-file only. Reject directory sources before
208
+ // the HDFS API can recursively copy their contents.
209
+ let from_meta = self.client.metadata(&from_path).map_err(new_std_io_error)?;
210
+ if !from_meta.is_file() {
211
+ return Err(
212
+ Error::new(ErrorKind::IsADirectory, "from path should be a file")
213
+ .with_context("from", &from_path),
214
+ );
215
+ }
216
+
217
+ let to_path = build_rooted_abs_path(&self.root, to);
218
+ match self.client.metadata(&to_path) {
219
+ Ok(meta) => {
220
+ // OpenDAL treats `to` as the exact destination file path. Reject
221
+ // an existing directory instead of copying the source into it.
222
+ if meta.is_dir() {
223
+ return Err(
224
+ Error::new(ErrorKind::IsADirectory, "to path should be a file")
225
+ .with_context("to", &to_path),
226
+ );
227
+ }
228
+ // The HDFS copy API does not replace an existing destination,
229
+ // so remove it first to preserve OpenDAL's overwrite semantics.
230
+ self.client
231
+ .remove_file(&to_path)
232
+ .map_err(new_std_io_error)?;
233
+ }
234
+ Err(err) if err.kind() == io::ErrorKind::NotFound => {
235
+ // hdrs copy_file requires the destination parent to already exist.
236
+ self.ensure_parent_dir(&to_path)?;
237
+ }
238
+ Err(err) => return Err(new_std_io_error(err)),
239
+ }
240
+
241
+ let client = self.client.clone();
242
+ let copy_from = from_path.clone();
243
+ let copy_to = to_path.clone();
244
+ tokio::task::spawn_blocking(move || client.copy_file(&copy_from, &copy_to))
245
+ .await
246
+ .map_err(|e| Error::new(ErrorKind::Unexpected, "tokio task join failed").set_source(e))?
247
+ .map_err(new_std_io_error)?;
248
+
249
+ Ok(MetadataBuilder::file(from_meta.len()).build())
250
+ }
251
+
252
+ fn ensure_parent_dir(&self, path: &str) -> Result<()> {
253
+ self.client
254
+ .create_dir(get_parent(path))
255
+ .map_err(new_std_io_error)
256
+ }
218
257
  }
219
258
 
220
259
  #[cfg(test)]
@@ -10,13 +10,21 @@ Depending on its configuration and the backing system, this service can expose:
10
10
  - [x] write
11
11
  - [x] delete
12
12
  - [x] list
13
- - [ ] copy
13
+ - [x] copy
14
14
  - [x] rename
15
15
  - [ ] ~~presign~~
16
16
 
17
17
  Inspect the effective capability set with [`opendal_core::Operator::info`] and
18
18
  [`opendal_core::OperatorInfo::capability`] after building an operator.
19
19
 
20
+ ## Copy behavior
21
+
22
+ The HDFS service copies files to exact destination file paths and rejects
23
+ directory sources and destinations. Copy overwrites an existing destination by
24
+ removing it before copying the source. This replacement is not atomic: if the
25
+ copy fails after removing the destination, the destination can be missing or
26
+ incomplete.
27
+
20
28
  ## Differences with webhdfs
21
29
 
22
30
  The [WebHDFS service](https://docs.rs/opendal-service-webhdfs) uses HDFS's
@@ -36,5 +36,5 @@ bytes = { workspace = true }
36
36
  futures = { workspace = true }
37
37
  hdfs-native = { version = "0.14" }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
40
40
  serde = { workspace = true, features = ["derive"] }
@@ -37,7 +37,7 @@ bytes = { workspace = true }
37
37
  hf-xet = "1.6.0"
38
38
  http = { workspace = true }
39
39
  log = { workspace = true }
40
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
40
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
41
41
  percent-encoding = "2"
42
42
  serde = { workspace = true, features = ["derive"] }
43
43
  serde_json = { workspace = true }
@@ -45,9 +45,9 @@ serde_json = { workspace = true }
45
45
  [dev-dependencies]
46
46
  base64 = { workspace = true }
47
47
  futures = { workspace = true }
48
- opendal-core = { path = "../../core", version = "0.59.3", features = [
48
+ opendal-core = { path = "../../core", version = "0.59.5", features = [
49
49
  "executors-tokio",
50
50
  ] }
51
- opendal-http-transport-reqwest = { path = "../../http-transports/reqwest", version = "0.59.3" }
51
+ opendal-http-transport-reqwest = { path = "../../http-transports/reqwest", version = "0.59.5" }
52
52
  serde_json = { workspace = true }
53
53
  tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
@@ -22,7 +22,7 @@ license = "Apache-2.0"
22
22
  name = "opendal-service-http"
23
23
  readme = "README.md"
24
24
  repository = "https://github.com/apache/opendal"
25
- version = "0.59.3"
25
+ version = "0.59.5"
26
26
 
27
27
  [package.metadata.docs.rs]
28
28
  all-features = true
@@ -30,9 +30,9 @@ all-features = true
30
30
  [dependencies]
31
31
  http = "1.4"
32
32
  log = "0.4"
33
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
33
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
34
34
  serde = { version = "1", features = ["derive"] }
35
35
 
36
36
  [dev-dependencies]
37
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
37
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
38
38
  tokio = { version = "1.52", features = ["macros", "rt-multi-thread"] }
@@ -177,7 +177,8 @@ pub(crate) fn parse_error(ctx: ErrorContext, resp: Response<Buffer>) -> Error {
177
177
  (ErrorKind::ConditionNotMatch, false)
178
178
  }
179
179
  StatusCode::RANGE_NOT_SATISFIABLE => (ErrorKind::RangeNotSatisfied, false),
180
- StatusCode::INTERNAL_SERVER_ERROR
180
+ StatusCode::TOO_MANY_REQUESTS
181
+ | StatusCode::INTERNAL_SERVER_ERROR
181
182
  | StatusCode::BAD_GATEWAY
182
183
  | StatusCode::SERVICE_UNAVAILABLE
183
184
  | StatusCode::GATEWAY_TIMEOUT => (ErrorKind::Unexpected, true),
@@ -35,7 +35,7 @@ all-features = true
35
35
  bytes = { workspace = true }
36
36
  http = { workspace = true }
37
37
  log = { workspace = true }
38
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
38
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
39
39
  prost = "0.14.3"
40
40
  serde = { workspace = true, features = ["derive"] }
41
41
 
@@ -32,7 +32,7 @@ version = { workspace = true }
32
32
  all-features = true
33
33
 
34
34
  [dependencies]
35
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
35
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
36
36
 
37
37
  bytes = { workspace = true }
38
38
  http = { workspace = true }
@@ -36,7 +36,7 @@ asyncband = { workspace = true, features = ["mutex", "once-cell"] }
36
36
  bytes = { workspace = true }
37
37
  http = { workspace = true }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
40
40
  serde = { workspace = true, features = ["derive"] }
41
41
  serde_json = { workspace = true }
42
42
 
@@ -35,7 +35,7 @@ all-features = true
35
35
  bytes = { workspace = true }
36
36
  http = { workspace = true }
37
37
  log = { workspace = true }
38
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
38
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
39
39
  serde = { workspace = true, features = ["derive"] }
40
40
  serde_json = { workspace = true }
41
41
 
@@ -33,7 +33,7 @@ all-features = true
33
33
 
34
34
  [dependencies]
35
35
  asyncband = { workspace = true, features = ["pool"] }
36
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
36
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
37
37
  serde = { workspace = true, features = ["derive"] }
38
38
  tokio = { workspace = true, features = ["io-util", "macros", "net", "time"] }
39
39
  url = { workspace = true }
@@ -34,5 +34,5 @@ all-features = true
34
34
  [dependencies]
35
35
  log = { workspace = true }
36
36
  mini-moka = "0.10"
37
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
37
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
38
38
  serde = { workspace = true, features = ["derive"] }
@@ -34,7 +34,7 @@ all-features = true
34
34
  [dependencies]
35
35
  log = { workspace = true }
36
36
  moka = { version = "0.12", features = ["future", "sync"] }
37
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
37
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
38
38
  serde = { workspace = true, features = ["derive"] }
39
39
 
40
40
  [dev-dependencies]
@@ -34,7 +34,7 @@ all-features = true
34
34
  [dependencies]
35
35
  asyncband = { workspace = true, features = ["once-cell"] }
36
36
  mongodb = { version = "3.3.0" }
37
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
37
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
38
38
  serde = { workspace = true, features = ["derive"] }
39
39
 
40
40
  [dev-dependencies]
@@ -41,7 +41,7 @@ monoio = { version = "0.2.4", features = [
41
41
  "unlinkat",
42
42
  "renameat",
43
43
  ] }
44
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
44
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
45
45
  serde = { workspace = true, features = ["derive"] }
46
46
 
47
47
  [dev-dependencies]
@@ -33,7 +33,7 @@ all-features = true
33
33
 
34
34
  [dependencies]
35
35
  asyncband = { workspace = true, features = ["once-cell"] }
36
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
36
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
37
37
  serde = { workspace = true, features = ["derive"] }
38
38
  sqlx = { version = "0.8.0", features = ["runtime-tokio-rustls", "mysql"] }
39
39
 
@@ -35,7 +35,7 @@ all-features = true
35
35
  bytes = { workspace = true }
36
36
  http = { workspace = true }
37
37
  log = { workspace = true }
38
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false, features = [
38
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false, features = [
39
39
  "reqsign",
40
40
  ] }
41
41
  quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
@@ -36,7 +36,7 @@ asyncband = { workspace = true, features = ["mutex"] }
36
36
  bytes = { workspace = true }
37
37
  http = { workspace = true }
38
38
  log = { workspace = true }
39
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
39
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
40
40
  serde = { workspace = true, features = ["derive"] }
41
41
  serde_json = { workspace = true }
42
42
  tokio = { workspace = true, features = ["time"] }
@@ -35,7 +35,7 @@ targets = ["wasm32-unknown-unknown"]
35
35
 
36
36
  [target.'cfg(target_arch = "wasm32")'.dependencies]
37
37
  js-sys = "0.3.77"
38
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false }
38
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false }
39
39
  send_wrapper = "0.6"
40
40
  serde = { workspace = true, features = ["derive"] }
41
41
  wasm-bindgen = "0.2.100"
@@ -35,7 +35,7 @@ all-features = true
35
35
  bytes = { workspace = true }
36
36
  http = { workspace = true }
37
37
  log = { workspace = true }
38
- opendal-core = { path = "../../core", version = "0.59.3", default-features = false, features = [
38
+ opendal-core = { path = "../../core", version = "0.59.5", default-features = false, features = [
39
39
  "reqsign",
40
40
  ] }
41
41
  quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }