@fluidframework/driver-utils 2.0.0-rc.1.0.4 → 2.0.0-rc.2.0.0

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 (297) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +5 -2
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +32 -0
  4. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  5. package/api-extractor-lint.json +1 -1
  6. package/api-extractor.json +1 -1
  7. package/api-report/driver-utils.api.md +22 -18
  8. package/dist/adapters/compression/documentServiceCompressionAdapter.d.ts +2 -2
  9. package/dist/adapters/compression/documentServiceCompressionAdapter.d.ts.map +1 -1
  10. package/dist/adapters/compression/documentServiceCompressionAdapter.js +8 -4
  11. package/dist/adapters/compression/documentServiceCompressionAdapter.js.map +1 -1
  12. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts +2 -2
  13. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts.map +1 -1
  14. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.js +7 -7
  15. package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.js.map +1 -1
  16. package/dist/adapters/compression/index.d.ts +3 -3
  17. package/dist/adapters/compression/index.d.ts.map +1 -1
  18. package/dist/adapters/compression/index.js +7 -7
  19. package/dist/adapters/compression/index.js.map +1 -1
  20. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts +2 -2
  21. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts.map +1 -1
  22. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.js +11 -11
  23. package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.js.map +1 -1
  24. package/dist/adapters/compression/summaryblob/index.d.ts +1 -1
  25. package/dist/adapters/compression/summaryblob/index.d.ts.map +1 -1
  26. package/dist/adapters/compression/summaryblob/index.js +3 -3
  27. package/dist/adapters/compression/summaryblob/index.js.map +1 -1
  28. package/dist/adapters/index.d.ts +2 -2
  29. package/dist/adapters/index.d.ts.map +1 -1
  30. package/dist/adapters/index.js +6 -6
  31. package/dist/adapters/index.js.map +1 -1
  32. package/dist/adapters/predefinedAdapters.d.ts +1 -1
  33. package/dist/adapters/predefinedAdapters.d.ts.map +1 -1
  34. package/dist/adapters/predefinedAdapters.js +4 -4
  35. package/dist/adapters/predefinedAdapters.js.map +1 -1
  36. package/dist/documentServiceProxy.d.ts +3 -2
  37. package/dist/documentServiceProxy.d.ts.map +1 -1
  38. package/dist/documentServiceProxy.js +3 -1
  39. package/dist/documentServiceProxy.js.map +1 -1
  40. package/dist/documentStorageServiceProxy.d.ts +2 -2
  41. package/dist/documentStorageServiceProxy.d.ts.map +1 -1
  42. package/dist/documentStorageServiceProxy.js +7 -3
  43. package/dist/documentStorageServiceProxy.js.map +1 -1
  44. package/dist/driver-utils-alpha.d.ts +6 -2
  45. package/dist/driver-utils-beta.d.ts +10 -2
  46. package/dist/driver-utils-public.d.ts +10 -2
  47. package/dist/driver-utils-untrimmed.d.ts +30 -17
  48. package/dist/error.d.ts +2 -2
  49. package/dist/error.d.ts.map +1 -1
  50. package/dist/error.js +1 -3
  51. package/dist/error.js.map +1 -1
  52. package/dist/index.d.ts +17 -16
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +64 -62
  55. package/dist/index.js.map +1 -1
  56. package/dist/insecureUrlResolver.d.ts +3 -2
  57. package/dist/insecureUrlResolver.d.ts.map +1 -1
  58. package/dist/insecureUrlResolver.js +9 -7
  59. package/dist/insecureUrlResolver.js.map +1 -1
  60. package/dist/network.d.ts +13 -10
  61. package/dist/network.d.ts.map +1 -1
  62. package/dist/network.js +9 -12
  63. package/dist/network.js.map +1 -1
  64. package/dist/networkUtils.d.ts +2 -3
  65. package/dist/networkUtils.d.ts.map +1 -1
  66. package/dist/networkUtils.js +3 -3
  67. package/dist/networkUtils.js.map +1 -1
  68. package/dist/package.json +3 -0
  69. package/dist/packageVersion.d.ts +1 -1
  70. package/dist/packageVersion.js +1 -1
  71. package/dist/packageVersion.js.map +1 -1
  72. package/dist/parallelRequests.d.ts +3 -3
  73. package/dist/parallelRequests.d.ts.map +1 -1
  74. package/dist/parallelRequests.js +10 -10
  75. package/dist/parallelRequests.js.map +1 -1
  76. package/dist/prefetchDocumentStorageService.d.ts +1 -1
  77. package/dist/prefetchDocumentStorageService.d.ts.map +1 -1
  78. package/dist/prefetchDocumentStorageService.js +4 -4
  79. package/dist/prefetchDocumentStorageService.js.map +1 -1
  80. package/dist/runWithRetry.js +6 -6
  81. package/dist/runWithRetry.js.map +1 -1
  82. package/dist/storageUtils.d.ts +13 -0
  83. package/dist/storageUtils.d.ts.map +1 -0
  84. package/dist/storageUtils.js +17 -0
  85. package/dist/storageUtils.js.map +1 -0
  86. package/dist/treeConversions.d.ts.map +1 -1
  87. package/dist/treeConversions.js +7 -6
  88. package/dist/treeConversions.js.map +1 -1
  89. package/dist/tsdoc-metadata.json +1 -1
  90. package/lib/adapters/compression/{compressionTypes.d.mts → compressionTypes.d.ts} +1 -1
  91. package/lib/adapters/compression/compressionTypes.d.ts.map +1 -0
  92. package/lib/adapters/compression/{compressionTypes.mjs → compressionTypes.js} +1 -1
  93. package/lib/adapters/compression/compressionTypes.js.map +1 -0
  94. package/lib/adapters/compression/{documentServiceCompressionAdapter.d.mts → documentServiceCompressionAdapter.d.ts} +3 -3
  95. package/lib/adapters/compression/documentServiceCompressionAdapter.d.ts.map +1 -0
  96. package/lib/adapters/compression/{documentServiceCompressionAdapter.mjs → documentServiceCompressionAdapter.js} +7 -3
  97. package/lib/adapters/compression/documentServiceCompressionAdapter.js.map +1 -0
  98. package/lib/adapters/compression/{documentServiceFactoryCompressionAdapter.d.mts → documentServiceFactoryCompressionAdapter.d.ts} +3 -3
  99. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts.map +1 -0
  100. package/lib/adapters/compression/{documentServiceFactoryCompressionAdapter.mjs → documentServiceFactoryCompressionAdapter.js} +4 -4
  101. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.js.map +1 -0
  102. package/lib/adapters/compression/{index.d.mts → index.d.ts} +4 -4
  103. package/lib/adapters/compression/index.d.ts.map +1 -0
  104. package/lib/adapters/compression/{index.mjs → index.js} +4 -4
  105. package/lib/adapters/compression/index.js.map +1 -0
  106. package/lib/adapters/compression/summaryblob/{documentStorageServiceSummaryBlobCompressionAdapter.d.mts → documentStorageServiceSummaryBlobCompressionAdapter.d.ts} +3 -3
  107. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts.map +1 -0
  108. package/lib/adapters/compression/summaryblob/{documentStorageServiceSummaryBlobCompressionAdapter.mjs → documentStorageServiceSummaryBlobCompressionAdapter.js} +3 -3
  109. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.js.map +1 -0
  110. package/lib/adapters/compression/summaryblob/{index.mjs → index.d.ts} +2 -2
  111. package/lib/adapters/compression/summaryblob/index.d.ts.map +1 -0
  112. package/lib/adapters/compression/summaryblob/{index.d.mts → index.js} +2 -2
  113. package/lib/adapters/compression/summaryblob/index.js.map +1 -0
  114. package/lib/adapters/{index.d.mts → index.d.ts} +3 -3
  115. package/lib/adapters/index.d.ts.map +1 -0
  116. package/lib/adapters/{index.mjs → index.js} +3 -3
  117. package/lib/adapters/index.js.map +1 -0
  118. package/lib/adapters/{predefinedAdapters.d.mts → predefinedAdapters.d.ts} +2 -2
  119. package/lib/adapters/predefinedAdapters.d.ts.map +1 -0
  120. package/lib/adapters/{predefinedAdapters.mjs → predefinedAdapters.js} +2 -2
  121. package/lib/adapters/predefinedAdapters.js.map +1 -0
  122. package/lib/{blob.d.mts → blob.d.ts} +1 -1
  123. package/lib/blob.d.ts.map +1 -0
  124. package/lib/{blob.mjs → blob.js} +1 -1
  125. package/lib/blob.js.map +1 -0
  126. package/lib/{buildSnapshotTree.d.mts → buildSnapshotTree.d.ts} +1 -1
  127. package/lib/buildSnapshotTree.d.ts.map +1 -0
  128. package/lib/{buildSnapshotTree.mjs → buildSnapshotTree.js} +1 -1
  129. package/lib/buildSnapshotTree.js.map +1 -0
  130. package/lib/{documentServiceFactoryProxy.d.mts → documentServiceFactoryProxy.d.ts} +1 -1
  131. package/lib/documentServiceFactoryProxy.d.ts.map +1 -0
  132. package/lib/{documentServiceFactoryProxy.mjs → documentServiceFactoryProxy.js} +1 -1
  133. package/lib/documentServiceFactoryProxy.js.map +1 -0
  134. package/lib/{documentServiceProxy.d.mts → documentServiceProxy.d.ts} +4 -3
  135. package/lib/documentServiceProxy.d.ts.map +1 -0
  136. package/lib/{documentServiceProxy.mjs → documentServiceProxy.js} +4 -2
  137. package/lib/documentServiceProxy.js.map +1 -0
  138. package/lib/{documentStorageServiceProxy.d.mts → documentStorageServiceProxy.d.ts} +3 -3
  139. package/lib/documentStorageServiceProxy.d.ts.map +1 -0
  140. package/lib/{documentStorageServiceProxy.mjs → documentStorageServiceProxy.js} +8 -4
  141. package/lib/documentStorageServiceProxy.js.map +1 -0
  142. package/lib/{driver-utils-alpha.d.mts → driver-utils-alpha.d.ts} +6 -2
  143. package/lib/{driver-utils-public.d.mts → driver-utils-beta.d.ts} +10 -2
  144. package/lib/{driver-utils-beta.d.mts → driver-utils-public.d.ts} +10 -2
  145. package/lib/{driver-utils-untrimmed.d.mts → driver-utils-untrimmed.d.ts} +30 -17
  146. package/lib/{error.d.mts → error.d.ts} +3 -3
  147. package/lib/error.d.ts.map +1 -0
  148. package/lib/{error.mjs → error.js} +3 -4
  149. package/lib/error.js.map +1 -0
  150. package/lib/{index.d.mts → index.d.ts} +18 -17
  151. package/lib/index.d.ts.map +1 -0
  152. package/lib/{index.mjs → index.js} +18 -17
  153. package/lib/index.js.map +1 -0
  154. package/lib/{insecureUrlResolver.d.mts → insecureUrlResolver.d.ts} +4 -3
  155. package/lib/insecureUrlResolver.d.ts.map +1 -0
  156. package/lib/{insecureUrlResolver.mjs → insecureUrlResolver.js} +10 -8
  157. package/lib/insecureUrlResolver.js.map +1 -0
  158. package/lib/{messageRecognition.d.mts → messageRecognition.d.ts} +5 -1
  159. package/lib/messageRecognition.d.ts.map +1 -0
  160. package/lib/{messageRecognition.mjs → messageRecognition.js} +5 -1
  161. package/lib/messageRecognition.js.map +1 -0
  162. package/lib/{network.d.mts → network.d.ts} +14 -11
  163. package/lib/network.d.ts.map +1 -0
  164. package/lib/{network.mjs → network.js} +11 -16
  165. package/lib/network.js.map +1 -0
  166. package/lib/networkUtils.d.ts +10 -0
  167. package/lib/networkUtils.d.ts.map +1 -0
  168. package/lib/{networkUtils.mjs → networkUtils.js} +2 -2
  169. package/lib/networkUtils.js.map +1 -0
  170. package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
  171. package/lib/packageVersion.d.ts.map +1 -0
  172. package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
  173. package/lib/packageVersion.js.map +1 -0
  174. package/lib/{parallelRequests.d.mts → parallelRequests.d.ts} +4 -4
  175. package/lib/parallelRequests.d.ts.map +1 -0
  176. package/lib/{parallelRequests.mjs → parallelRequests.js} +10 -5
  177. package/lib/parallelRequests.js.map +1 -0
  178. package/lib/{prefetchDocumentStorageService.d.mts → prefetchDocumentStorageService.d.ts} +6 -2
  179. package/lib/prefetchDocumentStorageService.d.ts.map +1 -0
  180. package/lib/{prefetchDocumentStorageService.mjs → prefetchDocumentStorageService.js} +7 -3
  181. package/lib/prefetchDocumentStorageService.js.map +1 -0
  182. package/lib/{rateLimiter.d.mts → rateLimiter.d.ts} +1 -1
  183. package/lib/rateLimiter.d.ts.map +1 -0
  184. package/lib/{rateLimiter.mjs → rateLimiter.js} +1 -1
  185. package/lib/rateLimiter.js.map +1 -0
  186. package/lib/{readAndParse.d.mts → readAndParse.d.ts} +1 -1
  187. package/lib/readAndParse.d.ts.map +1 -0
  188. package/lib/{readAndParse.mjs → readAndParse.js} +1 -1
  189. package/lib/readAndParse.js.map +1 -0
  190. package/lib/{runWithRetry.d.mts → runWithRetry.d.ts} +1 -1
  191. package/lib/runWithRetry.d.ts.map +1 -0
  192. package/lib/{runWithRetry.mjs → runWithRetry.js} +3 -3
  193. package/lib/runWithRetry.js.map +1 -0
  194. package/lib/storageUtils.d.ts +13 -0
  195. package/lib/storageUtils.d.ts.map +1 -0
  196. package/lib/storageUtils.js +13 -0
  197. package/lib/storageUtils.js.map +1 -0
  198. package/lib/{summaryForCreateNew.d.mts → summaryForCreateNew.d.ts} +1 -1
  199. package/lib/summaryForCreateNew.d.ts.map +1 -0
  200. package/lib/{summaryForCreateNew.mjs → summaryForCreateNew.js} +1 -1
  201. package/lib/summaryForCreateNew.js.map +1 -0
  202. package/lib/test/insecureUrlResolverTest.spec.js +101 -0
  203. package/lib/test/insecureUrlResolverTest.spec.js.map +1 -0
  204. package/lib/test/parallelRequests.spec.js +186 -0
  205. package/lib/test/parallelRequests.spec.js.map +1 -0
  206. package/lib/test/rateLimiter.spec.js +85 -0
  207. package/lib/test/rateLimiter.spec.js.map +1 -0
  208. package/lib/test/runWithRetry.spec.js +180 -0
  209. package/lib/test/runWithRetry.spec.js.map +1 -0
  210. package/lib/test/summaryCompressionData.js +170 -0
  211. package/lib/test/summaryCompressionData.js.map +1 -0
  212. package/lib/test/summaryCompresssionTester.spec.js +429 -0
  213. package/lib/test/summaryCompresssionTester.spec.js.map +1 -0
  214. package/lib/test/types/validateDriverUtilsPrevious.generated.js +108 -0
  215. package/lib/test/types/validateDriverUtilsPrevious.generated.js.map +1 -0
  216. package/lib/{treeConversions.d.mts → treeConversions.d.ts} +1 -1
  217. package/lib/treeConversions.d.ts.map +1 -0
  218. package/lib/{treeConversions.mjs → treeConversions.js} +4 -3
  219. package/lib/treeConversions.js.map +1 -0
  220. package/package.json +82 -28
  221. package/src/adapters/compression/documentServiceCompressionAdapter.ts +9 -3
  222. package/src/adapters/compression/documentServiceFactoryCompressionAdapter.ts +4 -4
  223. package/src/adapters/compression/index.ts +3 -3
  224. package/src/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.ts +2 -2
  225. package/src/adapters/compression/summaryblob/index.ts +1 -1
  226. package/src/adapters/index.ts +2 -2
  227. package/src/adapters/predefinedAdapters.ts +1 -1
  228. package/src/documentServiceProxy.ts +9 -2
  229. package/src/documentStorageServiceProxy.ts +12 -4
  230. package/src/error.ts +2 -4
  231. package/src/index.ts +17 -16
  232. package/src/insecureUrlResolver.ts +8 -6
  233. package/src/network.ts +11 -16
  234. package/src/networkUtils.ts +3 -4
  235. package/src/packageVersion.ts +1 -1
  236. package/src/parallelRequests.ts +11 -11
  237. package/src/prefetchDocumentStorageService.ts +2 -2
  238. package/src/runWithRetry.ts +2 -2
  239. package/src/storageUtils.ts +18 -0
  240. package/src/treeConversions.ts +3 -2
  241. package/tsconfig.cjs.json +7 -0
  242. package/tsconfig.json +2 -5
  243. package/lib/adapters/compression/compressionTypes.d.mts.map +0 -1
  244. package/lib/adapters/compression/compressionTypes.mjs.map +0 -1
  245. package/lib/adapters/compression/documentServiceCompressionAdapter.d.mts.map +0 -1
  246. package/lib/adapters/compression/documentServiceCompressionAdapter.mjs.map +0 -1
  247. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.d.mts.map +0 -1
  248. package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.mjs.map +0 -1
  249. package/lib/adapters/compression/index.d.mts.map +0 -1
  250. package/lib/adapters/compression/index.mjs.map +0 -1
  251. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.mts.map +0 -1
  252. package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.mjs.map +0 -1
  253. package/lib/adapters/compression/summaryblob/index.d.mts.map +0 -1
  254. package/lib/adapters/compression/summaryblob/index.mjs.map +0 -1
  255. package/lib/adapters/index.d.mts.map +0 -1
  256. package/lib/adapters/index.mjs.map +0 -1
  257. package/lib/adapters/predefinedAdapters.d.mts.map +0 -1
  258. package/lib/adapters/predefinedAdapters.mjs.map +0 -1
  259. package/lib/blob.d.mts.map +0 -1
  260. package/lib/blob.mjs.map +0 -1
  261. package/lib/buildSnapshotTree.d.mts.map +0 -1
  262. package/lib/buildSnapshotTree.mjs.map +0 -1
  263. package/lib/documentServiceFactoryProxy.d.mts.map +0 -1
  264. package/lib/documentServiceFactoryProxy.mjs.map +0 -1
  265. package/lib/documentServiceProxy.d.mts.map +0 -1
  266. package/lib/documentServiceProxy.mjs.map +0 -1
  267. package/lib/documentStorageServiceProxy.d.mts.map +0 -1
  268. package/lib/documentStorageServiceProxy.mjs.map +0 -1
  269. package/lib/error.d.mts.map +0 -1
  270. package/lib/error.mjs.map +0 -1
  271. package/lib/index.d.mts.map +0 -1
  272. package/lib/index.mjs.map +0 -1
  273. package/lib/insecureUrlResolver.d.mts.map +0 -1
  274. package/lib/insecureUrlResolver.mjs.map +0 -1
  275. package/lib/messageRecognition.d.mts.map +0 -1
  276. package/lib/messageRecognition.mjs.map +0 -1
  277. package/lib/network.d.mts.map +0 -1
  278. package/lib/network.mjs.map +0 -1
  279. package/lib/networkUtils.d.mts +0 -11
  280. package/lib/networkUtils.d.mts.map +0 -1
  281. package/lib/networkUtils.mjs.map +0 -1
  282. package/lib/packageVersion.d.mts.map +0 -1
  283. package/lib/packageVersion.mjs.map +0 -1
  284. package/lib/parallelRequests.d.mts.map +0 -1
  285. package/lib/parallelRequests.mjs.map +0 -1
  286. package/lib/prefetchDocumentStorageService.d.mts.map +0 -1
  287. package/lib/prefetchDocumentStorageService.mjs.map +0 -1
  288. package/lib/rateLimiter.d.mts.map +0 -1
  289. package/lib/rateLimiter.mjs.map +0 -1
  290. package/lib/readAndParse.d.mts.map +0 -1
  291. package/lib/readAndParse.mjs.map +0 -1
  292. package/lib/runWithRetry.d.mts.map +0 -1
  293. package/lib/runWithRetry.mjs.map +0 -1
  294. package/lib/summaryForCreateNew.d.mts.map +0 -1
  295. package/lib/summaryForCreateNew.mjs.map +0 -1
  296. package/lib/treeConversions.d.mts.map +0 -1
  297. package/lib/treeConversions.mjs.map +0 -1
