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
@@ -15,80 +15,64 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- //! The internal implementation details of [`Layer`].
18
+ //! Implementing a layer.
19
19
  //!
20
- //! OpenDAL has one layer composition surface:
20
+ //! A [`Layer`] intercepts an operator's composed service, operation context,
21
+ //! or both. Use a layer for behavior that applies across services, such as
22
+ //! retry, timeout, tracing, metrics, or runtime resource replacement.
21
23
  //!
22
- //! - [`Layer`] receives an already erased [`ServiceDyn`] stack and can wrap the
23
- //! service or its [`OperationContext`].
24
- //! - Layer wrappers still implement typed [`Service`], so their own reader,
25
- //! writer, lister, deleter, and copier bodies stay concrete.
26
- //! - The composition boundary is [`Servicer`]. Boxing operation
27
- //! bodies remains centralized in the blanket [`ServiceDyn`] implementation
28
- //! for typed [`Service`] values.
24
+ //! # Two composition hooks
29
25
  //!
30
- //! [`Layer`] itself is the runtime hook surface. Every hook returns `inner` by
31
- //! default, so a layer only implements the plane it needs:
26
+ //! [`Layer`] exposes two hooks:
32
27
  //!
33
- //! ```ignore
34
- //! pub trait Layer: Send + Sync + Debug + Unpin + 'static {
35
- //! fn apply_service(&self, srv: Servicer) -> Servicer;
36
- //! fn apply_context(&self, srv: Servicer, inner: OperationContext) -> OperationContext;
37
- //! }
28
+ //! ```text
29
+ //! fn apply_service(&self, service: Servicer) -> Servicer;
30
+ //! fn apply_context(
31
+ //! &self,
32
+ //! service: Servicer,
33
+ //! context: OperationContext,
34
+ //! ) -> OperationContext;
38
35
  //! ```
39
36
  //!
40
- //! [`Operator`] replays the same ordered layer list over the base service and
41
- //! base [`OperationContext`]. It first composes the operation service stack.
42
- //! Then context hooks receive the final [`Servicer`] and compose runtime
43
- //! resources such as HTTP transport and executor. The composed context is passed
44
- //! to service operations.
37
+ //! `apply_service` wraps storage operations. `apply_context` wraps or replaces
38
+ //! runtime resources such as the HTTP transport and executor. Each hook
39
+ //! returns its input unchanged by default, so a layer implements only the
40
+ //! plane it owns.
45
41
  //!
46
- //! An operation layer normally has two parts:
42
+ //! The operator first applies every service hook in insertion order. It then
43
+ //! applies every context hook in the same order, passing the final service
44
+ //! stack to each context hook. Adding a layer or replacing the base context
45
+ //! replays the complete layer list, producing a service stack and context from
46
+ //! the same ordering.
47
47
  //!
48
- //! - `XxxLayer` implements [`Layer`] and returns a typed service wrapper from
49
- //! `apply_service`.
50
- //! - `XxxService` stores the inner [`Servicer`] and implements [`Service`].
48
+ //! # Operation layers
51
49
  //!
52
- //! ```ignore
53
- //! pub struct XxxLayer;
50
+ //! An operation layer normally contains:
54
51
  //!
55
- //! impl Layer for XxxLayer {
56
- //! fn apply_service(&self, inner: Servicer) -> Servicer {
57
- //! Arc::new(XxxService { inner })
58
- //! }
59
- //! }
60
- //! ```
61
- //!
62
- //! Most operation layers only override the operations they need and forward the
63
- //! rest to `inner`. This works because [`Servicer`] implements [`Service`] by
64
- //! forwarding calls to [`ServiceDyn`], while the wrapper keeps concrete
65
- //! operation body types until it is returned as a [`Servicer`].
52
+ //! - An `XxxLayer` that implements [`Layer::apply_service`].
53
+ //! - An `XxxService` that stores the inner [`Servicer`] and implements
54
+ //! [`Service`].
66
55
  //!
67
- //! Resource-only layers can implement only `apply_context`. If they do not need
68
- //! the final service stack, they should name that parameter `_srv`.
56
+ //! The wrapper overrides only the operations it owns and forwards the rest to
57
+ //! the inner service. It must also return capabilities that describe the
58
+ //! behavior of the wrapped stack. The wrapper keeps its own operation body
59
+ //! types concrete until OpenDAL erases it back into a [`Servicer`].
69
60
  //!
