@fluidframework/driver-utils 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.224419

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 (390) hide show
  1. package/.eslintrc.js +17 -7
  2. package/.mocharc.js +12 -0
  3. package/CHANGELOG.md +141 -0
  4. package/README.md +68 -1
  5. package/api-extractor-lint.json +4 -0
  6. package/api-extractor.json +2 -2
  7. package/api-report/driver-utils.api.md +401 -0
  8. package/dist/adapters/compression/compressionTypes.cjs +20 -0
  9. package/dist/adapters/compression/compressionTypes.cjs.map +1 -0
  10. package/dist/adapters/compression/compressionTypes.d.ts +23 -0
  11. package/dist/adapters/compression/compressionTypes.d.ts.map +1 -0
  12. package/dist/adapters/compression/documentServiceCompressionAdapter.cjs +23 -0
  13. package/dist/adapters/compression/documentServiceCompressionAdapter.cjs.map +1 -0
  14. package/dist/adapters/compression/documentServiceCompressionAdapter.d.ts +13 -0
  15. package/dist/adapters/compression/documentServiceCompressionAdapter.d.ts.map +1 -0
  16. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.cjs +31 -0
  17. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.cjs.map +1 -0
  18. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts +16 -0
  19. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts.map +1 -0
  20. package/dist/adapters/compression/index.cjs +15 -0
  21. package/dist/adapters/compression/index.cjs.map +1 -0
  22. package/dist/adapters/compression/index.d.ts +8 -0
  23. package/dist/adapters/compression/index.d.ts.map +1 -0
  24. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.cjs +370 -0
  25. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.cjs.map +1 -0
  26. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts +165 -0
  27. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts.map +1 -0
  28. package/dist/adapters/compression/summaryblob/index.cjs +11 -0
  29. package/dist/adapters/compression/summaryblob/index.cjs.map +1 -0
  30. package/dist/adapters/compression/summaryblob/index.d.ts +6 -0
  31. package/dist/adapters/compression/summaryblob/index.d.ts.map +1 -0
  32. package/dist/adapters/index.cjs +14 -0
  33. package/dist/adapters/index.cjs.map +1 -0
  34. package/dist/adapters/index.d.ts +7 -0
  35. package/dist/adapters/index.d.ts.map +1 -0
  36. package/dist/adapters/predefinedAdapters.cjs +52 -0
  37. package/dist/adapters/predefinedAdapters.cjs.map +1 -0
  38. package/dist/adapters/predefinedAdapters.d.ts +21 -0
  39. package/dist/adapters/predefinedAdapters.d.ts.map +1 -0
  40. package/dist/blob.cjs +65 -0
  41. package/dist/blob.cjs.map +1 -0
  42. package/dist/blob.d.ts +56 -0
  43. package/dist/blob.d.ts.map +1 -0
  44. package/dist/{buildSnapshotTree.js → buildSnapshotTree.cjs} +7 -5
  45. package/dist/buildSnapshotTree.cjs.map +1 -0
  46. package/dist/buildSnapshotTree.d.ts +1 -0
  47. package/dist/buildSnapshotTree.d.ts.map +1 -1
  48. package/dist/documentServiceFactoryProxy.cjs +27 -0
  49. package/dist/documentServiceFactoryProxy.cjs.map +1 -0
  50. package/dist/documentServiceFactoryProxy.d.ts +19 -0
  51. package/dist/documentServiceFactoryProxy.d.ts.map +1 -0
  52. package/dist/documentServiceProxy.cjs +36 -0
  53. package/dist/documentServiceProxy.cjs.map +1 -0
  54. package/dist/documentServiceProxy.d.ts +21 -0
  55. package/dist/documentServiceProxy.d.ts.map +1 -0
  56. package/dist/{documentStorageServiceProxy.js → documentStorageServiceProxy.cjs} +10 -8
  57. package/dist/documentStorageServiceProxy.cjs.map +1 -0
  58. package/dist/documentStorageServiceProxy.d.ts +5 -2
  59. package/dist/documentStorageServiceProxy.d.ts.map +1 -1
  60. package/dist/driver-utils-alpha.d.ts +163 -0
  61. package/dist/driver-utils-beta.d.ts +178 -0
  62. package/dist/driver-utils-public.d.ts +178 -0
  63. package/dist/driver-utils-untrimmed.d.ts +590 -0
  64. package/dist/{error.js → error.cjs} +10 -3
  65. package/dist/error.cjs.map +1 -0
  66. package/dist/error.d.ts +8 -3
  67. package/dist/error.d.ts.map +1 -1
  68. package/dist/index.cjs +69 -0
  69. package/dist/index.cjs.map +1 -0
  70. package/dist/index.d.ts +16 -21
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/{insecureUrlResolver.js → insecureUrlResolver.cjs} +10 -11
  73. package/dist/insecureUrlResolver.cjs.map +1 -0
  74. package/dist/insecureUrlResolver.d.ts +1 -0
  75. package/dist/insecureUrlResolver.d.ts.map +1 -1
  76. package/dist/messageRecognition.cjs +38 -0
  77. package/dist/messageRecognition.cjs.map +1 -0
  78. package/dist/messageRecognition.d.ts +16 -26
  79. package/dist/messageRecognition.d.ts.map +1 -1
  80. package/dist/{network.js → network.cjs} +86 -24
  81. package/dist/network.cjs.map +1 -0
  82. package/dist/network.d.ts +69 -20
  83. package/dist/network.d.ts.map +1 -1
  84. package/dist/networkUtils.cjs +29 -0
  85. package/dist/networkUtils.cjs.map +1 -0
  86. package/dist/networkUtils.d.ts +4 -10
  87. package/dist/networkUtils.d.ts.map +1 -1
  88. package/dist/{packageVersion.js → packageVersion.cjs} +2 -2
  89. package/dist/packageVersion.cjs.map +1 -0
  90. package/dist/packageVersion.d.ts +1 -1
  91. package/dist/packageVersion.d.ts.map +1 -1
  92. package/dist/{parallelRequests.js → parallelRequests.cjs} +146 -74
  93. package/dist/parallelRequests.cjs.map +1 -0
  94. package/dist/parallelRequests.d.ts +19 -6
  95. package/dist/parallelRequests.d.ts.map +1 -1
  96. package/dist/{prefetchDocumentStorageService.js → prefetchDocumentStorageService.cjs} +7 -4
  97. package/dist/prefetchDocumentStorageService.cjs.map +1 -0
  98. package/dist/prefetchDocumentStorageService.d.ts +4 -2
  99. package/dist/prefetchDocumentStorageService.d.ts.map +1 -1
  100. package/dist/{rateLimiter.js → rateLimiter.cjs} +6 -3
  101. package/dist/rateLimiter.cjs.map +1 -0
  102. package/dist/rateLimiter.d.ts +3 -0
  103. package/dist/rateLimiter.d.ts.map +1 -1
  104. package/dist/readAndParse.cjs +28 -0
  105. package/dist/readAndParse.cjs.map +1 -0
  106. package/dist/readAndParse.d.ts +10 -4
  107. package/dist/readAndParse.d.ts.map +1 -1
  108. package/dist/runWithRetry.cjs +108 -0
  109. package/dist/runWithRetry.cjs.map +1 -0
  110. package/dist/runWithRetry.d.ts +26 -7
  111. package/dist/runWithRetry.d.ts.map +1 -1
  112. package/dist/{summaryForCreateNew.js → summaryForCreateNew.cjs} +20 -19
  113. package/dist/summaryForCreateNew.cjs.map +1 -0
  114. package/dist/summaryForCreateNew.d.ts +17 -4
  115. package/dist/summaryForCreateNew.d.ts.map +1 -1
  116. package/dist/{treeConversions.js → treeConversions.cjs} +16 -18
  117. package/dist/treeConversions.cjs.map +1 -0
  118. package/dist/treeConversions.d.ts +1 -0
  119. package/dist/treeConversions.d.ts.map +1 -1
  120. package/dist/tsdoc-metadata.json +11 -0
  121. package/lib/adapters/compression/compressionTypes.d.mts +23 -0
  122. package/lib/adapters/compression/compressionTypes.d.mts.map +1 -0
  123. package/lib/adapters/compression/compressionTypes.mjs +17 -0
  124. package/lib/adapters/compression/compressionTypes.mjs.map +1 -0
  125. package/lib/adapters/compression/documentServiceCompressionAdapter.d.mts +13 -0
  126. package/lib/adapters/compression/documentServiceCompressionAdapter.d.mts.map +1 -0
  127. package/lib/adapters/compression/documentServiceCompressionAdapter.mjs +19 -0
  128. package/lib/adapters/compression/documentServiceCompressionAdapter.mjs.map +1 -0
  129. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.d.mts +16 -0
  130. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.d.mts.map +1 -0
  131. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.mjs +27 -0
  132. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.mjs.map +1 -0
  133. package/lib/adapters/compression/index.d.mts +8 -0
  134. package/lib/adapters/compression/index.d.mts.map +1 -0
  135. package/lib/adapters/compression/index.mjs +8 -0
  136. package/lib/adapters/compression/index.mjs.map +1 -0
  137. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.mts +165 -0
  138. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.mts.map +1 -0
  139. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.mjs +366 -0
  140. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.mjs.map +1 -0
  141. package/lib/adapters/compression/summaryblob/index.d.mts +6 -0
  142. package/lib/adapters/compression/summaryblob/index.d.mts.map +1 -0
  143. package/lib/adapters/compression/summaryblob/index.mjs +6 -0
  144. package/lib/adapters/compression/summaryblob/index.mjs.map +1 -0
  145. package/lib/adapters/index.d.mts +7 -0
  146. package/lib/adapters/index.d.mts.map +1 -0
  147. package/lib/adapters/index.mjs +7 -0
  148. package/lib/adapters/index.mjs.map +1 -0
  149. package/lib/adapters/predefinedAdapters.d.mts +21 -0
  150. package/lib/adapters/predefinedAdapters.d.mts.map +1 -0
  151. package/lib/adapters/predefinedAdapters.mjs +47 -0
  152. package/lib/adapters/predefinedAdapters.mjs.map +1 -0
  153. package/lib/blob.d.mts +56 -0
  154. package/lib/blob.d.mts.map +1 -0
  155. package/lib/blob.mjs +59 -0
  156. package/lib/blob.mjs.map +1 -0
  157. package/lib/{buildSnapshotTree.d.ts → buildSnapshotTree.d.mts} +1 -0
  158. package/lib/buildSnapshotTree.d.mts.map +1 -0
  159. package/lib/{buildSnapshotTree.js → buildSnapshotTree.mjs} +6 -4
  160. package/lib/buildSnapshotTree.mjs.map +1 -0
  161. package/lib/documentServiceFactoryProxy.d.mts +19 -0
  162. package/lib/documentServiceFactoryProxy.d.mts.map +1 -0
  163. package/lib/documentServiceFactoryProxy.mjs +23 -0
  164. package/lib/documentServiceFactoryProxy.mjs.map +1 -0
  165. package/lib/documentServiceProxy.d.mts +21 -0
  166. package/lib/documentServiceProxy.d.mts.map +1 -0
  167. package/lib/documentServiceProxy.mjs +32 -0
  168. package/lib/documentServiceProxy.mjs.map +1 -0
  169. package/lib/{documentStorageServiceProxy.d.ts → documentStorageServiceProxy.d.mts} +5 -2
  170. package/lib/documentStorageServiceProxy.d.mts.map +1 -0
  171. package/lib/{documentStorageServiceProxy.js → documentStorageServiceProxy.mjs} +10 -8
  172. package/lib/documentStorageServiceProxy.mjs.map +1 -0
  173. package/lib/driver-utils-alpha.d.mts +163 -0
  174. package/lib/driver-utils-beta.d.mts +178 -0
  175. package/lib/driver-utils-public.d.mts +178 -0
  176. package/lib/driver-utils-untrimmed.d.mts +590 -0
  177. package/lib/error.d.mts +16 -0
  178. package/lib/error.d.mts.map +1 -0
  179. package/lib/error.mjs +19 -0
  180. package/lib/error.mjs.map +1 -0
  181. package/lib/index.d.mts +21 -0
  182. package/lib/index.d.mts.map +1 -0
  183. package/lib/index.mjs +21 -0
  184. package/lib/index.mjs.map +1 -0
  185. package/lib/{insecureUrlResolver.d.ts → insecureUrlResolver.d.mts} +1 -0
  186. package/lib/insecureUrlResolver.d.mts.map +1 -0
  187. package/lib/{insecureUrlResolver.js → insecureUrlResolver.mjs} +10 -11
  188. package/lib/insecureUrlResolver.mjs.map +1 -0
  189. package/lib/messageRecognition.d.mts +24 -0
  190. package/lib/messageRecognition.d.mts.map +1 -0
  191. package/lib/messageRecognition.mjs +29 -0
  192. package/lib/messageRecognition.mjs.map +1 -0
  193. package/lib/{network.d.ts → network.d.mts} +69 -20
  194. package/lib/network.d.mts.map +1 -0
  195. package/lib/{network.js → network.mjs} +85 -23
  196. package/lib/network.mjs.map +1 -0
  197. package/lib/networkUtils.d.mts +11 -0
  198. package/lib/networkUtils.d.mts.map +1 -0
  199. package/lib/networkUtils.mjs +25 -0
  200. package/lib/networkUtils.mjs.map +1 -0
  201. package/lib/{packageVersion.d.ts → packageVersion.d.mts} +1 -1
  202. package/lib/{packageVersion.d.ts.map → packageVersion.d.mts.map} +1 -1
  203. package/lib/{packageVersion.js → packageVersion.mjs} +2 -2
  204. package/lib/packageVersion.mjs.map +1 -0
  205. package/lib/{parallelRequests.d.ts → parallelRequests.d.mts} +19 -6
  206. package/lib/parallelRequests.d.mts.map +1 -0
  207. package/lib/{parallelRequests.js → parallelRequests.mjs} +119 -52
  208. package/lib/parallelRequests.mjs.map +1 -0
  209. package/lib/{prefetchDocumentStorageService.d.ts → prefetchDocumentStorageService.d.mts} +5 -7
  210. package/lib/prefetchDocumentStorageService.d.mts.map +1 -0
  211. package/lib/{prefetchDocumentStorageService.js → prefetchDocumentStorageService.mjs} +7 -8
  212. package/lib/prefetchDocumentStorageService.mjs.map +1 -0
  213. package/lib/{rateLimiter.d.ts → rateLimiter.d.mts} +3 -0
  214. package/lib/rateLimiter.d.mts.map +1 -0
  215. package/lib/{rateLimiter.js → rateLimiter.mjs} +5 -2
  216. package/lib/rateLimiter.mjs.map +1 -0
  217. package/lib/readAndParse.d.mts +20 -0
  218. package/lib/readAndParse.d.mts.map +1 -0
  219. package/lib/readAndParse.mjs +24 -0
  220. package/lib/readAndParse.mjs.map +1 -0
  221. package/lib/{runWithRetry.d.ts → runWithRetry.d.mts} +26 -7
  222. package/lib/runWithRetry.d.mts.map +1 -0
  223. package/lib/runWithRetry.mjs +103 -0
  224. package/lib/runWithRetry.mjs.map +1 -0
  225. package/lib/{summaryForCreateNew.d.ts → summaryForCreateNew.d.mts} +17 -4
  226. package/lib/summaryForCreateNew.d.mts.map +1 -0
  227. package/lib/{summaryForCreateNew.js → summaryForCreateNew.mjs} +18 -17
  228. package/lib/summaryForCreateNew.mjs.map +1 -0
  229. package/lib/{treeConversions.d.ts → treeConversions.d.mts} +1 -0
  230. package/lib/treeConversions.d.mts.map +1 -0
  231. package/lib/{treeConversions.js → treeConversions.mjs} +12 -14
  232. package/lib/treeConversions.mjs.map +1 -0
  233. package/package.json +88 -64
  234. package/prettier.config.cjs +8 -0
  235. package/src/adapters/compression/compressionTypes.ts +25 -0
  236. package/src/adapters/compression/documentServiceCompressionAdapter.ts +28 -0
  237. package/src/adapters/compression/documentServiceFactoryCompressionAdapter.ts +54 -0
  238. package/src/adapters/compression/index.ts +12 -0
  239. package/src/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.ts +451 -0
  240. package/src/adapters/compression/summaryblob/index.ts +9 -0
  241. package/src/adapters/index.ts +13 -0
  242. package/src/adapters/predefinedAdapters.ts +74 -0
  243. package/src/blob.ts +77 -0
  244. package/src/buildSnapshotTree.ts +58 -53
  245. package/src/documentServiceFactoryProxy.ts +47 -0
  246. package/src/documentServiceProxy.ts +46 -0
  247. package/src/documentStorageServiceProxy.ts +52 -37
  248. package/src/error.ts +13 -8
  249. package/src/index.ts +51 -21
  250. package/src/insecureUrlResolver.ts +125 -120
  251. package/src/messageRecognition.ts +24 -53
  252. package/src/network.ts +189 -111
  253. package/src/networkUtils.ts +24 -49
  254. package/src/packageVersion.ts +1 -1
  255. package/src/parallelRequests.ts +630 -519
  256. package/src/prefetchDocumentStorageService.ts +79 -74
  257. package/src/rateLimiter.ts +33 -30
  258. package/src/readAndParse.ts +18 -9
  259. package/src/runWithRetry.ts +145 -85
  260. package/src/summaryForCreateNew.ts +48 -29
  261. package/src/treeConversions.ts +49 -70
  262. package/tsc-multi.test.json +4 -0
  263. package/tsconfig.json +10 -12
  264. package/dist/blobAggregationStorage.d.ts +0 -43
  265. package/dist/blobAggregationStorage.d.ts.map +0 -1
  266. package/dist/blobAggregationStorage.js +0 -318
  267. package/dist/blobAggregationStorage.js.map +0 -1
  268. package/dist/blobCacheStorageService.d.ts +0 -16
  269. package/dist/blobCacheStorageService.d.ts.map +0 -1
  270. package/dist/blobCacheStorageService.js +0 -29
  271. package/dist/blobCacheStorageService.js.map +0 -1
  272. package/dist/buildSnapshotTree.js.map +0 -1
  273. package/dist/documentStorageServiceProxy.js.map +0 -1
  274. package/dist/emptyDocumentDeltaStorageService.d.ts +0 -13
  275. package/dist/emptyDocumentDeltaStorageService.d.ts.map +0 -1
  276. package/dist/emptyDocumentDeltaStorageService.js +0 -20
  277. package/dist/emptyDocumentDeltaStorageService.js.map +0 -1
  278. package/dist/error.js.map +0 -1
  279. package/dist/fluidResolvedUrl.d.ts +0 -8
  280. package/dist/fluidResolvedUrl.d.ts.map +0 -1
  281. package/dist/fluidResolvedUrl.js +0 -16
  282. package/dist/fluidResolvedUrl.js.map +0 -1
  283. package/dist/index.js +0 -38
  284. package/dist/index.js.map +0 -1
  285. package/dist/insecureUrlResolver.js.map +0 -1
  286. package/dist/messageRecognition.js +0 -73
  287. package/dist/messageRecognition.js.map +0 -1
  288. package/dist/multiDocumentServiceFactory.d.ts +0 -16
  289. package/dist/multiDocumentServiceFactory.d.ts.map +0 -1
  290. package/dist/multiDocumentServiceFactory.js +0 -63
  291. package/dist/multiDocumentServiceFactory.js.map +0 -1
  292. package/dist/multiUrlResolver.d.ts +0 -20
  293. package/dist/multiUrlResolver.d.ts.map +0 -1
  294. package/dist/multiUrlResolver.js +0 -45
  295. package/dist/multiUrlResolver.js.map +0 -1
  296. package/dist/network.js.map +0 -1
  297. package/dist/networkUtils.js +0 -59
  298. package/dist/networkUtils.js.map +0 -1
  299. package/dist/packageVersion.js.map +0 -1
  300. package/dist/parallelRequests.js.map +0 -1
  301. package/dist/prefetchDocumentStorageService.js.map +0 -1
  302. package/dist/rateLimiter.js.map +0 -1
  303. package/dist/readAndParse.js +0 -22
  304. package/dist/readAndParse.js.map +0 -1
  305. package/dist/runWithRetry.js +0 -69
  306. package/dist/runWithRetry.js.map +0 -1
  307. package/dist/summaryForCreateNew.js.map +0 -1
  308. package/dist/treeConversions.js.map +0 -1
  309. package/dist/treeUtils.d.ts +0 -51
  310. package/dist/treeUtils.d.ts.map +0 -1
  311. package/dist/treeUtils.js +0 -85
  312. package/dist/treeUtils.js.map +0 -1
  313. package/lib/blobAggregationStorage.d.ts +0 -43
  314. package/lib/blobAggregationStorage.d.ts.map +0 -1
  315. package/lib/blobAggregationStorage.js +0 -313
  316. package/lib/blobAggregationStorage.js.map +0 -1
  317. package/lib/blobCacheStorageService.d.ts +0 -16
  318. package/lib/blobCacheStorageService.d.ts.map +0 -1
  319. package/lib/blobCacheStorageService.js +0 -25
  320. package/lib/blobCacheStorageService.js.map +0 -1
  321. package/lib/buildSnapshotTree.d.ts.map +0 -1
  322. package/lib/buildSnapshotTree.js.map +0 -1
  323. package/lib/documentStorageServiceProxy.d.ts.map +0 -1
  324. package/lib/documentStorageServiceProxy.js.map +0 -1
  325. package/lib/emptyDocumentDeltaStorageService.d.ts +0 -13
  326. package/lib/emptyDocumentDeltaStorageService.d.ts.map +0 -1
  327. package/lib/emptyDocumentDeltaStorageService.js +0 -16
  328. package/lib/emptyDocumentDeltaStorageService.js.map +0 -1
  329. package/lib/error.d.ts +0 -11
  330. package/lib/error.d.ts.map +0 -1
  331. package/lib/error.js +0 -13
  332. package/lib/error.js.map +0 -1
  333. package/lib/fluidResolvedUrl.d.ts +0 -8
  334. package/lib/fluidResolvedUrl.d.ts.map +0 -1
  335. package/lib/fluidResolvedUrl.js +0 -11
  336. package/lib/fluidResolvedUrl.js.map +0 -1
  337. package/lib/index.d.ts +0 -26
  338. package/lib/index.d.ts.map +0 -1
  339. package/lib/index.js +0 -26
  340. package/lib/index.js.map +0 -1
  341. package/lib/insecureUrlResolver.d.ts.map +0 -1
  342. package/lib/insecureUrlResolver.js.map +0 -1
  343. package/lib/messageRecognition.d.ts +0 -38
  344. package/lib/messageRecognition.d.ts.map +0 -1
  345. package/lib/messageRecognition.js +0 -67
  346. package/lib/messageRecognition.js.map +0 -1
  347. package/lib/multiDocumentServiceFactory.d.ts +0 -16
  348. package/lib/multiDocumentServiceFactory.d.ts.map +0 -1
  349. package/lib/multiDocumentServiceFactory.js +0 -59
  350. package/lib/multiDocumentServiceFactory.js.map +0 -1
  351. package/lib/multiUrlResolver.d.ts +0 -20
  352. package/lib/multiUrlResolver.d.ts.map +0 -1
  353. package/lib/multiUrlResolver.js +0 -40
  354. package/lib/multiUrlResolver.js.map +0 -1
  355. package/lib/network.d.ts.map +0 -1
  356. package/lib/network.js.map +0 -1
  357. package/lib/networkUtils.d.ts +0 -17
  358. package/lib/networkUtils.d.ts.map +0 -1
  359. package/lib/networkUtils.js +0 -54
  360. package/lib/networkUtils.js.map +0 -1
  361. package/lib/packageVersion.js.map +0 -1
  362. package/lib/parallelRequests.d.ts.map +0 -1
  363. package/lib/parallelRequests.js.map +0 -1
  364. package/lib/prefetchDocumentStorageService.d.ts.map +0 -1
  365. package/lib/prefetchDocumentStorageService.js.map +0 -1
  366. package/lib/rateLimiter.d.ts.map +0 -1
  367. package/lib/rateLimiter.js.map +0 -1
  368. package/lib/readAndParse.d.ts +0 -14
  369. package/lib/readAndParse.d.ts.map +0 -1
  370. package/lib/readAndParse.js +0 -18
  371. package/lib/readAndParse.js.map +0 -1
  372. package/lib/runWithRetry.d.ts.map +0 -1
  373. package/lib/runWithRetry.js +0 -65
  374. package/lib/runWithRetry.js.map +0 -1
  375. package/lib/summaryForCreateNew.d.ts.map +0 -1
  376. package/lib/summaryForCreateNew.js.map +0 -1
  377. package/lib/treeConversions.d.ts.map +0 -1
  378. package/lib/treeConversions.js.map +0 -1
  379. package/lib/treeUtils.d.ts +0 -51
  380. package/lib/treeUtils.d.ts.map +0 -1
  381. package/lib/treeUtils.js +0 -80
  382. package/lib/treeUtils.js.map +0 -1
  383. package/src/blobAggregationStorage.ts +0 -374
  384. package/src/blobCacheStorageService.ts +0 -32
  385. package/src/emptyDocumentDeltaStorageService.ts +0 -24
  386. package/src/fluidResolvedUrl.ts +0 -15
  387. package/src/multiDocumentServiceFactory.ts +0 -80
  388. package/src/multiUrlResolver.ts +0 -51
  389. package/src/treeUtils.ts +0 -111
  390. package/tsconfig.esnext.json +0 -7
