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.
Files changed (566) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +89 -56
  3. data/Cargo.toml +1 -1
  4. data/DEPENDENCIES.rust.tsv +55 -41
  5. data/LICENSE +201 -0
  6. data/LICENSE-MPL-2.0.txt +373 -0
  7. data/NOTICE +5 -0
  8. data/core/CHANGELOG.md +175 -0
  9. data/core/Cargo.lock +225 -298
  10. data/core/Cargo.toml +100 -94
  11. data/core/DEPENDENCIES.rust.tsv +44 -73
  12. data/core/benches/metadata/README.md +21 -0
  13. data/core/benches/metadata/main.rs +541 -0
  14. data/core/benches/vs_fs/Cargo.toml +1 -1
  15. data/core/benches/vs_s3/Cargo.toml +1 -1
  16. data/core/core/Cargo.toml +7 -2
  17. data/core/core/src/blocking/delete.rs +5 -1
  18. data/core/core/src/blocking/operator.rs +12 -0
  19. data/core/core/src/blocking/read/std_reader.rs +25 -0
  20. data/core/core/src/docs/concepts.rs +70 -94
  21. data/core/core/src/docs/internals/accessor.rs +62 -293
  22. data/core/core/src/docs/internals/layer.rs +43 -59
  23. data/core/core/src/docs/internals/mod.rs +21 -23
  24. data/core/core/src/docs/mod.rs +10 -6
  25. data/core/core/src/docs/performance/concurrent_write.md +92 -55
  26. data/core/core/src/docs/performance/http_optimization.md +120 -104
  27. data/core/core/src/docs/performance/mod.rs +8 -6
  28. data/core/core/src/docs/rfcs/5485_conditional_reader.md +4 -0
  29. data/core/core/src/docs/rfcs/7182_restore_api.md +139 -557
  30. data/core/core/src/docs/rfcs/7945_limited_read.md +210 -0
  31. data/core/core/src/docs/rfcs/7948_s3_provider_presets.md +254 -0
  32. data/core/core/src/docs/rfcs/8109_writer_copy_from.md +330 -0
  33. data/core/core/src/docs/rfcs/8145_conflict_error_kind.md +210 -0
  34. data/core/core/src/docs/rfcs/8147_write_if_not_changed.md +233 -0
  35. data/core/core/src/docs/rfcs/8188_compose_api.md +292 -0
  36. data/core/core/src/docs/rfcs/8194_compact_metadata_and_operation_args.md +444 -0
  37. data/core/core/src/docs/rfcs/README.md +14 -3
  38. data/core/core/src/docs/rfcs/mod.rs +46 -22
  39. data/core/core/src/docs/specs/README.md +34 -0
  40. data/core/core/src/docs/specs/conditional-operations.md +156 -0
  41. data/core/core/src/docs/specs/metadata.md +63 -0
  42. data/core/core/src/docs/specs/mod.rs +26 -0
  43. data/core/core/src/docs/upgrade.md +114 -1
  44. data/core/core/src/layers/capability_override.rs +15 -2
  45. data/core/core/src/layers/complete.rs +347 -43
  46. data/core/core/src/layers/correctness_check.rs +718 -51
  47. data/core/core/src/layers/error_context.rs +76 -2
  48. data/core/core/src/layers/simulate.rs +91 -28
  49. data/core/core/src/lib.rs +1 -0
  50. data/core/core/src/raw/accessor.rs +91 -15
  51. data/core/core/src/raw/enum_utils.rs +7 -0
  52. data/core/core/src/raw/http_util/header.rs +22 -17
  53. data/core/core/src/raw/oio/compose/api.rs +92 -0
  54. data/core/core/src/raw/oio/compose/mod.rs +19 -0
  55. data/core/core/src/raw/oio/copy/api.rs +3 -3
  56. data/core/core/src/raw/oio/copy/block_copy.rs +32 -4
  57. data/core/core/src/raw/oio/copy/multipart_copy.rs +36 -7
  58. data/core/core/src/raw/oio/entry.rs +48 -22
  59. data/core/core/src/raw/oio/list/flat_list.rs +1 -1
  60. data/core/core/src/raw/oio/list/hierarchy_list.rs +3 -2
  61. data/core/core/src/raw/oio/mod.rs +3 -0
  62. data/core/core/src/raw/oio/read/position_read.rs +1 -1
  63. data/core/core/src/raw/oio/write/api.rs +40 -0
  64. data/core/core/src/raw/oio/write/append_write.rs +4 -4
  65. data/core/core/src/raw/oio/write/block_write.rs +2 -2
  66. data/core/core/src/raw/oio/write/multipart_write.rs +181 -48
  67. data/core/core/src/raw/oio/write/position_write.rs +1 -1
  68. data/core/core/src/raw/operation.rs +6 -0
  69. data/core/core/src/raw/ops.rs +1191 -456
  70. data/core/core/src/raw/rps.rs +11 -0
  71. data/core/core/src/raw/time.rs +14 -3
  72. data/core/core/src/services/memory/backend.rs +5 -10
  73. data/core/core/src/services/memory/lister.rs +4 -4
  74. data/core/core/src/services/memory/writer.rs +7 -6
  75. data/core/core/src/types/buffer.rs +102 -12
  76. data/core/core/src/types/bytes_range.rs +20 -1
  77. data/core/core/src/types/capability.rs +65 -0
  78. data/core/core/src/types/compact.rs +329 -0
  79. data/core/core/src/types/compose/composer.rs +183 -0
  80. data/core/core/src/types/compose/input.rs +57 -0
  81. data/core/core/src/types/compose/mod.rs +23 -0
  82. data/core/core/src/types/context/read.rs +16 -11
  83. data/core/core/src/types/context/write.rs +150 -2
  84. data/core/core/src/types/copy.rs +5 -3
  85. data/core/core/src/types/delete/deleter.rs +20 -12
  86. data/core/core/src/types/delete/input.rs +22 -64
  87. data/core/core/src/types/delete/mod.rs +0 -1
  88. data/core/core/src/types/entry.rs +8 -14
  89. data/core/core/src/types/error.rs +28 -11
  90. data/core/core/src/types/metadata.rs +709 -322
  91. data/core/core/src/types/mod.rs +9 -1
  92. data/core/core/src/types/operator/operator.rs +278 -29
  93. data/core/core/src/types/operator/operator_futures.rs +466 -105
  94. data/core/core/src/types/options.rs +631 -158
  95. data/core/core/src/types/read/futures_async_reader.rs +663 -50
  96. data/core/core/src/types/read/reader.rs +23 -5
  97. data/core/core/src/types/write/futures_async_writer.rs +27 -0
  98. data/core/core/src/types/write/writer.rs +47 -5
  99. data/core/http-transports/reqwest/Cargo.toml +1 -1
  100. data/core/layers/async-backtrace/Cargo.toml +2 -2
  101. data/core/layers/async-backtrace/src/lib.rs +21 -2
  102. data/core/layers/await-tree/Cargo.toml +2 -2
  103. data/core/layers/await-tree/src/lib.rs +25 -2
  104. data/core/layers/capability-check/Cargo.toml +2 -2
  105. data/core/layers/capability-check/src/lib.rs +98 -10
  106. data/core/layers/chaos/Cargo.toml +2 -2
  107. data/core/layers/chaos/src/lib.rs +18 -3
  108. data/core/layers/concurrent-limit/Cargo.toml +3 -3
  109. data/core/layers/concurrent-limit/src/lib.rs +53 -13
  110. data/core/layers/dtrace/Cargo.toml +2 -2
  111. data/core/layers/dtrace/src/lib.rs +29 -2
  112. data/core/layers/fastmetrics/Cargo.toml +3 -3
  113. data/core/layers/fastrace/Cargo.toml +2 -2
  114. data/core/layers/fastrace/src/lib.rs +28 -2
  115. data/core/layers/foyer/Cargo.toml +2 -2
  116. data/core/layers/foyer/src/full.rs +16 -19
  117. data/core/layers/foyer/src/lib.rs +67 -14
  118. data/core/layers/hotpath/Cargo.toml +2 -2
  119. data/core/layers/hotpath/src/lib.rs +20 -2
  120. data/core/layers/immutable-index/Cargo.toml +2 -2
  121. data/core/layers/immutable-index/src/lib.rs +48 -24
  122. data/core/layers/logging/Cargo.toml +2 -2
  123. data/core/layers/logging/src/lib.rs +46 -2
  124. data/core/layers/metrics/Cargo.toml +3 -3
  125. data/core/layers/mime-guess/Cargo.toml +2 -2
  126. data/core/layers/mime-guess/src/lib.rs +31 -4
  127. data/core/layers/observe-metrics-common/Cargo.toml +2 -2
  128. data/core/layers/observe-metrics-common/src/lib.rs +55 -2
  129. data/core/layers/otelmetrics/Cargo.toml +3 -3
  130. data/core/layers/oteltrace/Cargo.toml +2 -2
  131. data/core/layers/oteltrace/src/lib.rs +27 -2
  132. data/core/layers/prometheus/Cargo.toml +3 -3
  133. data/core/layers/prometheus-client/Cargo.toml +3 -3
  134. data/core/layers/retry/Cargo.toml +4 -4
  135. data/core/layers/retry/src/lib.rs +76 -19
  136. data/core/layers/route/Cargo.toml +3 -3
  137. data/core/layers/route/src/lib.rs +34 -7
  138. data/core/layers/tail-cut/Cargo.toml +2 -2
  139. data/core/layers/tail-cut/src/lib.rs +28 -2
  140. data/core/layers/throttle/Cargo.toml +2 -2
  141. data/core/layers/throttle/src/lib.rs +19 -2
  142. data/core/layers/timeout/Cargo.toml +3 -3
  143. data/core/layers/timeout/src/lib.rs +38 -13
  144. data/core/layers/tracing/Cargo.toml +2 -2
  145. data/core/layers/tracing/src/lib.rs +24 -3
  146. data/core/services/aliyun-drive/Cargo.toml +2 -2
  147. data/core/services/aliyun-drive/src/backend.rs +34 -24
  148. data/core/services/aliyun-drive/src/core.rs +143 -54
  149. data/core/services/aliyun-drive/src/lister.rs +19 -18
  150. data/core/services/aliyun-drive/src/reader.rs +4 -1
  151. data/core/services/aliyun-drive/src/writer.rs +3 -3
  152. data/core/services/alluxio/Cargo.toml +1 -1
  153. data/core/services/alluxio/src/backend.rs +1 -1
  154. data/core/services/alluxio/src/core.rs +113 -94
  155. data/core/services/alluxio/src/reader.rs +7 -3
  156. data/core/services/alluxio/src/writer.rs +2 -2
  157. data/core/services/azblob/Cargo.toml +2 -2
  158. data/core/services/azblob/src/backend.rs +17 -9
  159. data/core/services/azblob/src/copier.rs +41 -15
  160. data/core/services/azblob/src/core.rs +372 -135
  161. data/core/services/azblob/src/deleter.rs +41 -18
  162. data/core/services/azblob/src/lister.rs +16 -10
  163. data/core/services/azblob/src/reader.rs +4 -1
  164. data/core/services/azblob/src/writer.rs +48 -15
  165. data/core/services/azdls/Cargo.toml +3 -3
  166. data/core/services/azdls/src/backend.rs +45 -15
  167. data/core/services/azdls/src/config.rs +4 -1
  168. data/core/services/azdls/src/core.rs +276 -87
  169. data/core/services/azdls/src/deleter.rs +13 -4
  170. data/core/services/azdls/src/lister.rs +18 -12
  171. data/core/services/azdls/src/reader.rs +6 -2
  172. data/core/services/azdls/src/writer.rs +44 -23
  173. data/core/services/azfile/Cargo.toml +2 -2
  174. data/core/services/azfile/src/backend.rs +24 -8
  175. data/core/services/azfile/src/core.rs +195 -77
  176. data/core/services/azfile/src/deleter.rs +8 -1
  177. data/core/services/azfile/src/lister.rs +20 -14
  178. data/core/services/azfile/src/reader.rs +5 -2
  179. data/core/services/azfile/src/writer.rs +27 -15
  180. data/core/services/azure-common/Cargo.toml +1 -1
  181. data/core/services/b2/Cargo.toml +2 -2
  182. data/core/services/b2/src/backend.rs +30 -11
  183. data/core/services/b2/src/core.rs +134 -120
  184. data/core/services/b2/src/deleter.rs +1 -1
  185. data/core/services/b2/src/lister.rs +5 -2
  186. data/core/services/b2/src/reader.rs +5 -2
  187. data/core/services/b2/src/writer.rs +29 -12
  188. data/core/services/cacache/Cargo.toml +1 -1
  189. data/core/services/cacache/src/backend.rs +4 -5
  190. data/core/services/cacache/src/reader.rs +4 -1
  191. data/core/services/cacache/src/writer.rs +6 -2
  192. data/core/services/cloudflare-kv/Cargo.toml +1 -1
  193. data/core/services/cloudflare-kv/src/backend.rs +26 -15
  194. data/core/services/cloudflare-kv/src/config.rs +13 -2
  195. data/core/services/cloudflare-kv/src/core.rs +62 -56
  196. data/core/services/cloudflare-kv/src/deleter.rs +12 -3
  197. data/core/services/cloudflare-kv/src/lister.rs +66 -17
  198. data/core/services/cloudflare-kv/src/reader.rs +14 -9
  199. data/core/services/cloudflare-kv/src/writer.rs +10 -7
  200. data/core/services/compfs/Cargo.toml +1 -1
  201. data/core/services/compfs/src/backend.rs +11 -7
  202. data/core/services/compfs/src/lister.rs +7 -7
  203. data/core/services/compfs/src/writer.rs +1 -1
  204. data/core/services/cos/Cargo.toml +1 -1
  205. data/core/services/cos/src/backend.rs +129 -16
  206. data/core/services/cos/src/core.rs +198 -80
  207. data/core/services/cos/src/deleter.rs +4 -1
  208. data/core/services/cos/src/lister.rs +42 -27
  209. data/core/services/cos/src/reader.rs +6 -2
  210. data/core/services/cos/src/writer.rs +45 -21
  211. data/core/services/d1/Cargo.toml +1 -1
  212. data/core/services/d1/src/backend.rs +6 -5
  213. data/core/services/d1/src/core.rs +79 -63
  214. data/core/services/d1/src/reader.rs +4 -1
  215. data/core/services/d1/src/writer.rs +6 -2
  216. data/core/services/dashmap/Cargo.toml +1 -1
  217. data/core/services/dashmap/src/backend.rs +2 -2
  218. data/core/services/dashmap/src/reader.rs +4 -1
  219. data/core/services/dashmap/src/writer.rs +11 -8
  220. data/core/services/dbfs/Cargo.toml +1 -1
  221. data/core/services/dbfs/src/backend.rs +21 -15
  222. data/core/services/dbfs/src/core.rs +65 -60
  223. data/core/services/dbfs/src/deleter.rs +4 -1
  224. data/core/services/dbfs/src/lister.rs +10 -10
  225. data/core/services/dbfs/src/writer.rs +6 -3
  226. data/core/services/dropbox/Cargo.toml +2 -2
  227. data/core/services/dropbox/src/backend.rs +30 -23
  228. data/core/services/dropbox/src/core.rs +65 -63
  229. data/core/services/dropbox/src/deleter.rs +1 -1
  230. data/core/services/dropbox/src/lister.rs +17 -8
  231. data/core/services/dropbox/src/reader.rs +4 -1
  232. data/core/services/dropbox/src/writer.rs +13 -10
  233. data/core/services/etcd/Cargo.toml +1 -1
  234. data/core/services/etcd/src/backend.rs +8 -5
  235. data/core/services/etcd/src/core.rs +5 -11
  236. data/core/services/etcd/src/lister.rs +6 -1
  237. data/core/services/etcd/src/reader.rs +4 -1
  238. data/core/services/etcd/src/writer.rs +6 -3
  239. data/core/services/foundationdb/Cargo.toml +1 -1
  240. data/core/services/foundationdb/src/backend.rs +6 -5
  241. data/core/services/foundationdb/src/reader.rs +4 -1
  242. data/core/services/foundationdb/src/writer.rs +6 -2
  243. data/core/services/foyer/Cargo.toml +3 -3
  244. data/core/services/foyer/src/backend.rs +6 -5
  245. data/core/services/foyer/src/reader.rs +4 -1
  246. data/core/services/foyer/src/writer.rs +6 -2
  247. data/core/services/fs/Cargo.toml +1 -1
  248. data/core/services/fs/src/backend.rs +4 -3
  249. data/core/services/fs/src/core.rs +44 -26
  250. data/core/services/fs/src/lister.rs +9 -6
  251. data/core/services/fs/src/writer.rs +20 -13
  252. data/core/services/ftp/Cargo.toml +4 -6
  253. data/core/services/ftp/src/backend.rs +9 -5
  254. data/core/services/ftp/src/core.rs +9 -7
  255. data/core/services/ftp/src/lister.rs +7 -8
  256. data/core/services/ftp/src/reader.rs +3 -3
  257. data/core/services/ftp/src/writer.rs +3 -3
  258. data/core/services/gcs/Cargo.toml +4 -2
  259. data/core/services/gcs/src/backend.rs +53 -7
  260. data/core/services/gcs/src/composer.rs +705 -0
  261. data/core/services/gcs/src/copier.rs +14 -4
  262. data/core/services/gcs/src/core.rs +828 -124
  263. data/core/services/gcs/src/deleter.rs +33 -18
  264. data/core/services/gcs/src/lib.rs +1 -0
  265. data/core/services/gcs/src/lister.rs +21 -12
  266. data/core/services/gcs/src/reader.rs +12 -5
  267. data/core/services/gcs/src/writer.rs +632 -10
  268. data/core/services/gcs-grpc/Cargo.toml +58 -0
  269. data/core/services/gcs-grpc/README.md +19 -0
  270. data/core/services/gcs-grpc/proto/README.md +23 -0
  271. data/core/services/gcs-grpc/proto/google/storage/v2/storage.proto +171 -0
  272. data/core/services/gcs-grpc/proto/upstream-descriptor.bin +0 -0
  273. data/core/services/gcs-grpc/src/backend.rs +449 -0
  274. data/core/services/gcs-grpc/src/config.rs +116 -0
  275. data/core/services/gcs-grpc/src/copier.rs +98 -0
  276. data/core/services/gcs-grpc/src/core.rs +298 -0
  277. data/core/services/gcs-grpc/src/deleter.rs +65 -0
  278. data/core/services/gcs-grpc/src/docs.md +19 -0
  279. data/core/services/gcs-grpc/src/generated/google.storage.v2.rs +541 -0
  280. data/core/services/gcs-grpc/src/generated/mod.rs +24 -0
  281. data/core/services/gcs-grpc/src/lib.rs +43 -0
  282. data/core/services/gcs-grpc/src/lister.rs +125 -0
  283. data/core/services/gcs-grpc/src/reader.rs +140 -0
  284. data/core/services/gcs-grpc/src/writer.rs +780 -0
  285. data/core/services/gdrive/Cargo.toml +2 -2
  286. data/core/services/gdrive/src/backend.rs +123 -69
  287. data/core/services/gdrive/src/core.rs +87 -69
  288. data/core/services/gdrive/src/deleter.rs +8 -2
  289. data/core/services/gdrive/src/lister.rs +38 -26
  290. data/core/services/gdrive/src/path_index.rs +2 -2
  291. data/core/services/gdrive/src/reader.rs +9 -3
  292. data/core/services/gdrive/src/writer.rs +13 -7
  293. data/core/services/ghac/Cargo.toml +2 -2
  294. data/core/services/ghac/src/backend.rs +5 -2
  295. data/core/services/ghac/src/core.rs +59 -37
  296. data/core/services/ghac/src/reader.rs +5 -2
  297. data/core/services/ghac/src/writer.rs +16 -6
  298. data/core/services/github/Cargo.toml +1 -1
  299. data/core/services/github/src/backend.rs +16 -8
  300. data/core/services/github/src/core.rs +88 -76
  301. data/core/services/github/src/lister.rs +17 -15
  302. data/core/services/github/src/reader.rs +5 -2
  303. data/core/services/github/src/writer.rs +12 -6
  304. data/core/services/goosefs/Cargo.toml +2 -2
  305. data/core/services/goosefs/src/backend.rs +2 -2
  306. data/core/services/goosefs/src/core.rs +291 -208
  307. data/core/services/goosefs/src/docs.md +3 -0
  308. data/core/services/goosefs/src/lister.rs +2 -3
  309. data/core/services/goosefs/src/reader.rs +7 -3
  310. data/core/services/goosefs/src/writer.rs +21 -10
  311. data/core/services/goosefs/tests/safe_conditional_put.rs +37 -0
  312. data/core/services/gridfs/Cargo.toml +2 -2
  313. data/core/services/gridfs/src/backend.rs +12 -8
  314. data/core/services/gridfs/src/core.rs +1 -1
  315. data/core/services/gridfs/src/reader.rs +4 -1
  316. data/core/services/gridfs/src/writer.rs +6 -2
  317. data/core/services/hdfs/Cargo.toml +1 -1
  318. data/core/services/hdfs/src/backend.rs +1 -1
  319. data/core/services/hdfs/src/core.rs +7 -4
  320. data/core/services/hdfs/src/lister.rs +7 -9
  321. data/core/services/hdfs/src/writer.rs +5 -1
  322. data/core/services/hdfs-native/Cargo.toml +1 -1
  323. data/core/services/hdfs-native/src/backend.rs +1 -1
  324. data/core/services/hdfs-native/src/core.rs +44 -50
  325. data/core/services/hdfs-native/src/lister.rs +8 -10
  326. data/core/services/hdfs-native/src/writer.rs +5 -1
  327. data/core/services/hf/Cargo.toml +4 -3
  328. data/core/services/hf/src/backend.rs +4 -3
  329. data/core/services/hf/src/core.rs +907 -153
  330. data/core/services/hf/src/lister.rs +16 -6
  331. data/core/services/hf/src/reader.rs +377 -57
  332. data/core/services/hf/src/writer.rs +6 -2
  333. data/core/services/http/Cargo.toml +3 -3
  334. data/core/services/http/src/backend.rs +8 -6
  335. data/core/services/http/src/core.rs +57 -35
  336. data/core/services/http/src/reader.rs +5 -2
  337. data/core/services/ipfs/Cargo.toml +1 -1
  338. data/core/services/ipfs/src/backend.rs +20 -9
  339. data/core/services/ipfs/src/core.rs +43 -34
  340. data/core/services/ipfs/src/reader.rs +5 -2
  341. data/core/services/ipmfs/Cargo.toml +1 -1
  342. data/core/services/ipmfs/src/backend.rs +17 -8
  343. data/core/services/ipmfs/src/core.rs +66 -60
  344. data/core/services/ipmfs/src/deleter.rs +5 -2
  345. data/core/services/ipmfs/src/lister.rs +15 -12
  346. data/core/services/ipmfs/src/reader.rs +5 -2
  347. data/core/services/ipmfs/src/writer.rs +6 -3
  348. data/core/services/koofr/Cargo.toml +2 -2
  349. data/core/services/koofr/src/backend.rs +46 -17
  350. data/core/services/koofr/src/core.rs +64 -48
  351. data/core/services/koofr/src/deleter.rs +4 -1
  352. data/core/services/koofr/src/lister.rs +11 -10
  353. data/core/services/koofr/src/reader.rs +5 -2
  354. data/core/services/koofr/src/writer.rs +13 -7
  355. data/core/services/lakefs/Cargo.toml +1 -1
  356. data/core/services/lakefs/src/backend.rs +25 -8
  357. data/core/services/lakefs/src/core.rs +79 -73
  358. data/core/services/lakefs/src/deleter.rs +4 -1
  359. data/core/services/lakefs/src/lister.rs +17 -14
  360. data/core/services/lakefs/src/reader.rs +5 -2
  361. data/core/services/lakefs/src/writer.rs +11 -10
  362. data/core/services/memcached/Cargo.toml +1 -1
  363. data/core/services/memcached/src/backend.rs +57 -7
  364. data/core/services/memcached/src/config.rs +13 -2
  365. data/core/services/memcached/src/core.rs +11 -1
  366. data/core/services/memcached/src/reader.rs +4 -1
  367. data/core/services/memcached/src/writer.rs +6 -2
  368. data/core/services/mini_moka/Cargo.toml +1 -1
  369. data/core/services/mini_moka/src/backend.rs +8 -8
  370. data/core/services/mini_moka/src/reader.rs +4 -1
  371. data/core/services/mini_moka/src/writer.rs +11 -7
  372. data/core/services/moka/Cargo.toml +1 -1
  373. data/core/services/moka/src/backend.rs +7 -7
  374. data/core/services/moka/src/reader.rs +4 -1
  375. data/core/services/moka/src/writer.rs +10 -6
  376. data/core/services/mongodb/Cargo.toml +2 -2
  377. data/core/services/mongodb/src/backend.rs +7 -6
  378. data/core/services/mongodb/src/core.rs +1 -1
  379. data/core/services/mongodb/src/reader.rs +4 -1
  380. data/core/services/mongodb/src/writer.rs +6 -2
  381. data/core/services/monoiofs/Cargo.toml +2 -2
  382. data/core/services/monoiofs/src/backend.rs +16 -10
  383. data/core/services/monoiofs/src/core.rs +8 -9
  384. data/core/services/monoiofs/src/reader.rs +8 -10
  385. data/core/services/monoiofs/src/writer.rs +19 -24
  386. data/core/services/mysql/Cargo.toml +2 -2
  387. data/core/services/mysql/src/backend.rs +7 -6
  388. data/core/services/mysql/src/core.rs +1 -1
  389. data/core/services/mysql/src/lister.rs +7 -3
  390. data/core/services/mysql/src/reader.rs +4 -1
  391. data/core/services/mysql/src/writer.rs +6 -2
  392. data/core/services/obs/Cargo.toml +1 -1
  393. data/core/services/obs/src/backend.rs +29 -11
  394. data/core/services/obs/src/core.rs +81 -82
  395. data/core/services/obs/src/deleter.rs +4 -1
  396. data/core/services/obs/src/lister.rs +12 -5
  397. data/core/services/obs/src/reader.rs +5 -2
  398. data/core/services/obs/src/writer.rs +40 -19
  399. data/core/services/onedrive/Cargo.toml +2 -2
  400. data/core/services/onedrive/src/backend.rs +30 -21
  401. data/core/services/onedrive/src/config.rs +2 -2
  402. data/core/services/onedrive/src/core.rs +191 -90
  403. data/core/services/onedrive/src/deleter.rs +5 -2
  404. data/core/services/onedrive/src/graph_model.rs +10 -51
  405. data/core/services/onedrive/src/lister.rs +60 -24
  406. data/core/services/onedrive/src/reader.rs +17 -2
  407. data/core/services/onedrive/src/writer.rs +26 -15
  408. data/core/services/opfs/Cargo.toml +1 -1
  409. data/core/services/opfs/src/backend.rs +6 -13
  410. data/core/services/opfs/src/core.rs +33 -37
  411. data/core/services/opfs/src/lister.rs +4 -4
  412. data/core/services/opfs/src/writer.rs +1 -3
  413. data/core/services/oss/Cargo.toml +1 -1
  414. data/core/services/oss/src/backend.rs +40 -8
  415. data/core/services/oss/src/core.rs +192 -92
  416. data/core/services/oss/src/deleter.rs +16 -6
  417. data/core/services/oss/src/lister.rs +43 -27
  418. data/core/services/oss/src/reader.rs +6 -2
  419. data/core/services/oss/src/writer.rs +40 -22
  420. data/core/services/pcloud/Cargo.toml +1 -1
  421. data/core/services/pcloud/src/backend.rs +40 -6
  422. data/core/services/pcloud/src/core.rs +80 -66
  423. data/core/services/pcloud/src/deleter.rs +8 -1
  424. data/core/services/pcloud/src/lister.rs +4 -1
  425. data/core/services/pcloud/src/reader.rs +5 -2
  426. data/core/services/pcloud/src/writer.rs +6 -3
  427. data/core/services/persy/Cargo.toml +1 -1
  428. data/core/services/persy/src/backend.rs +6 -5
  429. data/core/services/persy/src/core.rs +60 -15
  430. data/core/services/persy/src/reader.rs +4 -1
  431. data/core/services/persy/src/writer.rs +6 -2
  432. data/core/services/postgresql/Cargo.toml +2 -2
  433. data/core/services/postgresql/src/backend.rs +7 -6
  434. data/core/services/postgresql/src/core.rs +1 -1
  435. data/core/services/postgresql/src/reader.rs +4 -1
  436. data/core/services/postgresql/src/writer.rs +6 -2
  437. data/core/services/redb/Cargo.toml +1 -1
  438. data/core/services/redb/src/backend.rs +6 -5
  439. data/core/services/redb/src/reader.rs +4 -1
  440. data/core/services/redb/src/writer.rs +6 -2
  441. data/core/services/redis/Cargo.toml +1 -1
  442. data/core/services/redis/src/backend.rs +18 -8
  443. data/core/services/redis/src/config.rs +13 -2
  444. data/core/services/redis/src/reader.rs +8 -4
  445. data/core/services/redis/src/writer.rs +6 -2
  446. data/core/services/rocksdb/Cargo.toml +1 -1
  447. data/core/services/rocksdb/src/backend.rs +6 -5
  448. data/core/services/rocksdb/src/lister.rs +6 -5
  449. data/core/services/rocksdb/src/reader.rs +4 -1
  450. data/core/services/rocksdb/src/writer.rs +6 -2
  451. data/core/services/s3/Cargo.toml +5 -4
  452. data/core/services/s3/src/backend.rs +995 -39
  453. data/core/services/s3/src/compatible_services.md +57 -0
  454. data/core/services/s3/src/config.rs +16 -0
  455. data/core/services/s3/src/copier.rs +190 -55
  456. data/core/services/s3/src/core.rs +299 -190
  457. data/core/services/s3/src/deleter.rs +26 -7
  458. data/core/services/s3/src/docs.md +57 -0
  459. data/core/services/s3/src/lister.rs +55 -36
  460. data/core/services/s3/src/reader.rs +22 -2
  461. data/core/services/s3/src/writer.rs +154 -32
  462. data/core/services/seafile/Cargo.toml +2 -2
  463. data/core/services/seafile/src/backend.rs +3 -3
  464. data/core/services/seafile/src/core.rs +105 -79
  465. data/core/services/seafile/src/lister.rs +11 -8
  466. data/core/services/seafile/src/reader.rs +5 -2
  467. data/core/services/seafile/src/writer.rs +6 -3
  468. data/core/services/sftp/Cargo.toml +1 -1
  469. data/core/services/sftp/src/backend.rs +19 -4
  470. data/core/services/sftp/src/core.rs +51 -46
  471. data/core/services/sftp/src/lister.rs +4 -4
  472. data/core/services/sftp/src/writer.rs +1 -1
  473. data/core/services/sled/Cargo.toml +1 -1
  474. data/core/services/sled/src/backend.rs +6 -5
  475. data/core/services/sled/src/core.rs +28 -6
  476. data/core/services/sled/src/lister.rs +6 -5
  477. data/core/services/sled/src/reader.rs +4 -1
  478. data/core/services/sled/src/writer.rs +6 -2
  479. data/core/services/sqlite/Cargo.toml +2 -2
  480. data/core/services/sqlite/src/backend.rs +12 -7
  481. data/core/services/sqlite/src/core.rs +3 -3
  482. data/core/services/sqlite/src/reader.rs +4 -1
  483. data/core/services/sqlite/src/writer.rs +7 -3
  484. data/core/services/surrealdb/Cargo.toml +2 -2
  485. data/core/services/surrealdb/src/backend.rs +7 -6
  486. data/core/services/surrealdb/src/core.rs +1 -1
  487. data/core/services/surrealdb/src/reader.rs +4 -1
  488. data/core/services/surrealdb/src/writer.rs +6 -2
  489. data/core/services/swift/Cargo.toml +1 -1
  490. data/core/services/swift/src/backend.rs +38 -8
  491. data/core/services/swift/src/core.rs +63 -67
  492. data/core/services/swift/src/deleter.rs +8 -2
  493. data/core/services/swift/src/lister.rs +11 -8
  494. data/core/services/swift/src/reader.rs +5 -2
  495. data/core/services/swift/src/writer.rs +17 -8
  496. data/core/services/tikv/Cargo.toml +2 -2
  497. data/core/services/tikv/src/backend.rs +7 -6
  498. data/core/services/tikv/src/core.rs +31 -14
  499. data/core/services/tikv/src/reader.rs +4 -1
  500. data/core/services/tikv/src/writer.rs +6 -2
  501. data/core/services/tos/Cargo.toml +2 -2
  502. data/core/services/tos/src/backend.rs +45 -21
  503. data/core/services/tos/src/copier.rs +44 -17
  504. data/core/services/tos/src/core.rs +147 -117
  505. data/core/services/tos/src/deleter.rs +9 -3
  506. data/core/services/tos/src/docs.md +1 -1
  507. data/core/services/tos/src/lister.rs +43 -28
  508. data/core/services/tos/src/reader.rs +5 -2
  509. data/core/services/tos/src/writer.rs +37 -16
  510. data/core/services/upyun/Cargo.toml +1 -1
  511. data/core/services/upyun/src/backend.rs +30 -7
  512. data/core/services/upyun/src/core.rs +122 -87
  513. data/core/services/upyun/src/deleter.rs +4 -1
  514. data/core/services/upyun/src/lister.rs +10 -10
  515. data/core/services/upyun/src/reader.rs +5 -2
  516. data/core/services/upyun/src/writer.rs +19 -7
  517. data/core/services/vercel-artifacts/Cargo.toml +1 -1
  518. data/core/services/vercel-artifacts/src/backend.rs +6 -3
  519. data/core/services/vercel-artifacts/src/core.rs +32 -27
  520. data/core/services/vercel-artifacts/src/reader.rs +5 -2
  521. data/core/services/vercel-artifacts/src/writer.rs +6 -3
  522. data/core/services/vercel-blob/Cargo.toml +1 -1
  523. data/core/services/vercel-blob/src/backend.rs +23 -6
  524. data/core/services/vercel-blob/src/core.rs +92 -81
  525. data/core/services/vercel-blob/src/lister.rs +12 -3
  526. data/core/services/vercel-blob/src/reader.rs +5 -2
  527. data/core/services/vercel-blob/src/writer.rs +19 -7
  528. data/core/services/webdav/Cargo.toml +2 -2
  529. data/core/services/webdav/src/backend.rs +25 -5
  530. data/core/services/webdav/src/core.rs +116 -59
  531. data/core/services/webdav/src/deleter.rs +4 -1
  532. data/core/services/webdav/src/lister.rs +4 -1
  533. data/core/services/webdav/src/reader.rs +6 -2
  534. data/core/services/webdav/src/writer.rs +17 -7
  535. data/core/services/webhdfs/Cargo.toml +2 -2
  536. data/core/services/webhdfs/src/backend.rs +24 -11
  537. data/core/services/webhdfs/src/core.rs +99 -98
  538. data/core/services/webhdfs/src/deleter.rs +5 -2
  539. data/core/services/webhdfs/src/lister.rs +21 -9
  540. data/core/services/webhdfs/src/reader.rs +5 -2
  541. data/core/services/webhdfs/src/writer.rs +49 -14
  542. data/core/services/yandex-disk/Cargo.toml +1 -1
  543. data/core/services/yandex-disk/src/backend.rs +28 -6
  544. data/core/services/yandex-disk/src/core.rs +97 -79
  545. data/core/services/yandex-disk/src/deleter.rs +4 -1
  546. data/core/services/yandex-disk/src/lister.rs +25 -9
  547. data/core/services/yandex-disk/src/reader.rs +5 -2
  548. data/core/services/yandex-disk/src/writer.rs +6 -3
  549. data/core/src/lib.rs +5 -0
  550. data/core/testkit/Cargo.toml +4 -4
  551. data/core/testkit/src/utils.rs +53 -8
  552. data/core/tests/behavior/async_compose.rs +297 -0
  553. data/core/tests/behavior/async_copy.rs +162 -1
  554. data/core/tests/behavior/async_delete.rs +364 -3
  555. data/core/tests/behavior/async_read.rs +86 -0
  556. data/core/tests/behavior/async_restore.rs +162 -0
  557. data/core/tests/behavior/async_stat.rs +90 -0
  558. data/core/tests/behavior/async_write.rs +330 -2
  559. data/core/tests/behavior/main.rs +4 -0
  560. data/core/upgrade.md +114 -1
  561. data/src/capability.rs +0 -1
  562. data/src/io.rs +0 -1
  563. data/src/lister.rs +0 -1
  564. data/src/metadata.rs +0 -1
  565. data/src/operator_info.rs +0 -1
  566. metadata +44 -2