70
- //! ```ignore
71
- //! pub struct TransportLayer {
72
- //! transport: HttpTransporter,
73
- //! }
61
+ //! # Resource layers
74
62
  //!
75
- //! impl Layer for TransportLayer {
76
- //! fn apply_context(&self, _srv: Servicer, inner: OperationContext) -> OperationContext {
77
- //! inner.with_http_transport(self.transport.clone())
78
- //! }
79
- //! }
80
- //! ```
63
+ //! A resource-only layer implements [`Layer::apply_context`]. It should
64
+ //! preserve the previous resource when lower layers must remain effective. A
65
+ //! layer that wraps an HTTP transport or executor must decide explicitly
66
+ //! whether requests continue through the previous value or replace it
67
+ //! entirely.
81
68
  //!
82
- //! Layers that need consistent policy across planes can implement both hooks,
83
- //! for example operation and I/O timeout handling. Resource wrappers that
84
- //! replace HTTP transport or executor must forward to the previous value when
85
- //! they want lower layers to remain effective.
69
+ //! Layers that coordinate policy across operation and I/O phases can implement
70
+ //! both hooks. Shared mutable state requires interior mutability and must
71
+ //! remain `Send` and `Sync`, because cloned operators can run operations
72
+ //! concurrently.
86
73
  //!
87
74
  //! [`Layer`]: crate::raw::Layer
75
+ //! [`Layer::apply_service`]: crate::raw::Layer::apply_service
76
+ //! [`Layer::apply_context`]: crate::raw::Layer::apply_context
88
77
  //! [`Service`]: crate::raw::Service
89
- //! [`ServiceDyn`]: crate::raw::ServiceDyn
90
78
  //! [`Servicer`]: crate::raw::Servicer
91
- //! [`HttpTransporter`]: crate::HttpTransporter
92
- //! [`Executor`]: crate::Executor
93
- //! [`OperationContext`]: crate::raw::OperationContext
94
- //! [`Operator`]: crate::Operator
@@ -17,37 +17,35 @@
17
17
 
18
18
  //! The internal implementation details of OpenDAL.
19
19
  //!
20
- //! OpenDAL provides unified abstraction via two-level API sets:
20
+ //! This guide explains the extension boundaries used to implement OpenDAL
21
+ //! storage services and layers. Application code should use the public
22
+ //! [`Operator`] API; the raw APIs described here can change between minor
23
+ //! releases.
21
24
  //!
22
- //! - Public API like [`Operator`] provides user-level API.
23
- //! - Raw API like [`Service`], [`Layer`] provides developer-level API.
24
- //!
25
- //! OpenDAL tries its best to keep the public API stable. But raw APIs
26
- //! may change between minor releases from time to time. So most users
27
- //! should only use the public API. Developers use raw APIs to implement
28
- //! storage services or their own [`Layer`].
29
- //!
30
- //! In this section, we will talk about the following components:
31
- //!
32
- //! - [`Service`][accessor]: to connect underlying storage services.
33
- //! - [`Layer`][layer]: middleware/interceptor between storage services.
34
- //!
35
- //! The relation between [`Service`], [`Layer`], [`Servicer`], [`OperationContext`],
36
- //! and [`Operator`] looks like the following:
25
+ //! OpenDAL keeps service implementations typed until it composes them into an
26
+ //! operator:
37
27
  //!
38
28
  //! ```text
39
- //! ┌──────────────┐ ┌──────────────────────────────┐ ┌──────────────┐
40
- //! │ Service │ │ Servicer │ │ Operator │
41
- //! │ builders ├────►│ + Layer::apply_* replay ├────►│ srv + ctx │
42
- //! └──────────────┘ │ + OperationContext resources │ └──────────────┘
43
- //! └──────────────────────────────┘
29
+ //! Builder -> Service -> ServiceDyn -> Servicer -> Layer stack -> Operator
30
+ //! ^ |
31
+ //! +------ type erasure ------+
44
32
  //! ```
45
33
  //!
46
- //! [`Builder`]: crate::Builder
34
+ //! - A [`Service`] implements storage operations and reports the capabilities
35
+ //! it provides.
36
+ //! - [`ServiceDyn`] is the object-safe boundary that erases a typed service
37
+ //! and its operation bodies.
38
+ //! - A [`Servicer`] is the shared, type-erased service handle stored by
39
+ //! operators and layers.
40
+ //! - A [`Layer`] wraps the service stack, the operation context, or both.
41
+ //!
42
+ //! Continue with [implementing a service][accessor] or
43
+ //! [implementing a layer][layer].
44
+ //!
47
45
  //! [`Operator`]: crate::Operator