@@ -2,18 +2,20 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { assert, Deferred, performance } from "@fluidframework/common-utils";
6
- import { ITelemetryLogger, ITelemetryProperties } from "@fluidframework/common-definitions";
7
- import { PerformanceEvent } from "@fluidframework/telemetry-utils";
5
+ import { performance } from "@fluid-internal/client-utils";
6
+ import { ITelemetryProperties } from "@fluidframework/core-interfaces";
7
+ import { assert, Deferred } from "@fluidframework/core-utils";
8
+ import { ITelemetryLoggerExt, PerformanceEvent } from "@fluidframework/telemetry-utils";
8
9
  import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
9
10
  import { IDeltasFetchResult, IStream, IStreamResult } from "@fluidframework/driver-definitions";
10
11
  import { getRetryDelayFromError, canRetryOnError, createGenericNetworkError } from "./network";
11
- import { waitForConnectedState, logNetworkFailure } from "./networkUtils";
12
+ import { logNetworkFailure } from "./networkUtils";
12
13
  // For now, this package is versioned and released in unison with the specific drivers
13
14
  import { pkgVersion as driverVersion } from "./packageVersion";
15
+ import { calculateMaxWaitTime } from "./runWithRetry";
14
16
 
15
- const MaxFetchDelayInMs = 10000;
16
- const MissingFetchDelayInMs = 100;
17
+ // We double this value in first try in when we calculate time to wait for in "calculateMaxWaitTime" function.
18
+ const MissingFetchDelayInMs = 50;
17
19
 