@@ -25,9 +25,9 @@ use log::debug;
25
25
  use super::VERCEL_BLOB_SCHEME;
26
26
  use super::config::VercelBlobConfig;
27
27
  use super::core::Blob;
28
- use super::core::VercelBlobCore;
29
28
  use super::core::parse_blob;
30
29
  use super::core::parse_error;
30
+ use super::core::{ErrorContext, VercelBlobCore};
31
31
  use super::deleter::VercelBlobDeleter;
32
32
  use super::lister::VercelBlobLister;
33
33
  use super::reader::*;
@@ -138,6 +138,7 @@ impl Service for VercelBlobBackend {
138
138
  type Lister = oio::PageLister<VercelBlobLister>;
139
139
  type Deleter = oio::OneShotDeleter<VercelBlobDeleter>;
140
140
  type Copier = oio::OneShotCopier;
141
+ type Composer = ();
141
142
 
142
143
  fn info(&self) -> ServiceInfo {
143
144
  self.core.info.clone()
@@ -173,7 +174,10 @@ impl Service for VercelBlobBackend {
173
174
 
174
175
  parse_blob(&resp).map(RpStat::new)
175
176
  }
176
- _ => Err(parse_error(resp)),
177
+ _ => Err(parse_error(
178
+ ErrorContext::new(ServiceOperation("HeadBlob")),
179
+ resp,
180
+ )),
177
181
  }
178
182
  }