48
46
  //! [`Service`]: crate::raw::Service
47
+ //! [`ServiceDyn`]: crate::raw::ServiceDyn
49
48
  //! [`Servicer`]: crate::raw::Servicer
50
- //! [`OperationContext`]: crate::raw::OperationContext
51
49
  //! [`Layer`]: crate::raw::Layer
52
50
 
53
51
  pub mod accessor;
@@ -15,29 +15,33 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- //! This module holds documentation for OpenDAL.
18
+ //! OpenDAL contracts, Rust core guides, and historical project documents.
19
19
  //!
20
- //! It's highly recommended that you start by reading [`concepts`] first.
20
+ //! Start with [`concepts`] for the Rust core API model. [`specs`] defines the
21
+ //! current portable contracts implemented by OpenDAL. Service and layer authors
22
+ //! can continue with [`internals`], while [`performance`] covers application
23
+ //! tuning. Accepted RFCs in [`rfcs`] preserve the decisions and context that
24
+ //! led to current designs.
21
25
 
22
26
  #![allow(rustdoc::bare_urls)]
23
27
 
24
- pub mod comparisons;
25
-
26
28
  pub mod concepts;
27
-
28
29
  pub mod internals;
29
-
30
30
  pub mod performance;
31
+ pub mod specs;
31
32
 
32
33
  /// Changes log for all OpenDAL released versions.
33
34
  #[doc = include_str!("../../../CHANGELOG.md")]
34
35
  #[cfg(not(doctest))]
36
+ #[allow(rustdoc::broken_intra_doc_links, rustdoc::invalid_rust_codeblocks)]
35
37
  pub mod changelog {}
36
38
 
37
39
  #[cfg(not(doctest))]
40
+ #[allow(rustdoc::broken_intra_doc_links, rustdoc::invalid_rust_codeblocks)]
38
41
  pub mod rfcs;
39
42
 
40
43
  /// Upgrade and migrate procedures while OpenDAL meets breaking changes.
41
44
  #[doc = include_str!("upgrade.md")]
42
45
  #[cfg(not(doctest))]
46
+ #[allow(rustdoc::broken_intra_doc_links, rustdoc::invalid_rust_codeblocks)]
43
47
  pub mod upgrade {}
@@ -1,101 +1,138 @@
1
- # Concurrent Write
1
+ # Concurrent Writes
2
2
 
3
- OpenDAL writes data sequentially by default.
3
+ OpenDAL writes parts sequentially by default. This keeps memory and request
4
+ pressure low, but one in-flight request often cannot fill the available
5
+ bandwidth on a high-latency path.
4
6
 
5
7
  ```rust
6
- # use opendal::Operator;
7
- # async fn test() {
8
- let w = op.writer("test.txt").await?;
9
- w.write(data1).await?;
10
- w.write(data2).await?;
11
- w.close().await?;
8
+ # use opendal_core::{Buffer, Operator, Result};
9
+ # async fn write_sequentially(
10
+ # op: &Operator,
11
+ # first: Buffer,
12
+ # second: Buffer,
13
+ # ) -> Result<()> {
14
+ let mut writer = op.writer("large-object.bin").await?;
15
+ writer.write(first).await?;
16
+ writer.write(second).await?;
17
+ writer.close().await?;
18
+ # Ok(())
12
19
  # }
13
20
  ```
14
21
 
15
- Most of the time, this can't maximize write performance due to limitations on a single connection. We can perform concurrent writes to improve performance.
22
+ Set `concurrent` above `1` to let services with multipart or block-based write
23
+ support upload independent parts in parallel:
16
24
 
17
25
  ```rust
18
- # use opendal::Operator;
19
- # async fn test() {
20
- let w = op
21
- .writer_with("test.txt")
26
+ # use opendal_core::{Buffer, Operator, Result};
27
+ # async fn write_concurrently(
28
+ # op: &Operator,
29
+ # first: Buffer,
30
+ # second: Buffer,
31
+ # ) -> Result<()> {
32
+ let mut writer = op
33
+ .writer_with("large-object.bin")
22
34
  .concurrent(8)
23
35
  .await?;
24
36
 
25
- w.write(data1).await?;
26
- w.write(data2).await?;
27
- w.close().await?;
37
+ writer.write(first).await?;
38
+ writer.write(second).await?;
39
+ writer.close().await?;
40
+ # Ok(())
28
41
  # }
29
42
  ```
