@fluidframework/odsp-driver 2.0.0-dev-rc.2.0.0.246488 → 2.0.0-dev-rc.3.0.0.250606

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 (353) hide show
  1. package/dist/WriteBufferUtils.d.ts.map +1 -1
  2. package/dist/WriteBufferUtils.js.map +1 -1
  3. package/dist/compactSnapshotParser.d.ts +1 -1
  4. package/dist/compactSnapshotParser.d.ts.map +1 -1
  5. package/dist/compactSnapshotParser.js +1 -1
  6. package/dist/compactSnapshotParser.js.map +1 -1
  7. package/dist/compactSnapshotWriter.d.ts.map +1 -1
  8. package/dist/compactSnapshotWriter.js +1 -1
  9. package/dist/compactSnapshotWriter.js.map +1 -1
  10. package/dist/contracts.d.ts +2 -2
  11. package/dist/contracts.d.ts.map +1 -1
  12. package/dist/contracts.js.map +1 -1
  13. package/dist/createFile.d.ts +2 -2
  14. package/dist/createFile.d.ts.map +1 -1
  15. package/dist/createFile.js +7 -7
  16. package/dist/createFile.js.map +1 -1
  17. package/dist/createNewContainerOnExistingFile.d.ts +2 -2
  18. package/dist/createNewContainerOnExistingFile.d.ts.map +1 -1
  19. package/dist/createNewContainerOnExistingFile.js +4 -4
  20. package/dist/createNewContainerOnExistingFile.js.map +1 -1
  21. package/dist/createNewUtils.d.ts +2 -2
  22. package/dist/createNewUtils.d.ts.map +1 -1
  23. package/dist/createNewUtils.js +4 -4
  24. package/dist/createNewUtils.js.map +1 -1
  25. package/dist/epochTracker.d.ts +3 -3
  26. package/dist/epochTracker.d.ts.map +1 -1
  27. package/dist/epochTracker.js +4 -4
  28. package/dist/epochTracker.js.map +1 -1
  29. package/dist/fetch.js.map +1 -1
  30. package/dist/fetchSnapshot.d.ts +2 -2
  31. package/dist/fetchSnapshot.d.ts.map +1 -1
  32. package/dist/fetchSnapshot.js +5 -5
  33. package/dist/fetchSnapshot.js.map +1 -1
  34. package/dist/getFileLink.d.ts +1 -1
  35. package/dist/getFileLink.d.ts.map +1 -1
  36. package/dist/getFileLink.js +1 -1
  37. package/dist/getFileLink.js.map +1 -1
  38. package/dist/localOdspDriver/localOdspDeltaStorageService.d.ts +1 -1
  39. package/dist/localOdspDriver/localOdspDeltaStorageService.d.ts.map +1 -1
  40. package/dist/localOdspDriver/localOdspDeltaStorageService.js +1 -1
  41. package/dist/localOdspDriver/localOdspDeltaStorageService.js.map +1 -1
  42. package/dist/localOdspDriver/localOdspDocumentService.d.ts +1 -1
  43. package/dist/localOdspDriver/localOdspDocumentService.d.ts.map +1 -1
  44. package/dist/localOdspDriver/localOdspDocumentService.js.map +1 -1
  45. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts +1 -1
  46. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -1
  47. package/dist/localOdspDriver/localOdspDocumentServiceFactory.js +1 -1
  48. package/dist/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -1
  49. package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts +1 -1
  50. package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +1 -1
  51. package/dist/localOdspDriver/localOdspDocumentStorageManager.js +2 -2
  52. package/dist/localOdspDriver/localOdspDocumentStorageManager.js.map +1 -1
  53. package/dist/odspCache.d.ts +1 -1
  54. package/dist/odspCache.d.ts.map +1 -1
  55. package/dist/odspCache.js.map +1 -1
  56. package/dist/odspDelayLoadedDeltaStream.d.ts +4 -4
  57. package/dist/odspDelayLoadedDeltaStream.d.ts.map +1 -1
  58. package/dist/odspDelayLoadedDeltaStream.js +11 -6
  59. package/dist/odspDelayLoadedDeltaStream.js.map +1 -1
  60. package/dist/odspDeltaStorageService.d.ts +3 -3
  61. package/dist/odspDeltaStorageService.d.ts.map +1 -1
  62. package/dist/odspDeltaStorageService.js +3 -3
  63. package/dist/odspDeltaStorageService.js.map +1 -1
  64. package/dist/odspDocumentDeltaConnection.d.ts +5 -4
  65. package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
  66. package/dist/odspDocumentDeltaConnection.js +3 -5
  67. package/dist/odspDocumentDeltaConnection.js.map +1 -1
  68. package/dist/odspDocumentService.d.ts +4 -4
  69. package/dist/odspDocumentService.d.ts.map +1 -1
  70. package/dist/odspDocumentService.js +2 -2
  71. package/dist/odspDocumentService.js.map +1 -1
  72. package/dist/odspDocumentServiceFactory.d.ts +1 -1
  73. package/dist/odspDocumentServiceFactory.d.ts.map +1 -1
  74. package/dist/odspDocumentServiceFactory.js +1 -1
  75. package/dist/odspDocumentServiceFactory.js.map +1 -1
  76. package/dist/odspDocumentServiceFactoryCore.d.ts +2 -2
  77. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  78. package/dist/odspDocumentServiceFactoryCore.js +2 -2
  79. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  80. package/dist/odspDocumentServiceFactoryWithCodeSplit.d.ts +1 -1
  81. package/dist/odspDocumentServiceFactoryWithCodeSplit.d.ts.map +1 -1
  82. package/dist/odspDocumentServiceFactoryWithCodeSplit.js.map +1 -1
  83. package/dist/odspDocumentStorageManager.d.ts +4 -4
  84. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  85. package/dist/odspDocumentStorageManager.js +3 -3
  86. package/dist/odspDocumentStorageManager.js.map +1 -1
  87. package/dist/odspDocumentStorageServiceBase.d.ts +1 -1
  88. package/dist/odspDocumentStorageServiceBase.d.ts.map +1 -1
  89. package/dist/odspDocumentStorageServiceBase.js.map +1 -1
  90. package/dist/odspDriverUrlResolver.d.ts.map +1 -1
  91. package/dist/odspDriverUrlResolver.js +3 -3
  92. package/dist/odspDriverUrlResolver.js.map +1 -1
  93. package/dist/odspDriverUrlResolverForShareLink.d.ts +1 -1
  94. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  95. package/dist/odspDriverUrlResolverForShareLink.js +2 -2
  96. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  97. package/dist/odspError.d.ts.map +1 -1
  98. package/dist/odspError.js +1 -1
  99. package/dist/odspError.js.map +1 -1
  100. package/dist/odspFluidFileLink.d.ts.map +1 -1
  101. package/dist/odspFluidFileLink.js.map +1 -1
  102. package/dist/odspPublicUtils.js.map +1 -1
  103. package/dist/odspSnapshotParser.d.ts.map +1 -1
  104. package/dist/odspSnapshotParser.js.map +1 -1
  105. package/dist/odspSummaryUploadManager.d.ts +1 -1
  106. package/dist/odspSummaryUploadManager.d.ts.map +1 -1
  107. package/dist/odspSummaryUploadManager.js +1 -1
  108. package/dist/odspSummaryUploadManager.js.map +1 -1
  109. package/dist/odspUtils.d.ts +2 -2
  110. package/dist/odspUtils.d.ts.map +1 -1
  111. package/dist/odspUtils.js +2 -2
  112. package/dist/odspUtils.js.map +1 -1
  113. package/dist/opsCaching.d.ts.map +1 -1
  114. package/dist/opsCaching.js.map +1 -1
  115. package/dist/packageVersion.d.ts +1 -1
  116. package/dist/packageVersion.js +1 -1
  117. package/dist/packageVersion.js.map +1 -1
  118. package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
  119. package/dist/prefetchLatestSnapshot.js +1 -1
  120. package/dist/prefetchLatestSnapshot.js.map +1 -1
  121. package/dist/retryErrorsStorageAdapter.d.ts +2 -2
  122. package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
  123. package/dist/retryErrorsStorageAdapter.js.map +1 -1
  124. package/dist/retryUtils.d.ts.map +1 -1
  125. package/dist/retryUtils.js.map +1 -1
  126. package/dist/vroom.d.ts +2 -2
  127. package/dist/vroom.d.ts.map +1 -1
  128. package/dist/vroom.js +2 -2
  129. package/dist/vroom.js.map +1 -1
  130. package/dist/zipItDataRepresentationUtils.d.ts.map +1 -1
  131. package/dist/zipItDataRepresentationUtils.js +1 -1
  132. package/dist/zipItDataRepresentationUtils.js.map +1 -1
  133. package/lib/WriteBufferUtils.d.ts.map +1 -1
  134. package/lib/WriteBufferUtils.js +1 -1
  135. package/lib/WriteBufferUtils.js.map +1 -1
  136. package/lib/compactSnapshotParser.d.ts +1 -1
  137. package/lib/compactSnapshotParser.d.ts.map +1 -1
  138. package/lib/compactSnapshotParser.js +1 -1
  139. package/lib/compactSnapshotParser.js.map +1 -1
  140. package/lib/compactSnapshotWriter.d.ts.map +1 -1
  141. package/lib/compactSnapshotWriter.js +2 -2
  142. package/lib/compactSnapshotWriter.js.map +1 -1
  143. package/lib/contracts.d.ts +2 -2
  144. package/lib/contracts.d.ts.map +1 -1
  145. package/lib/contracts.js.map +1 -1
  146. package/lib/createFile.d.ts +2 -2
  147. package/lib/createFile.d.ts.map +1 -1
  148. package/lib/createFile.js +7 -7
  149. package/lib/createFile.js.map +1 -1
  150. package/lib/createNewContainerOnExistingFile.d.ts +2 -2
  151. package/lib/createNewContainerOnExistingFile.d.ts.map +1 -1
  152. package/lib/createNewContainerOnExistingFile.js +4 -4
  153. package/lib/createNewContainerOnExistingFile.js.map +1 -1
  154. package/lib/createNewUtils.d.ts +2 -2
  155. package/lib/createNewUtils.d.ts.map +1 -1
  156. package/lib/createNewUtils.js +5 -5
  157. package/lib/createNewUtils.js.map +1 -1
  158. package/lib/epochTracker.d.ts +3 -3
  159. package/lib/epochTracker.d.ts.map +1 -1
  160. package/lib/epochTracker.js +6 -6
  161. package/lib/epochTracker.js.map +1 -1
  162. package/lib/fetch.js.map +1 -1
  163. package/lib/fetchSnapshot.d.ts +2 -2
  164. package/lib/fetchSnapshot.d.ts.map +1 -1
  165. package/lib/fetchSnapshot.js +6 -6
  166. package/lib/fetchSnapshot.js.map +1 -1
  167. package/lib/getFileLink.d.ts +1 -1
  168. package/lib/getFileLink.d.ts.map +1 -1
  169. package/lib/getFileLink.js +1 -1
  170. package/lib/getFileLink.js.map +1 -1
  171. package/lib/localOdspDriver/localOdspDeltaStorageService.d.ts +1 -1
  172. package/lib/localOdspDriver/localOdspDeltaStorageService.d.ts.map +1 -1
  173. package/lib/localOdspDriver/localOdspDeltaStorageService.js +1 -1
  174. package/lib/localOdspDriver/localOdspDeltaStorageService.js.map +1 -1
  175. package/lib/localOdspDriver/localOdspDocumentService.d.ts +1 -1
  176. package/lib/localOdspDriver/localOdspDocumentService.d.ts.map +1 -1
  177. package/lib/localOdspDriver/localOdspDocumentService.js.map +1 -1
  178. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts +1 -1
  179. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -1
  180. package/lib/localOdspDriver/localOdspDocumentServiceFactory.js +1 -1
  181. package/lib/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -1
  182. package/lib/localOdspDriver/localOdspDocumentStorageManager.d.ts +1 -1
  183. package/lib/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +1 -1
  184. package/lib/localOdspDriver/localOdspDocumentStorageManager.js +2 -2
  185. package/lib/localOdspDriver/localOdspDocumentStorageManager.js.map +1 -1
  186. package/lib/odspCache.d.ts +1 -1
  187. package/lib/odspCache.d.ts.map +1 -1
  188. package/lib/odspCache.js.map +1 -1
  189. package/lib/odspDelayLoadedDeltaStream.d.ts +4 -4
  190. package/lib/odspDelayLoadedDeltaStream.d.ts.map +1 -1
  191. package/lib/odspDelayLoadedDeltaStream.js +11 -6
  192. package/lib/odspDelayLoadedDeltaStream.js.map +1 -1
  193. package/lib/odspDeltaStorageService.d.ts +3 -3
  194. package/lib/odspDeltaStorageService.d.ts.map +1 -1
  195. package/lib/odspDeltaStorageService.js +3 -3
  196. package/lib/odspDeltaStorageService.js.map +1 -1
  197. package/lib/odspDocumentDeltaConnection.d.ts +5 -4
  198. package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
  199. package/lib/odspDocumentDeltaConnection.js +4 -6
  200. package/lib/odspDocumentDeltaConnection.js.map +1 -1
  201. package/lib/odspDocumentService.d.ts +4 -4
  202. package/lib/odspDocumentService.d.ts.map +1 -1
  203. package/lib/odspDocumentService.js +2 -2
  204. package/lib/odspDocumentService.js.map +1 -1
  205. package/lib/odspDocumentServiceFactory.d.ts +1 -1
  206. package/lib/odspDocumentServiceFactory.d.ts.map +1 -1
  207. package/lib/odspDocumentServiceFactory.js +1 -1
  208. package/lib/odspDocumentServiceFactory.js.map +1 -1
  209. package/lib/odspDocumentServiceFactoryCore.d.ts +2 -2
  210. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  211. package/lib/odspDocumentServiceFactoryCore.js +4 -4
  212. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  213. package/lib/odspDocumentServiceFactoryWithCodeSplit.d.ts +1 -1
  214. package/lib/odspDocumentServiceFactoryWithCodeSplit.d.ts.map +1 -1
  215. package/lib/odspDocumentServiceFactoryWithCodeSplit.js.map +1 -1
  216. package/lib/odspDocumentStorageManager.d.ts +4 -4
  217. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  218. package/lib/odspDocumentStorageManager.js +4 -4
  219. package/lib/odspDocumentStorageManager.js.map +1 -1
  220. package/lib/odspDocumentStorageServiceBase.d.ts +1 -1
  221. package/lib/odspDocumentStorageServiceBase.d.ts.map +1 -1
  222. package/lib/odspDocumentStorageServiceBase.js.map +1 -1
  223. package/lib/odspDriverUrlResolver.d.ts.map +1 -1
  224. package/lib/odspDriverUrlResolver.js +3 -3
  225. package/lib/odspDriverUrlResolver.js.map +1 -1
  226. package/lib/odspDriverUrlResolverForShareLink.d.ts +1 -1
  227. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  228. package/lib/odspDriverUrlResolverForShareLink.js +3 -3
  229. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  230. package/lib/odspError.d.ts.map +1 -1
  231. package/lib/odspError.js +1 -1
  232. package/lib/odspError.js.map +1 -1
  233. package/lib/odspFluidFileLink.d.ts.map +1 -1
  234. package/lib/odspFluidFileLink.js +1 -1
  235. package/lib/odspFluidFileLink.js.map +1 -1
  236. package/lib/odspPublicUtils.js +1 -1
  237. package/lib/odspPublicUtils.js.map +1 -1
  238. package/lib/odspSnapshotParser.d.ts.map +1 -1
  239. package/lib/odspSnapshotParser.js.map +1 -1
  240. package/lib/odspSummaryUploadManager.d.ts +1 -1
  241. package/lib/odspSummaryUploadManager.d.ts.map +1 -1
  242. package/lib/odspSummaryUploadManager.js +2 -2
  243. package/lib/odspSummaryUploadManager.js.map +1 -1
  244. package/lib/odspUtils.d.ts +2 -2
  245. package/lib/odspUtils.d.ts.map +1 -1
  246. package/lib/odspUtils.js +3 -3
  247. package/lib/odspUtils.js.map +1 -1
  248. package/lib/opsCaching.d.ts.map +1 -1
  249. package/lib/opsCaching.js.map +1 -1
  250. package/lib/packageVersion.d.ts +1 -1
  251. package/lib/packageVersion.js +1 -1
  252. package/lib/packageVersion.js.map +1 -1
  253. package/lib/prefetchLatestSnapshot.d.ts.map +1 -1
  254. package/lib/prefetchLatestSnapshot.js +2 -2
  255. package/lib/prefetchLatestSnapshot.js.map +1 -1
  256. package/lib/retryErrorsStorageAdapter.d.ts +2 -2
  257. package/lib/retryErrorsStorageAdapter.d.ts.map +1 -1
  258. package/lib/retryErrorsStorageAdapter.js.map +1 -1
  259. package/lib/retryUtils.d.ts.map +1 -1
  260. package/lib/retryUtils.js.map +1 -1
  261. package/lib/test/createNewUtilsTests.spec.js +3 -3
  262. package/lib/test/createNewUtilsTests.spec.js.map +1 -1
  263. package/lib/test/deltaStorageService.spec.js +2 -2
  264. package/lib/test/deltaStorageService.spec.js.map +1 -1
  265. package/lib/test/epochTests.spec.js +2 -2
  266. package/lib/test/epochTests.spec.js.map +1 -1
  267. package/lib/test/epochTestsWithRedemption.spec.js +2 -2
  268. package/lib/test/epochTestsWithRedemption.spec.js.map +1 -1
  269. package/lib/test/fetchSnapshot.spec.js +8 -8
  270. package/lib/test/fetchSnapshot.spec.js.map +1 -1
  271. package/lib/test/getFileLink.spec.js +1 -1
  272. package/lib/test/getFileLink.spec.js.map +1 -1
  273. package/lib/test/getVersions.spec.js +6 -6
  274. package/lib/test/getVersions.spec.js.map +1 -1
  275. package/lib/test/joinSessionCacheTests.spec.js +117 -1
  276. package/lib/test/joinSessionCacheTests.spec.js.map +1 -1
  277. package/lib/test/joinSessionPeriodicCall.spec.js +3 -3
  278. package/lib/test/joinSessionPeriodicCall.spec.js.map +1 -1
  279. package/lib/test/localOdspDriver.spec.js +2 -2
  280. package/lib/test/localOdspDriver.spec.js.map +1 -1
  281. package/lib/test/mockFetch.js +1 -1
  282. package/lib/test/mockFetch.js.map +1 -1
  283. package/lib/test/odspCreateContainer.spec.js +7 -7
  284. package/lib/test/odspCreateContainer.spec.js.map +1 -1
  285. package/lib/test/odspDriverResolverTest.spec.js +2 -2
  286. package/lib/test/odspDriverResolverTest.spec.js.map +1 -1
  287. package/lib/test/odspDriverUrlResolverForShareLink.spec.js +4 -4
  288. package/lib/test/odspDriverUrlResolverForShareLink.spec.js.map +1 -1
  289. package/lib/test/odspError.spec.js +2 -2
  290. package/lib/test/odspError.spec.js.map +1 -1
  291. package/lib/test/opsCaching.spec.js +1 -1
  292. package/lib/test/opsCaching.spec.js.map +1 -1
  293. package/lib/test/prefetchSnapshotTests.spec.js +8 -8
  294. package/lib/test/prefetchSnapshotTests.spec.js.map +1 -1
  295. package/lib/test/snapshotFormatTests.spec.js.map +1 -1
  296. package/lib/test/socketTests/deltaConnectionUpdateTests.spec.js +4 -4
  297. package/lib/test/socketTests/deltaConnectionUpdateTests.spec.js.map +1 -1
  298. package/lib/test/socketTests/socketMock.js +6 -2
  299. package/lib/test/socketTests/socketMock.js.map +1 -1
  300. package/lib/test/socketTests/socketTests.spec.js +4 -4
  301. package/lib/test/socketTests/socketTests.spec.js.map +1 -1
  302. package/lib/test/tokenFetch.spec.js +1 -1
  303. package/lib/test/tokenFetch.spec.js.map +1 -1
  304. package/lib/test/zipItDataRepresentationTests.spec.js +1 -1
  305. package/lib/test/zipItDataRepresentationTests.spec.js.map +1 -1
  306. package/lib/vroom.d.ts +2 -2
  307. package/lib/vroom.d.ts.map +1 -1
  308. package/lib/vroom.js +2 -2
  309. package/lib/vroom.js.map +1 -1
  310. package/lib/zipItDataRepresentationUtils.d.ts.map +1 -1
  311. package/lib/zipItDataRepresentationUtils.js +1 -1
  312. package/lib/zipItDataRepresentationUtils.js.map +1 -1
  313. package/package.json +19 -16
  314. package/src/WriteBufferUtils.ts +2 -2
  315. package/src/compactSnapshotParser.ts +6 -6
  316. package/src/compactSnapshotWriter.ts +4 -4
  317. package/src/contracts.ts +2 -2
  318. package/src/createFile.ts +18 -18
  319. package/src/createNewContainerOnExistingFile.ts +10 -10
  320. package/src/createNewUtils.ts +13 -13
  321. package/src/epochTracker.ts +21 -21
  322. package/src/fetch.ts +1 -1
  323. package/src/fetchSnapshot.ts +24 -24
  324. package/src/getFileLink.ts +1 -1
  325. package/src/localOdspDriver/localOdspDeltaStorageService.ts +2 -2
  326. package/src/localOdspDriver/localOdspDocumentService.ts +1 -1
  327. package/src/localOdspDriver/localOdspDocumentServiceFactory.ts +2 -2
  328. package/src/localOdspDriver/localOdspDocumentStorageManager.ts +3 -3
  329. package/src/odspCache.ts +4 -4
  330. package/src/odspDelayLoadedDeltaStream.ts +26 -22
  331. package/src/odspDeltaStorageService.ts +6 -6
  332. package/src/odspDocumentDeltaConnection.ts +17 -14
  333. package/src/odspDocumentService.ts +15 -15
  334. package/src/odspDocumentServiceFactory.ts +3 -3
  335. package/src/odspDocumentServiceFactoryCore.ts +14 -14
  336. package/src/odspDocumentServiceFactoryWithCodeSplit.ts +2 -2
  337. package/src/odspDocumentStorageManager.ts +22 -22
  338. package/src/odspDocumentStorageServiceBase.ts +4 -4
  339. package/src/odspDriverUrlResolver.ts +4 -4
  340. package/src/odspDriverUrlResolverForShareLink.ts +8 -8
  341. package/src/odspError.ts +2 -2
  342. package/src/odspFluidFileLink.ts +1 -1
  343. package/src/odspPublicUtils.ts +1 -1
  344. package/src/odspSnapshotParser.ts +1 -1
  345. package/src/odspSummaryUploadManager.ts +4 -4
  346. package/src/odspUtils.ts +25 -25
  347. package/src/opsCaching.ts +1 -1
  348. package/src/packageVersion.ts +1 -1
  349. package/src/prefetchLatestSnapshot.ts +12 -12
  350. package/src/retryErrorsStorageAdapter.ts +2 -2
  351. package/src/retryUtils.ts +1 -1
  352. package/src/vroom.ts +6 -6
  353. package/src/zipItDataRepresentationUtils.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"opsCaching.js","sourceRoot":"","sources":["../src/opsCaching.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 { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { performance } from \"@fluid-internal/client-utils\";\n\n// ISequencedDocumentMessage\nexport interface IMessage {\n\tsequenceNumber: number;\n}\n\nexport type CacheEntry = (IMessage | undefined)[];\n\nexport interface IBatch {\n\tremainingSlots: number;\n\tbatchData: CacheEntry;\n\t/**\n\t * Tells if this batch is dirty, i.e. it contains ops that were not flushed to cache\n\t */\n\tdirty: boolean;\n}\n\nexport interface ICache {\n\twrite(batchNumber: string, data: string): Promise<void>;\n\tread(batchNumber: string): Promise<string | undefined>;\n\tremove(): void;\n}\n\nexport class OpsCache {\n\tprivate readonly batches: Map<number, null | IBatch> = new Map();\n\tprivate timer: ReturnType<typeof setTimeout> | undefined;\n\n\tconstructor(\n\t\tstartingSequenceNumber: number,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate readonly cache: ICache,\n\t\tprivate readonly batchSize: number,\n\t\tprivate readonly timerGranularity: number,\n\t\tprivate totalOpsToCache: number,\n\t) {\n\t\t/**\n\t\t * Initial batch is a special case because it will never be full - all ops prior (inclusive) to\n\t\t * `startingSequenceNumber` are never going to show up (undefined)\n\t\t */\n\t\tconst remainingSlots =\n\t\t\tthis.batchSize - this.getPositionInBatchArray(startingSequenceNumber) - 1;\n\t\tif (remainingSlots !== 0) {\n\t\t\tthis.batches.set(this.getBatchNumber(startingSequenceNumber), {\n\t\t\t\tremainingSlots,\n\t\t\t\tbatchData: this.initializeNewBatchDataArray(),\n\t\t\t\tdirty: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.batches.clear();\n\t\tif (this.timer !== undefined) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = undefined;\n\t\t}\n\t}\n\n\tpublic flushOps(): void {\n\t\tfor (const [key, value] of this.batches) {\n\t\t\t// Don't flush if the batch has no ops, already flushed or has empty slots at both beginning and end.\n\t\t\tif (\n\t\t\t\tvalue === null ||\n\t\t\t\t!value.dirty ||\n\t\t\t\tvalue.batchData.length === 0 ||\n\t\t\t\t(value.batchData[0] === undefined &&\n\t\t\t\t\tvalue.batchData[value.batchData.length - 1] === undefined)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue.dirty = false;\n\t\t\tthis.write(key, value);\n\t\t}\n\t}\n\n\tpublic addOps(ops: IMessage[]): void {\n\t\tif (this.totalOpsToCache <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const op of ops) {\n\t\t\tconst batchNumber = this.getBatchNumber(op.sequenceNumber);\n\t\t\tconst positionInBatch = this.getPositionInBatchArray(op.sequenceNumber);\n\n\t\t\tlet currentBatch = this.batches.get(batchNumber);\n\n\t\t\tif (currentBatch === undefined) {\n\t\t\t\tcurrentBatch = {\n\t\t\t\t\tremainingSlots: this.batchSize - 1,\n\t\t\t\t\tbatchData: this.initializeNewBatchDataArray(),\n\t\t\t\t\tdirty: true,\n\t\t\t\t};\n\t\t\t\tcurrentBatch.batchData[positionInBatch] = op;\n\t\t\t\tthis.batches.set(batchNumber, currentBatch);\n\t\t\t} else if (\n\t\t\t\tcurrentBatch !== null &&\n\t\t\t\tcurrentBatch.batchData[positionInBatch] === undefined\n\t\t\t) {\n\t\t\t\tcurrentBatch.batchData[positionInBatch] = op;\n\t\t\t\tcurrentBatch.remainingSlots--;\n\t\t\t\tcurrentBatch.dirty = true;\n\t\t\t} else {\n\t\t\t\t// Either batch was flushed or this op was already there - nothing to do!\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (currentBatch.remainingSlots === 0) {\n\t\t\t\t// batch is full, flush to cache\n\t\t\t\tthis.write(batchNumber, currentBatch);\n\t\t\t\t// eslint-disable-next-line unicorn/no-null\n\t\t\t\tthis.batches.set(batchNumber, null);\n\t\t\t} else {\n\t\t\t\tthis.scheduleTimer();\n\t\t\t}\n\n\t\t\tthis.totalOpsToCache--;\n\t\t\tif (this.totalOpsToCache === 0) {\n\t\t\t\tthis.logger.sendPerformanceEvent({ eventName: \"CacheOpsLimitHit\" });\n\t\t\t\tthis.cache.remove();\n\t\t\t\tthis.dispose();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves ops from cache\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tprivate async getCore(from: number, to?: number): Promise<IMessage[]> {\n\t\tconst messages: IMessage[] = [];\n\t\tlet batchNumber = this.getBatchNumber(from);\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\n\t\t\tconst res = await this.cache.read(`${this.batchSize}_${batchNumber}`);\n\t\t\tif (res === undefined) {\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tconst result: CacheEntry = JSON.parse(res) as CacheEntry;\n\t\t\tconst prevMessagesLength = messages.length;\n\t\t\tfor (const op of result) {\n\t\t\t\t// Note that we write out undefined, but due to JSON.stringify, it turns into null!\n\t\t\t\tif (op) {\n\t\t\t\t\tif (to !== undefined && op.sequenceNumber >= to) {\n\t\t\t\t\t\treturn messages;\n\t\t\t\t\t}\n\t\t\t\t\tif (messages.length === 0) {\n\t\t\t\t\t\tif (op.sequenceNumber > from) {\n\t\t\t\t\t\t\treturn messages;\n\t\t\t\t\t\t} else if (op.sequenceNumber < from) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tmessages.push(op);\n\t\t\t\t} else if (messages.length > 0) {\n\t\t\t\t\t// If there is any gap, return the messages till now.\n\t\t\t\t\treturn messages;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we didn't get any op from this batch, then return messages till now. As it tells us that,\n\t\t\t// either the first message \"from\" is not present in cache or a gap will occur from 1 batch to next.\n\t\t\tif (prevMessagesLength === messages.length) {\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tbatchNumber++;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves ops from cache\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tpublic async get(from: number, to?: number): Promise<IMessage[]> {\n\t\tconst start = performance.now();\n\n\t\tconst messages = await this.getCore(from, to);\n\n\t\tconst duration = performance.now() - start;\n\t\tif (messages.length > 0 || duration > 1000) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"CacheOpsUsed\",\n\t\t\t\tfrom,\n\t\t\t\tto,\n\t\t\t\tlength: messages.length,\n\t\t\t\tduration,\n\t\t\t});\n\t\t}\n\t\treturn messages;\n\t}\n\n\tprotected write(batchNumber: number, payload: IBatch): void {\n\t\t// Errors are caught and logged by PersistedCacheWithErrorHandling that sits\n\t\t// in the adapter chain of cache adapters\n\t\tthis.cache\n\t\t\t.write(`${this.batchSize}_${batchNumber}`, JSON.stringify(payload.batchData))\n\t\t\t.catch(() => {\n\t\t\t\tthis.totalOpsToCache = 0;\n\t\t\t});\n\t}\n\n\tprotected scheduleTimer(): void {\n\t\tif (!this.timer && this.timerGranularity > 0) {\n\t\t\tthis.timer = setTimeout(() => {\n\t\t\t\tthis.timer = undefined;\n\t\t\t\tthis.flushOps();\n\t\t\t}, this.timerGranularity);\n\t\t}\n\t}\n\n\tprivate getBatchNumber(sequenceNumber: number): number {\n\t\treturn Math.floor(sequenceNumber / this.batchSize);\n\t}\n\n\tprivate getPositionInBatchArray(sequenceNumber: number): number {\n\t\treturn sequenceNumber % this.batchSize;\n\t}\n\n\tprivate initializeNewBatchDataArray(): IMessage[] {\n\t\tconst tempArray: IMessage[] = [];\n\t\ttempArray.length = this.batchSize; // fill with empty, undefined elements\n\t\treturn tempArray;\n\t}\n}\n"]}
