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
@@ -18,8 +18,8 @@
18
18
  use std::fmt::Debug;
19
19
  use std::sync::Arc;
20
20
 
21
+ use asyncband::rwlock::RwLock;
21
22
  use log::debug;
22
- use mea::rwlock::RwLock;
23
23
 
24
24
  use super::SEAFILE_SCHEME;
25
25
  use super::config::SeafileConfig;
@@ -196,6 +196,7 @@ impl Service for SeafileBackend {
196
196
  type Lister = oio::PageLister<SeafileLister>;
197
197
  type Deleter = oio::OneShotDeleter<SeafileDeleter>;
198
198
  type Copier = ();
199
+ type Composer = ();
199
200
 
200
201
  fn info(&self) -> ServiceInfo {
201
202
  self.core.info.clone()
@@ -217,7 +218,7 @@ impl Service for SeafileBackend {
217
218
 
218
219
  async fn stat(&self, ctx: &OperationContext, path: &str, _args: OpStat) -> Result<RpStat> {
219
220
  if path == "/" {
220
- return Ok(RpStat::new(Metadata::new(EntryMode::DIR)));
221
+ return Ok(RpStat::new(MetadataBuilder::dir().build()));
221
222
  }
222
223
 
223
224
  let metadata = if path.ends_with('/') {
@@ -281,7 +282,6 @@ impl Service for SeafileBackend {
281
282
  _from: &str,
282
283
  _to: &str,
283
284
  _args: OpCopy,
284
- _opts: OpCopier,
285
285
  ) -> Result<Self::Copier> {
286
286
  Err(Error::new(
287
287
  ErrorKind::Unsupported,
@@ -18,13 +18,13 @@
18
18
  use std::fmt::Debug;
19
19
  use std::sync::Arc;
20
20
 
21
+ use asyncband::rwlock::RwLock;
21
22
  use bytes::Buf;
22
23
  use bytes::Bytes;
23
24
  use http::Request;
24
25
  use http::Response;
25
26
  use http::StatusCode;
26
27
  use http::header;
27
- use mea::rwlock::RwLock;
28
28
  use serde::Deserialize;
29
29
 
30
30
  use opendal_core::raw::*;
@@ -109,7 +109,10 @@ impl SeafileCore {
109
109
  };
110
110
  }
111
111
  _ => {
112
- return Err(parse_error(resp));
112
+ return Err(parse_error(
113
+ ErrorContext::new(ServiceOperation("AuthToken")),
114
+ resp,
115
+ ));
113
116
  }
114
117
  }
115
118
 
@@ -150,7 +153,10 @@ impl SeafileCore {
150
153
  }
151
154
  }
152
155
  _ => {
153
- return Err(parse_error(resp));
156
+ return Err(parse_error(
157
+ ErrorContext::new(ServiceOperation("ListRepositories")),
158
+ resp,
159
+ ));
154
160
  }
155
161
  }
156
162
  Ok(signer.auth_info.clone())
@@ -185,7 +191,10 @@ impl SeafileCore {
185
191
  .map_err(new_json_deserialize_error)?;
186
192
  Ok(upload_url)
187
193
  }
188
- _ => Err(parse_error(resp)),
194
+ _ => Err(parse_error(
195
+ ErrorContext::new(ServiceOperation("GetUploadLink")),
196
+ resp,
197
+ )),
189
198
  }
190
199
  }
191
200
 
@@ -256,7 +265,10 @@ impl SeafileCore {
256
265
 
257
266
  match resp.status() {
258
267
  StatusCode::OK | StatusCode::CREATED => Ok(()),
259
- _ => Err(parse_error(resp)),
268
+ _ => Err(parse_error(
269
+ ErrorContext::new(ServiceOperation("Mkdir")),
270
+ resp,
271
+ )),
260
272
  }
261
273
  }
262
274
 
@@ -290,7 +302,10 @@ impl SeafileCore {
290
302
 
291
303
  Ok(download_url)
292
304
  }
293
- _ => Err(parse_error(resp)),
305
+ _ => Err(parse_error(
306
+ ErrorContext::new(ServiceOperation("GetDownloadLink")),
307
+ resp,
308
+ )),
294
309
  }
295
310
  }
296
311
 
@@ -344,7 +359,10 @@ impl SeafileCore {
344
359
  .map_err(new_json_deserialize_error)?;
345
360
  Ok(file_detail)
346
361
  }