30
43
 
31
- After setting `concurrent`, OpenDAL will attempt to write the specified file concurrently. The maximum level of concurrency is determined by the `concurrent` parameter. By default, it is set to 1, indicating a sequential write operation.
44
+ For multipart and block writers, OpenDAL schedules part uploads through its
45
+ [`Executor`][crate::Executor] and tracks their results in a task queue. A write
46
+ call can return while earlier parts are still in flight when the queue has
47
+ capacity. [`Writer::close`][crate::Writer::close] drains the queue and performs
48
+ the final commit, so applications must always check the result from `close`.
32
49
 
33
- Under the hood, OpenDAL maintains a task queue to manage concurrent writes. It spawns asynchronous tasks in the background using the [`Executor`][crate::Executor] and tracks the status of each task. The task queue is flushed when the writer is closed, allowing data to be written concurrently without blocking the main thread.
34
-
35
- Take our example here, the write of `data1` will not block the write of `data2`. The two writes will be executed concurrently.
36
-
37
- The underlying implementation of concurrent writes may vary depending on the backend. For instance, the `s3` backend leverages the S3 Multipart Uploads API to handle concurrent writes, while the `azblob` backend utilizes the Block API for the same purpose.
50
+ The storage service determines the native mechanism. S3 uses multipart upload,
51
+ while Azure Blob uses block upload. Services without a concurrent write path
52
+ continue to execute sequentially even when the option is present. Check
53
+ [`Capability::write_can_multi`][crate::Capability::write_can_multi] before
54
+ tuning multipart or block writes.
38
55
 
39
56
  ## Tuning
40
57
 
41
- There are two parameters that can be tuned to optimize concurrent writes:
58
+ Concurrent writes have two controls:
42
59
 
43
- - `concurrent`: This parameter controls the maximum number of concurrent writes. The default value is 1.
44
- - `chunk`: This parameter specifies the size of each chunk of data to be written. The default value is vary for different storage services.
60
+ - `concurrent` is the maximum number of part uploads OpenDAL attempts to keep
61
+ in flight. The default is `1`, and values below `1` are normalized to `1`.
62
+ - `chunk` is the target size of each part. Its default and valid range depend on
63
+ the service.
45
64
 
46
65
  ### `concurrent`
47
66
 
48
- The most important thing to understand is that `concurrent` is not a strict limit. It represents the maximum number of concurrent writes that OpenDAL will attempt to perform. The actual number of concurrent writes may be lower, depending on the input data throughput.
49
-
50
- For example, if you set `concurrent` to 8, OpenDAL will attempt to perform up to 8 concurrent writes. However, if the input data throughput is low, it might only carry out 2 or 3 concurrent writes at a time, as there isn't enough data to keep all 8 writes active.
51
-
52
- The best value for `concurrent` depends on the specific use case and the underlying storage service. In general, a higher value can lead to better performance, but it highly depends on the storage service and the network conditions. For example, if the storage service is robust and bandwidth is sufficient, you may observe a linear increase in performance with higher `concurrent` values. However, if the storage service has request limits or the network is nearly saturated, increasing `concurrent` may not lead to any performance improvement—and could even degrade performance due to infinite retries on errors.
67
+ `concurrent` is an upper bound, not a guaranteed level. Setting it to `8` does
68
+ not create eight active requests unless the input arrives quickly enough and
69
+ the object contains enough parts. Object size, request latency, and service
70
+ support can all reduce the observed concurrency.
53
71
 
54
- It's recommended to start with a lower value like `2` or `4` and gradually increase it while monitoring performance and resource usage.
72
+ Start with `2` or `4`, then try `8` while measuring the real workload. Higher
73
+ concurrency can improve bandwidth utilization, but it also increases in-flight
74
+ requests, buffered data, and pressure on service request limits. Once the
75
+ network or service is saturated, increasing it further can reduce throughput by
76
+ causing throttling and retries.
55
77
 
56
78
  ### `chunk`
57
79
 