18
20
  type WorkingState = "working" | "done" | "canceled";
19
21
 
@@ -23,329 +25,378 @@ type WorkingState = "working" | "done" | "canceled";
23
25
  * data in the right order. Take a look at UT for examples.
24
26
  * @param concurrency - level of concurrency
25
27
  * @param from - starting point of fetching data (inclusive)
26
- * @param to - ending point of fetching data. exclusive, or undefined if unknown
28
+ * @param to - ending point of fetching data. exclusive, or undefined if unknown
27
29
  * @param payloadSize - batch size
28
30
  * @param logger - logger to use
29
31
  * @param requestCallback - callback to request batches
30
- * @returns - Queue that can be used to retrieve data
32
+ * @returns Queue that can be used to retrieve data
33
+ * @internal
31
34
  */
32
35
  export class ParallelRequests<T> {
33
- private latestRequested: number;
34
- private nextToDeliver: number;
35
- private readonly results: Map<number, T[]> = new Map();
36
- private workingState: WorkingState = "working";
37
- private requestsInFlight = 0;
38
- private readonly endEvent = new Deferred<void>();
39
- private requests = 0;
40
- private readonly knewTo: boolean;
41
-
42
- private get working() { return this.workingState === "working"; }
43
- public get canceled() { return this.workingState === "canceled"; }
44
-
45
- constructor(
46
- from: number,
47
- private to: number | undefined,
48
- private readonly payloadSize: number,
49
- private readonly logger: ITelemetryLogger,
50
- private readonly requestCallback: (
51
- request: number,
52
- from: number,
53
- to: number,
54
- strongTo: boolean,
55
- props: ITelemetryProperties) => Promise<{ partial: boolean; cancel: boolean; payload: T[]; }>,
56
- private readonly responseCallback: (payload: T[]) => void) {
57
- this.latestRequested = from;
58
- this.nextToDeliver = from;
59
- this.knewTo = (to !== undefined);
60
- }
61
-
62
- public cancel() {
63
- if (this.working) {
64
- this.workingState = "canceled";
65
- this.endEvent.resolve();
66
- }
67
- }
68
-
69
- public async run(concurrency: number) {
70
- assert(concurrency > 0, 0x102 /* "invalid level of concurrency" */);
71
- assert(this.working, 0x103 /* "trying to parallel run while not working" */);
72
-
73
- let c = concurrency;
74
- while (c > 0) {
75
- c--;
76
- this.addRequest();
77
- }
78
- this.dispatch();// will recalculate and trigger this.endEvent if needed
79
- return this.endEvent.promise;
80
- }
81
-
82
- private done() {
83
- // We should satisfy request fully.
84
- assert(this.to !== undefined, 0x104 /* "undefined end point for parallel fetch" */);
85
- assert(this.nextToDeliver >= this.to, 0x105 /* "unexpected end point for parallel fetch" */);
86
- if (this.working) {
87
- this.workingState = "done";
88
- this.endEvent.resolve();
89
- }
90
- }
91
-
92
- private fail(error) {
93
- if (this.working) {
94
- this.workingState = "done";
95
- this.endEvent.reject(error);
96
- }
97
- }
98
-
99
- private dispatch() {
100
- while (this.working) {
101
- const value = this.results.get(this.nextToDeliver);
102
- if (value === undefined) {
103
- break;
104
- }
105
- this.results.delete(this.nextToDeliver);
106
- assert(value.length <= this.payloadSize, 0x1d9 /* "addRequestCore() should break into smaller chunks" */);
107
- this.nextToDeliver += value.length;
108
- this.responseCallback(value);
109
- }
110
-
111
- // Account for cancellation - state might be not in consistent state on cancelling operation
112
- if (this.working) {
113
- if (this.requestsInFlight === 0) {
114
- // we should have dispatched everything, no matter whether we knew about the end or not.
115
- // see comment in addRequestCore() around throwing away chunk if it's above this.to
116
- assert(this.results.size === 0,
117
- 0x107 /* "ending dispatch with remaining results to be sent" */);
118
- this.done();
119
- } else if (this.to !== undefined && this.nextToDeliver >= this.to) {
120
- // Learned about the end and dispatched all the ops up to it.
121
- // Ignore all the in-flight requests above boundary - unblock caller sooner.
122
- assert(!this.knewTo, 0x108 /* "ending results dispatch but knew in advance about more requests" */);
123
- this.done();
124
- }
125
- }
126
- }
127
-
128
- private getNextChunk() {
129
- if (!this.working) {
130
- return undefined;
131
- }
132
-
133
- const from = this.latestRequested;
134
- if (this.to !== undefined) {
135
- if (this.to <= from) {
136
- return undefined;
137
- }
138
- }
139
-
140
- // this.latestRequested
141
- // inclusive on the right side! Exclusive on the left.
142
- this.latestRequested += this.payloadSize;
143
-
144
- if (this.to !== undefined) {
145
- this.latestRequested = Math.min(this.to, this.latestRequested);
146
- }
147
-
148
- assert(from < this.latestRequested, 0x109 /* "unexpected next chunk position" */);
149
-
150
- return { from, to: this.latestRequested };
151
- }
152
-
153
- private addRequest() {
154
- const chunk = this.getNextChunk();
155
- if (chunk === undefined) {
156
- return;
157
- }
158
- this.addRequestCore(chunk.from, chunk.to).catch(this.fail.bind(this));
159
- }
160
-
161
- private async addRequestCore(fromArg: number, toArg: number) {
162
- assert(this.working, 0x10a /* "cannot add parallel request while not working" */);
163
-
164
- let from = fromArg;
165
- let to = toArg;
166
-
167
- // to & from are exclusive
168
- this.requestsInFlight++;
169
- while (this.working) {
170
- const requestedLength = to - from;
171
- assert(requestedLength > 0, 0x10b /* "invalid parallel request range" */);
172
-
173
- // We should not be wasting time asking for something useless.
174
- if (this.to !== undefined) {
175
- assert(from < this.to, 0x10c /* "invalid parallel request start point" */);
176
- assert(to <= this.to, 0x10d /* "invalid parallel request end point" */);
177
- }
178
-
179
- this.requests++;
180
-
181
- const promise = this.requestCallback(this.requests, from, to, this.to !== undefined, {});
182
-
183
- // dispatch any prior received data
184
- this.dispatch();
185
-
186
- const { payload, cancel, partial } = await promise;
187
-
188
- if (cancel) {
189
- this.cancel();
190
- }
191
-
192
- if (this.to !== undefined && from >= this.to) {
193
- // while we were waiting for response, we learned on what is the boundary
194
- // We can get here (with actual result!) if situation changed while this request was in
195
- // flight, i.e. the end was extended over what we learn in some other request
196
- // While it's useful not to throw this result, this is very corner cases and makes logic
197
- // (including consistency checks) much harder to write correctly.
198
- // So for now, we are throwing this result out the window.
199
- assert(!this.knewTo, 0x10e /* "should not throw result if we knew about boundary in advance" */);
200
- // Learn how often it happens and if it's too wasteful to throw these chunks.
201
- // If it pops into our view a lot, we would need to reconsider how we approach it.
202
- // Note that this is not visible to user other than potentially not hitting 100% of
203
- // what we can in perf domain.
204
- if (payload.length !== 0) {
205
- this.logger.sendErrorEvent({
206
- eventName: "ParallelRequests_GotExtra",
207
- from,
208
- to,
209
- end: this.to,
210
- length: payload.length,
211
- });
212
- }
213
-
214
- break;
215
- }
216
-
217
- if (this.working) {
218
- const fromOrig = from;
219
- const length = payload.length;
220
- let fullChunk = (requestedLength <= length); // we can possible get more than we asked.
221
-
222
- if (length !== 0) {
223
- // We can get more than we asked for!
224
- // This can screw up logic in dispatch!
225
- // So push only batch size, and keep the rest for later - if conditions are favorable, we
226
- // will be able to use it. If not (parallel request overlapping these ops), it's easier to
227
- // discard them and wait for another (overlapping) request to come in later.
228
- if (requestedLength < length) {
229
- // This is error in a sense that it's not expected and likely points bug in other layer.
230
- // This layer copes with this situation just fine.
231
- this.logger.sendTelemetryEvent({
232
- eventName: "ParallelRequests_Over",
233
- from,
234
- to,
235
- length,
236
- });
237
- }
238
- const data = payload.splice(0, requestedLength);
239
- this.results.set(from, data);
240
- from += data.length;
241
- } else {
242
- // 1. empty (partial) chunks should not be returned by various caching / adapter layers -
243
- // they should fall back to next layer. This might be important invariant to hold to ensure
244
- // that we are less likely have bugs where such layer would keep returning empty partial
245
- // result on each call.
246
- // 2. Current invariant is that callback does retries until it gets something,
247
- // with the goal of failing if zero data is retrieved in given amount of time.
248
- // This is very specific property of storage / ops, so this logic is not here, but given only
249
- // one user of this class, we assert that to catch issues earlier.
250
- // These invariant can be relaxed if needed.
251
- assert(!partial, 0x10f /* "empty/partial chunks should not be returned by caching" */);
252
- assert(!this.knewTo,
253
- 0x110 /* "callback should retry until valid fetch before it learns new boundary" */);
254
- }
255
-
256
- if (!partial && !fullChunk) {
257
- if (!this.knewTo) {
258
- if (this.to === undefined || this.to > from) {
259
- // The END
260
- this.to = from;
261
- }
262
- break;
263
- }
264
- // We know that there are more items to be retrieved
265
- // Can we get partial chunk? Ideally storage indicates that's not a full chunk
266
- // Note that it's possible that not all ops hit storage yet.
267
- // We will come back to request more, and if we can't get any more ops soon, it's
268
- // catastrophic failure (see comment above on responsibility of callback to return something)
269
- // This layer will just keep trying until it gets full set.
270
- this.logger.sendPerformanceEvent({
271
- eventName: "ParallelRequests_Partial",
272
- from: fromOrig,
273
- to,
274
- length,
275
- });
276
- }
277
-
278
- if (to === this.latestRequested) {
279
- // we can go after full chunk at the end if we received partial chunk, or more than asked
280
- // Also if we got more than we asked to, we can actually use those ops!
281
- if (payload.length !== 0) {
282
- this.results.set(from, payload);
283
- from += payload.length;
284
- }
285
-
286
- this.latestRequested = from;
287
- fullChunk = true;
288
- }
289
-
290
- if (fullChunk) {
291
- const chunk = this.getNextChunk();
292
- if (chunk === undefined) { break; }
293
- from = chunk.from;
294
- to = chunk.to;
295
- }
296
- }
297
- }
298
- this.requestsInFlight--;
299
- this.dispatch();
300
- }
36
+ private latestRequested: number;
37
+ private nextToDeliver: number;
38
+ private readonly results = new Map<number, T[]>();
39
+ private workingState: WorkingState = "working";
40
+ private requestsInFlight = 0;
41
+ private readonly endEvent = new Deferred<void>();
42
+ private requests = 0;
43
+ private readonly knewTo: boolean;
44
+
45
+ private get working() {
46
+ return this.workingState === "working";
47
+ }
48
+ public get canceled() {
49
+ return this.workingState === "canceled";
50
+ }
51
+
52
+ constructor(
53
+ from: number,
54
+ private to: number | undefined,
55
+ private readonly payloadSize: number,
56
+ private readonly logger: ITelemetryLoggerExt,
57
+ private readonly requestCallback: (
58
+ request: number,
59
+ from: number,
60
+ to: number,
61
+ strongTo: boolean,
62
+ props: ITelemetryProperties,
63
+ ) => Promise<{ partial: boolean; cancel: boolean; payload: T[] }>,
64
+ private readonly responseCallback: (payload: T[]) => void,
65
+ ) {
66
+ this.latestRequested = from;
67
+ this.nextToDeliver = from;
68
+ this.knewTo = to !== undefined;
69
+ }
70
+
71
+ public cancel() {
72
+ if (this.working) {
73
+ this.workingState = "canceled";
74
+ this.endEvent.resolve();
75
+ }
76
+ }
77
+
78
+ public async run(concurrency: number) {
79
+ assert(concurrency > 0, 0x102 /* "invalid level of concurrency" */);
80
+ assert(this.working, 0x103 /* "trying to parallel run while not working" */);
81
+
82
+ let c = concurrency;
83
+ while (c > 0) {
84
+ c--;
85
+ this.addRequest();
86
+ }
87
+ this.dispatch(); // will recalculate and trigger this.endEvent if needed
88
+ return this.endEvent.promise;
89
+ }
90
+
91
+ private done() {
92
+ // We should satisfy request fully.
93
+ assert(this.to !== undefined, 0x104 /* "undefined end point for parallel fetch" */);
94
+ assert(
95
+ this.nextToDeliver >= this.to,
96
+ 0x105 /* "unexpected end point for parallel fetch" */,
97
+ );
98
+ if (this.working) {
99
+ this.workingState = "done";
100
+ this.endEvent.resolve();
101
+ }
102
+ }
103
+
104
+ private fail(error) {
105
+ if (this.working) {
106
+ this.workingState = "done";
107
+ this.endEvent.reject(error);
108
+ }
109
+ }
110
+
111
+ private dispatch() {
112
+ while (this.working) {
113
+ const value = this.results.get(this.nextToDeliver);
114
+ if (value === undefined) {
115
+ break;
116
+ }
117
+ this.results.delete(this.nextToDeliver);
118
+ assert(
119
+ value.length <= this.payloadSize,
120
+ 0x1d9 /* "addRequestCore() should break into smaller chunks" */,
121
+ );
122
+ this.nextToDeliver += value.length;
123
+ this.responseCallback(value);
124
+ }
125
+
126
+ // Account for cancellation - state might be not in consistent state on cancelling operation
127
+ if (this.working) {
128
+ if (this.requestsInFlight === 0) {
129
+ // we should have dispatched everything, no matter whether we knew about the end or not.
130
+ // see comment in addRequestCore() around throwing away chunk if it's above this.to
131
+ assert(
132
+ this.results.size === 0,
133
+ 0x107 /* "ending dispatch with remaining results to be sent" */,
134
+ );
135
+ this.done();
136
+ } else if (this.to !== undefined && this.nextToDeliver >= this.to) {
137
+ // Learned about the end and dispatched all the ops up to it.
138
+ // Ignore all the in-flight requests above boundary - unblock caller sooner.
139
+ assert(
140
+ !this.knewTo,
141
+ 0x108 /* "ending results dispatch but knew in advance about more requests" */,
142
+ );
143
+ this.done();
144
+ }
145
+ }
146
+ }
147
+
148
+ private getNextChunk() {
149
+ if (!this.working) {
150
+ return undefined;
151
+ }
152
+
153
+ const from = this.latestRequested;
154
+ if (this.to !== undefined) {
155
+ if (this.to <= from) {
156
+ return undefined;
157
+ }
158
+ }
159
+
160
+ // this.latestRequested
161
+ // inclusive on the right side! Exclusive on the left.
162
+ this.latestRequested += this.payloadSize;
163
+
164
+ if (this.to !== undefined) {
165
+ this.latestRequested = Math.min(this.to, this.latestRequested);
166
+ }
167
+
168
+ assert(from < this.latestRequested, 0x109 /* "unexpected next chunk position" */);
169
+
170
+ return { from, to: this.latestRequested };
171
+ }
172
+
173
+ private addRequest() {
174
+ const chunk = this.getNextChunk();
175
+ if (chunk === undefined) {
176
+ return;
177
+ }
178
+ this.addRequestCore(chunk.from, chunk.to).catch(this.fail.bind(this));
179
+ }
180
+
181
+ private async addRequestCore(fromArg: number, toArg: number) {
182
+ assert(this.working, 0x10a /* "cannot add parallel request while not working" */);
183
+
184
+ let from = fromArg;
185
+ let to = toArg;
186
+
187
+ // to & from are exclusive
188
+ this.requestsInFlight++;
189
+ while (this.working) {
190
+ const requestedLength = to - from;
191
+ assert(requestedLength > 0, 0x10b /* "invalid parallel request range" */);
192
+
193
+ // We should not be wasting time asking for something useless.
194
+ if (this.to !== undefined) {
195
+ assert(from < this.to, 0x10c /* "invalid parallel request start point" */);
196
+ assert(to <= this.to, 0x10d /* "invalid parallel request end point" */);
197
+ }
198
+
199
+ this.requests++;
200
+
201
+ const promise = this.requestCallback(
202
+ this.requests,
203
+ from,
204
+ to,
205
+ this.to !== undefined,
206
+ {},
207
+ );
208
+
209
+ // dispatch any prior received data
210
+ this.dispatch();
211
+
212
+ const { payload, cancel, partial } = await promise;
213
+
214
+ if (cancel) {
215
+ this.cancel();
216
+ }
217
+
218
+ if (this.to !== undefined && from >= this.to) {
219
+ // while we were waiting for response, we learned on what is the boundary
220
+ // We can get here (with actual result!) if situation changed while this request was in
221
+ // flight, i.e. the end was extended over what we learn in some other request
222
+ // While it's useful not to throw this result, this is very corner cases and makes logic
223
+ // (including consistency checks) much harder to write correctly.
224
+ // So for now, we are throwing this result out the window.
225
+ assert(
226
+ !this.knewTo,
227
+ 0x10e /* "should not throw result if we knew about boundary in advance" */,
228
+ );
229
+ // Learn how often it happens and if it's too wasteful to throw these chunks.
230
+ // If it pops into our view a lot, we would need to reconsider how we approach it.
231
+ // Note that this is not visible to user other than potentially not hitting 100% of
232
+ // what we can in perf domain.
233
+ if (payload.length !== 0) {
234
+ this.logger.sendErrorEvent({
235
+ eventName: "ParallelRequests_GotExtra",
236
+ from,
237
+ to,
238
+ end: this.to,
239
+ length: payload.length,
240
+ });
241
+ }
242
+
243
+ break;
244
+ }
245
+
246
+ if (this.working) {
247
+ const fromOrig = from;
248
+ const length = payload.length;
249
+ let fullChunk = requestedLength <= length; // we can possible get more than we asked.
250
+
251
+ if (length !== 0) {
252
+ // We can get more than we asked for!
253
+ // This can screw up logic in dispatch!
254
+ // So push only batch size, and keep the rest for later - if conditions are favorable, we
255
+ // will be able to use it. If not (parallel request overlapping these ops), it's easier to
256
+ // discard them and wait for another (overlapping) request to come in later.
257
+ if (requestedLength < length) {
258
+ // This is error in a sense that it's not expected and likely points bug in other layer.
259
+ // This layer copes with this situation just fine.
260
+ this.logger.sendTelemetryEvent({
261
+ eventName: "ParallelRequests_Over",
262
+ from,
263
+ to,
264
+ length,
265
+ });
266
+ }
267
+ const data = payload.splice(0, requestedLength);
268
+ this.results.set(from, data);
269
+ from += data.length;
270
+ } else {
271
+ // 1. empty (partial) chunks should not be returned by various caching / adapter layers -
272
+ // they should fall back to next layer. This might be important invariant to hold to ensure
273
+ // that we are less likely have bugs where such layer would keep returning empty partial
274
+ // result on each call.
275
+ // 2. Current invariant is that callback does retries until it gets something,
276
+ // with the goal of failing if zero data is retrieved in given amount of time.
277
+ // This is very specific property of storage / ops, so this logic is not here, but given only
278
+ // one user of this class, we assert that to catch issues earlier.
279
+ // These invariant can be relaxed if needed.
280
+ assert(
281
+ !partial,
282
+ 0x10f /* "empty/partial chunks should not be returned by caching" */,
283
+ );
284
+ assert(
285
+ !this.knewTo,
286
+ 0x110 /* "callback should retry until valid fetch before it learns new boundary" */,
287
+ );
288
+ }
289
+
290
+ if (!partial && !fullChunk) {
291
+ if (!this.knewTo) {
292
+ if (this.to === undefined || this.to > from) {
293
+ // The END
294
+ this.to = from;
295
+ }
296
+ break;
297
+ }
298
+ // We know that there are more items to be retrieved
299
+ // Can we get partial chunk? Ideally storage indicates that's not a full chunk
300
+ // Note that it's possible that not all ops hit storage yet.
301
+ // We will come back to request more, and if we can't get any more ops soon, it's
302
+ // catastrophic failure (see comment above on responsibility of callback to return something)
303
+ // This layer will just keep trying until it gets full set.
304
+ this.logger.sendPerformanceEvent({
305
+ eventName: "ParallelRequests_Partial",
306
+ from: fromOrig,
307
+ to,
308
+ length,
309
+ });
310
+ }
311
+
312
+ if (to === this.latestRequested) {
313
+ // we can go after full chunk at the end if we received partial chunk, or more than asked
314
+ // Also if we got more than we asked to, we can actually use those ops!
315
+ while (payload.length !== 0) {
316
+ const data = payload.splice(0, requestedLength);
317
+ this.results.set(from, data);
318
+ from += data.length;
319
+ }
320
+
321
+ this.latestRequested = from;
322
+ fullChunk = true;
323
+ }
324
+
325
+ if (fullChunk) {
326
+ const chunk = this.getNextChunk();
327
+ if (chunk === undefined) {
328
+ break;
329
+ }
330
+ from = chunk.from;
331
+ to = chunk.to;
332
+ }
333
+ }
334
+ }
335
+ this.requestsInFlight--;
336
+ this.dispatch();
337
+ }
301
338
  }