1
+ {"version":3,"file":"opsCaching.js","sourceRoot":"","sources":["../src/opsCaching.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 { performance } from \"@fluid-internal/client-utils\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\n\n// ISequencedDocumentMessage\nexport interface IMessage {\n\tsequenceNumber: number;\n}\n\nexport type CacheEntry = (IMessage | undefined)[];\n\nexport interface IBatch {\n\tremainingSlots: number;\n\tbatchData: CacheEntry;\n\t/**\n\t * Tells if this batch is dirty, i.e. it contains ops that were not flushed to cache\n\t */\n\tdirty: boolean;\n}\n\nexport interface ICache {\n\twrite(batchNumber: string, data: string): Promise<void>;\n\tread(batchNumber: string): Promise<string | undefined>;\n\tremove(): void;\n}\n\nexport class OpsCache {\n\tprivate readonly batches: Map<number, null | IBatch> = new Map();\n\tprivate timer: ReturnType<typeof setTimeout> | undefined;\n\n\tconstructor(\n\t\tstartingSequenceNumber: number,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate readonly cache: ICache,\n\t\tprivate readonly batchSize: number,\n\t\tprivate readonly timerGranularity: number,\n\t\tprivate totalOpsToCache: number,\n\t) {\n\t\t/**\n\t\t * Initial batch is a special case because it will never be full - all ops prior (inclusive) to\n\t\t * `startingSequenceNumber` are never going to show up (undefined)\n\t\t */\n\t\tconst remainingSlots =\n\t\t\tthis.batchSize - this.getPositionInBatchArray(startingSequenceNumber) - 1;\n\t\tif (remainingSlots !== 0) {\n\t\t\tthis.batches.set(this.getBatchNumber(startingSequenceNumber), {\n\t\t\t\tremainingSlots,\n\t\t\t\tbatchData: this.initializeNewBatchDataArray(),\n\t\t\t\tdirty: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.batches.clear();\n\t\tif (this.timer !== undefined) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = undefined;\n\t\t}\n\t}\n\n\tpublic flushOps(): void {\n\t\tfor (const [key, value] of this.batches) {\n\t\t\t// Don't flush if the batch has no ops, already flushed or has empty slots at both beginning and end.\n\t\t\tif (\n\t\t\t\tvalue === null ||\n\t\t\t\t!value.dirty ||\n\t\t\t\tvalue.batchData.length === 0 ||\n\t\t\t\t(value.batchData[0] === undefined &&\n\t\t\t\t\tvalue.batchData[value.batchData.length - 1] === undefined)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue.dirty = false;\n\t\t\tthis.write(key, value);\n\t\t}\n\t}\n\n\tpublic addOps(ops: IMessage[]): void {\n\t\tif (this.totalOpsToCache <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const op of ops) {\n\t\t\tconst batchNumber = this.getBatchNumber(op.sequenceNumber);\n\t\t\tconst positionInBatch = this.getPositionInBatchArray(op.sequenceNumber);\n\n\t\t\tlet currentBatch = this.batches.get(batchNumber);\n\n\t\t\tif (currentBatch === undefined) {\n\t\t\t\tcurrentBatch = {\n\t\t\t\t\tremainingSlots: this.batchSize - 1,\n\t\t\t\t\tbatchData: this.initializeNewBatchDataArray(),\n\t\t\t\t\tdirty: true,\n\t\t\t\t};\n\t\t\t\tcurrentBatch.batchData[positionInBatch] = op;\n\t\t\t\tthis.batches.set(batchNumber, currentBatch);\n\t\t\t} else if (\n\t\t\t\tcurrentBatch !== null &&\n\t\t\t\tcurrentBatch.batchData[positionInBatch] === undefined\n\t\t\t) {\n\t\t\t\tcurrentBatch.batchData[positionInBatch] = op;\n\t\t\t\tcurrentBatch.remainingSlots--;\n\t\t\t\tcurrentBatch.dirty = true;\n\t\t\t} else {\n\t\t\t\t// Either batch was flushed or this op was already there - nothing to do!\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (currentBatch.remainingSlots === 0) {\n\t\t\t\t// batch is full, flush to cache\n\t\t\t\tthis.write(batchNumber, currentBatch);\n\t\t\t\t// eslint-disable-next-line unicorn/no-null\n\t\t\t\tthis.batches.set(batchNumber, null);\n\t\t\t} else {\n\t\t\t\tthis.scheduleTimer();\n\t\t\t}\n\n\t\t\tthis.totalOpsToCache--;\n\t\t\tif (this.totalOpsToCache === 0) {\n\t\t\t\tthis.logger.sendPerformanceEvent({ eventName: \"CacheOpsLimitHit\" });\n\t\t\t\tthis.cache.remove();\n\t\t\t\tthis.dispose();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves ops from cache\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tprivate async getCore(from: number, to?: number): Promise<IMessage[]> {\n\t\tconst messages: IMessage[] = [];\n\t\tlet batchNumber = this.getBatchNumber(from);\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\n\t\t\tconst res = await this.cache.read(`${this.batchSize}_${batchNumber}`);\n\t\t\tif (res === undefined) {\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tconst result: CacheEntry = JSON.parse(res) as CacheEntry;\n\t\t\tconst prevMessagesLength = messages.length;\n\t\t\tfor (const op of result) {\n\t\t\t\t// Note that we write out undefined, but due to JSON.stringify, it turns into null!\n\t\t\t\tif (op) {\n\t\t\t\t\tif (to !== undefined && op.sequenceNumber >= to) {\n\t\t\t\t\t\treturn messages;\n\t\t\t\t\t}\n\t\t\t\t\tif (messages.length === 0) {\n\t\t\t\t\t\tif (op.sequenceNumber > from) {\n\t\t\t\t\t\t\treturn messages;\n\t\t\t\t\t\t} else if (op.sequenceNumber < from) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tmessages.push(op);\n\t\t\t\t} else if (messages.length > 0) {\n\t\t\t\t\t// If there is any gap, return the messages till now.\n\t\t\t\t\treturn messages;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we didn't get any op from this batch, then return messages till now. As it tells us that,\n\t\t\t// either the first message \"from\" is not present in cache or a gap will occur from 1 batch to next.\n\t\t\tif (prevMessagesLength === messages.length) {\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tbatchNumber++;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves ops from cache\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tpublic async get(from: number, to?: number): Promise<IMessage[]> {\n\t\tconst start = performance.now();\n\n\t\tconst messages = await this.getCore(from, to);\n\n\t\tconst duration = performance.now() - start;\n\t\tif (messages.length > 0 || duration > 1000) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"CacheOpsUsed\",\n\t\t\t\tfrom,\n\t\t\t\tto,\n\t\t\t\tlength: messages.length,\n\t\t\t\tduration,\n\t\t\t});\n\t\t}\n\t\treturn messages;\n\t}\n\n\tprotected write(batchNumber: number, payload: IBatch): void {\n\t\t// Errors are caught and logged by PersistedCacheWithErrorHandling that sits\n\t\t// in the adapter chain of cache adapters\n\t\tthis.cache\n\t\t\t.write(`${this.batchSize}_${batchNumber}`, JSON.stringify(payload.batchData))\n\t\t\t.catch(() => {\n\t\t\t\tthis.totalOpsToCache = 0;\n\t\t\t});\n\t}\n\n\tprotected scheduleTimer(): void {\n\t\tif (!this.timer && this.timerGranularity > 0) {\n\t\t\tthis.timer = setTimeout(() => {\n\t\t\t\tthis.timer = undefined;\n\t\t\t\tthis.flushOps();\n\t\t\t}, this.timerGranularity);\n\t\t}\n\t}\n\n\tprivate getBatchNumber(sequenceNumber: number): number {\n\t\treturn Math.floor(sequenceNumber / this.batchSize);\n\t}\n\n\tprivate getPositionInBatchArray(sequenceNumber: number): number {\n\t\treturn sequenceNumber % this.batchSize;\n\t}\n\n\tprivate initializeNewBatchDataArray(): IMessage[] {\n\t\tconst tempArray: IMessage[] = [];\n\t\ttempArray.length = this.batchSize; // fill with empty, undefined elements\n\t\treturn tempArray;\n\t}\n}\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/odsp-driver";
8
- export declare const pkgVersion = "2.0.0-dev-rc.2.0.0.246488";
8
+ export declare const pkgVersion = "2.0.0-dev-rc.3.0.0.250606";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/odsp-driver";
8
- export const pkgVersion = "2.0.0-dev-rc.2.0.0.246488";
8
+ export const pkgVersion = "2.0.0-dev-rc.3.0.0.250606";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,2BAA2B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"2.0.0-dev-rc.2.0.0.246488\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,2BAA2B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"2.0.0-dev-rc.3.0.0.250606\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"prefetchLatestSnapshot.d.ts","sourceRoot":"","sources":["../src/prefetchLatestSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAEN,eAAe,EACf,gBAAgB,EAChB,6BAA6B,EAC7B,YAAY,EAGZ,MAAM,yCAAyC,CAAC;AAQjD,OAAO,EAIN,yBAAyB,EACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,sBAAsB,CAC3C,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,YAAY,CAAC,6BAA6B,CAAC,EAC5D,cAAc,EAAE,eAAe,EAC/B,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,oBAAoB,EAC5B,wBAAwB,EAAE,gBAAgB,GAAG,SAAS,EACtD,oBAAoB,GAAE,OAAc,EACpC,yBAAyB,CAAC,EAAE,OAAO,EACnC,uBAAuB,CAAC,EAAE,yBAAyB,EACnD,0BAA0B,CAAC,EAAE,0BAA0B,GACrD,OAAO,CAAC,OAAO,CAAC,CAgHlB"}
1
+ {"version":3,"file":"prefetchLatestSnapshot.d.ts","sourceRoot":"","sources":["../src/prefetchLatestSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAGN,eAAe,EACf,gBAAgB,EAChB,6BAA6B,EAC7B,YAAY,EAEZ,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAEN,yBAAyB,EAGzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAQ7E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,sBAAsB,CAC3C,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,YAAY,CAAC,6BAA6B,CAAC,EAC5D,cAAc,EAAE,eAAe,EAC/B,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,oBAAoB,EAC5B,wBAAwB,EAAE,gBAAgB,GAAG,SAAS,EACtD,oBAAoB,GAAE,OAAc,EACpC,yBAAyB,CAAC,EAAE,OAAO,EACnC,uBAAuB,CAAC,EAAE,yBAAyB,EACnD,0BAA0B,CAAC,EAAE,0BAA0B,GACrD,OAAO,CAAC,OAAO,CAAC,CAgHlB"}
@@ -5,9 +5,9 @@
5
5
  import { performance } from "@fluid-internal/client-utils";
6
6
  import { assert, Deferred } from "@fluidframework/core-utils";
7
7
  import { getKeyForCacheEntry, } from "@fluidframework/odsp-driver-definitions";
8
- import { createChildMonitoringContext, PerformanceEvent } from "@fluidframework/telemetry-utils";
9
- import { createCacheSnapshotKey, createOdspLogger, getOdspResolvedUrl, toInstrumentedOdspTokenFetcher, } from "./odspUtils.js";
8
+ import { PerformanceEvent, createChildMonitoringContext } from "@fluidframework/telemetry-utils";
10
9
  import { downloadSnapshot, fetchSnapshotWithRedeem, } from "./fetchSnapshot.js";
10
+ import { createCacheSnapshotKey, createOdspLogger, getOdspResolvedUrl, toInstrumentedOdspTokenFetcher, } from "./odspUtils.js";
11
11
  /**
12
12
  * Function to prefetch the snapshot and cached it in the persistant cache, so that when the container is loaded
13
13
  * the cached latest snapshot could be used and removes the network call from the critical path.
@@ -1 +1 @@
1
- {"version":3,"file":"prefetchLatestSnapshot.js","sourceRoot":"","sources":["../src/prefetchLatestSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAON,mBAAmB,GACnB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,EACN,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,8BAA8B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,gBAAgB,EAChB,uBAAuB,GAGvB,MAAM,oBAAoB,CAAC;AAK5B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,WAAyB,EACzB,eAA4D,EAC5D,cAA+B,EAC/B,sCAA+C,EAC/C,MAA4B,EAC5B,wBAAsD,EACtD,uBAAgC,IAAI,EACpC,yBAAmC,EACnC,uBAAmD,EACnD,0BAAuD;IAEvD,MAAM,EAAE,GAAG,4BAA4B,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACnF,MAAM,UAAU,GAAG,gBAAgB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,2BAA2B,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,CACvD,mDAAmD,CACnD,CAAC;IACF,4FAA4F;IAC5F,kDAAkD;IAClD,MAAM,eAAe,GAAG,2BAA2B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,MAAM,eAAe,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAExD,MAAM,eAAe,GAAkB;QACtC,OAAO,EAAE,eAAe,CAAC,OAAO;QAChC,OAAO,EAAE,eAAe,CAAC,OAAO;QAChC,MAAM,EAAE,eAAe,CAAC,MAAM;KAC9B,CAAC;IACF,MAAM,mBAAmB,GAAG,8BAA8B,CACzD,UAAU,EACV,eAAe,EACf,eAAe,EACf,IAAI,CAAC,sBAAsB,CAC3B,CAAC;IAEF,MAAM,kBAAkB,GAAG,KAAK,EAC/B,oBAAsC,EACtC,YAAoB,EACpB,cAAoC,EACpC,eAA6C,EAC7C,UAA4B,EACkB,EAAE;QAChD,OAAO,gBAAgB,CACtB,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,SAAS,EACT,UAAU,CACV,CAAC;IACH,CAAC,CAAC;IACF,MAAM,WAAW,GAAG,sBAAsB,CAAC,eAAe,CAAC,CAAC;IAC5D,IAAI,MAAiC,CAAC;IACtC,IAAI,aAAiC,CAAC;IACtC,MAAM,UAAU,GAAG,KAAK,EAAE,cAAwC,EAAiB,EAAE;QACpF,aAAa,GAAG,cAAc,CAAC,UAAU,CAAC;QAC1C,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,IAAmB,EAAE,CAAC,cAAc,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChG,OAAO,gBAAgB,CAAC,cAAc,CACrC,UAAU,EACV,EAAE,SAAS,EAAE,wBAAwB,EAAE,EACvC,KAAK,IAAI,EAAE;QACV,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC5C,kGAAkG;QAClG,MAAM,0BAA0B,GAAG,IAAI,QAAQ,EAA6B,CAAC;QAC7E,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC/D,MAAM,0BAA0B,GAC/B,0BAA0B,EAAE,2BAA2B,CAAC;QACzD,0BAA0B,EAAE,GAAG,CAC9B,qBAAqB,EACrB,KAAK,IAAI,EAAE,CAAC,0BAA0B,CAAC,OAAO,CAC9C,CAAC;QACF,MAAM,uBAAuB,CAC5B,eAAe,EACf,mBAAmB,EACnB,wBAAwB,EACxB,sCAAsC,EACtC,UAAU,EACV,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,eAAe,EACf,oBAAoB,CACpB;aACC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACrB,MAAM,CACL,CAAC,CAAC,aAAa,EACf,KAAK,CAAC,mDAAmD,CACzD,CAAC;YACF,0BAA0B,CAAC,OAAO,CAAC;gBAClC,GAAG,KAAK;gBACR,UAAU,EAAE,aAAa;gBACzB,iBAAiB;aACjB,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACvE,MAAM,MAAM,CAAC;YACb,6CAA6C;YAC7C,kGAAkG;YAClG,6FAA6F;YAC7F,mGAAmG;YACnG,kGAAkG;YAClG,mGAAmG;YACnG,2FAA2F;YAC3F,+FAA+F;YAC/F,qCAAqC;YACrC,UAAU,CAAC,GAAG,EAAE;gBACf,0BAA0B,EAAE,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAC3D,CAAC,EAAE,IAAI,CAAC,CAAC;QACV,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAChB,+DAA+D;YAC/D,0BAA0B,EAAE,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAC1D,0BAA0B,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QACJ,OAAO,IAAI,CAAC;IACb,CAAC,CACD,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACvB,UAAU,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,6BAA6B,EAAE,EAAE,KAAK,CAAC,CAAC;QAC/E,OAAO,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { performance } from \"@fluid-internal/client-utils\";\nimport { assert, Deferred } from \"@fluidframework/core-utils\";\nimport { IResolvedUrl } from \"@fluidframework/driver-definitions\";\nimport {\n\tIOdspResolvedUrl,\n\tIPersistedCache,\n\tISnapshotOptions,\n\tOdspResourceTokenFetchOptions,\n\tTokenFetcher,\n\tIOdspUrlParts,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { createChildMonitoringContext, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n\tcreateCacheSnapshotKey,\n\tcreateOdspLogger,\n\tgetOdspResolvedUrl,\n\ttoInstrumentedOdspTokenFetcher,\n} from \"./odspUtils.js\";\nimport {\n\tdownloadSnapshot,\n\tfetchSnapshotWithRedeem,\n\tISnapshotRequestAndResponseOptions,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot.js\";\nimport { IVersionedValueWithEpoch } from \"./contracts.js\";\nimport { IPrefetchSnapshotContents } from \"./odspCache.js\";\nimport { OdspDocumentServiceFactory } from \"./odspDocumentServiceFactory.js\";\n\n/**\n * Function to prefetch the snapshot and cached it in the persistant cache, so that when the container is loaded\n * the cached latest snapshot could be used and removes the network call from the critical path.\n *\n * @param resolvedUrl - Resolved url to fetch the snapshot.\n * @param getStorageToken - function that can provide the storage token for a given site. This is\n * is also referred to as the \"VROOM\" token in SPO.\n * @param persistedCache - Cache to store the fetched snapshot.\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header.\n * @param logger - Logger to have telemetry events.\n * @param hostSnapshotFetchOptions - Options to fetch the snapshot if any. Otherwise default will be used.\n * @param enableRedeemFallback - True to have the sharing link redeem fallback in case the Trees Latest/Redeem\n * 1RT call fails with redeem error. During fallback it will first redeem the sharing link and then make\n * the Trees latest call.\n * Note: this can be considered deprecated - it will be replaced with `snapshotFormatFetchType`.\n * @param fetchBinarySnapshotFormat - Control if we want to fetch binary format snapshot.\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param odspDocumentServiceFactory - factory to access the non persistent cache and store the prefetch promise.\n *\n * @returns `true` if the snapshot is cached, `false` otherwise.\n * @alpha\n */\nexport async function prefetchLatestSnapshot(\n\tresolvedUrl: IResolvedUrl,\n\tgetStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tpersistedCache: IPersistedCache,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryBaseLogger,\n\thostSnapshotFetchOptions: ISnapshotOptions | undefined,\n\tenableRedeemFallback: boolean = true,\n\tfetchBinarySnapshotFormat?: boolean,\n\tsnapshotFormatFetchType?: SnapshotFormatSupportType,\n\todspDocumentServiceFactory?: OdspDocumentServiceFactory,\n): Promise<boolean> {\n\tconst mc = createChildMonitoringContext({ logger, namespace: \"PrefetchSnapshot\" });\n\tconst odspLogger = createOdspLogger(mc.logger);\n\tconst useGroupIdsForSnapshotFetch = mc.config.getBoolean(\n\t\t\"Fluid.Container.UseLoadingGroupIdForSnapshotFetch\",\n\t);\n\t// For prefetch, we just want to fetch the ungrouped data and want to use the new API if the\n\t// feature gate is set, so provide an empty array.\n\tconst loadingGroupIds = useGroupIdsForSnapshotFetch ? [] : undefined;\n\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\n\tconst resolvedUrlData: IOdspUrlParts = {\n\t\tsiteUrl: odspResolvedUrl.siteUrl,\n\t\tdriveId: odspResolvedUrl.driveId,\n\t\titemId: odspResolvedUrl.itemId,\n\t};\n\tconst storageTokenFetcher = toInstrumentedOdspTokenFetcher(\n\t\todspLogger,\n\t\tresolvedUrlData,\n\t\tgetStorageToken,\n\t\ttrue /* throwOnNullToken */,\n\t);\n\n\tconst snapshotDownloader = async (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tloadingGroupId: string[] | undefined,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t): Promise<ISnapshotRequestAndResponseOptions> => {\n\t\treturn downloadSnapshot(\n\t\t\tfinalOdspResolvedUrl,\n\t\t\tstorageToken,\n\t\t\tloadingGroupId,\n\t\t\tsnapshotOptions,\n\t\t\tundefined,\n\t\t\tcontroller,\n\t\t);\n\t};\n\tconst snapshotKey = createCacheSnapshotKey(odspResolvedUrl);\n\tlet cacheP: Promise<void> | undefined;\n\tlet snapshotEpoch: string | undefined;\n\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch): Promise<void> => {\n\t\tsnapshotEpoch = valueWithEpoch.fluidEpoch;\n\t\tcacheP = persistedCache.put(snapshotKey, valueWithEpoch);\n\t\treturn cacheP;\n\t};\n\n\tconst removeEntries = async (): Promise<void> => persistedCache.removeEntries(snapshotKey.file);\n\treturn PerformanceEvent.timedExecAsync(\n\t\todspLogger,\n\t\t{ eventName: \"PrefetchLatestSnapshot\" },\n\t\tasync () => {\n\t\t\tconst prefetchStartTime = performance.now();\n\t\t\t// Add the deferred promise to the cache, so that it can be leveraged while loading the container.\n\t\t\tconst snapshotContentsWithEpochP = new Deferred<IPrefetchSnapshotContents>();\n\t\t\tconst nonPersistentCacheKey = getKeyForCacheEntry(snapshotKey);\n\t\t\tconst snapshotNonPersistentCache =\n\t\t\t\todspDocumentServiceFactory?.snapshotPrefetchResultCache;\n\t\t\tsnapshotNonPersistentCache?.add(\n\t\t\t\tnonPersistentCacheKey,\n\t\t\t\tasync () => snapshotContentsWithEpochP.promise,\n\t\t\t);\n\t\t\tawait fetchSnapshotWithRedeem(\n\t\t\t\todspResolvedUrl,\n\t\t\t\tstorageTokenFetcher,\n\t\t\t\thostSnapshotFetchOptions,\n\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\todspLogger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tloadingGroupIds,\n\t\t\t\tenableRedeemFallback,\n\t\t\t)\n\t\t\t\t.then(async (value) => {\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!!snapshotEpoch,\n\t\t\t\t\t\t0x585 /* prefetched snapshot should have a valid epoch */,\n\t\t\t\t\t);\n\t\t\t\t\tsnapshotContentsWithEpochP.resolve({\n\t\t\t\t\t\t...value,\n\t\t\t\t\t\tfluidEpoch: snapshotEpoch,\n\t\t\t\t\t\tprefetchStartTime,\n\t\t\t\t\t});\n\t\t\t\t\tassert(cacheP !== undefined, 0x1e7 /* \"caching was not performed!\" */);\n\t\t\t\t\tawait cacheP;\n\t\t\t\t\t// Schedule it to remove from cache after 5s.\n\t\t\t\t\t// 1. While it's in snapshotNonPersistentCache: Load flow will use this value and will not attempt\n\t\t\t\t\t// to fetch snapshot from network again. That's the best from perf POV, but cache will not be\n\t\t\t\t\t// updated if we keep it in this cache, thus we want to eventually remove snapshot from this cache.\n\t\t\t\t\t// 2. After it's removed from snapshotNonPersistentCache: snapshot is present in persistent cache,\n\t\t\t\t\t// so we sill still use it (in accordance with cache policy controlled by host). But load flow will\n\t\t\t\t\t// also fetch snapshot (in parallel) from storage and update cache. This is fine long term,\n\t\t\t\t\t// but is an extra cost (unneeded network call). However since it is 5s older, new network call\n\t\t\t\t\t// will update the snapshot in cache.\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsnapshotNonPersistentCache?.remove(nonPersistentCacheKey);\n\t\t\t\t\t}, 5000);\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\t// Remove it from the non persistent cache if an error occured.\n\t\t\t\t\tsnapshotNonPersistentCache?.remove(nonPersistentCacheKey);\n\t\t\t\t\tsnapshotContentsWithEpochP.reject(error);\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t\treturn true;\n\t\t},\n\t).catch(async (error) => {\n\t\todspLogger.sendErrorEvent({ eventName: \"PrefetchLatestSnapshotError\" }, error);\n\t\treturn false;\n\t});\n}\n"]}
1
+ {"version":3,"file":"prefetchLatestSnapshot.js","sourceRoot":"","sources":["../src/prefetchLatestSnapshot.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 { performance } from \"@fluid-internal/client-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred } from \"@fluidframework/core-utils\";\nimport { IResolvedUrl } from \"@fluidframework/driver-definitions\";\nimport {\n\tIOdspResolvedUrl,\n\tIOdspUrlParts,\n\tIPersistedCache,\n\tISnapshotOptions,\n\tOdspResourceTokenFetchOptions,\n\tTokenFetcher,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { PerformanceEvent, createChildMonitoringContext } from \"@fluidframework/telemetry-utils\";\nimport { IVersionedValueWithEpoch } from \"./contracts.js\";\nimport {\n\tISnapshotRequestAndResponseOptions,\n\tSnapshotFormatSupportType,\n\tdownloadSnapshot,\n\tfetchSnapshotWithRedeem,\n} from \"./fetchSnapshot.js\";\nimport { IPrefetchSnapshotContents } from \"./odspCache.js\";\nimport { OdspDocumentServiceFactory } from \"./odspDocumentServiceFactory.js\";\nimport {\n\tcreateCacheSnapshotKey,\n\tcreateOdspLogger,\n\tgetOdspResolvedUrl,\n\ttoInstrumentedOdspTokenFetcher,\n} from \"./odspUtils.js\";\n\n/**\n * Function to prefetch the snapshot and cached it in the persistant cache, so that when the container is loaded\n * the cached latest snapshot could be used and removes the network call from the critical path.\n *\n * @param resolvedUrl - Resolved url to fetch the snapshot.\n * @param getStorageToken - function that can provide the storage token for a given site. This is\n * is also referred to as the \"VROOM\" token in SPO.\n * @param persistedCache - Cache to store the fetched snapshot.\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header.\n * @param logger - Logger to have telemetry events.\n * @param hostSnapshotFetchOptions - Options to fetch the snapshot if any. Otherwise default will be used.\n * @param enableRedeemFallback - True to have the sharing link redeem fallback in case the Trees Latest/Redeem\n * 1RT call fails with redeem error. During fallback it will first redeem the sharing link and then make\n * the Trees latest call.\n * Note: this can be considered deprecated - it will be replaced with `snapshotFormatFetchType`.\n * @param fetchBinarySnapshotFormat - Control if we want to fetch binary format snapshot.\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param odspDocumentServiceFactory - factory to access the non persistent cache and store the prefetch promise.\n *\n * @returns `true` if the snapshot is cached, `false` otherwise.\n * @alpha\n */\nexport async function prefetchLatestSnapshot(\n\tresolvedUrl: IResolvedUrl,\n\tgetStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tpersistedCache: IPersistedCache,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryBaseLogger,\n\thostSnapshotFetchOptions: ISnapshotOptions | undefined,\n\tenableRedeemFallback: boolean = true,\n\tfetchBinarySnapshotFormat?: boolean,\n\tsnapshotFormatFetchType?: SnapshotFormatSupportType,\n\todspDocumentServiceFactory?: OdspDocumentServiceFactory,\n): Promise<boolean> {\n\tconst mc = createChildMonitoringContext({ logger, namespace: \"PrefetchSnapshot\" });\n\tconst odspLogger = createOdspLogger(mc.logger);\n\tconst useGroupIdsForSnapshotFetch = mc.config.getBoolean(\n\t\t\"Fluid.Container.UseLoadingGroupIdForSnapshotFetch\",\n\t);\n\t// For prefetch, we just want to fetch the ungrouped data and want to use the new API if the\n\t// feature gate is set, so provide an empty array.\n\tconst loadingGroupIds = useGroupIdsForSnapshotFetch ? [] : undefined;\n\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\n\tconst resolvedUrlData: IOdspUrlParts = {\n\t\tsiteUrl: odspResolvedUrl.siteUrl,\n\t\tdriveId: odspResolvedUrl.driveId,\n\t\titemId: odspResolvedUrl.itemId,\n\t};\n\tconst storageTokenFetcher = toInstrumentedOdspTokenFetcher(\n\t\todspLogger,\n\t\tresolvedUrlData,\n\t\tgetStorageToken,\n\t\ttrue /* throwOnNullToken */,\n\t);\n\n\tconst snapshotDownloader = async (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tloadingGroupId: string[] | undefined,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t): Promise<ISnapshotRequestAndResponseOptions> => {\n\t\treturn downloadSnapshot(\n\t\t\tfinalOdspResolvedUrl,\n\t\t\tstorageToken,\n\t\t\tloadingGroupId,\n\t\t\tsnapshotOptions,\n\t\t\tundefined,\n\t\t\tcontroller,\n\t\t);\n\t};\n\tconst snapshotKey = createCacheSnapshotKey(odspResolvedUrl);\n\tlet cacheP: Promise<void> | undefined;\n\tlet snapshotEpoch: string | undefined;\n\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch): Promise<void> => {\n\t\tsnapshotEpoch = valueWithEpoch.fluidEpoch;\n\t\tcacheP = persistedCache.put(snapshotKey, valueWithEpoch);\n\t\treturn cacheP;\n\t};\n\n\tconst removeEntries = async (): Promise<void> => persistedCache.removeEntries(snapshotKey.file);\n\treturn PerformanceEvent.timedExecAsync(\n\t\todspLogger,\n\t\t{ eventName: \"PrefetchLatestSnapshot\" },\n\t\tasync () => {\n\t\t\tconst prefetchStartTime = performance.now();\n\t\t\t// Add the deferred promise to the cache, so that it can be leveraged while loading the container.\n\t\t\tconst snapshotContentsWithEpochP = new Deferred<IPrefetchSnapshotContents>();\n\t\t\tconst nonPersistentCacheKey = getKeyForCacheEntry(snapshotKey);\n\t\t\tconst snapshotNonPersistentCache =\n\t\t\t\todspDocumentServiceFactory?.snapshotPrefetchResultCache;\n\t\t\tsnapshotNonPersistentCache?.add(\n\t\t\t\tnonPersistentCacheKey,\n\t\t\t\tasync () => snapshotContentsWithEpochP.promise,\n\t\t\t);\n\t\t\tawait fetchSnapshotWithRedeem(\n\t\t\t\todspResolvedUrl,\n\t\t\t\tstorageTokenFetcher,\n\t\t\t\thostSnapshotFetchOptions,\n\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\todspLogger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tloadingGroupIds,\n\t\t\t\tenableRedeemFallback,\n\t\t\t)\n\t\t\t\t.then(async (value) => {\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!!snapshotEpoch,\n\t\t\t\t\t\t0x585 /* prefetched snapshot should have a valid epoch */,\n\t\t\t\t\t);\n\t\t\t\t\tsnapshotContentsWithEpochP.resolve({\n\t\t\t\t\t\t...value,\n\t\t\t\t\t\tfluidEpoch: snapshotEpoch,\n\t\t\t\t\t\tprefetchStartTime,\n\t\t\t\t\t});\n\t\t\t\t\tassert(cacheP !== undefined, 0x1e7 /* \"caching was not performed!\" */);\n\t\t\t\t\tawait cacheP;\n\t\t\t\t\t// Schedule it to remove from cache after 5s.\n\t\t\t\t\t// 1. While it's in snapshotNonPersistentCache: Load flow will use this value and will not attempt\n\t\t\t\t\t// to fetch snapshot from network again. That's the best from perf POV, but cache will not be\n\t\t\t\t\t// updated if we keep it in this cache, thus we want to eventually remove snapshot from this cache.\n\t\t\t\t\t// 2. After it's removed from snapshotNonPersistentCache: snapshot is present in persistent cache,\n\t\t\t\t\t// so we sill still use it (in accordance with cache policy controlled by host). But load flow will\n\t\t\t\t\t// also fetch snapshot (in parallel) from storage and update cache. This is fine long term,\n\t\t\t\t\t// but is an extra cost (unneeded network call). However since it is 5s older, new network call\n\t\t\t\t\t// will update the snapshot in cache.\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsnapshotNonPersistentCache?.remove(nonPersistentCacheKey);\n\t\t\t\t\t}, 5000);\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\t// Remove it from the non persistent cache if an error occured.\n\t\t\t\t\tsnapshotNonPersistentCache?.remove(nonPersistentCacheKey);\n\t\t\t\t\tsnapshotContentsWithEpochP.reject(error);\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t\treturn true;\n\t\t},\n\t).catch(async (error) => {\n\t\todspLogger.sendErrorEvent({ eventName: \"PrefetchLatestSnapshotError\" }, error);\n\t\treturn false;\n\t});\n}\n"]}
@@ -2,10 +2,10 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
5
+ import { IDisposable } from "@fluidframework/core-interfaces";
6
6
  import { FetchSource, IDocumentStorageService, IDocumentStorageServicePolicies, ISnapshot, ISnapshotFetchOptions, ISummaryContext } from "@fluidframework/driver-definitions";
7
7
  import { ICreateBlobResponse, ISnapshotTree, ISummaryHandle, ISummaryTree, IVersion } from "@fluidframework/protocol-definitions";
8
- import { IDisposable } from "@fluidframework/core-interfaces";
8
+ import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
9
9
  export declare class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {
10
10
  private readonly internalStorageService;
11
11
  private readonly logger;
@@ -1 +1 @@
1
- {"version":3,"file":"retryErrorsStorageAdapter.d.ts","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAgB,mBAAmB,EAAc,MAAM,iCAAiC,CAAC;AAChG,OAAO,EACN,WAAW,EACX,uBAAuB,EACvB,+BAA+B,EAC/B,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAG9D,qBAAa,yBAA0B,YAAW,uBAAuB,EAAE,WAAW;IAGpF,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHxB,OAAO,CAAC,SAAS,CAAS;gBAER,sBAAsB,EAAE,uBAAuB,EAC/C,MAAM,EAAE,mBAAmB;IAG7C,IAAW,QAAQ,IAAI,+BAA+B,GAAG,SAAS,CAEjE;IACD,IAAW,QAAQ,IAAI,OAAO,CAE7B;IACM,OAAO,IAAI,IAAI;IAKT,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAOlE,WAAW,CAAC,oBAAoB,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC;IAS7E,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO9C,WAAW,CAEvB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,QAAQ,EAAE,CAAC;IAaT,wBAAwB,CACpC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,CAAC;IAQL,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9D,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO5E,OAAO,CAAC,oBAAoB;YASd,YAAY;CAG1B"}
1
+ {"version":3,"file":"retryErrorsStorageAdapter.d.ts","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EACN,WAAW,EACX,uBAAuB,EACvB,+BAA+B,EAC/B,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAA4B,MAAM,iCAAiC,CAAC;AAGhG,qBAAa,yBAA0B,YAAW,uBAAuB,EAAE,WAAW;IAGpF,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHxB,OAAO,CAAC,SAAS,CAAS;gBAER,sBAAsB,EAAE,uBAAuB,EAC/C,MAAM,EAAE,mBAAmB;IAG7C,IAAW,QAAQ,IAAI,+BAA+B,GAAG,SAAS,CAEjE;IACD,IAAW,QAAQ,IAAI,OAAO,CAE7B;IACM,OAAO,IAAI,IAAI;IAKT,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAOlE,WAAW,CAAC,oBAAoB,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC;IAS7E,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO9C,WAAW,CAEvB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,QAAQ,EAAE,CAAC;IAaT,wBAAwB,CACpC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,CAAC;IAQL,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9D,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO5E,OAAO,CAAC,oBAAoB;YASd,YAAY;CAG1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"retryErrorsStorageAdapter.js","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.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 { LoggingError, ITelemetryLoggerExt, UsageError } from \"@fluidframework/telemetry-utils\";\nimport {\n\tFetchSource,\n\tIDocumentStorageService,\n\tIDocumentStorageServicePolicies,\n\tISnapshot,\n\tISnapshotFetchOptions,\n\tISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n\tICreateBlobResponse,\n\tISnapshotTree,\n\tISummaryHandle,\n\tISummaryTree,\n\tIVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { runWithRetry } from \"./retryUtils.js\";\n\nexport class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {\n\tprivate _disposed = false;\n\tconstructor(\n\t\tprivate readonly internalStorageService: IDocumentStorageService,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {}\n\n\tpublic get policies(): IDocumentStorageServicePolicies | undefined {\n\t\treturn this.internalStorageService.policies;\n\t}\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.getSnapshotTree(version),\n\t\t\t\"storage_getSnapshotTree\",\n\t\t);\n\t}\n\n\tpublic async getSnapshot(snapshotFetchOptions?: ISnapshotFetchOptions): Promise<ISnapshot> {\n\t\treturn this.runWithRetry(async () => {\n\t\t\tif (this.internalStorageService.getSnapshot !== undefined) {\n\t\t\t\treturn this.internalStorageService.getSnapshot(snapshotFetchOptions);\n\t\t\t}\n\t\t\tthrow new UsageError(\"getSnapshot should exist in storage adapter in ODSP driver\");\n\t\t}, \"storage_getSnapshot\");\n\t}\n\n\tpublic async readBlob(id: string): Promise<ArrayBufferLike> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.readBlob(id),\n\t\t\t\"storage_readBlob\",\n\t\t);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tversionId: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<IVersion[]> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () =>\n\t\t\t\tthis.internalStorageService.getVersions(\n\t\t\t\t\tversionId,\n\t\t\t\t\tcount,\n\t\t\t\t\tscenarioName,\n\t\t\t\t\tfetchSource,\n\t\t\t\t),\n\t\t\t\"storage_getVersions\",\n\t\t);\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\t// Creation flow with attachment blobs - need to do retries!\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n\t\t\t\"storage_uploadSummaryWithContext\",\n\t\t);\n\t}\n\n\tpublic async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.downloadSummary(handle),\n\t\t\t\"storage_downloadSummary\",\n\t\t);\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.createBlob(file),\n\t\t\t\"storage_createBlob\",\n\t\t);\n\t}\n\n\tprivate checkStorageDisposed(): void {\n\t\tif (this._disposed) {\n\t\t\t// pre-0.58 error message: storageServiceDisposedCannotRetry\n\t\t\tthrow new LoggingError(\"Storage Service is disposed. Cannot retry\", {\n\t\t\t\tcanRetry: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n\t\treturn runWithRetry(api, callName, this.logger, () => this.checkStorageDisposed());\n\t}\n}\n"]}
1
+ {"version":3,"file":"retryErrorsStorageAdapter.js","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.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 { IDisposable } from \"@fluidframework/core-interfaces\";\nimport {\n\tFetchSource,\n\tIDocumentStorageService,\n\tIDocumentStorageServicePolicies,\n\tISnapshot,\n\tISnapshotFetchOptions,\n\tISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n\tICreateBlobResponse,\n\tISnapshotTree,\n\tISummaryHandle,\n\tISummaryTree,\n\tIVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt, LoggingError, UsageError } from \"@fluidframework/telemetry-utils\";\nimport { runWithRetry } from \"./retryUtils.js\";\n\nexport class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {\n\tprivate _disposed = false;\n\tconstructor(\n\t\tprivate readonly internalStorageService: IDocumentStorageService,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {}\n\n\tpublic get policies(): IDocumentStorageServicePolicies | undefined {\n\t\treturn this.internalStorageService.policies;\n\t}\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.getSnapshotTree(version),\n\t\t\t\"storage_getSnapshotTree\",\n\t\t);\n\t}\n\n\tpublic async getSnapshot(snapshotFetchOptions?: ISnapshotFetchOptions): Promise<ISnapshot> {\n\t\treturn this.runWithRetry(async () => {\n\t\t\tif (this.internalStorageService.getSnapshot !== undefined) {\n\t\t\t\treturn this.internalStorageService.getSnapshot(snapshotFetchOptions);\n\t\t\t}\n\t\t\tthrow new UsageError(\"getSnapshot should exist in storage adapter in ODSP driver\");\n\t\t}, \"storage_getSnapshot\");\n\t}\n\n\tpublic async readBlob(id: string): Promise<ArrayBufferLike> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.readBlob(id),\n\t\t\t\"storage_readBlob\",\n\t\t);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tversionId: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<IVersion[]> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () =>\n\t\t\t\tthis.internalStorageService.getVersions(\n\t\t\t\t\tversionId,\n\t\t\t\t\tcount,\n\t\t\t\t\tscenarioName,\n\t\t\t\t\tfetchSource,\n\t\t\t\t),\n\t\t\t\"storage_getVersions\",\n\t\t);\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\t// Creation flow with attachment blobs - need to do retries!\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n\t\t\t\"storage_uploadSummaryWithContext\",\n\t\t);\n\t}\n\n\tpublic async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.downloadSummary(handle),\n\t\t\t\"storage_downloadSummary\",\n\t\t);\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.createBlob(file),\n\t\t\t\"storage_createBlob\",\n\t\t);\n\t}\n\n\tprivate checkStorageDisposed(): void {\n\t\tif (this._disposed) {\n\t\t\t// pre-0.58 error message: storageServiceDisposedCannotRetry\n\t\t\tthrow new LoggingError(\"Storage Service is disposed. Cannot retry\", {\n\t\t\t\tcanRetry: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n\t\treturn runWithRetry(api, callName, this.logger, () => this.checkStorageDisposed());\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"retryUtils.d.ts","sourceRoot":"","sources":["../src/retryUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAOtE;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EACnC,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,mBAAmB,EAC3B,aAAa,CAAC,EAAE,MAAM,IAAI,GACxB,OAAO,CAAC,CAAC,CAAC,CAgFZ"}
1
+ {"version":3,"file":"retryUtils.d.ts","sourceRoot":"","sources":["../src/retryUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAGtE;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EACnC,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,mBAAmB,EAC3B,aAAa,CAAC,EAAE,MAAM,IAAI,GACxB,OAAO,CAAC,CAAC,CAAC,CAgFZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"retryUtils.js","sourceRoot":"","sources":["../src/retryUtils.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 { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { performance } from \"@fluid-internal/client-utils\";\nimport { delay } from \"@fluidframework/core-utils\";\nimport { canRetryOnError, getRetryDelayFromError } from \"@fluidframework/driver-utils\";\nimport { OdspErrorTypes } from \"@fluidframework/odsp-driver-definitions\";\nimport { Odsp409Error } from \"./epochTracker.js\";\n\n/**\n * This method retries only for retriable coherency and service read only errors.\n */\nexport async function runWithRetry<T>(\n\tapi: () => Promise<T>,\n\tcallName: string,\n\tlogger: ITelemetryLoggerExt,\n\tcheckDisposed?: () => void,\n): Promise<T> {\n\tlet retryAfter = 1000;\n\tconst start = performance.now();\n\tlet lastError: unknown;\n\tfor (let attempts = 1; ; attempts++) {\n\t\tif (checkDisposed !== undefined) {\n\t\t\tcheckDisposed();\n\t\t}\n\t\ttry {\n\t\t\tconst result = await api();\n\t\t\tif (attempts > 1) {\n\t\t\t\tlogger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"MultipleRetries\",\n\t\t\t\t\t\tcallName,\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tduration: performance.now() - start,\n\t\t\t\t\t},\n\t\t\t\t\tlastError,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn result;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tconst canRetry = canRetryOnError(error);\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tconst coherencyError = error?.[Odsp409Error] === true;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tconst serviceReadonlyError = error?.errorType === OdspErrorTypes.serviceReadOnly;\n\n\t\t\t// logging the first failed retry instead of every attempt. We want to avoid filling telemetry\n\t\t\t// when we have tight loop of retrying in offline mode, but we also want to know what caused\n\t\t\t// the failure in the first place\n\t\t\tif (attempts === 1) {\n\t\t\t\tlogger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: `${callName}_firstFailed`,\n\t\t\t\t\t\tcallName,\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tduration: performance.now() - start, // record total wait time.\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Retry for retriable 409 coherency errors or serviceReadOnly errors. These errors are always retriable\n\t\t\t// unless someone specifically set canRetry = false on the error like in fetchSnapshot() flow. So in\n\t\t\t// that case don't retry.\n\t\t\tif (!((coherencyError || serviceReadonlyError) && canRetry)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\t// SPO itself does number of retries internally before returning 409 to client.\n\t\t\t// That multiplied to 5 suggests need to reconsider current design, as client spends\n\t\t\t// too much time / bandwidth doing the same thing without any progress.\n\t\t\tif (attempts === 5) {\n\t\t\t\tlogger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: coherencyError\n\t\t\t\t\t\t\t? \"CoherencyErrorTooManyRetries\"\n\t\t\t\t\t\t\t: \"ServiceReadonlyErrorTooManyRetries\",\n\t\t\t\t\t\tcallName,\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tduration: performance.now() - start, // record total wait time.\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\t// Fail hard.\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\terror.canRetry = false;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tretryAfter = getRetryDelayFromError(error) ?? retryAfter;\n\t\t\tawait delay(Math.floor(retryAfter));\n\t\t\tretryAfter += (retryAfter / 4) * (1 + Math.random());\n\t\t\tlastError = error;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"retryUtils.js","sourceRoot":"","sources":["../src/retryUtils.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 { performance } from \"@fluid-internal/client-utils\";\nimport { delay } from \"@fluidframework/core-utils\";\nimport { canRetryOnError, getRetryDelayFromError } from \"@fluidframework/driver-utils\";\nimport { OdspErrorTypes } from \"@fluidframework/odsp-driver-definitions\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { Odsp409Error } from \"./epochTracker.js\";\n\n/**\n * This method retries only for retriable coherency and service read only errors.\n */\nexport async function runWithRetry<T>(\n\tapi: () => Promise<T>,\n\tcallName: string,\n\tlogger: ITelemetryLoggerExt,\n\tcheckDisposed?: () => void,\n): Promise<T> {\n\tlet retryAfter = 1000;\n\tconst start = performance.now();\n\tlet lastError: unknown;\n\tfor (let attempts = 1; ; attempts++) {\n\t\tif (checkDisposed !== undefined) {\n\t\t\tcheckDisposed();\n\t\t}\n\t\ttry {\n\t\t\tconst result = await api();\n\t\t\tif (attempts > 1) {\n\t\t\t\tlogger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"MultipleRetries\",\n\t\t\t\t\t\tcallName,\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tduration: performance.now() - start,\n\t\t\t\t\t},\n\t\t\t\t\tlastError,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn result;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tconst canRetry = canRetryOnError(error);\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tconst coherencyError = error?.[Odsp409Error] === true;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tconst serviceReadonlyError = error?.errorType === OdspErrorTypes.serviceReadOnly;\n\n\t\t\t// logging the first failed retry instead of every attempt. We want to avoid filling telemetry\n\t\t\t// when we have tight loop of retrying in offline mode, but we also want to know what caused\n\t\t\t// the failure in the first place\n\t\t\tif (attempts === 1) {\n\t\t\t\tlogger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: `${callName}_firstFailed`,\n\t\t\t\t\t\tcallName,\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tduration: performance.now() - start, // record total wait time.\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Retry for retriable 409 coherency errors or serviceReadOnly errors. These errors are always retriable\n\t\t\t// unless someone specifically set canRetry = false on the error like in fetchSnapshot() flow. So in\n\t\t\t// that case don't retry.\n\t\t\tif (!((coherencyError || serviceReadonlyError) && canRetry)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\t// SPO itself does number of retries internally before returning 409 to client.\n\t\t\t// That multiplied to 5 suggests need to reconsider current design, as client spends\n\t\t\t// too much time / bandwidth doing the same thing without any progress.\n\t\t\tif (attempts === 5) {\n\t\t\t\tlogger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: coherencyError\n\t\t\t\t\t\t\t? \"CoherencyErrorTooManyRetries\"\n\t\t\t\t\t\t\t: \"ServiceReadonlyErrorTooManyRetries\",\n\t\t\t\t\t\tcallName,\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tduration: performance.now() - start, // record total wait time.\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\t// Fail hard.\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\terror.canRetry = false;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tretryAfter = getRetryDelayFromError(error) ?? retryAfter;\n\t\t\tawait delay(Math.floor(retryAfter));\n\t\t\tretryAfter += (retryAfter / 4) * (1 + Math.random());\n\t\t\tlastError = error;\n\t\t}\n\t}\n}\n"]}
@@ -3,17 +3,17 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { strict as assert } from "node:assert";
6
- import * as api from "@fluidframework/protocol-definitions";
7
6
  import { bufferToString } from "@fluid-internal/client-utils";
8
7
  import { SharingLinkRole, SharingLinkScope, } from "@fluidframework/odsp-driver-definitions";
8
+ import * as api from "@fluidframework/protocol-definitions";
9
9
  import { createChildLogger } from "@fluidframework/telemetry-utils";
10
- import { convertCreateNewSummaryTreeToTreeAndBlobs } from "../createNewUtils.js";
11
10
  import { createNewFluidFile } from "../createFile.js";
12
11
  import { createNewContainerOnExistingFile } from "../createNewContainerOnExistingFile.js";
12
+ import { convertCreateNewSummaryTreeToTreeAndBlobs } from "../createNewUtils.js";
13
13
  import { EpochTracker } from "../epochTracker.js";
14
+ import { LocalPersistentCache } from "../odspCache.js";
14
15
  import { getHashedDocumentId } from "../odspPublicUtils.js";
15
16
  import { createCacheSnapshotKey } from "../odspUtils.js";
16
- import { LocalPersistentCache } from "../odspCache.js";
17
17
  import { mockFetchOk } from "./mockFetch.js";
18
18
  const createUtLocalCache = () => new LocalPersistentCache();
19
19
  describe("Create New Utils Tests", () => {
@@ -1 +1 @@
1
- {"version":3,"file":"createNewUtilsTests.spec.js","sourceRoot":"","sources":["../../src/test/createNewUtilsTests.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 \"node:assert\";\nimport { ISnapshot } from \"@fluidframework/driver-definitions\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport {\n\tIFileEntry,\n\tIOdspResolvedUrl,\n\tISharingLinkKind,\n\tSharingLinkRole,\n\tSharingLinkScope,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { convertCreateNewSummaryTreeToTreeAndBlobs } from \"../createNewUtils.js\";\nimport { createNewFluidFile } from \"../createFile.js\";\nimport { createNewContainerOnExistingFile } from \"../createNewContainerOnExistingFile.js\";\nimport { EpochTracker } from \"../epochTracker.js\";\nimport { getHashedDocumentId } from \"../odspPublicUtils.js\";\nimport { INewFileInfo, createCacheSnapshotKey, IExistingFileInfo } from \"../odspUtils.js\";\nimport { LocalPersistentCache } from \"../odspCache.js\";\nimport { mockFetchOk } from \"./mockFetch.js\";\n\nconst createUtLocalCache = (): LocalPersistentCache => new LocalPersistentCache();\n\ndescribe(\"Create New Utils Tests\", () => {\n\tconst documentAttributes: api.IDocumentAttributes = {\n\t\tminimumSequenceNumber: 0,\n\t\tsequenceNumber: 0,\n\t};\n\tconst blobContent = \"testing\";\n\tconst createSummary = (): api.ISummaryTree => {\n\t\tconst summary: api.ISummaryTree = {\n\t\t\ttype: api.SummaryType.Tree,\n\t\t\ttree: {},\n\t\t};\n\n\t\tsummary.tree[\".app\"] = {\n\t\t\ttype: api.SummaryType.Tree,\n\t\t\ttree: {\n\t\t\t\tattributes: {\n\t\t\t\t\ttype: api.SummaryType.Blob,\n\t\t\t\t\tcontent: blobContent,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tsummary.tree[\".protocol\"] = {\n\t\t\ttype: api.SummaryType.Tree,\n\t\t\ttree: {\n\t\t\t\tattributes: {\n\t\t\t\t\ttype: api.SummaryType.Blob,\n\t\t\t\t\tcontent: JSON.stringify(documentAttributes),\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\treturn summary;\n\t};\n\n\tconst siteUrl = \"https://microsoft.sharepoint-df.com/siteUrl\";\n\tconst driveId = \"driveId\";\n\tconst itemId = \"itemId\";\n\tconst resolvedUrl = {\n\t\tsiteUrl,\n\t\tdriveId,\n\t\titemId,\n\t\todspResolvedUrl: true,\n\t} as unknown as IOdspResolvedUrl;\n\tconst filePath = \"path\";\n\tlet newFileParams: INewFileInfo;\n\tlet hashedDocumentId: string;\n\tlet localCache: LocalPersistentCache;\n\tlet fileEntry: IFileEntry;\n\tlet epochTracker: EpochTracker;\n\n\tbefore(async () => {\n\t\thashedDocumentId = await getHashedDocumentId(driveId, itemId);\n\t\tfileEntry = {\n\t\t\tdocId: hashedDocumentId,\n\t\t\tresolvedUrl,\n\t\t};\n\t});\n\n\tbeforeEach(async () => {\n\t\tlocalCache = createUtLocalCache();\n\t\t// use null logger here as we expect errors\n\t\tepochTracker = new EpochTracker(\n\t\t\tlocalCache,\n\t\t\t{\n\t\t\t\tdocId: hashedDocumentId,\n\t\t\t\tresolvedUrl,\n\t\t\t},\n\t\t\tcreateChildLogger(),\n\t\t);\n\t\tnewFileParams = {\n\t\t\ttype: \"New\",\n\t\t\tdriveId,\n\t\t\tsiteUrl,\n\t\t\tfilePath,\n\t\t\tfilename: \"filename\",\n\t\t};\n\t});\n\n\tafterEach(async () => {\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tconst test = (snapshot: ISnapshot): void => {\n\t\tconst snapshotTree = snapshot.snapshotTree;\n\t\tassert.strictEqual(\n\t\t\tObject.entries(snapshotTree.trees).length,\n\t\t\t2,\n\t\t\t\"app and protocol should be there\",\n\t\t);\n\t\tassert.strictEqual(snapshot.blobContents.size, 2, \"2 blobs should be there\");\n\n\t\tconst appTree = snapshotTree.trees[\".app\"];\n\t\tconst protocolTree = snapshotTree.trees[\".protocol\"];\n\t\tassert(appTree !== undefined, \"App tree should be there\");\n\t\tassert(protocolTree !== undefined, \"Protocol tree should be there\");\n\n\t\tconst appTreeBlobId = appTree.blobs.attributes;\n\t\tconst appTreeBlobValBuffer = snapshot.blobContents.get(appTreeBlobId);\n\t\tassert(appTreeBlobValBuffer !== undefined, \"app blob value should exist\");\n\t\tconst appTreeBlobVal = bufferToString(appTreeBlobValBuffer, \"utf8\");\n\t\tassert(appTreeBlobVal === blobContent, \"Blob content should match\");\n\n\t\tconst docAttributesBlobId = protocolTree.blobs.attributes;\n\t\tconst docAttributesBuffer = snapshot.blobContents.get(docAttributesBlobId);\n\t\tassert(docAttributesBuffer !== undefined, \"protocol attributes blob value should exist\");\n\t\tconst docAttributesBlobValue = bufferToString(docAttributesBuffer, \"utf8\");\n\t\tassert(\n\t\t\tdocAttributesBlobValue === JSON.stringify(documentAttributes),\n\t\t\t\"Blob content should match\",\n\t\t);\n\n\t\tassert(snapshot.ops.length === 0, \"No ops should be there\");\n\t\tassert(snapshot.sequenceNumber === 0, \"Seq number should be 0\");\n\t};\n\n\tit(\"Should convert as expected and check contents\", async () => {\n\t\tconst snapshot = convertCreateNewSummaryTreeToTreeAndBlobs(createSummary(), \"\");\n\t\ttest(snapshot);\n\t});\n\n\tit(\"Should cache converted summary during createNewFluidFile\", async () => {\n\t\tconst odspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\tconst snapshot = await epochTracker.get(createCacheSnapshotKey(odspResolvedUrl));\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\ttest(snapshot);\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should cache converted summary during createNewContainerOnExistingFile\", async () => {\n\t\tconst existingFileParams: IExistingFileInfo = {\n\t\t\ttype: \"Existing\",\n\t\t\titemId: \"itemId1\",\n\t\t\tsiteUrl,\n\t\t\tdriveId,\n\t\t};\n\t\tconst odspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewContainerOnExistingFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\texistingFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\tconst snapshot = await epochTracker.get(createCacheSnapshotKey(odspResolvedUrl));\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\ttest(snapshot);\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should save 'sharing' information received during createNewFluidFile\", async () => {\n\t\tconst createLinkType: ISharingLinkKind = {\n\t\t\tscope: SharingLinkScope.users,\n\t\t\trole: SharingLinkRole.edit,\n\t\t};\n\t\tnewFileParams.createLinkType = createLinkType;\n\n\t\t// Test that sharing link is set appropriately when it is received in the response from ODSP\n\t\tconst mockSharingLinkData = {\n\t\t\tlocalizedDescription: \"Specific users with the link can view\",\n\t\t\ticonUrl: \"https://mock.icon.url\",\n\t\t\tscope: \"organization\",\n\t\t\ttype: \"view\",\n\t\t\twebUrl: \"https://mock.url\",\n\t\t\tblocksDownload: false,\n\t\t\tcreateOnly: false,\n\t\t\tstatus: \"Created\",\n\t\t\tcreatedDateTime: \"2022-05-18T02:58:17.0256105Z\",\n\t\t};\n\t\tconst mockSharingData = {\n\t\t\tshareId: \"c40e6f0a-666e-48bf-9509-066900a73b2b\",\n\t\t\tsharingLink: mockSharingLinkData,\n\t\t};\n\t\tlet odspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\tfalse /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t\ttrue /* enableSingleRequestForShareLinkWithCreate */,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\titemId: \"mockItemId\",\n\t\t\t\tid: \"mockId\",\n\t\t\t\tsharing: mockSharingData,\n\t\t\t\tsharingLinkErrorReason: undefined,\n\t\t\t},\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert.deepStrictEqual(odspResolvedUrl.shareLinkInfo?.createLink, {\n\t\t\tshareId: mockSharingData.shareId,\n\t\t\tlink: {\n\t\t\t\trole: mockSharingData.sharingLink.type,\n\t\t\t\t...mockSharingData.sharingLink,\n\t\t\t},\n\t\t\terror: undefined,\n\t\t});\n\n\t\t// Test that error message is set appropriately when it is received in the response from ODSP\n\t\tconst mockSharingError = {\n\t\t\terror: {\n\t\t\t\tcode: \"invalidRequest\",\n\t\t\t\tmessage: \"Invalid request\",\n\t\t\t\tinnerError: {\n\t\t\t\t\tcode: \"invalidRequest\",\n\t\t\t\t\terrorType: \"expected\",\n\t\t\t\t\tmessage: \"The CreateLinkScope 'asdf' is not valid or supported.\",\n\t\t\t\t\tstackTrace: \"Exceptions.InvalidRequestException\",\n\t\t\t\t\tthrowSite: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\todspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\tfalse /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t\ttrue /* enableSingleRequestForShareLinkWithCreate */,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\titemId: \"mockItemId\",\n\t\t\t\tid: \"mockId\",\n\t\t\t\tsharingLinkErrorReason: \"mockError\",\n\t\t\t\tsharing: mockSharingError,\n\t\t\t},\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert.deepStrictEqual(odspResolvedUrl.shareLinkInfo?.createLink, {\n\t\t\tshareId: undefined,\n\t\t\tlink: undefined,\n\t\t\terror: mockSharingError.error,\n\t\t});\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should set the isClpCompliantApp prop on resolved url if already present when createNewFluidFile\", async () => {\n\t\tconst odspResolvedUrl1 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\ttrue /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(odspResolvedUrl1.isClpCompliantApp, \"isClpCompliantApp should be set\");\n\n\t\tconst odspResolvedUrl2 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(!odspResolvedUrl2.isClpCompliantApp, \"isClpCompliantApp should be falsy\");\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should set the isClpCompliantApp prop on resolved url if already present when createNewContainerOnExistingFile\", async () => {\n\t\tconst existingFileParams: IExistingFileInfo = {\n\t\t\ttype: \"Existing\",\n\t\t\titemId: \"itemId1\",\n\t\t\tsiteUrl,\n\t\t\tdriveId,\n\t\t};\n\t\tconst odspResolvedUrl1 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewContainerOnExistingFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\texistingFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\ttrue /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(odspResolvedUrl1.isClpCompliantApp, \"isClpCompliantApp should be set\");\n\n\t\tconst odspResolvedUrl2 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(!odspResolvedUrl2.isClpCompliantApp, \"isClpCompliantApp should be falsy\");\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n});\n"]}
1
+ {"version":3,"file":"createNewUtilsTests.spec.js","sourceRoot":"","sources":["../../src/test/createNewUtilsTests.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 \"node:assert\";\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport { ISnapshot } from \"@fluidframework/driver-definitions\";\nimport {\n\tIFileEntry,\n\tIOdspResolvedUrl,\n\tISharingLinkKind,\n\tSharingLinkRole,\n\tSharingLinkScope,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { createNewFluidFile } from \"../createFile.js\";\nimport { createNewContainerOnExistingFile } from \"../createNewContainerOnExistingFile.js\";\nimport { convertCreateNewSummaryTreeToTreeAndBlobs } from \"../createNewUtils.js\";\nimport { EpochTracker } from \"../epochTracker.js\";\nimport { LocalPersistentCache } from \"../odspCache.js\";\nimport { getHashedDocumentId } from \"../odspPublicUtils.js\";\nimport { IExistingFileInfo, INewFileInfo, createCacheSnapshotKey } from \"../odspUtils.js\";\nimport { mockFetchOk } from \"./mockFetch.js\";\n\nconst createUtLocalCache = (): LocalPersistentCache => new LocalPersistentCache();\n\ndescribe(\"Create New Utils Tests\", () => {\n\tconst documentAttributes: api.IDocumentAttributes = {\n\t\tminimumSequenceNumber: 0,\n\t\tsequenceNumber: 0,\n\t};\n\tconst blobContent = \"testing\";\n\tconst createSummary = (): api.ISummaryTree => {\n\t\tconst summary: api.ISummaryTree = {\n\t\t\ttype: api.SummaryType.Tree,\n\t\t\ttree: {},\n\t\t};\n\n\t\tsummary.tree[\".app\"] = {\n\t\t\ttype: api.SummaryType.Tree,\n\t\t\ttree: {\n\t\t\t\tattributes: {\n\t\t\t\t\ttype: api.SummaryType.Blob,\n\t\t\t\t\tcontent: blobContent,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tsummary.tree[\".protocol\"] = {\n\t\t\ttype: api.SummaryType.Tree,\n\t\t\ttree: {\n\t\t\t\tattributes: {\n\t\t\t\t\ttype: api.SummaryType.Blob,\n\t\t\t\t\tcontent: JSON.stringify(documentAttributes),\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\treturn summary;\n\t};\n\n\tconst siteUrl = \"https://microsoft.sharepoint-df.com/siteUrl\";\n\tconst driveId = \"driveId\";\n\tconst itemId = \"itemId\";\n\tconst resolvedUrl = {\n\t\tsiteUrl,\n\t\tdriveId,\n\t\titemId,\n\t\todspResolvedUrl: true,\n\t} as unknown as IOdspResolvedUrl;\n\tconst filePath = \"path\";\n\tlet newFileParams: INewFileInfo;\n\tlet hashedDocumentId: string;\n\tlet localCache: LocalPersistentCache;\n\tlet fileEntry: IFileEntry;\n\tlet epochTracker: EpochTracker;\n\n\tbefore(async () => {\n\t\thashedDocumentId = await getHashedDocumentId(driveId, itemId);\n\t\tfileEntry = {\n\t\t\tdocId: hashedDocumentId,\n\t\t\tresolvedUrl,\n\t\t};\n\t});\n\n\tbeforeEach(async () => {\n\t\tlocalCache = createUtLocalCache();\n\t\t// use null logger here as we expect errors\n\t\tepochTracker = new EpochTracker(\n\t\t\tlocalCache,\n\t\t\t{\n\t\t\t\tdocId: hashedDocumentId,\n\t\t\t\tresolvedUrl,\n\t\t\t},\n\t\t\tcreateChildLogger(),\n\t\t);\n\t\tnewFileParams = {\n\t\t\ttype: \"New\",\n\t\t\tdriveId,\n\t\t\tsiteUrl,\n\t\t\tfilePath,\n\t\t\tfilename: \"filename\",\n\t\t};\n\t});\n\n\tafterEach(async () => {\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tconst test = (snapshot: ISnapshot): void => {\n\t\tconst snapshotTree = snapshot.snapshotTree;\n\t\tassert.strictEqual(\n\t\t\tObject.entries(snapshotTree.trees).length,\n\t\t\t2,\n\t\t\t\"app and protocol should be there\",\n\t\t);\n\t\tassert.strictEqual(snapshot.blobContents.size, 2, \"2 blobs should be there\");\n\n\t\tconst appTree = snapshotTree.trees[\".app\"];\n\t\tconst protocolTree = snapshotTree.trees[\".protocol\"];\n\t\tassert(appTree !== undefined, \"App tree should be there\");\n\t\tassert(protocolTree !== undefined, \"Protocol tree should be there\");\n\n\t\tconst appTreeBlobId = appTree.blobs.attributes;\n\t\tconst appTreeBlobValBuffer = snapshot.blobContents.get(appTreeBlobId);\n\t\tassert(appTreeBlobValBuffer !== undefined, \"app blob value should exist\");\n\t\tconst appTreeBlobVal = bufferToString(appTreeBlobValBuffer, \"utf8\");\n\t\tassert(appTreeBlobVal === blobContent, \"Blob content should match\");\n\n\t\tconst docAttributesBlobId = protocolTree.blobs.attributes;\n\t\tconst docAttributesBuffer = snapshot.blobContents.get(docAttributesBlobId);\n\t\tassert(docAttributesBuffer !== undefined, \"protocol attributes blob value should exist\");\n\t\tconst docAttributesBlobValue = bufferToString(docAttributesBuffer, \"utf8\");\n\t\tassert(\n\t\t\tdocAttributesBlobValue === JSON.stringify(documentAttributes),\n\t\t\t\"Blob content should match\",\n\t\t);\n\n\t\tassert(snapshot.ops.length === 0, \"No ops should be there\");\n\t\tassert(snapshot.sequenceNumber === 0, \"Seq number should be 0\");\n\t};\n\n\tit(\"Should convert as expected and check contents\", async () => {\n\t\tconst snapshot = convertCreateNewSummaryTreeToTreeAndBlobs(createSummary(), \"\");\n\t\ttest(snapshot);\n\t});\n\n\tit(\"Should cache converted summary during createNewFluidFile\", async () => {\n\t\tconst odspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\tconst snapshot = await epochTracker.get(createCacheSnapshotKey(odspResolvedUrl));\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\ttest(snapshot);\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should cache converted summary during createNewContainerOnExistingFile\", async () => {\n\t\tconst existingFileParams: IExistingFileInfo = {\n\t\t\ttype: \"Existing\",\n\t\t\titemId: \"itemId1\",\n\t\t\tsiteUrl,\n\t\t\tdriveId,\n\t\t};\n\t\tconst odspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewContainerOnExistingFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\texistingFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\tconst snapshot = await epochTracker.get(createCacheSnapshotKey(odspResolvedUrl));\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\ttest(snapshot);\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should save 'sharing' information received during createNewFluidFile\", async () => {\n\t\tconst createLinkType: ISharingLinkKind = {\n\t\t\tscope: SharingLinkScope.users,\n\t\t\trole: SharingLinkRole.edit,\n\t\t};\n\t\tnewFileParams.createLinkType = createLinkType;\n\n\t\t// Test that sharing link is set appropriately when it is received in the response from ODSP\n\t\tconst mockSharingLinkData = {\n\t\t\tlocalizedDescription: \"Specific users with the link can view\",\n\t\t\ticonUrl: \"https://mock.icon.url\",\n\t\t\tscope: \"organization\",\n\t\t\ttype: \"view\",\n\t\t\twebUrl: \"https://mock.url\",\n\t\t\tblocksDownload: false,\n\t\t\tcreateOnly: false,\n\t\t\tstatus: \"Created\",\n\t\t\tcreatedDateTime: \"2022-05-18T02:58:17.0256105Z\",\n\t\t};\n\t\tconst mockSharingData = {\n\t\t\tshareId: \"c40e6f0a-666e-48bf-9509-066900a73b2b\",\n\t\t\tsharingLink: mockSharingLinkData,\n\t\t};\n\t\tlet odspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\tfalse /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t\ttrue /* enableSingleRequestForShareLinkWithCreate */,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\titemId: \"mockItemId\",\n\t\t\t\tid: \"mockId\",\n\t\t\t\tsharing: mockSharingData,\n\t\t\t\tsharingLinkErrorReason: undefined,\n\t\t\t},\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert.deepStrictEqual(odspResolvedUrl.shareLinkInfo?.createLink, {\n\t\t\tshareId: mockSharingData.shareId,\n\t\t\tlink: {\n\t\t\t\trole: mockSharingData.sharingLink.type,\n\t\t\t\t...mockSharingData.sharingLink,\n\t\t\t},\n\t\t\terror: undefined,\n\t\t});\n\n\t\t// Test that error message is set appropriately when it is received in the response from ODSP\n\t\tconst mockSharingError = {\n\t\t\terror: {\n\t\t\t\tcode: \"invalidRequest\",\n\t\t\t\tmessage: \"Invalid request\",\n\t\t\t\tinnerError: {\n\t\t\t\t\tcode: \"invalidRequest\",\n\t\t\t\t\terrorType: \"expected\",\n\t\t\t\t\tmessage: \"The CreateLinkScope 'asdf' is not valid or supported.\",\n\t\t\t\t\tstackTrace: \"Exceptions.InvalidRequestException\",\n\t\t\t\t\tthrowSite: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\todspResolvedUrl = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\tfalse /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t\ttrue /* enableSingleRequestForShareLinkWithCreate */,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\titemId: \"mockItemId\",\n\t\t\t\tid: \"mockId\",\n\t\t\t\tsharingLinkErrorReason: \"mockError\",\n\t\t\t\tsharing: mockSharingError,\n\t\t\t},\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert.deepStrictEqual(odspResolvedUrl.shareLinkInfo?.createLink, {\n\t\t\tshareId: undefined,\n\t\t\tlink: undefined,\n\t\t\terror: mockSharingError.error,\n\t\t});\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should set the isClpCompliantApp prop on resolved url if already present when createNewFluidFile\", async () => {\n\t\tconst odspResolvedUrl1 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\ttrue /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(odspResolvedUrl1.isClpCompliantApp, \"isClpCompliantApp should be set\");\n\n\t\tconst odspResolvedUrl2 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(!odspResolvedUrl2.isClpCompliantApp, \"isClpCompliantApp should be falsy\");\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n\n\tit(\"Should set the isClpCompliantApp prop on resolved url if already present when createNewContainerOnExistingFile\", async () => {\n\t\tconst existingFileParams: IExistingFileInfo = {\n\t\t\ttype: \"Existing\",\n\t\t\titemId: \"itemId1\",\n\t\t\tsiteUrl,\n\t\t\tdriveId,\n\t\t};\n\t\tconst odspResolvedUrl1 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewContainerOnExistingFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\texistingFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\ttrue /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(odspResolvedUrl1.isClpCompliantApp, \"isClpCompliantApp should be set\");\n\n\t\tconst odspResolvedUrl2 = await mockFetchOk(\n\t\t\tasync () =>\n\t\t\t\tcreateNewFluidFile(\n\t\t\t\t\tasync (_options) => \"token\",\n\t\t\t\t\tnewFileParams,\n\t\t\t\t\tcreateChildLogger(),\n\t\t\t\t\tcreateSummary(),\n\t\t\t\t\tepochTracker,\n\t\t\t\t\tfileEntry,\n\t\t\t\t\ttrue /* createNewCaching */,\n\t\t\t\t\tfalse /* forceAccessTokenViaAuthorizationHeader */,\n\t\t\t\t\tundefined /* isClpCompliantApp */,\n\t\t\t\t),\n\t\t\t{ itemId: \"itemId1\", id: \"Summary handle\" },\n\t\t\t{ \"x-fluid-epoch\": \"epoch1\" },\n\t\t);\n\t\tassert(!odspResolvedUrl2.isClpCompliantApp, \"isClpCompliantApp should be falsy\");\n\t\tawait epochTracker.removeEntries().catch(() => {});\n\t});\n});\n"]}
@@ -4,9 +4,9 @@
4
4
  */
5
5
  import { strict as assert } from "node:assert";
6
6
  import { MockLogger } from "@fluidframework/telemetry-utils";
7
- import { OdspDeltaStorageService, OdspDeltaStorageWithCache } from "../odspDeltaStorageService.js";
8
- import { LocalPersistentCache } from "../odspCache.js";
9
7
  import { EpochTracker } from "../epochTracker.js";
8
+ import { LocalPersistentCache } from "../odspCache.js";
9
+ import { OdspDeltaStorageService, OdspDeltaStorageWithCache } from "../odspDeltaStorageService.js";
10
10
  import { mockFetchOk } from "./mockFetch.js";
11
11
  const createUtLocalCache = () => new LocalPersistentCache(2000);
12
12
  const createUtEpochTracker = (fileEntry, logger) => new EpochTracker(createUtLocalCache(), fileEntry, logger);
@@ -1 +1 @@
1
- {"version":3,"file":"deltaStorageService.spec.js","sourceRoot":"","sources":["../../src/test/deltaStorageService.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 \"node:assert\";\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { IDeltasFetchResult } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt, MockLogger } from \"@fluidframework/telemetry-utils\";\nimport { IOdspResolvedUrl, IFileEntry } from \"@fluidframework/odsp-driver-definitions\";\nimport { OdspDeltaStorageService, OdspDeltaStorageWithCache } from \"../odspDeltaStorageService.js\";\nimport { LocalPersistentCache } from \"../odspCache.js\";\nimport { EpochTracker } from \"../epochTracker.js\";\nimport { OdspDocumentStorageService } from \"../odspDocumentStorageManager.js\";\nimport { mockFetchOk } from \"./mockFetch.js\";\n\nconst createUtLocalCache = (): LocalPersistentCache => new LocalPersistentCache(2000);\nconst createUtEpochTracker = (fileEntry: IFileEntry, logger: ITelemetryBaseLogger): EpochTracker =>\n\tnew EpochTracker(createUtLocalCache(), fileEntry, logger as ITelemetryLoggerExt);\n\ndescribe(\"DeltaStorageService\", () => {\n\t/*\n\t * Use fake urls so we don't accidental make real calls that make our tests flakey.\n\t * Using microsoft.com as the domain so we don't send traffic somewhere hostile on accident.\n\t */\n\tconst deltaStorageBasePath = \"https://fake.microsoft.com\";\n\tconst deltaStorageRelativePath = \"/drives/testdrive/items/testitem/opStream\";\n\tconst testDeltaStorageUrl = `${deltaStorageBasePath}${deltaStorageRelativePath}`;\n\tconst siteUrl = \"https://fake.microsoft.com\";\n\tconst driveId = \"testdrive\";\n\tconst itemId = \"testitem\";\n\tconst resolvedUrl = {\n\t\tsiteUrl,\n\t\tdriveId,\n\t\titemId,\n\t\todspResolvedUrl: true,\n\t} as unknown as IOdspResolvedUrl;\n\tconst fileEntry = { docId: \"docId\", resolvedUrl };\n\n\tit(\"Should build the correct sharepoint delta url with auth\", async () => {\n\t\tconst logger = new MockLogger();\n\t\tconst deltaStorageService = new OdspDeltaStorageService(\n\t\t\ttestDeltaStorageUrl,\n\t\t\tasync (_refresh) => \"?access_token=123\",\n\t\t\tcreateUtEpochTracker(fileEntry, logger),\n\t\t\tlogger.toTelemetryLogger(),\n\t\t);\n\t\tconst actualDeltaUrl = deltaStorageService.buildUrl(3, 8);\n\t\tconst expectedDeltaUrl = `${deltaStorageBasePath}/drives/testdrive/items/testitem/opStream?ump=1&filter=sequenceNumber%20ge%203%20and%20sequenceNumber%20le%207`;\n\t\tassert.equal(actualDeltaUrl, expectedDeltaUrl, \"The constructed delta url is invalid\");\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t});\n\n\tdescribe(\"Get Returns Response With Op Envelope\", () => {\n\t\tconst expectedDeltaFeedResponse = {\n\t\t\tvalue: [\n\t\t\t\t{\n\t\t\t\t\top: {\n\t\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\t\tcontents: null,\n\t\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\t\tsequenceNumber: 1,\n\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tsequenceNumber: 1,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\top: {\n\t\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\t\tcontents: null,\n\t\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\t\tsequenceNumber: 2,\n\t\t\t\t\t\ttype: \"noop\",\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tsequenceNumber: 2,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tlet deltaStorageService: OdspDeltaStorageService;\n\t\tconst logger = new MockLogger();\n\t\tbefore(() => {\n\t\t\tdeltaStorageService = new OdspDeltaStorageService(\n\t\t\t\ttestDeltaStorageUrl,\n\t\t\t\tasync (_refresh) => \"\",\n\t\t\t\tcreateUtEpochTracker(fileEntry, logger),\n\t\t\t\tlogger.toTelemetryLogger(),\n\t\t\t);\n\t\t});\n\t\tafterEach(() => {\n\t\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t\t});\n\n\t\tit(\"Should deserialize the delta feed response correctly\", async () => {\n\t\t\tconst { messages, partialResult } = await mockFetchOk(\n\t\t\t\tasync () => deltaStorageService.get(2, 8, {}),\n\t\t\t\texpectedDeltaFeedResponse,\n\t\t\t);\n\t\t\tassert(!partialResult, \"partialResult === false\");\n\t\t\tassert.equal(\n\t\t\t\tmessages.length,\n\t\t\t\t2,\n\t\t\t\t\"Deserialized feed response is not of expected length\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[0].sequenceNumber,\n\t\t\t\t1,\n\t\t\t\t\"First element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].sequenceNumber,\n\t\t\t\t2,\n\t\t\t\t\"Second element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].type,\n\t\t\t\t\"noop\",\n\t\t\t\t\"Second element of feed response has invalid op type\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"Get Returns Response With Op Envelope\", () => {\n\t\tconst expectedDeltaFeedResponse = {\n\t\t\tvalue: [\n\t\t\t\t{\n\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\tcontents: null,\n\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\tsequenceNumber: 1,\n\t\t\t\t\ttext: \"\",\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\tcontents: null,\n\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\tsequenceNumber: 2,\n\t\t\t\t\ttype: \"noop\",\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tlet deltaStorageService: OdspDeltaStorageService;\n\t\tconst logger = new MockLogger();\n\t\tbefore(() => {\n\t\t\tdeltaStorageService = new OdspDeltaStorageService(\n\t\t\t\ttestDeltaStorageUrl,\n\t\t\t\tasync (_refresh) => \"\",\n\t\t\t\tcreateUtEpochTracker(fileEntry, logger),\n\t\t\t\tlogger.toTelemetryLogger(),\n\t\t\t);\n\t\t});\n\t\tafterEach(() => {\n\t\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t\t});\n\n\t\tit(\"Should deserialize the delta feed response correctly\", async () => {\n\t\t\tconst { messages, partialResult } = await mockFetchOk(\n\t\t\t\tasync () => deltaStorageService.get(2, 8, {}),\n\t\t\t\texpectedDeltaFeedResponse,\n\t\t\t);\n\t\t\tassert(!partialResult, \"partialResult === false\");\n\t\t\tassert.equal(\n\t\t\t\tmessages.length,\n\t\t\t\t2,\n\t\t\t\t\"Deserialized feed response is not of expected length\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[0].sequenceNumber,\n\t\t\t\t1,\n\t\t\t\t\"First element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].sequenceNumber,\n\t\t\t\t2,\n\t\t\t\t\"Second element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].type,\n\t\t\t\t\"noop\",\n\t\t\t\t\"Second element of feed response has invalid op type\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"DeltaStorageServiceWith Cache Tests\", () => {\n\t\tconst logger = new MockLogger();\n\t\tafterEach(() => {\n\t\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t\t});\n\n\t\tit(\"FirstCacheMiss should update to first miss op seq number correctly\", async () => {\n\t\t\tconst deltasFetchResult: IDeltasFetchResult = { messages: [], partialResult: false };\n\t\t\tlet count = 0;\n\t\t\tconst getCached = async (\n\t\t\t\tfrom: number,\n\t\t\t\tto: number,\n\t\t\t): Promise<ISequencedDocumentMessage[]> => {\n\t\t\t\tif (count === 0) {\n\t\t\t\t\tcount += 1;\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\t\t\tcontents: null,\n\t\t\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\t\t\tsequenceNumber: from,\n\t\t\t\t\t\t\ttype: \"dds\",\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcount += 1;\n\t\t\t\tassert.fail(\"Should not reach here\");\n\t\t\t};\n\t\t\tconst odspDeltaStorageServiceWithCache = new OdspDeltaStorageWithCache(\n\t\t\t\t[],\n\t\t\t\tlogger.toTelemetryLogger(),\n\t\t\t\t1000,\n\t\t\t\t1,\n\t\t\t\tasync (from, to, props, reason) => deltasFetchResult,\n\t\t\t\tasync (from, to) => getCached(from, to),\n\t\t\t\t(from, to) => [],\n\t\t\t\t(ops) => {},\n\t\t\t\t() =>\n\t\t\t\t\t({\n\t\t\t\t\t\tisFirstSnapshotFromNetwork: false,\n\t\t\t\t\t}) as unknown as OdspDocumentStorageService,\n\t\t\t);\n\n\t\t\tconst messages = odspDeltaStorageServiceWithCache.fetchMessages(1, undefined);\n\t\t\tconst batch1 = await messages.read();\n\t\t\tconst batch2 = await messages.read();\n\t\t\tassert(count === 1, \"There should be only 1 cache access\");\n\t\t\tassert(batch1.done === false, \"Firt batch should have returned 1 op\");\n\t\t\tassert(batch2.done === true, \"No ops should be present in second batch\");\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"deltaStorageService.spec.js","sourceRoot":"","sources":["../../src/test/deltaStorageService.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 \"node:assert\";\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { IDeltasFetchResult } from \"@fluidframework/driver-definitions\";\nimport { IFileEntry, IOdspResolvedUrl } from \"@fluidframework/odsp-driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt, MockLogger } from \"@fluidframework/telemetry-utils\";\nimport { EpochTracker } from \"../epochTracker.js\";\nimport { LocalPersistentCache } from \"../odspCache.js\";\nimport { OdspDeltaStorageService, OdspDeltaStorageWithCache } from \"../odspDeltaStorageService.js\";\nimport { OdspDocumentStorageService } from \"../odspDocumentStorageManager.js\";\nimport { mockFetchOk } from \"./mockFetch.js\";\n\nconst createUtLocalCache = (): LocalPersistentCache => new LocalPersistentCache(2000);\nconst createUtEpochTracker = (fileEntry: IFileEntry, logger: ITelemetryBaseLogger): EpochTracker =>\n\tnew EpochTracker(createUtLocalCache(), fileEntry, logger as ITelemetryLoggerExt);\n\ndescribe(\"DeltaStorageService\", () => {\n\t/*\n\t * Use fake urls so we don't accidental make real calls that make our tests flakey.\n\t * Using microsoft.com as the domain so we don't send traffic somewhere hostile on accident.\n\t */\n\tconst deltaStorageBasePath = \"https://fake.microsoft.com\";\n\tconst deltaStorageRelativePath = \"/drives/testdrive/items/testitem/opStream\";\n\tconst testDeltaStorageUrl = `${deltaStorageBasePath}${deltaStorageRelativePath}`;\n\tconst siteUrl = \"https://fake.microsoft.com\";\n\tconst driveId = \"testdrive\";\n\tconst itemId = \"testitem\";\n\tconst resolvedUrl = {\n\t\tsiteUrl,\n\t\tdriveId,\n\t\titemId,\n\t\todspResolvedUrl: true,\n\t} as unknown as IOdspResolvedUrl;\n\tconst fileEntry = { docId: \"docId\", resolvedUrl };\n\n\tit(\"Should build the correct sharepoint delta url with auth\", async () => {\n\t\tconst logger = new MockLogger();\n\t\tconst deltaStorageService = new OdspDeltaStorageService(\n\t\t\ttestDeltaStorageUrl,\n\t\t\tasync (_refresh) => \"?access_token=123\",\n\t\t\tcreateUtEpochTracker(fileEntry, logger),\n\t\t\tlogger.toTelemetryLogger(),\n\t\t);\n\t\tconst actualDeltaUrl = deltaStorageService.buildUrl(3, 8);\n\t\tconst expectedDeltaUrl = `${deltaStorageBasePath}/drives/testdrive/items/testitem/opStream?ump=1&filter=sequenceNumber%20ge%203%20and%20sequenceNumber%20le%207`;\n\t\tassert.equal(actualDeltaUrl, expectedDeltaUrl, \"The constructed delta url is invalid\");\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t});\n\n\tdescribe(\"Get Returns Response With Op Envelope\", () => {\n\t\tconst expectedDeltaFeedResponse = {\n\t\t\tvalue: [\n\t\t\t\t{\n\t\t\t\t\top: {\n\t\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\t\tcontents: null,\n\t\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\t\tsequenceNumber: 1,\n\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tsequenceNumber: 1,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\top: {\n\t\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\t\tcontents: null,\n\t\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\t\tsequenceNumber: 2,\n\t\t\t\t\t\ttype: \"noop\",\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tsequenceNumber: 2,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tlet deltaStorageService: OdspDeltaStorageService;\n\t\tconst logger = new MockLogger();\n\t\tbefore(() => {\n\t\t\tdeltaStorageService = new OdspDeltaStorageService(\n\t\t\t\ttestDeltaStorageUrl,\n\t\t\t\tasync (_refresh) => \"\",\n\t\t\t\tcreateUtEpochTracker(fileEntry, logger),\n\t\t\t\tlogger.toTelemetryLogger(),\n\t\t\t);\n\t\t});\n\t\tafterEach(() => {\n\t\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t\t});\n\n\t\tit(\"Should deserialize the delta feed response correctly\", async () => {\n\t\t\tconst { messages, partialResult } = await mockFetchOk(\n\t\t\t\tasync () => deltaStorageService.get(2, 8, {}),\n\t\t\t\texpectedDeltaFeedResponse,\n\t\t\t);\n\t\t\tassert(!partialResult, \"partialResult === false\");\n\t\t\tassert.equal(\n\t\t\t\tmessages.length,\n\t\t\t\t2,\n\t\t\t\t\"Deserialized feed response is not of expected length\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[0].sequenceNumber,\n\t\t\t\t1,\n\t\t\t\t\"First element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].sequenceNumber,\n\t\t\t\t2,\n\t\t\t\t\"Second element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].type,\n\t\t\t\t\"noop\",\n\t\t\t\t\"Second element of feed response has invalid op type\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"Get Returns Response With Op Envelope\", () => {\n\t\tconst expectedDeltaFeedResponse = {\n\t\t\tvalue: [\n\t\t\t\t{\n\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\tcontents: null,\n\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\tsequenceNumber: 1,\n\t\t\t\t\ttext: \"\",\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\tcontents: null,\n\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\tsequenceNumber: 2,\n\t\t\t\t\ttype: \"noop\",\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: \"Unruffled Bose\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tlet deltaStorageService: OdspDeltaStorageService;\n\t\tconst logger = new MockLogger();\n\t\tbefore(() => {\n\t\t\tdeltaStorageService = new OdspDeltaStorageService(\n\t\t\t\ttestDeltaStorageUrl,\n\t\t\t\tasync (_refresh) => \"\",\n\t\t\t\tcreateUtEpochTracker(fileEntry, logger),\n\t\t\t\tlogger.toTelemetryLogger(),\n\t\t\t);\n\t\t});\n\t\tafterEach(() => {\n\t\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t\t});\n\n\t\tit(\"Should deserialize the delta feed response correctly\", async () => {\n\t\t\tconst { messages, partialResult } = await mockFetchOk(\n\t\t\t\tasync () => deltaStorageService.get(2, 8, {}),\n\t\t\t\texpectedDeltaFeedResponse,\n\t\t\t);\n\t\t\tassert(!partialResult, \"partialResult === false\");\n\t\t\tassert.equal(\n\t\t\t\tmessages.length,\n\t\t\t\t2,\n\t\t\t\t\"Deserialized feed response is not of expected length\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[0].sequenceNumber,\n\t\t\t\t1,\n\t\t\t\t\"First element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].sequenceNumber,\n\t\t\t\t2,\n\t\t\t\t\"Second element of feed response has invalid sequence number\",\n\t\t\t);\n\t\t\tassert.equal(\n\t\t\t\tmessages[1].type,\n\t\t\t\t\"noop\",\n\t\t\t\t\"Second element of feed response has invalid op type\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"DeltaStorageServiceWith Cache Tests\", () => {\n\t\tconst logger = new MockLogger();\n\t\tafterEach(() => {\n\t\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t\t});\n\n\t\tit(\"FirstCacheMiss should update to first miss op seq number correctly\", async () => {\n\t\t\tconst deltasFetchResult: IDeltasFetchResult = { messages: [], partialResult: false };\n\t\t\tlet count = 0;\n\t\t\tconst getCached = async (\n\t\t\t\tfrom: number,\n\t\t\t\tto: number,\n\t\t\t): Promise<ISequencedDocumentMessage[]> => {\n\t\t\t\tif (count === 0) {\n\t\t\t\t\tcount += 1;\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tclientId: \"present-place\",\n\t\t\t\t\t\t\tclientSequenceNumber: 71,\n\t\t\t\t\t\t\tcontents: null,\n\t\t\t\t\t\t\tminimumSequenceNumber: 1,\n\t\t\t\t\t\t\treferenceSequenceNumber: 1,\n\t\t\t\t\t\t\tsequenceNumber: from,\n\t\t\t\t\t\t\ttype: \"dds\",\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcount += 1;\n\t\t\t\tassert.fail(\"Should not reach here\");\n\t\t\t};\n\t\t\tconst odspDeltaStorageServiceWithCache = new OdspDeltaStorageWithCache(\n\t\t\t\t[],\n\t\t\t\tlogger.toTelemetryLogger(),\n\t\t\t\t1000,\n\t\t\t\t1,\n\t\t\t\tasync (from, to, props, reason) => deltasFetchResult,\n\t\t\t\tasync (from, to) => getCached(from, to),\n\t\t\t\t(from, to) => [],\n\t\t\t\t(ops) => {},\n\t\t\t\t() =>\n\t\t\t\t\t({\n\t\t\t\t\t\tisFirstSnapshotFromNetwork: false,\n\t\t\t\t\t}) as unknown as OdspDocumentStorageService,\n\t\t\t);\n\n\t\t\tconst messages = odspDeltaStorageServiceWithCache.fetchMessages(1, undefined);\n\t\t\tconst batch1 = await messages.read();\n\t\t\tconst batch2 = await messages.read();\n\t\t\tassert(count === 1, \"There should be only 1 cache access\");\n\t\t\tassert(batch1.done === false, \"Firt batch should have returned 1 op\");\n\t\t\tassert(batch2.done === true, \"No ops should be present in second batch\");\n\t\t});\n\t});\n});\n"]}
@@ -3,8 +3,8 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { strict as assert } from "node:assert";
6
- import { OdspErrorTypes, maximumCacheDurationMs, } from "@fluidframework/odsp-driver-definitions";
7
6
  import { ThrottlingError } from "@fluidframework/driver-utils";
7
+ import { OdspErrorTypes, maximumCacheDurationMs, } from "@fluidframework/odsp-driver-definitions";
8
8
  import { createChildLogger } from "@fluidframework/telemetry-utils";
9
9
  import { stub } from "sinon";
10
10
  import { persistedCacheValueVersion } from "../contracts.js";
@@ -12,7 +12,7 @@ import { EpochTracker } from "../epochTracker.js";
12
12
  import { LocalPersistentCache } from "../odspCache.js";
13
13
  import { getHashedDocumentId } from "../odspPublicUtils.js";
14
14
  import * as odspUtilsModule from "../odspUtils.js";
15
- import { mockFetchOk, mockFetchSingle, createResponse } from "./mockFetch.js";
15
+ import { createResponse, mockFetchOk, mockFetchSingle } from "./mockFetch.js";
16
16
  const createUtLocalCache = () => new LocalPersistentCache();
17
17
  describe("Tests for Epoch Tracker", () => {
18
18
  const siteUrl = "https://microsoft.sharepoint-df.com/siteUrl";