58
- The `chunk` parameter specifies the size of each chunk of data to be written. A larger chunk size can improve performance, but it may also increase memory usage. The default value is vary for different storage services.
80
+ OpenDAL buffers small writes until it can form a part of the configured size.
81
+ This avoids issuing one storage request for every small input buffer. The final
82
+ part may be smaller.
59
83
 
60
- For example, s3 is using `5MiB` as the default chunk size. It's also the minimum chunk size for s3. If you set a smaller chunk size, OpenDAL will automatically adjust it to `5MiB`.
84
+ Larger chunks reduce request count and per-request overhead, but use more memory
85
+ per in-flight part and require more data to be retried after a failed upload.
86
+ Smaller chunks begin parallel work sooner, but increase request rate and may be
87
+ invalid for the service. For example, S3 multipart upload has a 5 MiB minimum
88
+ part size; OpenDAL raises smaller configured values to the service minimum.
61
89
 
62
- The best value for `chunk` depends on the specific use case and the underlying storage service. For most object storage services, a chunk size of `8MiB` or larger is recommended. However, if you're working with smaller files or have limited memory resources, you may want to use a smaller chunk size.
90
+ Inspect [`Capability::write_multi_min_size`][crate::Capability::write_multi_min_size]
91
+ and [`Capability::write_multi_max_size`][crate::Capability::write_multi_max_size]
92
+ before overriding the service default. For large object-storage uploads, 8 MiB
93
+ is a useful starting point, followed by measurements at the expected object
94
+ sizes and concurrency.
63
95
 
64
- Please note that if you input small chunks of data, OpenDAL will attempt to merge them into a larger chunk before writing. This helps avoid the overhead of writing numerous small chunks, which can negatively affect performance.
96
+ ## One-shot and adapter APIs
65
97
 
66
- ## Usage
67
-
68
- To upload a large in-memory chunk concurrently:
98
+ `write_with` can split one in-memory buffer into concurrent parts:
69
99
 
70
100
  ```rust
71
- # use opendal::Operator;
72
- # async fn test() {
73
- let data = vec![0; 10 * 1024 * 1024]; // 10MiB
74
- let _ = op.write_with("test.txt", data).concurrent(4).await?;
101
+ # use opendal_core::{Buffer, Operator, Result};
102
+ # async fn upload(op: &Operator, data: Buffer) -> Result<()> {
103
+ let _metadata = op
104
+ .write_with("large-object.bin", data)
105
+ .chunk(8 * 1024 * 1024)
106
+ .concurrent(4)
107
+ .await?;
108
+ # Ok(())
75
109
  # }
76
110
  ```
77
111
 
78
- `concurrent` and `chunk` also works in [`into_sink`][crate::Writer::into_sink], [`into_bytes_sink`][crate::Writer::into_bytes_sink] and [`into_futures_async_write`][crate::Writer::into_futures_async_write]:
112
+ A configured writer keeps the same chunking and concurrency behavior after it
113
+ is converted with [`Writer::into_sink`][crate::Writer::into_sink],
114
+ [`Writer::into_bytes_sink`][crate::Writer::into_bytes_sink], or
115
+ [`Writer::into_futures_async_write`][crate::Writer::into_futures_async_write].
79
116
 
80
117
  ```rust
81
118
  use std::io;
82
119
 
83
- use bytes::Bytes;
84
120
  use futures::SinkExt;
85
- use opendal::{Buffer, Operator};
86
- use opendal::Result;
87
-
88
- async fn test(op: Operator) -> io::Result<()> {
89
- let mut w = op
90
- .writer_with("hello.txt")
91
- .concurrent(8)
92
- .chunk(256)
121
+ use opendal_core::{Buffer, Operator};
122
+
123
+ async fn upload_with_sink(op: Operator, data: Buffer) -> io::Result<()> {
124
+ let mut sink = op
125
+ .writer_with("large-object.bin")
126
+ .chunk(8 * 1024 * 1024)
127
+ .concurrent(4)
93
128
  .await?
94
129
  .into_sink();
95
- let bs = "Hello, World!".as_bytes();
96
- w.send(Buffer::from(bs)).await?;
97
- w.close().await?;
98
130
 
131
+ sink.send(data).await?;
132
+ sink.close().await?;
99
133
  Ok(())
100
134
  }
101
135
  ```
136
+
137
+ Measure end-to-end throughput and completion latency together with peak memory,
138
+ request count, retries, throttling, and the result from the final close.