347
- _ => Err(parse_error(resp)),
362
+ _ => Err(parse_error(
363
+ ErrorContext::new(ServiceOperation("GetFileDetail")),
364
+ resp,
365
+ )),
348
366
  }
349
367
  }
350
368
 
@@ -377,7 +395,10 @@ impl SeafileCore {
377
395
  .map_err(new_json_deserialize_error)?;
378
396
  Ok(dir_detail)
379
397
  }
380
- _ => Err(parse_error(resp)),
398
+ _ => Err(parse_error(
399
+ ErrorContext::new(ServiceOperation("GetDirDetail")),
400
+ resp,
401
+ )),
381
402
  }
382
403
  }
383
404
 
@@ -415,7 +436,10 @@ impl SeafileCore {
415
436
 
416
437
  match status {
417
438
  StatusCode::OK => Ok(()),
418
- _ => Err(parse_error(resp)),
439
+ _ => Err(parse_error(
440
+ ErrorContext::new(ServiceOperation("Delete")),
441
+ resp,
442
+ )),
419
443
  }
420
444
  }
421
445
 
@@ -457,7 +481,10 @@ impl SeafileCore {
457
481
  infos: None,
458
482
  rooted_abs_path,
459
483
  }),
460
- _ => Err(parse_error(resp)),
484
+ _ => Err(parse_error(
485
+ ErrorContext::new(ServiceOperation("ListDir")),
486
+ resp,
487
+ )),
461
488
  }
462
489
  }
463
490
  }
@@ -479,20 +506,18 @@ pub struct DirDetail {
479
506
  }
480
507
 
481
508
  pub fn parse_dir_detail(dir_detail: DirDetail) -> Result<Metadata> {
482
- let mut md = Metadata::new(EntryMode::DIR);
509
+ let mut md = MetadataBuilder::dir();
483
510
 
484
- md.set_last_modified(dir_detail.mtime.parse::<Timestamp>()?);
511
+ md.last_modified(dir_detail.mtime.parse::<Timestamp>()?);
485
512
 
486
- Ok(md)
513
+ Ok(md.build())
487
514
  }
488
515
 
489
516
  pub fn parse_file_detail(file_detail: FileDetail) -> Result<Metadata> {
490
- let mut md = Metadata::new(EntryMode::FILE);
517
+ let mut md = MetadataBuilder::file(file_detail.size);
518
+ md.last_modified(file_detail.last_modified.parse::<Timestamp>()?);
491
519
 
492
- md.set_content_length(file_detail.size);
493
- md.set_last_modified(file_detail.last_modified.parse::<Timestamp>()?);
494
-
495
- Ok(md)
520
+ Ok(md.build())
496
521
  }
497
522
 
498
523
  #[derive(Clone, Default)]
@@ -528,77 +553,78 @@ pub struct ListResponse {
528
553
  pub rooted_abs_path: String,
529
554
  }
530
555
 