179
183
  fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
@@ -208,21 +212,34 @@ impl Service for VercelBlobBackend {
208
212
  ctx: &OperationContext,
209
213
  from: &str,
210
214
  to: &str,
211
- _args: OpCopy,
212
- _opts: OpCopier,
215
+ args: OpCopy,
213
216
  ) -> Result<Self::Copier> {
217
+ let backend = self.clone();
214
218
  let core = self.core.clone();
215
219
  let ctx = ctx.clone();
216
220
  let from = from.to_string();
217
221
  let to = to.to_string();
222
+ let source_content_length_hint = args.source_content_length_hint();
218
223
 
219
224
  Ok(oio::OneShotCopier::new(async move {
225
+ let source_size = match source_content_length_hint {
226
+ Some(size) => size,
227
+ None => backend
228
+ .stat(&ctx, &from, OpStat::default())
229
+ .await?
230
+ .into_metadata()
231
+ .content_length(),
232
+ };
233
+
220
234
  let resp = core.copy(&ctx, &from, &to).await?;
221
235
  let status = resp.status();
222
236
 
223
237
  match status {
224
- StatusCode::OK => Ok(Metadata::default()),
225
- _ => Err(parse_error(resp)),
238
+ StatusCode::OK => Ok(MetadataBuilder::file(source_size).build()),
239
+ _ => Err(parse_error(
240
+ ErrorContext::new(ServiceOperation("CopyBlob")),
241
+ resp,
242
+ )),
226
243
  }
227
244
  }))
228
245
  }