@@ -0,0 +1,186 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "assert";
6
+ import { MockLogger } from "@fluidframework/telemetry-utils";
7
+ import { unreachableCase } from "@fluidframework/core-utils";
8
+ import { ParallelRequests } from "../parallelRequests.js";
9
+ var HowMany;
10
+ (function (HowMany) {
11
+ HowMany[HowMany["Exact"] = 0] = "Exact";
12
+ HowMany[HowMany["Partial"] = 1] = "Partial";
13
+ HowMany[HowMany["TooMany"] = 2] = "TooMany";
14
+ })(HowMany || (HowMany = {}));
15
+ describe("Parallel Requests", () => {
16
+ async function test(concurrency, payloadSize, from, to, expectedRequests, knownTo, howMany = HowMany.Exact) {
17
+ let nextElement = from;
18
+ let requests = 0;
19
+ let dispatches = 0;
20
+ const logger = new MockLogger();
21
+ const manager = new ParallelRequests(from, knownTo ? to : undefined, payloadSize, logger.toTelemetryLogger(), async (request, _from, _to) => {
22
+ let length = _to - _from;
23
+ requests++;
24
+ assert(_from >= from);
25
+ assert(length <= payloadSize);
26
+ assert(requests <= request);
27
+ assert(!knownTo || _to <= to);
28
+ switch (howMany) {
29
+ case HowMany.Partial:
30
+ length = Math.min(length, payloadSize / 2 + 1);
31
+ break;
32
+ case HowMany.TooMany:
33
+ length = 2 * length + 2;
34
+ break;
35
+ case HowMany.Exact:
36
+ break;
37
+ default:
38
+ unreachableCase(howMany);
39
+ }
40
+ // covering knownTo === false case
41
+ const actualTo = Math.min(_from + length, to);
42
+ const payload = [];
43
+ for (let i = _from; i < actualTo; i++) {
44
+ payload.push(i);
45
+ }
46
+ return {
47
+ partial: _from !== to && howMany === HowMany.Partial,
48
+ cancel: false,
49
+ payload,
50
+ };
51
+ }, (deltas) => {
52
+ dispatches++;
53
+ // Big chunks are broken into smaller ones
54
+ assert(dispatches <= requests || howMany === HowMany.TooMany);
55
+ for (const el of deltas) {
56
+ assert(el === nextElement);
57
+ nextElement++;
58
+ }
59
+ });
60
+ await manager.run(concurrency);
61
+ assert(nextElement === to);
62
+ assert(!knownTo || dispatches === requests);
63
+ assert.equal(requests, expectedRequests, "expected requests");
64
+ logger.assertMatchNone([{ category: "error" }]);
65
+ }
66
+ async function testCancel(from, to, cancelAt, payloadSize, expectedRequests) {
67
+ let nextElement = from;
68
+ let requests = 0;
69
+ let dispatches = 0;
70
+ const logger = new MockLogger();
71
+ const manager = new ParallelRequests(from, to, payloadSize, logger.toTelemetryLogger(), async (request, _from, _to) => {
72
+ const length = _to - _from;
73
+ requests++;
74
+ assert(_from >= from);
75
+ assert(length <= payloadSize);
76
+ assert(requests <= request);
77
+ assert(to === undefined || _to <= to);
78
+ if (_to > cancelAt) {
79
+ return { partial: false, cancel: true, payload: [] };
80
+ }
81
+ const payload = [];
82
+ for (let i = _from; i < _to; i++) {
83
+ payload.push(i);
84
+ }
85
+ return { partial: false, cancel: false, payload };
86
+ }, (deltas) => {
87
+ dispatches++;
88
+ assert(dispatches <= requests);
89
+ for (const el of deltas) {
90
+ assert(el === nextElement);
91
+ nextElement++;
92
+ }
93
+ });
94
+ await manager.run(10);
95
+ assert(dispatches <= requests);
96
+ assert(requests === expectedRequests);
97
+ logger.assertMatchNone([{ category: "error" }]);
98
+ }
99
+ it("no concurrency, single request, over", async () => {
100
+ await test(1, 100, 123, 156, 1, true);
101
+ await test(1, 100, 123, 156, 1, false);
102
+ await test(1, 100, 123, 156, 1, true, HowMany.TooMany);
103
+ await test(1, 100, 123, 156, 1, true, HowMany.Partial);
104
+ });
105
+ it("no concurrency, single request, exact", async () => {
106
+ await test(1, 156 - 123, 123, 156, 1, true);
107
+ await test(1, 156 - 123, 123, 156, 2, false);
108
+ await test(1, 156 - 123, 123, 156, 1, true, HowMany.TooMany);
109
+ await test(1, 156 - 123, 123, 156, 2, true, HowMany.Partial);
110
+ await test(1, 156 - 123, 123, 156, 2, false, HowMany.TooMany);
111
+ await test(1, 156 - 123, 123, 156, 3, false, HowMany.Partial);
112
+ });
113
+ it("concurrency, single request, exact", async () => {
114
+ await test(2, 156 - 123, 123, 156, 1, true);
115
+ await test(2, 156 - 123, 123, 156, 1, true, HowMany.TooMany);
116
+ await test(2, 156 - 123, 123, 156, 2, true, HowMany.Partial);
117
+ // here, the number of actual requests is Ok to be 2..3
118
+ await test(2, 156 - 123, 123, 156, 3, false);
119
+ await test(2, 156 - 123, 123, 156, 3, false, HowMany.TooMany);
120
+ await test(2, 156 - 123, 123, 156, 3, false, HowMany.Partial);
121
+ });
122
+ it("no concurrency, multiple requests", async () => {
123
+ await test(1, 10, 123, 156, 4, true);
124
+ await test(1, 10, 123, 156, 4, false);
125
+ await test(1, 10, 123, 156, 3, false, HowMany.TooMany);
126
+ });
127
+ it("two concurrent requests exact", async () => {
128
+ await test(2, 10, 123, 153, 3, true);
129
+ await test(2, 10, 123, 153, 3, true, HowMany.TooMany);
130
+ await test(2, 10, 123, 153, 6, true, HowMany.Partial);
131
+ await test(2, 10, 123, 153, 5, false);
132
+ await test(2, 10, 123, 153, 5, false, HowMany.TooMany);
133
+ await test(2, 10, 123, 153, 8, false, HowMany.Partial);
134
+ });
135
+ it("two concurrent requests one over", async () => {
136
+ await test(2, 10, 123, 154, 4, true);
137
+ // here, the number of actual requests is Ok to be 4..5
138
+ await test(2, 10, 123, 154, 5, false);
139
+ });
140
+ it("four concurrent requests", async () => {
141
+ await test(4, 10, 123, 156, 4, true);
142
+ // here, the number of actual requests is Ok to be 4..7
143
+ await test(4, 10, 123, 156, 7, false);
144
+ });
145
+ it("cancellation", async () => {
146
+ await testCancel(1, 1000, 502, 10, 60);
147
+ await testCancel(1, undefined, 502, 10, 60);
148
+ });
149
+ it("exception in request", async () => {
150
+ const logger = new MockLogger();
151
+ const manager = new ParallelRequests(1, 100, 10, logger.toTelemetryLogger(), async (request, _from, _to) => {
152
+ throw new Error("request");
153
+ }, (deltas) => {
154
+ throw new Error("response");
155
+ });
156
+ let success = true;
157
+ try {
158
+ await manager.run(10);
159
+ }
160
+ catch (error) {
161
+ success = false;
162
+ assert(error.message === "request");
163
+ }
164
+ assert(!success);
165
+ logger.assertMatchNone([{ category: "error" }]);
166
+ });
167
+ it("exception in response", async () => {
168
+ const logger = new MockLogger();
169
+ const manager = new ParallelRequests(1, 100, 10, logger.toTelemetryLogger(), async (request, _from, _to) => {
170
+ return { cancel: false, partial: false, payload: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] };
171
+ }, (deltas) => {
172
+ throw new Error("response");
173
+ });
174
+ let success = true;
175
+ try {
176
+ await manager.run(10);
177
+ }
178
+ catch (error) {
179
+ success = false;
180
+ assert(error.message === "response");
181
+ }
182
+ assert(!success);
183
+ logger.assertMatchNone([{ category: "error" }]);
184
+ });
185
+ });
186
+ //# sourceMappingURL=parallelRequests.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallelRequests.spec.js","sourceRoot":"","sources":["../../src/test/parallelRequests.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { MockLogger } from \"@fluidframework/telemetry-utils\";\nimport { unreachableCase } from \"@fluidframework/core-utils\";\nimport { ParallelRequests } from \"../parallelRequests.js\";\n\nenum HowMany {\n\tExact,\n\tPartial,\n\tTooMany,\n}\n\ndescribe(\"Parallel Requests\", () => {\n\tasync function test(\n\t\tconcurrency: number,\n\t\tpayloadSize: number,\n\t\tfrom: number,\n\t\tto: number,\n\t\texpectedRequests: number,\n\t\tknownTo: boolean,\n\t\thowMany: HowMany = HowMany.Exact,\n\t) {\n\t\tlet nextElement = from;\n\t\tlet requests = 0;\n\t\tlet dispatches = 0;\n\n\t\tconst logger = new MockLogger();\n\n\t\tconst manager = new ParallelRequests<number>(\n\t\t\tfrom,\n\t\t\tknownTo ? to : undefined,\n\t\t\tpayloadSize,\n\t\t\tlogger.toTelemetryLogger(),\n\t\t\tasync (request: number, _from: number, _to: number) => {\n\t\t\t\tlet length = _to - _from;\n\t\t\t\trequests++;\n\n\t\t\t\tassert(_from >= from);\n\t\t\t\tassert(length <= payloadSize);\n\t\t\t\tassert(requests <= request);\n\t\t\t\tassert(!knownTo || _to <= to);\n\n\t\t\t\tswitch (howMany) {\n\t\t\t\t\tcase HowMany.Partial:\n\t\t\t\t\t\tlength = Math.min(length, payloadSize / 2 + 1);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HowMany.TooMany:\n\t\t\t\t\t\tlength = 2 * length + 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HowMany.Exact:\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tunreachableCase(howMany);\n\t\t\t\t}\n\t\t\t\t// covering knownTo === false case\n\t\t\t\tconst actualTo = Math.min(_from + length, to);\n\n\t\t\t\tconst payload: number[] = [];\n\t\t\t\tfor (let i = _from; i < actualTo; i++) {\n\t\t\t\t\tpayload.push(i);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tpartial: _from !== to && howMany === HowMany.Partial,\n\t\t\t\t\tcancel: false,\n\t\t\t\t\tpayload,\n\t\t\t\t};\n\t\t\t},\n\t\t\t(deltas: number[]) => {\n\t\t\t\tdispatches++;\n\t\t\t\t// Big chunks are broken into smaller ones\n\t\t\t\tassert(dispatches <= requests || howMany === HowMany.TooMany);\n\t\t\t\tfor (const el of deltas) {\n\t\t\t\t\tassert(el === nextElement);\n\t\t\t\t\tnextElement++;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tawait manager.run(concurrency);\n\n\t\tassert(nextElement === to);\n\t\tassert(!knownTo || dispatches === requests);\n\t\tassert.equal(requests, expectedRequests, \"expected requests\");\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t}\n\n\tasync function testCancel(\n\t\tfrom: number,\n\t\tto: number | undefined,\n\t\tcancelAt: number,\n\t\tpayloadSize,\n\t\texpectedRequests: number,\n\t) {\n\t\tlet nextElement = from;\n\t\tlet requests = 0;\n\t\tlet dispatches = 0;\n\t\tconst logger = new MockLogger();\n\n\t\tconst manager = new ParallelRequests<number>(\n\t\t\tfrom,\n\t\t\tto,\n\t\t\tpayloadSize,\n\t\t\tlogger.toTelemetryLogger(),\n\t\t\tasync (request: number, _from: number, _to: number) => {\n\t\t\t\tconst length = _to - _from;\n\t\t\t\trequests++;\n\n\t\t\t\tassert(_from >= from);\n\t\t\t\tassert(length <= payloadSize);\n\t\t\t\tassert(requests <= request);\n\t\t\t\tassert(to === undefined || _to <= to);\n\n\t\t\t\tif (_to > cancelAt) {\n\t\t\t\t\treturn { partial: false, cancel: true, payload: [] };\n\t\t\t\t}\n\n\t\t\t\tconst payload: number[] = [];\n\t\t\t\tfor (let i = _from; i < _to; i++) {\n\t\t\t\t\tpayload.push(i);\n\t\t\t\t}\n\n\t\t\t\treturn { partial: false, cancel: false, payload };\n\t\t\t},\n\t\t\t(deltas: number[]) => {\n\t\t\t\tdispatches++;\n\t\t\t\tassert(dispatches <= requests);\n\t\t\t\tfor (const el of deltas) {\n\t\t\t\t\tassert(el === nextElement);\n\t\t\t\t\tnextElement++;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tawait manager.run(10);\n\n\t\tassert(dispatches <= requests);\n\t\tassert(requests === expectedRequests);\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t}\n\n\tit(\"no concurrency, single request, over\", async () => {\n\t\tawait test(1, 100, 123, 156, 1, true);\n\t\tawait test(1, 100, 123, 156, 1, false);\n\t\tawait test(1, 100, 123, 156, 1, true, HowMany.TooMany);\n\t\tawait test(1, 100, 123, 156, 1, true, HowMany.Partial);\n\t});\n\n\tit(\"no concurrency, single request, exact\", async () => {\n\t\tawait test(1, 156 - 123, 123, 156, 1, true);\n\t\tawait test(1, 156 - 123, 123, 156, 2, false);\n\t\tawait test(1, 156 - 123, 123, 156, 1, true, HowMany.TooMany);\n\t\tawait test(1, 156 - 123, 123, 156, 2, true, HowMany.Partial);\n\t\tawait test(1, 156 - 123, 123, 156, 2, false, HowMany.TooMany);\n\t\tawait test(1, 156 - 123, 123, 156, 3, false, HowMany.Partial);\n\t});\n\n\tit(\"concurrency, single request, exact\", async () => {\n\t\tawait test(2, 156 - 123, 123, 156, 1, true);\n\t\tawait test(2, 156 - 123, 123, 156, 1, true, HowMany.TooMany);\n\t\tawait test(2, 156 - 123, 123, 156, 2, true, HowMany.Partial);\n\t\t// here, the number of actual requests is Ok to be 2..3\n\t\tawait test(2, 156 - 123, 123, 156, 3, false);\n\t\tawait test(2, 156 - 123, 123, 156, 3, false, HowMany.TooMany);\n\t\tawait test(2, 156 - 123, 123, 156, 3, false, HowMany.Partial);\n\t});\n\n\tit(\"no concurrency, multiple requests\", async () => {\n\t\tawait test(1, 10, 123, 156, 4, true);\n\t\tawait test(1, 10, 123, 156, 4, false);\n\t\tawait test(1, 10, 123, 156, 3, false, HowMany.TooMany);\n\t});\n\n\tit(\"two concurrent requests exact\", async () => {\n\t\tawait test(2, 10, 123, 153, 3, true);\n\t\tawait test(2, 10, 123, 153, 3, true, HowMany.TooMany);\n\t\tawait test(2, 10, 123, 153, 6, true, HowMany.Partial);\n\t\tawait test(2, 10, 123, 153, 5, false);\n\t\tawait test(2, 10, 123, 153, 5, false, HowMany.TooMany);\n\t\tawait test(2, 10, 123, 153, 8, false, HowMany.Partial);\n\t});\n\n\tit(\"two concurrent requests one over\", async () => {\n\t\tawait test(2, 10, 123, 154, 4, true);\n\t\t// here, the number of actual requests is Ok to be 4..5\n\t\tawait test(2, 10, 123, 154, 5, false);\n\t});\n\n\tit(\"four concurrent requests\", async () => {\n\t\tawait test(4, 10, 123, 156, 4, true);\n\t\t// here, the number of actual requests is Ok to be 4..7\n\t\tawait test(4, 10, 123, 156, 7, false);\n\t});\n\n\tit(\"cancellation\", async () => {\n\t\tawait testCancel(1, 1000, 502, 10, 60);\n\t\tawait testCancel(1, undefined, 502, 10, 60);\n\t});\n\n\tit(\"exception in request\", async () => {\n\t\tconst logger = new MockLogger();\n\n\t\tconst manager = new ParallelRequests<number>(\n\t\t\t1,\n\t\t\t100,\n\t\t\t10,\n\t\t\tlogger.toTelemetryLogger(),\n\t\t\tasync (request: number, _from: number, _to: number) => {\n\t\t\t\tthrow new Error(\"request\");\n\t\t\t},\n\t\t\t(deltas: number[]) => {\n\t\t\t\tthrow new Error(\"response\");\n\t\t\t},\n\t\t);\n\n\t\tlet success = true;\n\t\ttry {\n\t\t\tawait manager.run(10);\n\t\t} catch (error: any) {\n\t\t\tsuccess = false;\n\t\t\tassert(error.message === \"request\");\n\t\t}\n\t\tassert(!success);\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t});\n\n\tit(\"exception in response\", async () => {\n\t\tconst logger = new MockLogger();\n\n\t\tconst manager = new ParallelRequests<number>(\n\t\t\t1,\n\t\t\t100,\n\t\t\t10,\n\t\t\tlogger.toTelemetryLogger(),\n\t\t\tasync (request: number, _from: number, _to: number) => {\n\t\t\t\treturn { cancel: false, partial: false, payload: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] };\n\t\t\t},\n\t\t\t(deltas: number[]) => {\n\t\t\t\tthrow new Error(\"response\");\n\t\t\t},\n\t\t);\n\n\t\tlet success = true;\n\t\ttry {\n\t\t\tawait manager.run(10);\n\t\t} catch (error: any) {\n\t\t\tsuccess = false;\n\t\t\tassert(error.message === \"response\");\n\t\t}\n\t\tassert(!success);\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t});\n});\n"]}
@@ -0,0 +1,85 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "assert";
6
+ import { RateLimiter } from "../rateLimiter.js";
7
+ describe("Rate Limiter", () => {
8
+ let limiter;
9
+ beforeEach(() => {
10
+ limiter = new RateLimiter(3);
11
+ });
12
+ it("can run task", async () => {
13
+ let done = false;
14
+ assert(limiter.waitQueueLength === 0);
15
+ await limiter.schedule(async () => {
16
+ assert(limiter.waitQueueLength === 0);
17
+ done = true;
18
+ });
19
+ assert(done);
20
+ });
21
+ it("can run 3 tasks", async () => {
22
+ let done = false;
23
+ await limiter.schedule(async () => {
24
+ await limiter.schedule(async () => {
25
+ await limiter.schedule(async () => {
26
+ assert(limiter.waitQueueLength === 0);
27
+ done = true;
28
+ });
29
+ });
30
+ });
31
+ assert(done);
32
+ });
33
+ it("can run 4 tasks", async () => {
34
+ let done = false;
35
+ let promise;
36
+ await limiter.schedule(async () => {
37
+ await limiter.schedule(async () => {
38
+ await limiter.schedule(async () => {
39
+ promise = limiter.schedule(async () => {
40
+ done = true;
41
+ });
42
+ assert(limiter.waitQueueLength === 1);
43
+ });
44
+ assert(limiter.waitQueueLength === 0);
45
+ });
46
+ });
47
+ assert(promise !== undefined);
48
+ await promise;
49
+ assert(done);
50
+ assert(limiter.waitQueueLength === 0);
51
+ });
52
+ it("can run a lot of tasks", async () => {
53
+ let counter = 0;
54
+ const tasks = 100;
55
+ const promises = [];
56
+ for (let i = 0; i < tasks; i++) {
57
+ promises.push(limiter.schedule(async () => {
58
+ counter++;
59
+ }));
60
+ }
61
+ // This is implementation detail and may not be true in the future.
62
+ // I.e. RateLimiter may asynchronously pick up first 3 tasks.
63
+ assert(limiter.waitQueueLength === tasks - 3);
64
+ await Promise.all(promises);
65
+ assert(counter === tasks);
66
+ assert(limiter.waitQueueLength === 0);
67
+ });
68
+ it("can run many tasks sequentially", async () => {
69
+ let counter = 0;
70
+ const promises = [];
71
+ for (let i = 0; i < 3; i++) {
72
+ promises.push(limiter.schedule(async () => {
73
+ counter++;
74
+ }));
75
+ }
76
+ await Promise.all(promises);
77
+ // Now check that we can schedule another task.
78
+ await limiter.schedule(async () => {
79
+ counter++;
80
+ });
81
+ assert(counter === 4);
82
+ assert(limiter.waitQueueLength === 0);
83
+ });
84
+ });
85
+ //# sourceMappingURL=rateLimiter.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimiter.spec.js","sourceRoot":"","sources":["../../src/test/rateLimiter.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { RateLimiter } from \"../rateLimiter.js\";\n\ndescribe(\"Rate Limiter\", () => {\n\tlet limiter: RateLimiter;\n\n\tbeforeEach(() => {\n\t\tlimiter = new RateLimiter(3);\n\t});\n\n\tit(\"can run task\", async () => {\n\t\tlet done = false;\n\t\tassert(limiter.waitQueueLength === 0);\n\t\tawait limiter.schedule(async () => {\n\t\t\tassert(limiter.waitQueueLength === 0);\n\t\t\tdone = true;\n\t\t});\n\t\tassert(done);\n\t});\n\n\tit(\"can run 3 tasks\", async () => {\n\t\tlet done = false;\n\t\tawait limiter.schedule(async () => {\n\t\t\tawait limiter.schedule(async () => {\n\t\t\t\tawait limiter.schedule(async () => {\n\t\t\t\t\tassert(limiter.waitQueueLength === 0);\n\t\t\t\t\tdone = true;\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\tassert(done);\n\t});\n\n\tit(\"can run 4 tasks\", async () => {\n\t\tlet done = false;\n\t\tlet promise: Promise<void> | undefined;\n\t\tawait limiter.schedule(async () => {\n\t\t\tawait limiter.schedule(async () => {\n\t\t\t\tawait limiter.schedule(async () => {\n\t\t\t\t\tpromise = limiter.schedule(async () => {\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t});\n\t\t\t\t\tassert(limiter.waitQueueLength === 1);\n\t\t\t\t});\n\t\t\t\tassert(limiter.waitQueueLength === 0);\n\t\t\t});\n\t\t});\n\t\tassert(promise !== undefined);\n\t\tawait promise;\n\t\tassert(done);\n\t\tassert(limiter.waitQueueLength === 0);\n\t});\n\n\tit(\"can run a lot of tasks\", async () => {\n\t\tlet counter = 0;\n\t\tconst tasks = 100;\n\t\tconst promises: Promise<void>[] = [];\n\t\tfor (let i = 0; i < tasks; i++) {\n\t\t\tpromises.push(\n\t\t\t\tlimiter.schedule(async () => {\n\t\t\t\t\tcounter++;\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// This is implementation detail and may not be true in the future.\n\t\t// I.e. RateLimiter may asynchronously pick up first 3 tasks.\n\t\tassert(limiter.waitQueueLength === tasks - 3);\n\n\t\tawait Promise.all(promises);\n\t\tassert(counter === tasks);\n\t\tassert(limiter.waitQueueLength === 0);\n\t});\n\n\tit(\"can run many tasks sequentially\", async () => {\n\t\tlet counter = 0;\n\t\tconst promises: Promise<void>[] = [];\n\t\tfor (let i = 0; i < 3; i++) {\n\t\t\tpromises.push(\n\t\t\t\tlimiter.schedule(async () => {\n\t\t\t\t\tcounter++;\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tawait Promise.all(promises);\n\t\t// Now check that we can schedule another task.\n\t\tawait limiter.schedule(async () => {\n\t\t\tcounter++;\n\t\t});\n\t\tassert(counter === 4);\n\t\tassert(limiter.waitQueueLength === 0);\n\t});\n});\n"]}
@@ -0,0 +1,180 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "assert";
6
+ import { DriverErrorTypes } from "@fluidframework/driver-definitions";
7
+ import { createChildLogger } from "@fluidframework/telemetry-utils";
8
+ import { runWithRetry } from "../runWithRetry.js";
9
+ const _setTimeout = global.setTimeout;
10
+ const fastSetTimeout = (callback, ms, ...args) => _setTimeout(callback, ms / 1000.0, ...args);
11
+ async function runWithFastSetTimeout(callback) {
12
+ global.setTimeout = fastSetTimeout;
13
+ return callback().finally(() => {
14
+ global.setTimeout = _setTimeout;
15
+ });
16
+ }
17
+ describe("runWithRetry Tests", () => {
18
+ const logger = createChildLogger();
19
+ it("Should succeed at first time", async () => {
20
+ let retryTimes = 1;
21
+ let success = false;
22
+ const api = async () => {
23
+ retryTimes -= 1;
24
+ return true;
25
+ };
26
+ let emitDelayInfoTimes = 0;
27
+ success = await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {
28
+ onRetry: () => {
29
+ emitDelayInfoTimes += 1;
30
+ },
31
+ }));
32
+ assert.strictEqual(retryTimes, 0, "Should succeed at first time");
33
+ assert.strictEqual(success, true, "Retry should succeed ultimately");
34
+ assert.strictEqual(emitDelayInfoTimes, 0, "Should not emit delay at first time");
35
+ });
36
+ it("Check that it retries infinitely", async () => {
37
+ const maxTries = 5;
38
+ let retryTimes = maxTries;
39
+ let success = false;
40
+ const api = async () => {
41
+ if (retryTimes > 0) {
42
+ retryTimes -= 1;
43
+ const error = new Error("Throw error");
44
+ error.retryAfterSeconds = 10;
45
+ error.canRetry = true;
46
+ throw error;
47
+ }
48
+ return true;
49
+ };
50
+ let emitDelayInfoTimes = 0;
51
+ success = await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {
52
+ onRetry: () => {
53
+ emitDelayInfoTimes += 1;
54
+ },
55
+ }));
56
+ assert.strictEqual(retryTimes, 0, "Should keep retrying until success");
57
+ assert.strictEqual(success, true, "Retry should succeed ultimately");
58
+ assert.strictEqual(emitDelayInfoTimes, maxTries, "Should emit delay at each try");
59
+ });
60
+ it("Check that it retries after retry seconds", async () => {
61
+ let retryTimes = 1;
62
+ let success = false;
63
+ const api = async () => {
64
+ if (retryTimes > 0) {
65
+ retryTimes -= 1;
66
+ const error = new Error("Throttle Error");
67
+ error.errorType = DriverErrorTypes.throttlingError;
68
+ error.retryAfterSeconds = 400;
69
+ error.canRetry = true;
70
+ throw error;
71
+ }
72
+ return true;
73
+ };
74
+ success = await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {}));
75
+ assert.strictEqual(retryTimes, 0, "Should retry once");
76
+ assert.strictEqual(success, true, "Retry should succeed ultimately");
77
+ });
78
+ it("If error is just a string, should retry as canRetry is not false", async () => {
79
+ let retryTimes = 1;
80
+ let success = false;
81
+ const api = async () => {
82
+ if (retryTimes > 0) {
83
+ retryTimes -= 1;
84
+ const err = new Error("error");
85
+ err.canRetry = true;
86
+ throw err;
87
+ }
88
+ return true;
89
+ };
90
+ try {
91
+ success = await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {}));
92
+ }
93
+ catch (error) { }
94
+ assert.strictEqual(retryTimes, 0, "Should retry");
95
+ assert.strictEqual(success, true, "Should succeed as retry should be successful");
96
+ });
97
+ it("Should not retry if canRetry is set as false", async () => {
98
+ let retryTimes = 1;
99
+ let success = false;
100
+ const api = async () => {
101
+ if (retryTimes > 0) {
102
+ retryTimes -= 1;
103
+ const error = new Error("error");
104
+ error.canRetry = false;
105
+ throw error;
106
+ }
107
+ return true;
108
+ };
109
+ try {
110
+ success = await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {}));
111
+ assert.fail("Should not succeed");
112
+ }
113
+ catch (error) { }
114
+ assert.strictEqual(retryTimes, 0, "Should not retry");
115
+ assert.strictEqual(success, false, "Should not succeed as canRetry was not set");
116
+ });
117
+ it("Should not retry if canRetry is not set", async () => {
118
+ let retryTimes = 1;
119
+ let success = false;
120
+ const api = async () => {
121
+ if (retryTimes > 0) {
122
+ retryTimes -= 1;
123
+ const error = new Error("error");
124
+ throw error;
125
+ }
126
+ return true;
127
+ };
128
+ try {
129
+ success = await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {}));
130
+ assert.fail("Should not succeed");
131
+ }
132
+ catch (error) { }
133
+ assert.strictEqual(retryTimes, 0, "Should not retry");
134
+ assert.strictEqual(success, false, "Should not succeed as canRetry was not set");
135
+ });
136
+ it("Should not retry if it is disabled", async () => {
137
+ let retryTimes = 1;
138
+ let success = false;
139
+ const api = async () => {
140
+ if (retryTimes > 0) {
141
+ retryTimes -= 1;
142
+ const error = new Error("error");
143
+ error.canRetry = true;
144
+ throw error;
145
+ }
146
+ return true;
147
+ };
148
+ try {
149
+ success = await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {
150
+ onRetry: () => {
151
+ throw new Error("disposed");
152
+ },
153
+ }));
154
+ assert.fail("Should not succeed");
155
+ }
156
+ catch (error) { }
157
+ assert.strictEqual(retryTimes, 0, "Should not retry");
158
+ assert.strictEqual(success, false, "Should not succeed as retrying was disabled");
159
+ });
160
+ it("Abort reason is included in thrown exception", async () => {
161
+ const abortController = new AbortController();
162
+ const api = () => {
163
+ abortController.abort("Sample abort reason");
164
+ const error = new Error("aborted");
165
+ error.canRetry = true;
166
+ throw error;
167
+ };
168
+ try {
169
+ await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {
170
+ cancel: abortController.signal,
171
+ }));
172
+ assert.fail("Should not succeed");
173
+ }
174
+ catch (error) {
175
+ assert.strictEqual(error.message, "runWithRetry was Aborted");
176
+ assert.strictEqual(error.reason, "Sample abort reason");
177
+ }
178
+ });
179
+ });
180
+ //# sourceMappingURL=runWithRetry.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runWithRetry.spec.js","sourceRoot":"","sources":["../../src/test/runWithRetry.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { runWithRetry } from \"../runWithRetry.js\";\n\nconst _setTimeout = global.setTimeout;\nconst fastSetTimeout: any = (callback: (...cbArgs: any[]) => void, ms: number, ...args: any[]) =>\n\t_setTimeout(callback, ms / 1000.0, ...args);\nasync function runWithFastSetTimeout<T>(callback: () => Promise<T>): Promise<T> {\n\tglobal.setTimeout = fastSetTimeout;\n\treturn callback().finally(() => {\n\t\tglobal.setTimeout = _setTimeout;\n\t});\n}\n\ndescribe(\"runWithRetry Tests\", () => {\n\tconst logger = createChildLogger();\n\n\tit(\"Should succeed at first time\", async () => {\n\t\tlet retryTimes: number = 1;\n\t\tlet success = false;\n\t\tconst api = async () => {\n\t\t\tretryTimes -= 1;\n\t\t\treturn true;\n\t\t};\n\n\t\tlet emitDelayInfoTimes: number = 0;\n\t\tsuccess = await runWithFastSetTimeout(async () =>\n\t\t\trunWithRetry(api, \"test\", logger, {\n\t\t\t\tonRetry: () => {\n\t\t\t\t\temitDelayInfoTimes += 1;\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t\tassert.strictEqual(retryTimes, 0, \"Should succeed at first time\");\n\t\tassert.strictEqual(success, true, \"Retry should succeed ultimately\");\n\t\tassert.strictEqual(emitDelayInfoTimes, 0, \"Should not emit delay at first time\");\n\t});\n\n\tit(\"Check that it retries infinitely\", async () => {\n\t\tconst maxTries: number = 5;\n\t\tlet retryTimes: number = maxTries;\n\t\tlet success = false;\n\t\tconst api = async () => {\n\t\t\tif (retryTimes > 0) {\n\t\t\t\tretryTimes -= 1;\n\t\t\t\tconst error = new Error(\"Throw error\");\n\t\t\t\t(error as any).retryAfterSeconds = 10;\n\t\t\t\t(error as any).canRetry = true;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tlet emitDelayInfoTimes: number = 0;\n\t\tsuccess = await runWithFastSetTimeout(async () =>\n\t\t\trunWithRetry(api, \"test\", logger, {\n\t\t\t\tonRetry: () => {\n\t\t\t\t\temitDelayInfoTimes += 1;\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t\tassert.strictEqual(retryTimes, 0, \"Should keep retrying until success\");\n\t\tassert.strictEqual(success, true, \"Retry should succeed ultimately\");\n\t\tassert.strictEqual(emitDelayInfoTimes, maxTries, \"Should emit delay at each try\");\n\t});\n\n\tit(\"Check that it retries after retry seconds\", async () => {\n\t\tlet retryTimes: number = 1;\n\t\tlet success = false;\n\t\tconst api = async () => {\n\t\t\tif (retryTimes > 0) {\n\t\t\t\tretryTimes -= 1;\n\t\t\t\tconst error = new Error(\"Throttle Error\");\n\t\t\t\t(error as any).errorType = DriverErrorTypes.throttlingError;\n\t\t\t\t(error as any).retryAfterSeconds = 400;\n\t\t\t\t(error as any).canRetry = true;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\t\tsuccess = await runWithFastSetTimeout(async () => runWithRetry(api, \"test\", logger, {}));\n\t\tassert.strictEqual(retryTimes, 0, \"Should retry once\");\n\t\tassert.strictEqual(success, true, \"Retry should succeed ultimately\");\n\t});\n\n\tit(\"If error is just a string, should retry as canRetry is not false\", async () => {\n\t\tlet retryTimes: number = 1;\n\t\tlet success = false;\n\t\tconst api = async () => {\n\t\t\tif (retryTimes > 0) {\n\t\t\t\tretryTimes -= 1;\n\t\t\t\tconst err = new Error(\"error\");\n\t\t\t\t(err as any).canRetry = true;\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\t\ttry {\n\t\t\tsuccess = await runWithFastSetTimeout(async () =>\n\t\t\t\trunWithRetry(api, \"test\", logger, {}),\n\t\t\t);\n\t\t} catch (error) {}\n\t\tassert.strictEqual(retryTimes, 0, \"Should retry\");\n\t\tassert.strictEqual(success, true, \"Should succeed as retry should be successful\");\n\t});\n\n\tit(\"Should not retry if canRetry is set as false\", async () => {\n\t\tlet retryTimes: number = 1;\n\t\tlet success = false;\n\t\tconst api = async () => {\n\t\t\tif (retryTimes > 0) {\n\t\t\t\tretryTimes -= 1;\n\t\t\t\tconst error = new Error(\"error\");\n\t\t\t\t(error as any).canRetry = false;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\t\ttry {\n\t\t\tsuccess = await runWithFastSetTimeout(async () =>\n\t\t\t\trunWithRetry(api, \"test\", logger, {}),\n\t\t\t);\n\t\t\tassert.fail(\"Should not succeed\");\n\t\t} catch (error) {}\n\t\tassert.strictEqual(retryTimes, 0, \"Should not retry\");\n\t\tassert.strictEqual(success, false, \"Should not succeed as canRetry was not set\");\n\t});\n\n\tit(\"Should not retry if canRetry is not set\", async () => {\n\t\tlet retryTimes: number = 1;\n\t\tlet success = false;\n\t\tconst api = async () => {\n\t\t\tif (retryTimes > 0) {\n\t\t\t\tretryTimes -= 1;\n\t\t\t\tconst error = new Error(\"error\");\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\t\ttry {\n\t\t\tsuccess = await runWithFastSetTimeout(async () =>\n\t\t\t\trunWithRetry(api, \"test\", logger, {}),\n\t\t\t);\n\t\t\tassert.fail(\"Should not succeed\");\n\t\t} catch (error) {}\n\t\tassert.strictEqual(retryTimes, 0, \"Should not retry\");\n\t\tassert.strictEqual(success, false, \"Should not succeed as canRetry was not set\");\n\t});\n\n\tit(\"Should not retry if it is disabled\", async () => {\n\t\tlet retryTimes: number = 1;\n\t\tlet success = false;\n\t\tconst api = async () => {\n\t\t\tif (retryTimes > 0) {\n\t\t\t\tretryTimes -= 1;\n\t\t\t\tconst error = new Error(\"error\");\n\t\t\t\t(error as any).canRetry = true;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\t\ttry {\n\t\t\tsuccess = await runWithFastSetTimeout(async () =>\n\t\t\t\trunWithRetry(api, \"test\", logger, {\n\t\t\t\t\tonRetry: () => {\n\t\t\t\t\t\tthrow new Error(\"disposed\");\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\t\t\tassert.fail(\"Should not succeed\");\n\t\t} catch (error) {}\n\t\tassert.strictEqual(retryTimes, 0, \"Should not retry\");\n\t\tassert.strictEqual(success, false, \"Should not succeed as retrying was disabled\");\n\t});\n\n\tit(\"Abort reason is included in thrown exception\", async () => {\n\t\tconst abortController = new AbortController();\n\n\t\tconst api = () => {\n\t\t\tabortController.abort(\"Sample abort reason\");\n\t\t\tconst error = new Error(\"aborted\");\n\t\t\t(error as any).canRetry = true;\n\t\t\tthrow error;\n\t\t};\n\t\ttry {\n\t\t\tawait runWithFastSetTimeout(async () =>\n\t\t\t\trunWithRetry(api, \"test\", logger, {\n\t\t\t\t\tcancel: abortController.signal,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tassert.fail(\"Should not succeed\");\n\t\t} catch (error) {\n\t\t\tassert.strictEqual((error as any).message, \"runWithRetry was Aborted\");\n\t\t\tassert.strictEqual((error as any).reason, \"Sample abort reason\");\n\t\t}\n\t});\n});\n"]}