302
339
 
303
340
  /**
304
341
  * Helper queue class to allow async push / pull
305
342
  * It's essentially a pipe allowing multiple writers, and single reader
343
+ * @internal
306
344
  */
307
345
  export class Queue<T> implements IStream<T> {
308
- private readonly queue: Promise<IStreamResult<T>>[] = [];
309
- private deferred: Deferred<IStreamResult<T>> | undefined;
310
- private done = false;
311
-
312
- public pushValue(value: T) {
313
- this.pushCore(Promise.resolve({ done: false, value }));
314
- }
315
-
316
- public pushError(error: any) {
317
- this.pushCore(Promise.reject(error));
318
- this.done = true;
319
- }
320
-
321
- public pushDone() {
322
- this.pushCore(Promise.resolve({ done: true }));
323
- this.done = true;
324
- }
325
-
326
- protected pushCore(value: Promise<IStreamResult<T>>) {
327
- assert(!this.done, 0x112 /* "cannot push onto queue if done" */);
328
- if (this.deferred) {
329
- assert(this.queue.length === 0, 0x113 /* "deferred queue should be empty" */);
330
- this.deferred.resolve(value);
331
- this.deferred = undefined;
332
- } else {
333
- this.queue.push(value);
334
- }
335
- }
336
-
337
- public async read(): Promise<IStreamResult<T>> {
338
- assert(this.deferred === undefined, 0x114 /* "cannot pop if deferred" */);
339
- const value = this.queue.shift();
340
- if (value !== undefined) {
341
- return value;
342
- }
343
- assert(!this.done, 0x115 /* "queue should not be done during pop" */);
344
- this.deferred = new Deferred<IStreamResult<T>>();
345
- return this.deferred.promise;
346
- }
346
+ private readonly queue: Promise<IStreamResult<T>>[] = [];
347
+ private deferred: Deferred<IStreamResult<T>> | undefined;
348
+ private done = false;
349
+
350
+ public pushValue(value: T) {
351
+ this.pushCore(Promise.resolve({ done: false, value }));
352
+ }
353
+
354
+ public pushError(error: any) {
355
+ this.pushCore(Promise.reject(error));
356
+ this.done = true;
357
+ }
358
+
359
+ public pushDone() {
360
+ this.pushCore(Promise.resolve({ done: true }));
361
+ this.done = true;
362
+ }
363
+
364
+ protected pushCore(value: Promise<IStreamResult<T>>) {
365
+ assert(!this.done, 0x112 /* "cannot push onto queue if done" */);
366
+ if (this.deferred) {
367
+ assert(this.queue.length === 0, 0x113 /* "deferred queue should be empty" */);
368
+ this.deferred.resolve(value);
369
+ this.deferred = undefined;
370
+ } else {
371
+ this.queue.push(value);
372
+ }
373
+ }
374
+
375
+ public async read(): Promise<IStreamResult<T>> {
376
+ assert(this.deferred === undefined, 0x114 /* "cannot pop if deferred" */);
377
+ const value = this.queue.shift();
378
+ if (value !== undefined) {
379
+ return value;
380
+ }
381
+ assert(!this.done, 0x115 /* "queue should not be done during pop" */);
382
+ this.deferred = new Deferred<IStreamResult<T>>();
383
+ return this.deferred.promise;
384
+ }
347
385
  }