531
- mod error {
532
- use bytes::Buf;
533
- use http::Response;
534
- use serde::Deserialize;
556
+ /// the error response of seafile
557
+ #[derive(Default, Debug, Deserialize)]
558
+ #[allow(dead_code)]
559
+ struct SeafileError {
560
+ error_msg: String,
561
+ }
535
562
 
536
- use opendal_core::raw::*;
537
- use opendal_core::*;
563
+ /// Context needed to classify an error from this service.
564
+ #[derive(Clone, Copy, Debug)]
565
+ pub(crate) struct ErrorContext {
566
+ service_operation: ServiceOperation,
567
+ }
538
568
 
539
- /// the error response of seafile
540
- #[derive(Default, Debug, Deserialize)]
541
- #[allow(dead_code)]
542
- struct SeafileError {
543
- error_msg: String,
569
+ impl ErrorContext {
570
+ pub(crate) const fn new(service_operation: ServiceOperation) -> Self {
571
+ Self { service_operation }
544
572
  }
573
+ }
545
574
 
546
- /// Parse error response into Error.
547
- pub(crate) fn parse_error(resp: Response<Buffer>) -> Error {
548
- let (parts, body) = resp.into_parts();
549
- let bs = body.to_bytes();
575
+ /// Parse an error response using its service request context.
576
+ pub(crate) fn parse_error(ctx: ErrorContext, resp: Response<Buffer>) -> Error {
577
+ let (parts, body) = resp.into_parts();
578
+ let bs = body.to_bytes();
550
579
 
551
- let (kind, _retryable) = match parts.status.as_u16() {
552
- 403 => (ErrorKind::PermissionDenied, false),
553
- 404 => (ErrorKind::NotFound, false),
554
- 520 => (ErrorKind::Unexpected, false),
555
- _ => (ErrorKind::Unexpected, false),
556
- };
580
+ let (kind, _retryable) = match parts.status.as_u16() {
581
+ 403 => (ErrorKind::PermissionDenied, false),
582
+ 404 => (ErrorKind::NotFound, false),
583
+ 520 => (ErrorKind::Unexpected, false),
584
+ _ => (ErrorKind::Unexpected, false),
585
+ };
557
586
 
558
- let (message, _seafile_err) =
559
- serde_json::from_reader::<_, SeafileError>(bs.clone().reader())
560
- .map(|seafile_err| (format!("{seafile_err:?}"), Some(seafile_err)))
561
- .unwrap_or_else(|_| (String::from_utf8_lossy(&bs).into_owned(), None));
587
+ let (message, _seafile_err) = serde_json::from_reader::<_, SeafileError>(bs.clone().reader())
588
+ .map(|seafile_err| (format!("{seafile_err:?}"), Some(seafile_err)))
589
+ .unwrap_or_else(|_| (String::from_utf8_lossy(&bs).into_owned(), None));
562
590
 
563
- let mut err = Error::new(kind, message);
591
+ let mut err = Error::new(kind, message);
564
592
 
565
- err = with_error_response_context(err, parts);
593
+ err = err.with_context("service_operation", ctx.service_operation.0);
594
+ err = with_error_response_context(err, parts);
566
595
 
567
- err
568
- }
596
+ err
597
+ }
569
598
 
570
- #[cfg(test)]
571
- mod test {
572
- use http::StatusCode;
573
-
574
- use super::*;
575
-
576
- #[tokio::test]
577
- async fn test_parse_error() {
578
- let err_res = vec![
579
- (
580
- r#"{"error_msg": "Permission denied"}"#,
581
- ErrorKind::PermissionDenied,
582
- StatusCode::FORBIDDEN,
583
- ),
584
- (
585
- r#"{"error_msg": "Folder /e982e75a-fead-487c-9f41-63094d9bf0de/a9d867b9-778d-4612-b674-47e674c14c28/ not found."}"#,
586
- ErrorKind::NotFound,
587
- StatusCode::NOT_FOUND,
588
- ),
589
- ];
590
-
591
- for res in err_res {
592
- let bs = bytes::Bytes::from(res.0);
593
- let body = Buffer::from(bs);
594
- let resp = Response::builder().status(res.2).body(body).unwrap();
595
-
596
- let err = parse_error(resp);
597
-
598
- assert_eq!(err.kind(), res.1);
599
- }
599
+ #[cfg(test)]
600
+ mod tests {
601
+ use http::StatusCode;
602
+
603
+ use super::*;
604
+
605
+ #[tokio::test]
606
+ async fn test_parse_error() {
607
+ let err_res = vec![
608
+ (
609
+ r#"{"error_msg": "Permission denied"}"#,
610
+ ErrorKind::PermissionDenied,
611
+ StatusCode::FORBIDDEN,
612
+ ),
613
+ (
614
+ r#"{"error_msg": "Folder /e982e75a-fead-487c-9f41-63094d9bf0de/a9d867b9-778d-4612-b674-47e674c14c28/ not found."}"#,
615
+ ErrorKind::NotFound,
616
+ StatusCode::NOT_FOUND,
617
+ ),
618
+ ];
619
+
620
+ for res in err_res {
621
+ let bs = bytes::Bytes::from(res.0);
622
+ let body = Buffer::from(bs);
623
+ let resp = Response::builder().status(res.2).body(body).unwrap();
624
+
625
+ let err = parse_error(ErrorContext::new(ServiceOperation("Test")), resp);
626
+
627
+ assert_eq!(err.kind(), res.1);
600
628
  }
601
629
  }
602
630
  }
603
-
604
- pub(super) use error::*;
@@ -47,7 +47,7 @@ impl oio::PageList for SeafileLister {
47
47
  // add path itself
48
48
  ctx.entries.push_back(Entry::new(
49
49
  self.path.as_str(),
50
- Metadata::new(EntryMode::DIR),
50
+ MetadataBuilder::dir().build(),
51
51
  ));
52
52
 
53
53
  for info in infos {
@@ -58,15 +58,18 @@ impl oio::PageList for SeafileLister {
58
58
  );
59
59
 
60
60
  let entry = if info.type_field == "file" {
61
- let mut meta = Metadata::new(EntryMode::FILE)
62
- .with_last_modified(Timestamp::from_second(info.mtime)?);
63
- if let Some(size) = info.size {
64
- meta.set_content_length(size);
65
- }
66
- Entry::new(&rel_path, meta)
61
+ let size = info.size.ok_or_else(|| {
62
+ Error::new(
63
+ ErrorKind::Unexpected,
64
+ "seafile list response does not contain file size",
65
+ )
66
+ })?;
67
+ let mut meta = MetadataBuilder::file(size);
68
+ meta.last_modified(Timestamp::from_second(info.mtime)?);
69
+ Entry::new(&rel_path, meta.build())
67
70
  } else {
68
71
  let path = format!("{rel_path}/");
69
- Entry::new(&path, Metadata::new(EntryMode::DIR))
72
+ Entry::new(&path, MetadataBuilder::dir().build())
70
73
  };
71
74
 
72
75
  ctx.entries.push_back(entry);
@@ -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::*;
@@ -60,7 +60,10 @@ impl oio::StreamRead for SeafileReader {
60
60
  _ => {
61
61
  let (part, mut body) = resp.into_parts();
62
62
  let buf = body.to_buffer().await?;
63
- return Err(parse_error(Response::from_parts(part, buf)));
63
+ return Err(parse_error(
64
+ ErrorContext::new(ServiceOperation("DownloadFile")),
65
+ Response::from_parts(part, buf),
66
+ ));
64
67
  }
65
68
  };
66
69
 
@@ -19,8 +19,8 @@ use std::sync::Arc;
19
19
 
20
20
  use http::StatusCode;
21
21
 
22
- use super::core::SeafileCore;
23
22
  use super::core::parse_error;
23
+ use super::core::{ErrorContext, SeafileCore};
24
24
  use opendal_core::raw::*;
25
25
  use opendal_core::*;
26
26
 
@@ -50,8 +50,11 @@ impl oio::OneShotWrite for SeafileWriter {
50
50
 
51
51
  let status = resp.status();
52
52
  match status {
53
- StatusCode::OK => Ok(Metadata::default()),
54
- _ => Err(parse_error(resp)),
53
+ StatusCode::OK => Ok(MetadataBuilder::unknown().build()),
54
+ _ => Err(parse_error(
55
+ ErrorContext::new(ServiceOperation("UploadFile")),
56
+ resp,
57
+ )),
55
58
  }
56
59
  }
57
60
  }
@@ -32,7 +32,7 @@ version = { workspace = true }
32
32
  all-features = true
33
33
 
34
34
  [dependencies]
35
- opendal-core = { path = "../../core", version = "0.58.1", default-features = false }
35
+ opendal-core = { path = "../../core", version = "0.59.0", default-features = false }
36
36
 
37
37
  bytes = { workspace = true }
38
38
  fastpool = "1.0.2"
@@ -208,6 +208,7 @@ impl Service for SftpBackend {
208
208
  type Lister = SftpLazyLister;
209
209
  type Deleter = oio::OneShotDeleter<SftpDeleter>;
210
210
  type Copier = oio::OneShotCopier;
211
+ type Composer = ();
211
212
 
212
213
  fn info(&self) -> ServiceInfo {
213
214
  self.core.info.clone()
@@ -250,7 +251,7 @@ impl Service for SftpBackend {
250
251
  let mut fs = client.fs();
251
252
  fs.set_cwd(&self.core.root);
252
253
 
253
- let meta: Metadata = to_metadata(fs.metadata(path).await.map_err(parse_sftp_error)?);
254
+ let meta: Metadata = to_metadata(fs.metadata(path).await.map_err(parse_sftp_error)?)?;
254
255
 
255
256
  Ok(RpStat::new(meta))
256
257
  }
@@ -289,8 +290,7 @@ impl Service for SftpBackend {
289
290
  ctx: &OperationContext,
290
291
  from: &str,
291
292
  to: &str,
292
- _: OpCopy,
293
- _opts: OpCopier,
293
+ args: OpCopy,
294
294
  ) -> Result<Self::Copier> {
295
295
  let backend = self.clone();
296
296
  let ctx = ctx.clone();
@@ -313,12 +313,27 @@ impl Service for SftpBackend {
313
313
  let mut src_file = client.open(&src).await.map_err(parse_sftp_error)?;
314
314
  let mut dst_file = client.create(dst).await.map_err(parse_sftp_error)?;
315
315
 
316
+ let source_size = match args.source_content_length_hint() {
317
+ Some(size) => size,
318
+ None => src_file
319
+ .metadata()
320
+ .await
321
+ .map_err(parse_sftp_error)?
322
+ .len()
323
+ .ok_or_else(|| {
324
+ Error::new(
325
+ ErrorKind::Unexpected,
326
+ "sftp source metadata does not contain file length",
327
+ )
328
+ })?,
329
+ };
330
+
316
331
  src_file
317
332
  .copy_all_to(&mut dst_file)
318
333
  .await
319
334
  .map_err(parse_sftp_error)?;
320
335
 
321
- Ok(Metadata::default())
336
+ Ok(MetadataBuilder::file(source_size).build())
322
337
  }))
323
338
  }
324
339
 
@@ -160,63 +160,63 @@ impl ManageObject for Manager {
160
160
  }
161
161
  }
162
162
 
163
- mod error {
164
- use openssh::Error as SshError;
165
- use openssh_sftp_client::Error as SftpClientError;
166
- use openssh_sftp_client::error::SftpErrorKind;
167
-
168
- use opendal_core::Error;
169
- use opendal_core::ErrorKind;
170
-
171
- pub fn parse_sftp_error(e: SftpClientError) -> Error {
172
- let kind = match &e {
173
- SftpClientError::UnsupportedSftpProtocol { version: _ } => ErrorKind::Unsupported,
174
- SftpClientError::SftpError(kind, _msg) => match kind {
175
- SftpErrorKind::NoSuchFile => ErrorKind::NotFound,
176
- SftpErrorKind::PermDenied => ErrorKind::PermissionDenied,
177
- SftpErrorKind::OpUnsupported => ErrorKind::Unsupported,
178
- _ => ErrorKind::Unexpected,
179
- },
163
+ use openssh::Error as SshError;
164
+ use openssh_sftp_client::Error as SftpClientError;
165
+ use openssh_sftp_client::error::SftpErrorKind;
166
+
167
+ use opendal_core::Error;
168
+ use opendal_core::ErrorKind;
169
+
170
+ pub fn parse_sftp_error(e: SftpClientError) -> Error {
171
+ let kind = match &e {
172
+ SftpClientError::UnsupportedSftpProtocol { version: _ } => ErrorKind::Unsupported,
173
+ SftpClientError::SftpError(kind, _msg) => match kind {
174
+ SftpErrorKind::NoSuchFile => ErrorKind::NotFound,
175
+ SftpErrorKind::PermDenied => ErrorKind::PermissionDenied,
176
+ SftpErrorKind::OpUnsupported => ErrorKind::Unsupported,
180
177
  _ => ErrorKind::Unexpected,
181
- };
178
+ },
179
+ _ => ErrorKind::Unexpected,
180
+ };
182
181
 
183
- let mut err = Error::new(kind, "sftp error").set_source(e);
182
+ let mut err = Error::new(kind, "sftp error").set_source(e);
184
183
 
185
- // Mark error as temporary if it's unexpected.
186
- if kind == ErrorKind::Unexpected {
187
- err = err.set_temporary();
188
- }
189
-
190
- err
184
+ // Mark error as temporary if it's unexpected.
185
+ if kind == ErrorKind::Unexpected {
186
+ err = err.set_temporary();
191
187
  }
192
188
 
193
- pub fn parse_ssh_error(e: SshError) -> Error {
194
- Error::new(ErrorKind::Unexpected, "ssh error").set_source(e)
195
- }
189
+ err
190
+ }
196
191
 
197
- pub(crate) fn is_not_found(e: &SftpClientError) -> bool {
198
- matches!(e, SftpClientError::SftpError(SftpErrorKind::NoSuchFile, _))
199
- }
192
+ pub fn parse_ssh_error(e: SshError) -> Error {
193
+ Error::new(ErrorKind::Unexpected, "ssh error").set_source(e)
194
+ }
200
195
 
201
- pub(crate) fn is_sftp_protocol_error(e: &SftpClientError) -> bool {
202
- matches!(e, SftpClientError::SftpError(_, _))
203
- }
196
+ pub(crate) fn is_not_found(e: &SftpClientError) -> bool {
197
+ matches!(e, SftpClientError::SftpError(SftpErrorKind::NoSuchFile, _))
198
+ }
204
199
 
205
- pub(crate) fn is_sftp_failure(e: &SftpClientError) -> bool {
206
- matches!(e, SftpClientError::SftpError(SftpErrorKind::Failure, _))
207
- }
200
+ pub(crate) fn is_sftp_protocol_error(e: &SftpClientError) -> bool {
201
+ matches!(e, SftpClientError::SftpError(_, _))
208
202
  }
209
203
 
210
- pub(super) use error::*;
204
+ pub(crate) fn is_sftp_failure(e: &SftpClientError) -> bool {
205
+ matches!(e, SftpClientError::SftpError(SftpErrorKind::Failure, _))
206
+ }
211
207
 
212
208
  mod utils {
213
209
  use openssh_sftp_client::metadata::MetaData as SftpMeta;
214
210
 
215
211
  use opendal_core::EntryMode;
212
+ use opendal_core::Error;
213
+ use opendal_core::ErrorKind;
216
214
  use opendal_core::Metadata;
215
+ use opendal_core::MetadataBuilder;
216
+ use opendal_core::Result;
217
217
  use opendal_core::raw::Timestamp;
218
218
 
219
- pub fn to_metadata(meta: SftpMeta) -> Metadata {
219
+ pub fn to_metadata(meta: SftpMeta) -> Result<Metadata> {
220
220
  let mode = meta
221
221
  .file_type()
222
222
  .map(|filetype| {
@@ -230,19 +230,24 @@ mod utils {
230
230
  })
231
231
  .unwrap_or(EntryMode::Unknown);
232
232
 
233
- let mut metadata = Metadata::new(mode);
234
-
235
- if let Some(size) = meta.len() {
236
- metadata.set_content_length(size);
237
- }
233
+ let mut metadata = match mode {
234
+ EntryMode::FILE => MetadataBuilder::file(meta.len().ok_or_else(|| {
235
+ Error::new(
236
+ ErrorKind::Unexpected,
237
+ "sftp metadata does not contain file length",
238
+ )
239
+ })?),
240
+ EntryMode::DIR => MetadataBuilder::dir(),
241
+ EntryMode::Unknown => MetadataBuilder::unknown(),
242
+ };
238
243
 
239
244
  if let Some(modified) = meta.modified()
240
245
  && let Ok(m) = Timestamp::try_from(modified.as_system_time())
241
246
  {
242
- metadata.set_last_modified(m);
247
+ metadata.last_modified(m);
243
248
  }
244
249
 
245
- metadata
250
+ Ok(metadata.build())
246
251
  }
247
252
  }
248
253
 
@@ -62,9 +62,9 @@ impl oio::List for SftpLister {
62
62
  if self.prefix.is_empty() {
63
63
  path = "/";
64
64
  }
65
- return Ok(Some(Entry::new(path, to_metadata(e.metadata()))));
65
+ return Ok(Some(Entry::new(path, to_metadata(e.metadata())?)));
66
66
  } else {
67
- return Ok(Some(map_entry(self.prefix.as_str(), e)));
67
+ return Ok(Some(map_entry(self.prefix.as_str(), e)?));
68
68
  }
69
69
  }
70
70
  None => return Ok(None),
@@ -73,7 +73,7 @@ impl oio::List for SftpLister {
73
73
  }
74
74
  }
75
75
 
76
- fn map_entry(prefix: &str, value: DirEntry) -> Entry {
76
+ fn map_entry(prefix: &str, value: DirEntry) -> Result<Entry> {
77
77
  let path = format!(
78
78
  "{}{}{}",
79
79
  prefix,
@@ -85,5 +85,5 @@ fn map_entry(prefix: &str, value: DirEntry) -> Entry {
85
85
  }
86
86
  );
87
87
 
88
- Entry::new(path.as_str(), to_metadata(value.metadata()))
88
+ Ok(Entry::new(path.as_str(), to_metadata(value.metadata())?))
89
89
  }
@@ -55,7 +55,7 @@ impl oio::Write for SftpWriter {
55
55
  async fn close(&mut self) -> Result<Metadata> {
56
56
  self.file.shutdown().await.map_err(new_std_io_error)?;
57
57
 
58
- Ok(Metadata::default())
58
+ Ok(MetadataBuilder::unknown().build())
59
59
  }
60
60
 
61
61
  async fn abort(&mut self) -> Result<()> {
@@ -32,7 +32,7 @@ version = { workspace = true }
32
32
  all-features = true
33
33
 
34
34
  [dependencies]
35
- opendal-core = { path = "../../core", version = "0.58.1", default-features = false }
35
+ opendal-core = { path = "../../core", version = "0.59.0", default-features = false }
36
36
  serde = { workspace = true, features = ["derive"] }
37
37
  sled = "0.34.7"
38
38