@@ -96,7 +96,7 @@ impl VercelBlobCore {
96
96
  let p = build_abs_path(&self.root, path);
97
97
  // Vercel blob use an unguessable random id url to download the file
98
98
  // So we use list to get the url of the file and then use it to download the file
99
- let resp = self.list(ctx, &p, Some(1)).await?;
99
+ let resp = self.list(ctx, &p, Some(1), None).await?;
100
100
 
101
101
  // Use the mtach url to download the file
102
102
  let url = resolve_blob(resp.blobs, p);
@@ -161,7 +161,7 @@ impl VercelBlobCore {
161
161
  pub async fn head(&self, ctx: &OperationContext, path: &str) -> Result<Response<Buffer>> {
162
162
  let p = build_abs_path(&self.root, path);
163
163
 
164
- let resp = self.list(ctx, &p, Some(1)).await?;
164
+ let resp = self.list(ctx, &p, Some(1), None).await?;
165
165
 
166
166
  let url = resolve_blob(resp.blobs, p);
167
167
 
@@ -194,7 +194,7 @@ impl VercelBlobCore {
194
194
  ) -> Result<Response<Buffer>> {
195
195
  let from = build_abs_path(&self.root, from);
196
196
 
197
- let resp = self.list(ctx, &from, Some(1)).await?;
197
+ let resp = self.list(ctx, &from, Some(1), None).await?;
198
198
 
199
199
  let from_url = resolve_blob(resp.blobs, from);
200
200
 
@@ -229,6 +229,7 @@ impl VercelBlobCore {
229
229
  ctx: &OperationContext,
230
230
  prefix: &str,
231
231
  limit: Option<usize>,
232
+ cursor: Option<&str>,
232
233
  ) -> Result<ListResponse> {
233
234
  let prefix = if prefix == "/" { "" } else { prefix };
234
235
 
@@ -241,6 +242,10 @@ impl VercelBlobCore {
241
242
  url.push_str(&format!("&limit={limit}"))
242
243
  }
243
244
 
245
+ if let Some(cursor) = cursor {
246
+ url.push_str(&format!("&cursor={}", percent_encode_path(cursor)));
247
+ }
248
+
244
249
  let req = Request::get(&url);
245
250
 
246
251
  let req = self.sign(req);
@@ -257,7 +262,10 @@ impl VercelBlobCore {
257
262
  let status = resp.status();
258
263
 
259
264
  if status != StatusCode::OK {
260
- return Err(parse_error(resp));
265
+ return Err(parse_error(
266
+ ErrorContext::new(ServiceOperation("ListBlobs")),
267
+ resp,
268
+ ));
261
269
  }
262
270
 
263
271
  let body = resp.into_body();
@@ -271,7 +279,7 @@ impl VercelBlobCore {
271
279
  pub async fn vercel_delete_blob(&self, ctx: &OperationContext, path: &str) -> Result<()> {
272
280
  let p = build_abs_path(&self.root, path);
273
281
 
274
- let resp = self.list(ctx, &p, Some(1)).await?;
282
+ let resp = self.list(ctx, &p, Some(1), None).await?;
275
283
 
276
284
  let url = resolve_blob(resp.blobs, p);
277
285
 
@@ -301,7 +309,10 @@ impl VercelBlobCore {
301
309
 
302
310
  match status {
303
311
  StatusCode::OK => Ok(()),
304
- _ => Err(parse_error(resp)),
312
+ _ => Err(parse_error(
313
+ ErrorContext::new(ServiceOperation("DeleteBlob")),
314
+ resp,
315
+ )),
305
316
  }
306
317
  }
307
318
 
@@ -411,19 +422,17 @@ impl VercelBlobCore {
411
422
  }
412
423
 
413
424
  pub fn parse_blob(blob: &Blob) -> Result<Metadata> {
414
- let mode = if blob.pathname.ends_with('/') {
415
- EntryMode::DIR
425
+ let mut md = if blob.pathname.ends_with('/') {
426
+ MetadataBuilder::dir()
416
427
  } else {
417
- EntryMode::FILE
428
+ MetadataBuilder::file(blob.size)
418
429
  };
419
- let mut md = Metadata::new(mode);
420
430
  if let Some(content_type) = blob.content_type.clone() {
421
- md.set_content_type(&content_type);
431
+ md.content_type(&content_type);
422
432
  }
423
- md.set_content_length(blob.size);
424
- md.set_last_modified(blob.uploaded_at.parse::<Timestamp>()?);
425
- md.set_content_disposition(&blob.content_disposition);
426
- Ok(md)
433
+ md.last_modified(blob.uploaded_at.parse::<Timestamp>()?);
434
+ md.content_disposition(&blob.content_disposition);
435
+ Ok(md.build())
427
436
  }
428
437
 
429
438
  fn resolve_blob(blobs: Vec<Blob>, path: String) -> String {
@@ -474,101 +483,103 @@ pub struct UploadPartResponse {
474
483
  pub etag: String,
475
484
  }
476
485
 
477
- mod error {
478
- use bytes::Buf;
479
- use http::Response;
480
- use quick_xml::de;
481
- use serde::Deserialize;
486
+ use quick_xml::de;
482
487
 
483
- use opendal_core::raw::*;
484
- use opendal_core::*;
488
+ /// VercelBlobError is the error returned by VercelBlob service.
489
+ #[derive(Default, Debug, Deserialize)]
490
+ #[serde(default)]
491
+ struct VercelBlobError {
492
+ error: VercelBlobErrorDetail,
493
+ }
485
494
 
486
- /// VercelBlobError is the error returned by VercelBlob service.
487
- #[derive(Default, Debug, Deserialize)]
488
- #[serde(default)]
489
- struct VercelBlobError {
490
- error: VercelBlobErrorDetail,
491
- }
495
+ #[derive(Default, Debug, Deserialize)]
496
+ #[serde(default)]
497
+ struct VercelBlobErrorDetail {
498
+ code: String,
499
+ message: Option<String>,
500
+ }
492
501
 
493
- #[derive(Default, Debug, Deserialize)]
494
- #[serde(default)]
495
- struct VercelBlobErrorDetail {
496
- code: String,
497
- message: Option<String>,
498
- }
502
+ /// Context needed to classify an error from this service.
503
+ #[derive(Clone, Copy, Debug)]
504
+ pub(crate) struct ErrorContext {
505
+ service_operation: ServiceOperation,
506
+ }
499
507
 
500
- /// Parse error response into Error.
501
- pub(crate) fn parse_error(resp: Response<Buffer>) -> Error {
502
- let (parts, body) = resp.into_parts();
503
- let bs = body.to_bytes();
508
+ impl ErrorContext {
509
+ pub(crate) const fn new(service_operation: ServiceOperation) -> Self {
510
+ Self { service_operation }
511
+ }
512
+ }
504
513
 
505
- let (kind, retryable) = match parts.status.as_u16() {
506
- 403 => (ErrorKind::PermissionDenied, false),
507
- 404 => (ErrorKind::NotFound, false),
508
- 500 | 502 | 503 | 504 => (ErrorKind::Unexpected, true),
509
- _ => (ErrorKind::Unexpected, false),
510
- };
514
+ /// Parse an error response using its service request context.
515
+ pub(crate) fn parse_error(ctx: ErrorContext, resp: Response<Buffer>) -> Error {
516
+ let (parts, body) = resp.into_parts();
517
+ let bs = body.to_bytes();
511
518
 
512
- let (message, _vercel_blob_err) =
513
- de::from_reader::<_, VercelBlobError>(bs.clone().reader())
514
- .map(|vercel_blob_err| (format!("{vercel_blob_err:?}"), Some(vercel_blob_err)))
515
- .unwrap_or_else(|_| (String::from_utf8_lossy(&bs).into_owned(), None));
519
+ let (kind, retryable) = match parts.status.as_u16() {
520
+ 403 => (ErrorKind::PermissionDenied, false),
521
+ 404 => (ErrorKind::NotFound, false),
522
+ 500 | 502 | 503 | 504 => (ErrorKind::Unexpected, true),
523
+ _ => (ErrorKind::Unexpected, false),
524
+ };
516
525
 
517
- let mut err = Error::new(kind, message);
526
+ let (message, _vercel_blob_err) = de::from_reader::<_, VercelBlobError>(bs.clone().reader())
527
+ .map(|vercel_blob_err| (format!("{vercel_blob_err:?}"), Some(vercel_blob_err)))
528
+ .unwrap_or_else(|_| (String::from_utf8_lossy(&bs).into_owned(), None));
518
529
 
519
- err = with_error_response_context(err, parts);
530
+ let mut err = Error::new(kind, message);
520
531
 
521
- if retryable {
522
- err = err.set_temporary();
523
- }
532
+ err = err.with_context("service_operation", ctx.service_operation.0);
533
+ err = with_error_response_context(err, parts);
524
534
 
525
- err
535
+ if retryable {
536
+ err = err.set_temporary();
526
537
  }
527
538
 
528
- #[cfg(test)]
529
- mod test {
530
- use http::StatusCode;
539
+ err
540
+ }
541
+
542
+ #[cfg(test)]
543
+ mod tests {
544
+ use http::StatusCode;
531
545
 
532
- use super::*;
546
+ use super::*;
533
547
 
534
- #[tokio::test]
535
- async fn test_parse_error() {
536
- let err_res = vec![(
537
- r#"{
548
+ #[tokio::test]
549
+ async fn test_parse_error() {
550
+ let err_res = vec![(
551
+ r#"{
538
552
  "error": {
539
553
  "code": "forbidden",
540
554
  "message": "Invalid token"
541
555
  }
542
556
  }"#,
543
- ErrorKind::PermissionDenied,
544
- StatusCode::FORBIDDEN,
545
- )];
557
+ ErrorKind::PermissionDenied,
558
+ StatusCode::FORBIDDEN,
559
+ )];
546
560
 
547
- for res in err_res {
548
- let body = Buffer::from(res.0.as_bytes().to_vec());
549
- let resp = Response::builder().status(res.2).body(body).unwrap();
561
+ for res in err_res {
562
+ let body = Buffer::from(res.0.as_bytes().to_vec());
563
+ let resp = Response::builder().status(res.2).body(body).unwrap();
550
564
 
551
- let err = parse_error(resp);
565
+ let err = parse_error(ErrorContext::new(ServiceOperation("Test")), resp);
552
566
 
553
- assert_eq!(err.kind(), res.1);
554
- }
567
+ assert_eq!(err.kind(), res.1);
568
+ }
555
569
 
556
- let bs = bytes::Bytes::from(
557
- r#"{
570
+ let bs = bytes::Bytes::from(
571
+ r#"{
558
572
  "error": {
559
573
  "code": "forbidden",
560
574
  "message": "Invalid token"
561
575
  }
562
576
  }"#,
563
- );
577
+ );
564
578
 
565
- let out: VercelBlobError = serde_json::from_reader(bs.reader()).expect("must success");
566
- println!("{out:?}");
579
+ let out: VercelBlobError = serde_json::from_reader(bs.reader()).expect("must success");
580
+ println!("{out:?}");
567
581
 
568
- assert_eq!(out.error.code, "forbidden");
569
- assert_eq!(out.error.message, Some("Invalid token".to_string()));
570
- }
582
+ assert_eq!(out.error.code, "forbidden");
583
+ assert_eq!(out.error.message, Some("Invalid token".to_string()));
571
584
  }
572
585
  }
573
-
574
- pub(super) use error::*;
@@ -52,12 +52,21 @@ impl oio::PageList for VercelBlobLister {
52
52
  async fn next_page(&self, ctx: &mut oio::PageContext) -> Result<()> {
53
53
  let p = build_abs_path(&self.core.root, &self.path);
54
54
 
55
- let resp = self.core.list(&self.ctx, &p, self.limit).await?;
55
+ let cursor = if ctx.token.is_empty() {
56
+ None
57
+ } else {
58
+ Some(ctx.token.as_str())
59
+ };
60
+
61
+ let resp = self.core.list(&self.ctx, &p, self.limit, cursor).await?;
56
62
 
57
63
  ctx.done = !resp.has_more;
58
64
 
59
- if let Some(cursor) = resp.cursor {
60
- ctx.token = cursor;
65
+ match resp.cursor {
66
+ Some(cursor) => ctx.token = cursor,
67
+ // More pages were reported but nothing was handed back to resume from. Stopping
68
+ // truncates the listing; the alternative is re-requesting the same page forever.
69
+ None => ctx.done = true,
61
70
  }
62
71
 
63
72
  for blob in resp.blobs {
@@ -16,7 +16,7 @@
16
16
  // under the License.
17
17
 
18
18
  use super::backend::*;
19
- use super::core::parse_error;
19
+ use super::core::{ErrorContext, parse_error};
20
20
  use http::Response;
21
21
  use http::StatusCode;
22
22
  use opendal_core::raw::*;
@@ -63,7 +63,10 @@ impl oio::StreamRead for VercelBlobReader {
63
63
  _ => {
64
64
  let (part, mut body) = resp.into_parts();
65
65
  let buf = body.to_buffer().await?;
66
- return Err(parse_error(Response::from_parts(part, buf)));
66
+ return Err(parse_error(
67
+ ErrorContext::new(ServiceOperation("DownloadBlob")),
68
+ Response::from_parts(part, buf),
69
+ ));
67
70
  }
68
71
  };
69
72
 
@@ -23,8 +23,8 @@ use http::StatusCode;
23
23
  use super::core::InitiateMultipartUploadResponse;
24
24
  use super::core::Part;
25
25
  use super::core::UploadPartResponse;
26
- use super::core::VercelBlobCore;
27
26
  use super::core::parse_error;
27
+ use super::core::{ErrorContext, VercelBlobCore};
28
28
  use opendal_core::raw::*;
29
29
  use opendal_core::*;
30
30
 
@@ -63,8 +63,11 @@ impl oio::MultipartWrite for VercelBlobWriter {
63
63
  let status = resp.status();
64
64
 
65
65
  match status {
66
- StatusCode::OK => Ok(Metadata::default()),
67
- _ => Err(parse_error(resp)),
66
+ StatusCode::OK => Ok(MetadataBuilder::unknown().build()),
67
+ _ => Err(parse_error(
68
+ ErrorContext::new(ServiceOperation("PutBlob")),
69
+ resp,
70
+ )),
68
71
  }
69
72
  }
70
73
 
@@ -85,7 +88,10 @@ impl oio::MultipartWrite for VercelBlobWriter {
85
88
 
86
89
  Ok(resp.upload_id)
87
90
  }
88
- _ => Err(parse_error(resp)),
91
+ _ => Err(parse_error(
92
+ ErrorContext::new(ServiceOperation("CreateMultipartUpload")),
93
+ resp,
94
+ )),
89
95
  }
90
96
  }
91
97
 
@@ -119,7 +125,10 @@ impl oio::MultipartWrite for VercelBlobWriter {
119
125
  size: None,
120
126
  })
121
127
  }
122
- _ => Err(parse_error(resp)),
128
+ _ => Err(parse_error(
129
+ ErrorContext::new(ServiceOperation("UploadPart")),
130
+ resp,
131
+ )),
123
132
  }
124
133
  }
125
134
 
@@ -144,8 +153,11 @@ impl oio::MultipartWrite for VercelBlobWriter {
144
153
  let status = resp.status();
145
154
 
146
155
  match status {
147
- StatusCode::OK => Ok(Metadata::default()),
148
- _ => Err(parse_error(resp)),
156
+ StatusCode::OK => Ok(MetadataBuilder::unknown().build()),
157
+ _ => Err(parse_error(
158
+ ErrorContext::new(ServiceOperation("CompleteMultipartUpload")),
159
+ resp,
160
+ )),
149
161
  }
150
162
  }
151
163
 
@@ -33,11 +33,11 @@ all-features = true
33
33
 
34
34
  [dependencies]
35
35
  anyhow = { version = "1.0.100", features = ["std"] }
36
+ asyncband = { workspace = true }
36
37
  bytes = { workspace = true }
37
38
  http = { workspace = true }
38
39
  log = { workspace = true }
39
- mea = { workspace = true }
40
- opendal-core = { path = "../../core", version = "0.58.1", default-features = false }
40
+ opendal-core = { path = "../../core", version = "0.59.0", default-features = false }
41
41
  quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
42
42
  serde = { workspace = true, features = ["derive"] }
43
43
 
@@ -273,6 +273,7 @@ impl Service for WebdavBackend {
273
273
  type Lister = oio::PageLister<WebdavLister>;
274
274
  type Deleter = oio::OneShotDeleter<WebdavDeleter>;
275
275
  type Copier = oio::OneShotCopier;
276
+ type Composer = ();
276
277
 
277
278
  fn info(&self) -> ServiceInfo {
278
279
  self.core.info.clone()
@@ -351,27 +352,43 @@ impl Service for WebdavBackend {
351
352
  ctx: &OperationContext,
352
353
  from: &str,
353
354
  to: &str,
354
- _args: OpCopy,
355
- _opts: OpCopier,
355
+ args: OpCopy,
356
356
  ) -> Result<Self::Copier> {
357
+ let backend = self.clone();
357
358
  let core = self.core.clone();
358
359
  let ctx = ctx.clone();
359
360
  let from = from.to_string();
360
361
  let to = to.to_string();
362
+ let source_content_length_hint = args.source_content_length_hint();
361
363
 
362
364
  Ok(oio::OneShotCopier::new_with(move || {
365
+ let backend = backend.clone();
363
366
  let core = core.clone();
364
367
  let ctx = ctx.clone();
365
368
  let from = from.clone();
366
369
  let to = to.clone();
367
370
 
368
371
  async move {
372
+ let source_size = match source_content_length_hint {
373
+ Some(size) => size,
374
+ None => backend
375
+ .stat(&ctx, &from, OpStat::default())
376
+ .await?
377
+ .into_metadata()
378
+ .content_length(),
379
+ };
380
+
369
381
  let resp = core.webdav_copy(&ctx, &from, &to).await?;
370
382
  let status = resp.status();
371
383
 
372
384
  match status {
373
- StatusCode::CREATED | StatusCode::NO_CONTENT => Ok(Metadata::default()),
374
- _ => Err(parse_error(resp)),
385
+ StatusCode::CREATED | StatusCode::NO_CONTENT => {
386
+ Ok(MetadataBuilder::file(source_size).build())
387
+ }
388
+ _ => Err(parse_error(
389
+ ErrorContext::new(ServiceOperation("Copy")),
390
+ resp,
391
+ )),
375
392
  }
376
393
  }
377
394
  }))
@@ -391,7 +408,10 @@ impl Service for WebdavBackend {
391
408
  StatusCode::CREATED | StatusCode::NO_CONTENT | StatusCode::OK => {
392
409
  Ok(RpRename::default())
393
410
  }
394
- _ => Err(parse_error(resp)),
411
+ _ => Err(parse_error(
412
+ ErrorContext::new(ServiceOperation("Move")),
413
+ resp,
414
+ )),
395
415
  }
396
416
  }
397
417