348
386
 
387
+ const waitForOnline = async (): Promise<void> => {
388
+ // Only wait if we have a strong signal that we're offline - otherwise assume we're online.
389
+ if (globalThis.navigator?.onLine === false && globalThis.addEventListener !== undefined) {
390
+ return new Promise<void>((resolve) => {
391
+ const resolveAndRemoveListener = () => {
392
+ resolve();
393
+ globalThis.removeEventListener("online", resolveAndRemoveListener);
394
+ };
395
+ globalThis.addEventListener("online", resolveAndRemoveListener);
396
+ });
397
+ }
398
+ };
399
+
349
400
  /**
350
401
  * Retrieve single batch of ops
351
402
  * @param request - request index
@@ -357,96 +408,118 @@ export class Queue<T> implements IStream<T> {
357
408
  * @param logger - logger object to use to log progress & errors
358
409
  * @param signal - cancelation signal
359
410
  * @param scenarioName - reason for fetching ops
360
- * @returns - an object with resulting ops and cancellation / partial result flags
411
+ * @returns An object with resulting ops and cancellation / partial result flags
361
412
  */
362
413
  async function getSingleOpBatch(
363
- get: (telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,
364
- props: ITelemetryProperties,
365
- strongTo: boolean,
366
- logger: ITelemetryLogger,
367
- signal?: AbortSignal,
368
- scenarioName?: string):
369
- Promise<{ partial: boolean; cancel: boolean; payload: ISequencedDocumentMessage[]; }> {
370
- let lastSuccessTime: number | undefined;
371
-
372
- let retry: number = 0;
373
- const deltas: ISequencedDocumentMessage[] = [];
374
- const nothing = { partial: false, cancel: true, payload: [] };
375
-
376
- while (signal?.aborted !== true) {
377
- retry++;
378
- let delay = Math.min(MaxFetchDelayInMs, MissingFetchDelayInMs * Math.pow(2, retry));
379
- const startTime = performance.now();
380
-
381
- try {
382
- // Issue async request for deltas - limit the number fetched to MaxBatchDeltas
383
- const deltasP = get({ ...props, retry } /* telemetry props */);
384
-
385
- const { messages, partialResult } = await deltasP;
386
- deltas.push(...messages);
387
-
388
- const deltasRetrievedLast = messages.length;
389
-
390
- if (deltasRetrievedLast !== 0 || !strongTo) {
391
- return { payload: deltas, cancel: false, partial: partialResult };
392
- }
393
-
394
- // Storage does not have ops we need.
395
- // Attempt to fetch more deltas. If we didn't receive any in the previous call we up our retry
396
- // count since something prevented us from seeing those deltas
397
-
398
- if (lastSuccessTime === undefined) {
399
- lastSuccessTime = performance.now();
400
- } else if (performance.now() - lastSuccessTime > 30000) {
401
- // If we are connected and receiving proper responses from server, but can't get any ops back,
402
- // then give up after some time. This likely indicates the issue with ordering service not flushing
403
- // ops to storage quick enough, and possibly waiting for summaries, while summarizer can't get
404
- // current as it can't get ops.
405
- throw createGenericNetworkError(
406
- // pre-0.58 error message: failedToRetrieveOpsFromStorage:TooManyRetries
407
- "Failed to retrieve ops from storage (Too Many Retries)",
408
- { canRetry: false },
409
- {
410
- retry,
411
- driverVersion,
412
- ...props,
413
- },
414
- );
415
- }
416
- } catch (error) {
417
- const canRetry = canRetryOnError(error);
418
-
419
- lastSuccessTime = undefined;
420
-
421
- const retryAfter = getRetryDelayFromError(error);
422
-
423
- // This will log to error table only if the error is non-retryable
424
- logNetworkFailure(
425
- logger,
426
- {
427
- eventName: "GetDeltas_Error",
428
- ...props,
429
- retry,
430
- duration: performance.now() - startTime,
431
- retryAfter,
432
- reason: scenarioName,
433
- },
434
- error);
435
-
436
- if (!canRetry) {
437
- // It's game over scenario.
438
- throw error;
439
- }
440
-
441
- if (retryAfter !== undefined && retryAfter >= 0) {
442
- delay = retryAfter;
443
- }
444
- }
445
-
446
- await waitForConnectedState(delay);
447
- }
448
-
449
- return nothing;
414
+ get: (telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,
415
+ props: ITelemetryProperties,
416
+ strongTo: boolean,
417
+ logger: ITelemetryLoggerExt,
418
+ signal?: AbortSignal,
419
+ scenarioName?: string,
420
+ ): Promise<{ partial: boolean; cancel: boolean; payload: ISequencedDocumentMessage[] }> {
421
+ let lastSuccessTime: number | undefined;
422
+ let totalRetryAfterTime = 0;
423
+ let telemetryEvent: PerformanceEvent | undefined;
424
+ let retry: number = 0;
425
+ const nothing = { partial: false, cancel: true, payload: [] };
426
+ let waitStartTime: number = 0;
427
+ let waitTime = MissingFetchDelayInMs;
428
+
429
+ while (signal?.aborted !== true) {
430
+ retry++;
431
+ let lastError: unknown;
432
+ const startTime = performance.now();
433
+
434
+ try {
435
+ // Issue async request for deltas
436
+ const { messages, partialResult } = await get(
437
+ { ...props, retry } /* telemetry props */,
438
+ );
439
+
440
+ // If we got messages back, return them. Return regardless of whether we got messages back if we didn't
441
+ // specify a "to", since we don't have an expectation of how many to receive.
442
+ if (messages.length !== 0 || !strongTo) {
443
+ // Report this event if we waited to fetch ops due to being offline or throttling.
444
+ telemetryEvent?.end({
445
+ duration: totalRetryAfterTime,
446
+ ...props,
447
+ reason: scenarioName,
448
+ });
449
+ return { payload: messages, cancel: false, partial: partialResult };
450
+ }
451
+
452
+ // Otherwise, the storage gave us back an empty set of ops but we were expecting a non-empty set.
453
+
454
+ if (lastSuccessTime === undefined) {
455
+ // Take timestamp of the first time server responded successfully, even though it wasn't with the ops we asked for.
456
+ // If we keep getting empty responses we'll eventually fail out below.
457
+ lastSuccessTime = performance.now();
458
+ } else if (performance.now() - lastSuccessTime > 30000) {
459
+ // If we are connected and receiving proper responses from server, but can't get any ops back,
460
+ // then give up after some time. This likely indicates the issue with ordering service not flushing
461
+ // ops to storage quick enough, and possibly waiting for summaries, while summarizer can't get
462
+ // current as it can't get ops.
463
+ throw createGenericNetworkError(
464
+ // pre-0.58 error message: failedToRetrieveOpsFromStorage:TooManyRetries
465
+ "Failed to retrieve ops from storage (Too Many Retries)",
466
+ { canRetry: false },
467
+ {
468
+ retry,
469
+ driverVersion,
470
+ ...props,
471
+ },
472
+ );
473
+ }
474
+ } catch (error) {
475
+ lastError = error;
476
+ const canRetry = canRetryOnError(error);
477
+
478
+ const retryAfter = getRetryDelayFromError(error);
479
+
480
+ // This will log to error table only if the error is non-retryable
481
+ logNetworkFailure(
482
+ logger,
483
+ {
484
+ eventName: "GetDeltas_Error",
485
+ ...props,
486
+ retry,
487
+ duration: performance.now() - startTime,
488
+ retryAfter,
489
+ reason: scenarioName,
490
+ },
491
+ error,
492
+ );
493
+
494
+ if (!canRetry) {
495
+ // It's game over scenario.
496
+ throw error;
497
+ }
498
+ }
499
+
500
+ if (telemetryEvent === undefined) {
501
+ waitStartTime = performance.now();
502
+ telemetryEvent = PerformanceEvent.start(logger, {
503
+ eventName: "GetDeltasWaitTime",
504
+ });
505
+ }
506
+
507
+ waitTime = calculateMaxWaitTime(waitTime, lastError);
508
+
509
+ // If we get here something has gone wrong - either got an unexpected empty set of messages back or a real error.
510
+ // Either way we will wait a little bit before retrying.
511
+ await new Promise<void>((resolve) => {
512
+ setTimeout(resolve, waitTime);
513
+ });
514
+
515
+ // If we believe we're offline, we assume there's no point in trying until we at least think we're online.
516
+ // NOTE: This isn't strictly true for drivers that don't require network (e.g. local driver). Really this logic
517
+ // should probably live in the driver.
518
+ await waitForOnline();
519
+ totalRetryAfterTime += performance.now() - waitStartTime;
520
+ }
521
+
522
+ return nothing;
450
523
  }
451
524
 
452
525
  /**
@@ -459,130 +532,168 @@ async function getSingleOpBatch(
459
532
  * @param logger - Logger to log progress and errors
460
533
  * @param signal - Cancelation signal
461
534
  * @param scenarioName - Reason for fetching ops
462
- * @returns - Messages fetched
535
+ * @returns Messages fetched
536
+ * @internal
463
537
  */
464
538
  export function requestOps(
465
- get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,
466
- concurrency: number,
467
- fromTotal: number,
468
- toTotal: number | undefined,
469
- payloadSize: number,
470
- logger: ITelemetryLogger,
471
- signal?: AbortSignal,
472
- scenarioName?: string,
539
+ get: (
540
+ from: number,
541
+ to: number,
542
+ telemetryProps: ITelemetryProperties,
543
+ ) => Promise<IDeltasFetchResult>,
544
+ concurrency: number,
545
+ fromTotal: number,
546
+ toTotal: number | undefined,
547
+ payloadSize: number,
548
+ logger: ITelemetryLoggerExt,
549
+ signal?: AbortSignal,
550
+ scenarioName?: string,
473
551
  ): IStream<ISequencedDocumentMessage[]> {
474
- let requests = 0;
475
- let lastFetch: number | undefined;
476
- let length = 0;
477
- const queue = new Queue<ISequencedDocumentMessage[]>();
478
-
479
- const propsTotal: ITelemetryProperties = {
480
- fromTotal,
481
- toTotal,
482
- };
483
-
484
- const telemetryEvent = PerformanceEvent.start(logger, {
485
- eventName: "GetDeltas",
486
- ...propsTotal,
487
- reason: scenarioName,
488
- });
489
-
490
- const manager = new ParallelRequests<ISequencedDocumentMessage>(
491
- fromTotal,
492
- toTotal,
493
- payloadSize,
494
- logger,
495
- async (request: number, from: number, to: number, strongTo: boolean, propsPerRequest: ITelemetryProperties) => {
496
- requests++;
497
- return getSingleOpBatch(
498
- async (propsAll) => get(from, to, propsAll),
499
- { request, from, to, ...propsTotal, ...propsPerRequest },
500
- strongTo,
501
- logger,
502
- signal,
503
- scenarioName,
504
- );
505
- },
506
- (deltas: ISequencedDocumentMessage[]) => {
507
- // Assert continuing and right start.
508
- if (lastFetch === undefined) {
509
- assert(deltas[0].sequenceNumber === fromTotal, 0x26d /* "wrong start" */);
510
- } else {
511
- assert(deltas[0].sequenceNumber === lastFetch + 1, 0x26e /* "wrong start" */);
512
- }
513
- lastFetch = deltas[deltas.length - 1].sequenceNumber;
514
- assert(lastFetch - deltas[0].sequenceNumber + 1 === deltas.length,
515
- 0x26f /* "continuous and no duplicates" */);
516
- length += deltas.length;
517
- queue.pushValue(deltas);
518
- });
519
-
520
- // Implement faster cancellation. getSingleOpBatch() checks signal, but only in between
521
- // waits (up to 10 seconds) and fetches (can take infinite amount of time).
522
- // While every such case should be improved and take into account signal (and thus cancel immediately),
523
- // it is beneficial to have catch-all
524
- const listener = (event: Event) => { manager.cancel(); };
525
- if (signal !== undefined) {
526
- signal.addEventListener("abort", listener);
527
- }
528
-
529
- manager.run(concurrency)
530
- .finally(() => {
531
- if (signal !== undefined) {
532
- signal.removeEventListener("abort", listener);
533
- }
534
- }).then(() => {
535
- const props = {
536
- lastFetch,
537
- length,
538
- requests,
539
- };
540
- if (manager.canceled) {
541
- telemetryEvent.cancel({ ...props, error: "ops request cancelled by client" });
542
- } else {
543
- assert(toTotal === undefined || lastFetch !== undefined && lastFetch >= toTotal - 1,
544
- 0x270 /* "All requested ops fetched" */);
545
- telemetryEvent.end(props);
546
- }
547
- queue.pushDone();
548
- })
549
- .catch((error) => {
550
- telemetryEvent.cancel({
551
- lastFetch,
552
- length,
553
- requests,
554
- }, error);
555
- queue.pushError(error);
556
- });
557
-
558
- return queue;
552
+ let requests = 0;
553
+ let lastFetch: number | undefined;
554
+ let length = 0;
555
+ const queue = new Queue<ISequencedDocumentMessage[]>();
556
+
557
+ const propsTotal: ITelemetryProperties = {
558
+ fromTotal,
559
+ toTotal,
560
+ };
561
+
562
+ const telemetryEvent = PerformanceEvent.start(logger, {
563
+ eventName: "GetDeltas",
564
+ ...propsTotal,
565
+ reason: scenarioName,
566
+ });
567
+
568
+ const manager = new ParallelRequests<ISequencedDocumentMessage>(
569
+ fromTotal,
570
+ toTotal,
571
+ payloadSize,
572
+ logger,
573
+ async (
574
+ request: number,
575
+ from: number,
576
+ to: number,
577
+ strongTo: boolean,
578
+ propsPerRequest: ITelemetryProperties,
579
+ ) => {
580
+ requests++;
581
+ return getSingleOpBatch(
582
+ async (propsAll) => get(from, to, propsAll),
583
+ { request, from, to, ...propsTotal, ...propsPerRequest },
584
+ strongTo,
585
+ logger,
586
+ signal,
587
+ scenarioName,
588
+ );
589
+ },
590
+ (deltas: ISequencedDocumentMessage[]) => {
591
+ // Assert continuing and right start.
592
+ if (lastFetch === undefined) {
593
+ assert(deltas[0].sequenceNumber === fromTotal, 0x26d /* "wrong start" */);
594
+ } else {
595
+ assert(deltas[0].sequenceNumber === lastFetch + 1, 0x26e /* "wrong start" */);
596
+ }
597
+ lastFetch = deltas[deltas.length - 1].sequenceNumber;
598
+ assert(
599
+ lastFetch - deltas[0].sequenceNumber + 1 === deltas.length,
600
+ 0x26f /* "continuous and no duplicates" */,
601
+ );
602
+ length += deltas.length;
603
+ queue.pushValue(deltas);
604
+ },
605
+ );
606
+
607
+ // Implement faster cancellation. getSingleOpBatch() checks signal, but only in between
608
+ // waits (up to 10 seconds) and fetches (can take infinite amount of time).
609
+ // While every such case should be improved and take into account signal (and thus cancel immediately),
610
+ // it is beneficial to have catch-all
611
+ const listener = (event: Event) => {
612
+ manager.cancel();
613
+ };
614
+ if (signal !== undefined) {
615
+ signal.addEventListener("abort", listener);
616
+ }
617
+
618
+ manager
619
+ .run(concurrency)
620
+ .finally(() => {
621
+ if (signal !== undefined) {
622
+ signal.removeEventListener("abort", listener);
623
+ }
624
+ })
625
+ .then(() => {
626
+ const props = {
627
+ lastFetch,
628
+ length,
629
+ requests,
630
+ };
631
+ if (manager.canceled) {
632
+ telemetryEvent.cancel({ ...props, error: "ops request cancelled by client" });
633
+ } else {
634
+ assert(
635
+ toTotal === undefined || (lastFetch !== undefined && lastFetch >= toTotal - 1),
636
+ 0x270 /* "All requested ops fetched" */,
637
+ );
638
+ telemetryEvent.end(props);
639
+ }
640
+ queue.pushDone();
641
+ })
642
+ .catch((error) => {
643
+ telemetryEvent.cancel(
644
+ {
645
+ lastFetch,
646
+ length,
647
+ requests,
648
+ },
649
+ error,
650
+ );
651
+ queue.pushError(error);
652
+ });
653
+
654
+ return queue;
559
655
  }
560
656
 
657
+ /**
658
+ * @internal
659
+ */
561
660
  export const emptyMessageStream: IStream<ISequencedDocumentMessage[]> = {
562
- read: async () => { return { done: true }; },
661
+ read: async () => {
662
+ return { done: true };
663
+ },
563
664
  };
564
665
 
565
- export function streamFromMessages(messagesArg: Promise<ISequencedDocumentMessage[]>):
566
- IStream<ISequencedDocumentMessage[]> {
567
- let messages: Promise<ISequencedDocumentMessage[]> | undefined = messagesArg;
568
- return {
569
- read: async () => {
570
- if (messages === undefined) {
571
- return { done: true };
572
- }
573
- const value = await messages;
574
- messages = undefined;
575
- return value.length === 0 ? { done: true } : { done: false, value };
576
- },
577
- };
666
+ /**
667
+ * @internal
668
+ */
669
+ export function streamFromMessages(
670
+ messagesArg: Promise<ISequencedDocumentMessage[]>,
671
+ ): IStream<ISequencedDocumentMessage[]> {
672
+ let messages: Promise<ISequencedDocumentMessage[]> | undefined = messagesArg;
673
+ return {
674
+ read: async () => {
675
+ if (messages === undefined) {
676
+ return { done: true };
677
+ }
678
+ const value = await messages;
679
+ messages = undefined;
680
+ return value.length === 0 ? { done: true } : { done: false, value };
681
+ },
682
+ };
578
683
  }
579
684
 
580
- export function streamObserver<T>(stream: IStream<T>, handler: (value: IStreamResult<T>) => void): IStream<T> {
581
- return {
582
- read: async () => {
583
- const value = await stream.read();
584
- handler(value);
585
- return value;
586
- },
587
- };
685
+ /**
686
+ * @internal
687
+ */
688
+ export function streamObserver<T>(
689
+ stream: IStream<T>,
690
+ handler: (value: IStreamResult<T>) => void,
691
+ ): IStream<T> {
692
+ return {
693
+ read: async () => {
694
+ const value = await stream.read();
695
+ handler(value);
696
+ return value;
697
+ },
698
+ };
588
699
  }