@fluidframework/container-runtime 2.0.0-dev.5.3.2.178189 → 2.0.0-dev.6.4.0.191258

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 (526) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/README.md +4 -3
  3. package/dist/batchTracker.d.ts +3 -2
  4. package/dist/batchTracker.d.ts.map +1 -1
  5. package/dist/batchTracker.js +6 -5
  6. package/dist/batchTracker.js.map +1 -1
  7. package/dist/blobManager.d.ts +10 -16
  8. package/dist/blobManager.d.ts.map +1 -1
  9. package/dist/blobManager.js +184 -172
  10. package/dist/blobManager.js.map +1 -1
  11. package/dist/connectionTelemetry.d.ts.map +1 -1
  12. package/dist/connectionTelemetry.js +25 -16
  13. package/dist/connectionTelemetry.js.map +1 -1
  14. package/dist/containerRuntime.d.ts +161 -35
  15. package/dist/containerRuntime.d.ts.map +1 -1
  16. package/dist/containerRuntime.js +697 -449
  17. package/dist/containerRuntime.js.map +1 -1
  18. package/dist/dataStore.d.ts.map +1 -1
  19. package/dist/dataStore.js +15 -7
  20. package/dist/dataStore.js.map +1 -1
  21. package/dist/dataStoreContext.d.ts +3 -2
  22. package/dist/dataStoreContext.d.ts.map +1 -1
  23. package/dist/dataStoreContext.js +83 -87
  24. package/dist/dataStoreContext.js.map +1 -1
  25. package/dist/dataStoreContexts.d.ts +1 -2
  26. package/dist/dataStoreContexts.d.ts.map +1 -1
  27. package/dist/dataStoreContexts.js +8 -9
  28. package/dist/dataStoreContexts.js.map +1 -1
  29. package/dist/dataStoreRegistry.js +2 -2
  30. package/dist/dataStoreRegistry.js.map +1 -1
  31. package/dist/dataStores.d.ts +22 -6
  32. package/dist/dataStores.d.ts.map +1 -1
  33. package/dist/dataStores.js +123 -81
  34. package/dist/dataStores.js.map +1 -1
  35. package/dist/deltaManagerProxyBase.d.ts +35 -0
  36. package/dist/deltaManagerProxyBase.d.ts.map +1 -0
  37. package/dist/deltaManagerProxyBase.js +77 -0
  38. package/dist/deltaManagerProxyBase.js.map +1 -0
  39. package/dist/deltaManagerSummarizerProxy.d.ts +1 -1
  40. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  41. package/dist/deltaManagerSummarizerProxy.js +4 -2
  42. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  43. package/dist/deltaScheduler.d.ts.map +1 -1
  44. package/dist/deltaScheduler.js +10 -10
  45. package/dist/deltaScheduler.js.map +1 -1
  46. package/dist/error.d.ts +14 -0
  47. package/dist/error.d.ts.map +1 -0
  48. package/dist/error.js +21 -0
  49. package/dist/error.js.map +1 -0
  50. package/dist/gc/garbageCollection.d.ts +10 -9
  51. package/dist/gc/garbageCollection.d.ts.map +1 -1
  52. package/dist/gc/garbageCollection.js +61 -53
  53. package/dist/gc/garbageCollection.js.map +1 -1
  54. package/dist/gc/gcConfigs.d.ts.map +1 -1
  55. package/dist/gc/gcConfigs.js +18 -14
  56. package/dist/gc/gcConfigs.js.map +1 -1
  57. package/dist/gc/gcDefinitions.d.ts +17 -4
  58. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  59. package/dist/gc/gcDefinitions.js +14 -15
  60. package/dist/gc/gcDefinitions.js.map +1 -1
  61. package/dist/gc/gcHelpers.d.ts +0 -8
  62. package/dist/gc/gcHelpers.d.ts.map +1 -1
  63. package/dist/gc/gcHelpers.js +11 -24
  64. package/dist/gc/gcHelpers.js.map +1 -1
  65. package/dist/gc/gcSummaryStateTracker.d.ts +4 -7
  66. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  67. package/dist/gc/gcSummaryStateTracker.js +19 -58
  68. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  69. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  70. package/dist/gc/gcTelemetry.js +45 -35
  71. package/dist/gc/gcTelemetry.js.map +1 -1
  72. package/dist/gc/gcUnreferencedStateTracker.js +4 -4
  73. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  74. package/dist/gc/index.d.ts +2 -2
  75. package/dist/gc/index.d.ts.map +1 -1
  76. package/dist/gc/index.js +3 -5
  77. package/dist/gc/index.js.map +1 -1
  78. package/dist/id-compressor/appendOnlySortedMap.d.ts +8 -30
  79. package/dist/id-compressor/appendOnlySortedMap.d.ts.map +1 -1
  80. package/dist/id-compressor/appendOnlySortedMap.js +26 -68
  81. package/dist/id-compressor/appendOnlySortedMap.js.map +1 -1
  82. package/dist/id-compressor/finalSpace.d.ts +29 -0
  83. package/dist/id-compressor/finalSpace.d.ts.map +1 -0
  84. package/dist/id-compressor/finalSpace.js +62 -0
  85. package/dist/id-compressor/finalSpace.js.map +1 -0
  86. package/dist/id-compressor/idCompressor.d.ts +25 -250
  87. package/dist/id-compressor/idCompressor.d.ts.map +1 -1
  88. package/dist/id-compressor/idCompressor.js +390 -1153
  89. package/dist/id-compressor/idCompressor.js.map +1 -1
  90. package/dist/id-compressor/identifiers.d.ts +32 -0
  91. package/dist/id-compressor/identifiers.d.ts.map +1 -0
  92. package/dist/id-compressor/identifiers.js +15 -0
  93. package/dist/id-compressor/identifiers.js.map +1 -0
  94. package/dist/id-compressor/index.d.ts +5 -6
  95. package/dist/id-compressor/index.d.ts.map +1 -1
  96. package/dist/id-compressor/index.js +20 -26
  97. package/dist/id-compressor/index.js.map +1 -1
  98. package/dist/id-compressor/persistanceUtilities.d.ts +22 -0
  99. package/dist/id-compressor/persistanceUtilities.d.ts.map +1 -0
  100. package/dist/id-compressor/persistanceUtilities.js +43 -0
  101. package/dist/id-compressor/persistanceUtilities.js.map +1 -0
  102. package/dist/id-compressor/sessionSpaceNormalizer.d.ts +46 -0
  103. package/dist/id-compressor/sessionSpaceNormalizer.d.ts.map +1 -0
  104. package/dist/id-compressor/sessionSpaceNormalizer.js +80 -0
  105. package/dist/id-compressor/sessionSpaceNormalizer.js.map +1 -0
  106. package/dist/id-compressor/sessions.d.ts +115 -0
  107. package/dist/id-compressor/sessions.d.ts.map +1 -0
  108. package/dist/id-compressor/sessions.js +305 -0
  109. package/dist/id-compressor/sessions.js.map +1 -0
  110. package/dist/id-compressor/utilities.d.ts +49 -0
  111. package/dist/id-compressor/utilities.d.ts.map +1 -0
  112. package/dist/id-compressor/utilities.js +166 -0
  113. package/dist/id-compressor/utilities.js.map +1 -0
  114. package/dist/index.d.ts +3 -3
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +6 -4
  117. package/dist/index.js.map +1 -1
  118. package/dist/opLifecycle/batchManager.js +10 -6
  119. package/dist/opLifecycle/batchManager.js.map +1 -1
  120. package/dist/opLifecycle/opCompressor.d.ts +2 -2
  121. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  122. package/dist/opLifecycle/opCompressor.js +12 -7
  123. package/dist/opLifecycle/opCompressor.js.map +1 -1
  124. package/dist/opLifecycle/opDecompressor.d.ts +2 -2
  125. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  126. package/dist/opLifecycle/opDecompressor.js +23 -20
  127. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  128. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  129. package/dist/opLifecycle/opGroupingManager.js +19 -9
  130. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  131. package/dist/opLifecycle/opSplitter.d.ts +2 -2
  132. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  133. package/dist/opLifecycle/opSplitter.js +22 -19
  134. package/dist/opLifecycle/opSplitter.js.map +1 -1
  135. package/dist/opLifecycle/outbox.d.ts +7 -5
  136. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  137. package/dist/opLifecycle/outbox.js +22 -31
  138. package/dist/opLifecycle/outbox.js.map +1 -1
  139. package/dist/opLifecycle/remoteMessageProcessor.d.ts +6 -1
  140. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  141. package/dist/opLifecycle/remoteMessageProcessor.js +19 -7
  142. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  143. package/dist/opProperties.js +1 -2
  144. package/dist/opProperties.js.map +1 -1
  145. package/dist/packageVersion.d.ts +1 -1
  146. package/dist/packageVersion.js +1 -1
  147. package/dist/packageVersion.js.map +1 -1
  148. package/dist/pendingStateManager.d.ts +18 -8
  149. package/dist/pendingStateManager.d.ts.map +1 -1
  150. package/dist/pendingStateManager.js +73 -51
  151. package/dist/pendingStateManager.js.map +1 -1
  152. package/dist/scheduleManager.d.ts.map +1 -1
  153. package/dist/scheduleManager.js +36 -32
  154. package/dist/scheduleManager.js.map +1 -1
  155. package/dist/summary/index.d.ts +3 -3
  156. package/dist/summary/index.d.ts.map +1 -1
  157. package/dist/summary/index.js +2 -1
  158. package/dist/summary/index.js.map +1 -1
  159. package/dist/summary/orderedClientElection.d.ts +3 -3
  160. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  161. package/dist/summary/orderedClientElection.js +26 -27
  162. package/dist/summary/orderedClientElection.js.map +1 -1
  163. package/dist/summary/runWhileConnectedCoordinator.js +3 -3
  164. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  165. package/dist/summary/runningSummarizer.d.ts +31 -10
  166. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  167. package/dist/summary/runningSummarizer.js +271 -139
  168. package/dist/summary/runningSummarizer.js.map +1 -1
  169. package/dist/summary/summarizer.d.ts +8 -7
  170. package/dist/summary/summarizer.d.ts.map +1 -1
  171. package/dist/summary/summarizer.js +79 -78
  172. package/dist/summary/summarizer.js.map +1 -1
  173. package/dist/summary/summarizerClientElection.d.ts +2 -2
  174. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  175. package/dist/summary/summarizerClientElection.js +7 -11
  176. package/dist/summary/summarizerClientElection.js.map +1 -1
  177. package/dist/summary/summarizerHeuristics.js +10 -14
  178. package/dist/summary/summarizerHeuristics.js.map +1 -1
  179. package/dist/summary/summarizerNode/index.d.ts +1 -1
  180. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  181. package/dist/summary/summarizerNode/index.js.map +1 -1
  182. package/dist/summary/summarizerNode/summarizerNode.d.ts +10 -19
  183. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  184. package/dist/summary/summarizerNode/summarizerNode.js +57 -130
  185. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  186. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +6 -30
  187. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  188. package/dist/summary/summarizerNode/summarizerNodeUtils.js +2 -4
  189. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  190. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -14
  191. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  192. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +15 -101
  193. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  194. package/dist/summary/summarizerTypes.d.ts +38 -25
  195. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  196. package/dist/summary/summarizerTypes.js.map +1 -1
  197. package/dist/summary/summaryCollection.d.ts +2 -3
  198. package/dist/summary/summaryCollection.d.ts.map +1 -1
  199. package/dist/summary/summaryCollection.js +12 -13
  200. package/dist/summary/summaryCollection.js.map +1 -1
  201. package/dist/summary/summaryFormat.d.ts +3 -0
  202. package/dist/summary/summaryFormat.d.ts.map +1 -1
  203. package/dist/summary/summaryFormat.js +6 -4
  204. package/dist/summary/summaryFormat.js.map +1 -1
  205. package/dist/summary/summaryGenerator.d.ts +10 -4
  206. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  207. package/dist/summary/summaryGenerator.js +106 -57
  208. package/dist/summary/summaryGenerator.js.map +1 -1
  209. package/dist/summary/summaryManager.d.ts +8 -8
  210. package/dist/summary/summaryManager.d.ts.map +1 -1
  211. package/dist/summary/summaryManager.js +38 -28
  212. package/dist/summary/summaryManager.js.map +1 -1
  213. package/lib/batchTracker.d.ts +3 -2
  214. package/lib/batchTracker.d.ts.map +1 -1
  215. package/lib/batchTracker.js +5 -4
  216. package/lib/batchTracker.js.map +1 -1
  217. package/lib/blobManager.d.ts +10 -16
  218. package/lib/blobManager.d.ts.map +1 -1
  219. package/lib/blobManager.js +159 -147
  220. package/lib/blobManager.js.map +1 -1
  221. package/lib/connectionTelemetry.d.ts.map +1 -1
  222. package/lib/connectionTelemetry.js +15 -6
  223. package/lib/connectionTelemetry.js.map +1 -1
  224. package/lib/containerRuntime.d.ts +161 -35
  225. package/lib/containerRuntime.d.ts.map +1 -1
  226. package/lib/containerRuntime.js +651 -402
  227. package/lib/containerRuntime.js.map +1 -1
  228. package/lib/dataStore.d.ts.map +1 -1
  229. package/lib/dataStore.js +13 -5
  230. package/lib/dataStore.js.map +1 -1
  231. package/lib/dataStoreContext.d.ts +3 -2
  232. package/lib/dataStoreContext.d.ts.map +1 -1
  233. package/lib/dataStoreContext.js +47 -51
  234. package/lib/dataStoreContext.js.map +1 -1
  235. package/lib/dataStoreContexts.d.ts +1 -2
  236. package/lib/dataStoreContexts.d.ts.map +1 -1
  237. package/lib/dataStoreContexts.js +3 -4
  238. package/lib/dataStoreContexts.js.map +1 -1
  239. package/lib/dataStoreRegistry.js +1 -1
  240. package/lib/dataStoreRegistry.js.map +1 -1
  241. package/lib/dataStores.d.ts +22 -6
  242. package/lib/dataStores.d.ts.map +1 -1
  243. package/lib/dataStores.js +107 -65
  244. package/lib/dataStores.js.map +1 -1
  245. package/lib/deltaManagerProxyBase.d.ts +35 -0
  246. package/lib/deltaManagerProxyBase.d.ts.map +1 -0
  247. package/lib/deltaManagerProxyBase.js +73 -0
  248. package/lib/deltaManagerProxyBase.js.map +1 -0
  249. package/lib/deltaManagerSummarizerProxy.d.ts +1 -1
  250. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
  251. package/lib/deltaManagerSummarizerProxy.js +3 -1
  252. package/lib/deltaManagerSummarizerProxy.js.map +1 -1
  253. package/lib/deltaScheduler.d.ts.map +1 -1
  254. package/lib/deltaScheduler.js +7 -7
  255. package/lib/deltaScheduler.js.map +1 -1
  256. package/lib/error.d.ts +14 -0
  257. package/lib/error.d.ts.map +1 -0
  258. package/lib/error.js +17 -0
  259. package/lib/error.js.map +1 -0
  260. package/lib/gc/garbageCollection.d.ts +10 -9
  261. package/lib/gc/garbageCollection.d.ts.map +1 -1
  262. package/lib/gc/garbageCollection.js +61 -53
  263. package/lib/gc/garbageCollection.js.map +1 -1
  264. package/lib/gc/gcConfigs.d.ts.map +1 -1
  265. package/lib/gc/gcConfigs.js +16 -12
  266. package/lib/gc/gcConfigs.js.map +1 -1
  267. package/lib/gc/gcDefinitions.d.ts +17 -4
  268. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  269. package/lib/gc/gcDefinitions.js +13 -14
  270. package/lib/gc/gcDefinitions.js.map +1 -1
  271. package/lib/gc/gcHelpers.d.ts +0 -8
  272. package/lib/gc/gcHelpers.d.ts.map +1 -1
  273. package/lib/gc/gcHelpers.js +5 -17
  274. package/lib/gc/gcHelpers.js.map +1 -1
  275. package/lib/gc/gcSummaryStateTracker.d.ts +4 -7
  276. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  277. package/lib/gc/gcSummaryStateTracker.js +20 -59
  278. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  279. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  280. package/lib/gc/gcTelemetry.js +46 -36
  281. package/lib/gc/gcTelemetry.js.map +1 -1
  282. package/lib/gc/gcUnreferencedStateTracker.js +1 -1
  283. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
  284. package/lib/gc/index.d.ts +2 -2
  285. package/lib/gc/index.d.ts.map +1 -1
  286. package/lib/gc/index.js +2 -2
  287. package/lib/gc/index.js.map +1 -1
  288. package/lib/id-compressor/appendOnlySortedMap.d.ts +8 -30
  289. package/lib/id-compressor/appendOnlySortedMap.d.ts.map +1 -1
  290. package/lib/id-compressor/appendOnlySortedMap.js +25 -66
  291. package/lib/id-compressor/appendOnlySortedMap.js.map +1 -1
  292. package/lib/id-compressor/finalSpace.d.ts +29 -0
  293. package/lib/id-compressor/finalSpace.d.ts.map +1 -0
  294. package/lib/id-compressor/finalSpace.js +58 -0
  295. package/lib/id-compressor/finalSpace.js.map +1 -0
  296. package/lib/id-compressor/idCompressor.d.ts +25 -250
  297. package/lib/id-compressor/idCompressor.d.ts.map +1 -1
  298. package/lib/id-compressor/idCompressor.js +385 -1142
  299. package/lib/id-compressor/idCompressor.js.map +1 -1
  300. package/lib/id-compressor/identifiers.d.ts +32 -0
  301. package/lib/id-compressor/identifiers.d.ts.map +1 -0
  302. package/lib/id-compressor/identifiers.js +11 -0
  303. package/lib/id-compressor/identifiers.js.map +1 -0
  304. package/lib/id-compressor/index.d.ts +5 -6
  305. package/lib/id-compressor/index.d.ts.map +1 -1
  306. package/lib/id-compressor/index.js +5 -6
  307. package/lib/id-compressor/index.js.map +1 -1
  308. package/lib/id-compressor/persistanceUtilities.d.ts +22 -0
  309. package/lib/id-compressor/persistanceUtilities.d.ts.map +1 -0
  310. package/lib/id-compressor/persistanceUtilities.js +34 -0
  311. package/lib/id-compressor/persistanceUtilities.js.map +1 -0
  312. package/lib/id-compressor/sessionSpaceNormalizer.d.ts +46 -0
  313. package/lib/id-compressor/sessionSpaceNormalizer.d.ts.map +1 -0
  314. package/lib/id-compressor/sessionSpaceNormalizer.js +76 -0
  315. package/lib/id-compressor/sessionSpaceNormalizer.js.map +1 -0
  316. package/lib/id-compressor/sessions.d.ts +115 -0
  317. package/lib/id-compressor/sessions.d.ts.map +1 -0
  318. package/lib/id-compressor/sessions.js +290 -0
  319. package/lib/id-compressor/sessions.js.map +1 -0
  320. package/lib/id-compressor/utilities.d.ts +49 -0
  321. package/lib/id-compressor/utilities.d.ts.map +1 -0
  322. package/lib/id-compressor/utilities.js +148 -0
  323. package/lib/id-compressor/utilities.js.map +1 -0
  324. package/lib/index.d.ts +3 -3
  325. package/lib/index.d.ts.map +1 -1
  326. package/lib/index.js +2 -2
  327. package/lib/index.js.map +1 -1
  328. package/lib/opLifecycle/batchManager.js +10 -6
  329. package/lib/opLifecycle/batchManager.js.map +1 -1
  330. package/lib/opLifecycle/opCompressor.d.ts +2 -2
  331. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  332. package/lib/opLifecycle/opCompressor.js +10 -5
  333. package/lib/opLifecycle/opCompressor.js.map +1 -1
  334. package/lib/opLifecycle/opDecompressor.d.ts +2 -2
  335. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  336. package/lib/opLifecycle/opDecompressor.js +15 -12
  337. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  338. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  339. package/lib/opLifecycle/opGroupingManager.js +17 -7
  340. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  341. package/lib/opLifecycle/opSplitter.d.ts +2 -2
  342. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  343. package/lib/opLifecycle/opSplitter.js +13 -10
  344. package/lib/opLifecycle/opSplitter.js.map +1 -1
  345. package/lib/opLifecycle/outbox.d.ts +7 -5
  346. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  347. package/lib/opLifecycle/outbox.js +13 -22
  348. package/lib/opLifecycle/outbox.js.map +1 -1
  349. package/lib/opLifecycle/remoteMessageProcessor.d.ts +6 -1
  350. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  351. package/lib/opLifecycle/remoteMessageProcessor.js +20 -8
  352. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  353. package/lib/opProperties.js +1 -2
  354. package/lib/opProperties.js.map +1 -1
  355. package/lib/packageVersion.d.ts +1 -1
  356. package/lib/packageVersion.js +1 -1
  357. package/lib/packageVersion.js.map +1 -1
  358. package/lib/pendingStateManager.d.ts +18 -8
  359. package/lib/pendingStateManager.d.ts.map +1 -1
  360. package/lib/pendingStateManager.js +62 -40
  361. package/lib/pendingStateManager.js.map +1 -1
  362. package/lib/scheduleManager.d.ts.map +1 -1
  363. package/lib/scheduleManager.js +18 -14
  364. package/lib/scheduleManager.js.map +1 -1
  365. package/lib/summary/index.d.ts +3 -3
  366. package/lib/summary/index.d.ts.map +1 -1
  367. package/lib/summary/index.js +1 -1
  368. package/lib/summary/index.js.map +1 -1
  369. package/lib/summary/orderedClientElection.d.ts +3 -3
  370. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  371. package/lib/summary/orderedClientElection.js +21 -22
  372. package/lib/summary/orderedClientElection.js.map +1 -1
  373. package/lib/summary/runWhileConnectedCoordinator.js +1 -1
  374. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  375. package/lib/summary/runningSummarizer.d.ts +31 -10
  376. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  377. package/lib/summary/runningSummarizer.js +265 -133
  378. package/lib/summary/runningSummarizer.js.map +1 -1
  379. package/lib/summary/summarizer.d.ts +8 -7
  380. package/lib/summary/summarizer.d.ts.map +1 -1
  381. package/lib/summary/summarizer.js +75 -74
  382. package/lib/summary/summarizer.js.map +1 -1
  383. package/lib/summary/summarizerClientElection.d.ts +2 -2
  384. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  385. package/lib/summary/summarizerClientElection.js +6 -10
  386. package/lib/summary/summarizerClientElection.js.map +1 -1
  387. package/lib/summary/summarizerHeuristics.js +9 -13
  388. package/lib/summary/summarizerHeuristics.js.map +1 -1
  389. package/lib/summary/summarizerNode/index.d.ts +1 -1
  390. package/lib/summary/summarizerNode/index.d.ts.map +1 -1
  391. package/lib/summary/summarizerNode/index.js.map +1 -1
  392. package/lib/summary/summarizerNode/summarizerNode.d.ts +10 -19
  393. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  394. package/lib/summary/summarizerNode/summarizerNode.js +42 -115
  395. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  396. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +6 -30
  397. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  398. package/lib/summary/summarizerNode/summarizerNodeUtils.js +2 -4
  399. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  400. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -14
  401. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  402. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +14 -100
  403. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  404. package/lib/summary/summarizerTypes.d.ts +38 -25
  405. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  406. package/lib/summary/summarizerTypes.js.map +1 -1
  407. package/lib/summary/summaryCollection.d.ts +2 -3
  408. package/lib/summary/summaryCollection.d.ts.map +1 -1
  409. package/lib/summary/summaryCollection.js +5 -6
  410. package/lib/summary/summaryCollection.js.map +1 -1
  411. package/lib/summary/summaryFormat.d.ts +3 -0
  412. package/lib/summary/summaryFormat.d.ts.map +1 -1
  413. package/lib/summary/summaryFormat.js +5 -3
  414. package/lib/summary/summaryFormat.js.map +1 -1
  415. package/lib/summary/summaryGenerator.d.ts +10 -4
  416. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  417. package/lib/summary/summaryGenerator.js +100 -51
  418. package/lib/summary/summaryGenerator.js.map +1 -1
  419. package/lib/summary/summaryManager.d.ts +8 -8
  420. package/lib/summary/summaryManager.d.ts.map +1 -1
  421. package/lib/summary/summaryManager.js +35 -25
  422. package/lib/summary/summaryManager.js.map +1 -1
  423. package/package.json +28 -31
  424. package/src/batchTracker.ts +7 -5
  425. package/src/blobManager.ts +188 -166
  426. package/src/connectionTelemetry.ts +9 -4
  427. package/src/containerRuntime.ts +806 -441
  428. package/src/dataStore.ts +12 -4
  429. package/src/dataStoreContext.ts +39 -43
  430. package/src/dataStoreContexts.ts +4 -6
  431. package/src/dataStoreRegistry.ts +1 -1
  432. package/src/dataStores.ts +114 -80
  433. package/src/deltaManagerProxyBase.ts +111 -0
  434. package/src/deltaManagerSummarizerProxy.ts +4 -1
  435. package/src/deltaScheduler.ts +7 -11
  436. package/src/error.ts +18 -0
  437. package/src/gc/garbageCollection.md +53 -5
  438. package/src/gc/garbageCollection.ts +58 -52
  439. package/src/gc/gcConfigs.ts +4 -2
  440. package/src/gc/gcDefinitions.ts +17 -20
  441. package/src/gc/gcEarlyAdoption.md +145 -0
  442. package/src/gc/gcHelpers.ts +1 -12
  443. package/src/gc/gcSummaryStateTracker.ts +19 -65
  444. package/src/gc/gcTelemetry.ts +14 -12
  445. package/src/gc/gcUnreferencedStateTracker.ts +1 -1
  446. package/src/gc/index.ts +2 -4
  447. package/src/id-compressor/appendOnlySortedMap.ts +26 -87
  448. package/src/id-compressor/finalSpace.ts +67 -0
  449. package/src/id-compressor/idCompressor.ts +458 -1682
  450. package/src/id-compressor/identifiers.ts +42 -0
  451. package/src/id-compressor/index.ts +11 -20
  452. package/src/id-compressor/persistanceUtilities.ts +58 -0
  453. package/src/id-compressor/sessionSpaceNormalizer.ts +83 -0
  454. package/src/id-compressor/sessions.ts +405 -0
  455. package/src/id-compressor/utilities.ts +187 -0
  456. package/src/index.ts +7 -2
  457. package/src/opLifecycle/opCompressor.ts +6 -5
  458. package/src/opLifecycle/opDecompressor.ts +6 -4
  459. package/src/opLifecycle/opGroupingManager.ts +9 -6
  460. package/src/opLifecycle/opSplitter.ts +7 -6
  461. package/src/opLifecycle/outbox.ts +23 -32
  462. package/src/opLifecycle/remoteMessageProcessor.ts +27 -8
  463. package/src/packageVersion.ts +1 -1
  464. package/src/pendingStateManager.ts +72 -42
  465. package/src/scheduleManager.ts +7 -5
  466. package/src/summary/index.ts +4 -3
  467. package/src/summary/orderedClientElection.ts +10 -6
  468. package/src/summary/runWhileConnectedCoordinator.ts +1 -1
  469. package/src/summary/runningSummarizer.ts +291 -163
  470. package/src/summary/summarizer.ts +27 -16
  471. package/src/summary/summarizerClientElection.ts +2 -2
  472. package/src/summary/summarizerHeuristics.ts +1 -1
  473. package/src/summary/summarizerNode/index.ts +1 -2
  474. package/src/summary/summarizerNode/summarizerNode.ts +36 -160
  475. package/src/summary/summarizerNode/summarizerNodeUtils.ts +7 -38
  476. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -130
  477. package/src/summary/summarizerTypes.ts +40 -25
  478. package/src/summary/summaryCollection.ts +3 -3
  479. package/src/summary/summaryFormat.ts +4 -1
  480. package/src/summary/summaryGenerator.ts +52 -52
  481. package/src/summary/summaryManager.ts +44 -17
  482. package/dist/id-compressor/idRange.d.ts +0 -11
  483. package/dist/id-compressor/idRange.d.ts.map +0 -1
  484. package/dist/id-compressor/idRange.js +0 -29
  485. package/dist/id-compressor/idRange.js.map +0 -1
  486. package/dist/id-compressor/numericUuid.d.ts +0 -59
  487. package/dist/id-compressor/numericUuid.d.ts.map +0 -1
  488. package/dist/id-compressor/numericUuid.js +0 -325
  489. package/dist/id-compressor/numericUuid.js.map +0 -1
  490. package/dist/id-compressor/sessionIdNormalizer.d.ts +0 -138
  491. package/dist/id-compressor/sessionIdNormalizer.d.ts.map +0 -1
  492. package/dist/id-compressor/sessionIdNormalizer.js +0 -488
  493. package/dist/id-compressor/sessionIdNormalizer.js.map +0 -1
  494. package/dist/id-compressor/utils.d.ts +0 -57
  495. package/dist/id-compressor/utils.d.ts.map +0 -1
  496. package/dist/id-compressor/utils.js +0 -90
  497. package/dist/id-compressor/utils.js.map +0 -1
  498. package/dist/id-compressor/uuidUtilities.d.ts +0 -28
  499. package/dist/id-compressor/uuidUtilities.d.ts.map +0 -1
  500. package/dist/id-compressor/uuidUtilities.js +0 -104
  501. package/dist/id-compressor/uuidUtilities.js.map +0 -1
  502. package/lib/id-compressor/idRange.d.ts +0 -11
  503. package/lib/id-compressor/idRange.d.ts.map +0 -1
  504. package/lib/id-compressor/idRange.js +0 -25
  505. package/lib/id-compressor/idRange.js.map +0 -1
  506. package/lib/id-compressor/numericUuid.d.ts +0 -59
  507. package/lib/id-compressor/numericUuid.d.ts.map +0 -1
  508. package/lib/id-compressor/numericUuid.js +0 -315
  509. package/lib/id-compressor/numericUuid.js.map +0 -1
  510. package/lib/id-compressor/sessionIdNormalizer.d.ts +0 -138
  511. package/lib/id-compressor/sessionIdNormalizer.d.ts.map +0 -1
  512. package/lib/id-compressor/sessionIdNormalizer.js +0 -484
  513. package/lib/id-compressor/sessionIdNormalizer.js.map +0 -1
  514. package/lib/id-compressor/utils.d.ts +0 -57
  515. package/lib/id-compressor/utils.d.ts.map +0 -1
  516. package/lib/id-compressor/utils.js +0 -79
  517. package/lib/id-compressor/utils.js.map +0 -1
  518. package/lib/id-compressor/uuidUtilities.d.ts +0 -28
  519. package/lib/id-compressor/uuidUtilities.d.ts.map +0 -1
  520. package/lib/id-compressor/uuidUtilities.js +0 -96
  521. package/lib/id-compressor/uuidUtilities.js.map +0 -1
  522. package/src/id-compressor/idRange.ts +0 -35
  523. package/src/id-compressor/numericUuid.ts +0 -383
  524. package/src/id-compressor/sessionIdNormalizer.ts +0 -609
  525. package/src/id-compressor/utils.ts +0 -114
  526. package/src/id-compressor/uuidUtilities.ts +0 -120
@@ -17,21 +17,17 @@ import {
17
17
  responseToException,
18
18
  SummaryTreeBuilder,
19
19
  } from "@fluidframework/runtime-utils";
20
- import {
21
- assert,
22
- bufferToString,
23
- Deferred,
24
- stringToBuffer,
25
- TypedEventEmitter,
26
- } from "@fluidframework/common-utils";
20
+ import { assert, Deferred } from "@fluidframework/core-utils";
21
+ import { bufferToString, stringToBuffer, TypedEventEmitter } from "@fluid-internal/client-utils";
27
22
  import {
28
23
  IContainerRuntime,
29
24
  IContainerRuntimeEvents,
30
25
  } from "@fluidframework/container-runtime-definitions";
31
26
  import { AttachState, ICriticalContainerError } from "@fluidframework/container-definitions";
32
27
  import {
33
- ChildLogger,
34
- loggerToMonitoringContext,
28
+ createChildMonitoringContext,
29
+ GenericError,
30
+ LoggingError,
35
31
  MonitoringContext,
36
32
  PerformanceEvent,
37
33
  } from "@fluidframework/telemetry-utils";
@@ -40,9 +36,13 @@ import {
40
36
  ISummaryTreeWithStats,
41
37
  ITelemetryContext,
42
38
  } from "@fluidframework/runtime-definitions";
43
- import { GenericError } from "@fluidframework/container-utils";
39
+
44
40
  import { ContainerRuntime, TombstoneResponseHeaderKey } from "./containerRuntime";
45
- import { sendGCUnexpectedUsageEvent, sweepAttachmentBlobsKey, throwOnTombstoneLoadKey } from "./gc";
41
+ import {
42
+ sendGCUnexpectedUsageEvent,
43
+ disableAttachmentBlobSweepKey,
44
+ throwOnTombstoneLoadKey,
45
+ } from "./gc";
46
46
  import { Throttler, formExponentialFn, IThrottler } from "./throttler";
47
47
  import { summarizerClientType } from "./summary";
48
48
  import { IBlobMetadata } from "./metadata";
@@ -122,32 +122,26 @@ export type IBlobManagerRuntime = Pick<
122
122
  Pick<ContainerRuntime, "gcTombstoneEnforcementAllowed"> &
123
123
  TypedEventEmitter<IContainerRuntimeEvents>;
124
124
 
125
- // Note that while offline we "submit" an op before uploading the blob, but we always
126
- // expect blobs to be uploaded before we actually see the op round-trip
127
- enum PendingBlobStatus {
128
- OnlinePendingUpload,
129
- OnlinePendingOp,
130
- OfflinePendingUpload,
131
- OfflinePendingOp,
132
- }
133
-
134
125
  type ICreateBlobResponseWithTTL = ICreateBlobResponse & Partial<Record<"minTTLInSeconds", number>>;
135
126
 
136
127
  interface PendingBlob {
137
128
  blob: ArrayBufferLike;
138
- status: PendingBlobStatus;
129
+ uploading?: boolean;
130
+ opsent?: boolean;
139
131
  storageId?: string;
140
132
  handleP: Deferred<BlobHandle>;
141
- uploadP?: Promise<ICreateBlobResponse>;
133
+ uploadP?: Promise<ICreateBlobResponse | void>;
142
134
  uploadTime?: number;
143
135
  minTTLInSeconds?: number;
144
136
  attached?: boolean;
145
137
  acked?: boolean;
138
+ abortSignal?: AbortSignal;
146
139
  }
147
140
 
148
141
  export interface IPendingBlobs {
149
142
  [id: string]: {
150
143
  blob: string;
144
+ storageId?: string;
151
145
  uploadTime?: number;
152
146
  minTTLInSeconds?: number;
153
147
  attached?: boolean;
@@ -174,9 +168,7 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
174
168
  private readonly redirectTable: Map<string, string | undefined>;
175
169
 
176
170
  /**
177
- * Blobs which have not been uploaded or for which we have not yet seen a BlobAttach op round-trip.
178
- * Until we see the op round-trip, there is a possibility we may need to re-upload the blob, so
179
- * we must save it. This is true for both the online and offline flow.
171
+ * Blobs which we have not yet seen a BlobAttach op round-trip and not yet attached to a DDS.
180
172
  */
181
173
  private readonly pendingBlobs: Map<string, PendingBlob> = new Map();
182
174
 
@@ -232,15 +224,16 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
232
224
  private readonly closeContainer: (error?: ICriticalContainerError) => void,
233
225
  ) {
234
226
  super();
235
- this.mc = loggerToMonitoringContext(ChildLogger.create(this.runtime.logger, "BlobManager"));
227
+ this.mc = createChildMonitoringContext({
228
+ logger: this.runtime.logger,
229
+ namespace: "BlobManager",
230
+ });
236
231
  // Read the feature flag that tells whether to throw when a tombstone blob is requested.
237
232
  this.throwOnTombstoneLoad =
238
233
  this.mc.config.getBoolean(throwOnTombstoneLoadKey) === true &&
239
234
  this.runtime.gcTombstoneEnforcementAllowed &&
240
235
  this.runtime.clientDetails.type !== summarizerClientType;
241
236
 
242
- this.runtime.on("disconnected", () => this.onDisconnected());
243
-
244
237
  this.redirectTable = this.load(snapshot);
245
238
 
246
239
  // Begin uploading stashed blobs from previous container instance
@@ -248,14 +241,17 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
248
241
  const blob = stringToBuffer(entry.blob, "base64");
249
242
  const attached = entry.attached;
250
243
  const acked = entry.acked;
244
+ const storageId = entry.storageId; // entry.storageId = response.id
251
245
  if (entry.minTTLInSeconds && entry.uploadTime) {
252
246
  const timeLapseSinceLocalUpload = (Date.now() - entry.uploadTime) / 1000;
253
247
  // stashed entries with more than half-life in storage will not be reuploaded
254
248
  if (entry.minTTLInSeconds - timeLapseSinceLocalUpload > entry.minTTLInSeconds / 2) {
255
249
  this.pendingBlobs.set(localId, {
256
250
  blob,
257
- status: PendingBlobStatus.OfflinePendingOp,
251
+ uploading: false,
252
+ opsent: true,
258
253
  handleP: new Deferred(),
254
+ storageId,
259
255
  uploadP: undefined,
260
256
  uploadTime: entry.uploadTime,
261
257
  minTTLInSeconds: entry.minTTLInSeconds,
@@ -267,22 +263,26 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
267
263
  }
268
264
  this.pendingBlobs.set(localId, {
269
265
  blob,
270
- status: PendingBlobStatus.OfflinePendingUpload,
266
+ uploading: true,
271
267
  handleP: new Deferred(),
272
268
  uploadP: this.uploadBlob(localId, blob),
273
269
  attached,
274
270
  acked,
271
+ opsent: true,
275
272
  });
276
273
  });
277
274
 
278
275
  this.sendBlobAttachOp = (localId: string, blobId?: string) => {
279
276
  const pendingEntry = this.pendingBlobs.get(localId);
277
+ assert(
278
+ pendingEntry !== undefined,
279
+ 0x725 /* Must have pending blob entry for upcoming op */,
280
+ );
280
281
  if (pendingEntry?.uploadTime && pendingEntry?.minTTLInSeconds) {
281
282
  const secondsSinceUpload = (Date.now() - pendingEntry.uploadTime) / 1000;
282
283
  const expired = pendingEntry.minTTLInSeconds - secondsSinceUpload < 0;
283
284
  this.mc.logger.sendTelemetryEvent({
284
285
  eventName: "sendBlobAttach",
285
- entryStatus: pendingEntry.status,
286
286
  secondsSinceUpload,
287
287
  minTTLInSeconds: pendingEntry.minTTLInSeconds,
288
288
  expired,
@@ -296,25 +296,24 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
296
296
  {
297
297
  localId,
298
298
  blobId,
299
- entryStatus: pendingEntry.status,
300
299
  secondsSinceUpload,
301
300
  },
302
301
  ),
303
302
  );
304
303
  }
305
304
  }
305
+ pendingEntry.opsent = true;
306
306
  return sendBlobAttachOp(localId, blobId);
307
307
  };
308
308
  }
309
309
 
310
- private get pendingOfflineUploads() {
311
- return Array.from(this.pendingBlobs.values()).filter(
312
- (e) => e.status === PendingBlobStatus.OfflinePendingUpload,
313
- );
314
- }
315
-
316
- public get hasPendingOfflineUploads(): boolean {
317
- return this.pendingOfflineUploads.length > 0;
310
+ public get allBlobsAttached(): boolean {
311
+ for (const [, entry] of this.pendingBlobs) {
312
+ if (entry.attached === false) {
313
+ return false;
314
+ }
315
+ }
316
+ return true;
318
317
  }
319
318
 
320
319
  public get hasPendingBlobs(): boolean {
@@ -324,16 +323,24 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
324
323
  );
325
324
  }
326
325
 
326
+ private createAbortError(pending?: PendingBlob) {
327
+ return new LoggingError("uploadBlob aborted", {
328
+ acked: pending?.acked,
329
+ uploadTime: pending?.uploadTime,
330
+ });
331
+ }
327
332
  /**
328
333
  * Upload blobs added while offline. This must be completed before connecting and resubmitting ops.
329
334
  */
330
- public async onConnected() {
335
+ public async processStashedChanges() {
331
336
  this.retryThrottler.cancel();
332
- const pendingUploads = this.pendingOfflineUploads.map(async (e) => e.uploadP);
337
+ const pendingUploads = Array.from(this.pendingBlobs.values())
338
+ .filter((e) => e.uploading === true)
339
+ .map(async (e) => e.uploadP);
333
340
  await PerformanceEvent.timedExecAsync(
334
341
  this.mc.logger,
335
342
  {
336
- eventName: "BlobUploadOnConnected",
343
+ eventName: "BlobUploadProcessStashedChanges",
337
344
  count: pendingUploads.length,
338
345
  },
339
346
  async () => Promise.all(pendingUploads),
@@ -341,20 +348,6 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
341
348
  );
342
349
  }
343
350
 
344
- /**
345
- * Transition online blobs waiting for BlobAttach op round-trip since we will not see the op until we are connected
346
- * again
347
- */
348
- private onDisconnected() {
349
- for (const [localId, entry] of this.pendingBlobs) {
350
- if (entry.status === PendingBlobStatus.OnlinePendingOp) {
351
- // This will submit another BlobAttach op for this blob. This is necessary because the one we sent
352
- // already didn't have the local ID.
353
- this.transitionToOffline(localId);
354
- }
355
- }
356
- }
357
-
358
351
  /**
359
352
  * Set of actual storage IDs (i.e., IDs that can be requested from storage). This will be empty if the container is
360
353
  * detached or there are no (non-pending) attachment blobs in the document
@@ -420,6 +413,7 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
420
413
  const callback = pending
421
414
  ? () => {
422
415
  pending.attached = true;
416
+ this.emit("blobAttached", pending);
423
417
  this.deletePendingBlobMaybe(id);
424
418
  }
425
419
  : undefined;
@@ -441,7 +435,10 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
441
435
  return this.getBlobHandle(response.id);
442
436
  }
443
437
 
444
- public async createBlob(blob: ArrayBufferLike): Promise<IFluidHandle<ArrayBufferLike>> {
438
+ public async createBlob(
439
+ blob: ArrayBufferLike,
440
+ signal?: AbortSignal,
441
+ ): Promise<IFluidHandle<ArrayBufferLike>> {
445
442
  if (this.runtime.attachState === AttachState.Detached) {
446
443
  return this.createBlobDetached(blob);
447
444
  }
@@ -455,23 +452,41 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
455
452
  0x385 /* For clarity and paranoid defense against adding future attachment states */,
456
453
  );
457
454
 
455
+ if (signal?.aborted) {
456
+ throw this.createAbortError();
457
+ }
458
+
458
459
  // Create a local ID for the blob. After uploading it to storage and before returning it, a local ID to
459
460
  // storage ID mapping is created.
460
461
  const localId = uuid();
461
462
  const pendingEntry: PendingBlob = {
462
463
  blob,
463
- status: PendingBlobStatus.OnlinePendingUpload,
464
+ uploading: true,
464
465
  handleP: new Deferred(),
465
466
  uploadP: this.uploadBlob(localId, blob),
466
467
  attached: false,
467
468
  acked: false,
469
+ abortSignal: signal,
470
+ opsent: false,
468
471
  };
469
472
  this.pendingBlobs.set(localId, pendingEntry);
470
473
 
471
- return pendingEntry.handleP.promise;
474
+ const abortListener = () => {
475
+ if (!pendingEntry.acked) {
476
+ pendingEntry.handleP.reject(this.createAbortError(pendingEntry));
477
+ }
478
+ };
479
+ signal?.addEventListener("abort", abortListener, { once: true });
480
+
481
+ return pendingEntry.handleP.promise.finally(() => {
482
+ signal?.removeEventListener("abort", abortListener);
483
+ });
472
484
  }
473
485
 
474
- private async uploadBlob(localId: string, blob: ArrayBufferLike): Promise<ICreateBlobResponse> {
486
+ private async uploadBlob(
487
+ localId: string,
488
+ blob: ArrayBufferLike,
489
+ ): Promise<ICreateBlobResponse | void> {
475
490
  return PerformanceEvent.timedExecAsync(
476
491
  this.mc.logger,
477
492
  { eventName: "createBlob" },
@@ -495,72 +510,67 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
495
510
  if (this.pendingBlobs.has(id)) {
496
511
  const entry = this.pendingBlobs.get(id);
497
512
  if (entry?.attached && entry?.acked) {
498
- this.pendingBlobs.delete(id);
499
- if (!this.hasPendingBlobs) {
500
- this.emit("noPendingBlobs");
501
- }
513
+ this.deletePendingBlob(id);
502
514
  }
503
515
  }
504
516
  }
505
517
 
518
+ private deletePendingBlob(id: string) {
519
+ if (this.pendingBlobs.delete(id) && !this.hasPendingBlobs) {
520
+ this.emit("noPendingBlobs");
521
+ }
522
+ }
523
+
506
524
  private onUploadResolve(localId: string, response: ICreateBlobResponseWithTTL) {
507
525
  const entry = this.pendingBlobs.get(localId);
508
526
  assert(entry !== undefined, 0x6c8 /* pending blob entry not found for uploaded blob */);
527
+ if (entry.abortSignal?.aborted === true && !entry.opsent) {
528
+ this.deletePendingBlob(localId);
529
+ return;
530
+ }
509
531
  assert(
510
- entry.status === PendingBlobStatus.OnlinePendingUpload ||
511
- entry.status === PendingBlobStatus.OfflinePendingUpload,
532
+ entry.uploading === true,
512
533
  0x386 /* Must have pending blob entry for uploaded blob */,
513
534
  );
514
535
  entry.storageId = response.id;
515
536
  entry.uploadTime = Date.now();
516
537
  entry.minTTLInSeconds = response.minTTLInSeconds;
517
- if (this.runtime.connected) {
518
- if (entry.status === PendingBlobStatus.OnlinePendingUpload) {
519
- // Send a blob attach op. This serves two purposes:
520
- // 1. If its a new blob, i.e., it isn't de-duped, the server will keep the blob alive if it sees this op
521
- // until its storage ID is added to the next summary.
522
- // 2. It will create a local ID to storage ID mapping in all clients which is needed to retrieve the
523
- // blob from the server via the storage ID.
524
- this.sendBlobAttachOp(localId, response.id);
525
- if (this.storageIds.has(response.id)) {
526
- // The blob is de-duped. Set up a local ID to storage ID mapping and return the blob. Since this is
527
- // an existing blob, we don't have to wait for the op to be ack'd since this step has already
528
- // happened before and so, the server won't delete it.
529
- this.setRedirection(localId, response.id);
530
- entry.handleP.resolve(this.getBlobHandle(localId));
531
- this.deletePendingBlobMaybe(localId);
532
- } else {
533
- // If there is already an op for this storage ID, append the local ID to the list. Once any op for
534
- // this storage ID is ack'd, all pending blobs for it can be resolved since the op will keep the
535
- // blob alive in storage.
536
- this.opsInFlight.set(
537
- response.id,
538
- (this.opsInFlight.get(response.id) ?? []).concat(localId),
539
- );
540
- entry.status = PendingBlobStatus.OnlinePendingOp;
541
- }
542
- } else if (entry.status === PendingBlobStatus.OfflinePendingUpload) {
543
- // We already submitted a BlobAttach op for this blob when it was transitioned to offline flow
544
- entry.status = PendingBlobStatus.OfflinePendingOp;
545
- }
538
+ // Send a blob attach op. This serves two purposes:
539
+ // 1. If its a new blob, i.e., it isn't de-duped, the server will keep the blob alive if it sees this op
540
+ // until its storage ID is added to the next summary.
541
+ // 2. It will create a local ID to storage ID mapping in all clients which is needed to retrieve the
542
+ // blob from the server via the storage ID.
543
+ if (!entry.opsent) {
544
+ this.sendBlobAttachOp(localId, response.id);
545
+ }
546
+ if (this.storageIds.has(response.id)) {
547
+ // The blob is de-duped. Set up a local ID to storage ID mapping and return the blob. Since this is
548
+ // an existing blob, we don't have to wait for the op to be ack'd since this step has already
549
+ // happened before and so, the server won't delete it.
550
+ this.setRedirection(localId, response.id);
551
+ entry.handleP.resolve(this.getBlobHandle(localId));
552
+ this.deletePendingBlobMaybe(localId);
546
553
  } else {
547
- // connected to storage but not ordering service?
548
- this.mc.logger.sendTelemetryEvent({ eventName: "BlobUploadSuccessWhileDisconnected" });
549
- if (entry.status === PendingBlobStatus.OnlinePendingUpload) {
550
- this.transitionToOffline(localId);
551
- }
552
- entry.status = PendingBlobStatus.OfflinePendingOp;
554
+ // If there is already an op for this storage ID, append the local ID to the list. Once any op for
555
+ // this storage ID is ack'd, all pending blobs for it can be resolved since the op will keep the
556
+ // blob alive in storage.
557
+ this.opsInFlight.set(
558
+ response.id,
559
+ (this.opsInFlight.get(response.id) ?? []).concat(localId),
560
+ );
553
561
  }
562
+
554
563
  return response;
555
564
  }
556
565
 
557
- private async onUploadReject(localId: string, error) {
566
+ private async onUploadReject(localId: string, error: any) {
558
567
  const entry = this.pendingBlobs.get(localId);
559
568
  assert(!!entry, 0x387 /* Must have pending blob entry for blob which failed to upload */);
569
+ if (entry.abortSignal?.aborted === true && !entry.opsent) {
570
+ this.deletePendingBlob(localId);
571
+ return;
572
+ }
560
573
  if (!this.runtime.connected) {
561
- if (entry.status === PendingBlobStatus.OnlinePendingUpload) {
562
- this.transitionToOffline(localId);
563
- }
564
574
  // we are probably not connected to storage but start another upload request in case we are
565
575
  entry.uploadP = this.retryThrottler
566
576
  .getDelay()
@@ -572,39 +582,6 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
572
582
  }
573
583
  }
574
584
 
575
- private transitionToOffline(localId: string) {
576
- assert(
577
- !this.runtime.connected,
578
- 0x388 /* Must only transition to offline flow while runtime is disconnected */,
579
- );
580
- const entry = this.pendingBlobs.get(localId);
581
- assert(!!entry, 0x389 /* No pending blob entry */);
582
- assert(
583
- [PendingBlobStatus.OnlinePendingUpload, PendingBlobStatus.OnlinePendingOp].includes(
584
- entry.status,
585
- ),
586
- 0x38a /* Blob must be in online flow to transition to offline flow */,
587
- );
588
-
589
- /**
590
- * If we haven't already submitted a BlobAttach op for this entry, send it before returning the blob handle.
591
- * This will make sure that the BlobAttach op is sequenced prior to any ops referencing the handle. Otherwise,
592
- * an invalid handle could be added to the document.
593
- * storageId may be undefined but since we are not connected we will have a chance to add it when reSubmit()
594
- * is called on reconnection.
595
- */
596
- if (entry.status !== PendingBlobStatus.OnlinePendingOp) {
597
- this.sendBlobAttachOp(localId, entry.storageId);
598
- }
599
-
600
- entry.status =
601
- entry.status === PendingBlobStatus.OnlinePendingUpload
602
- ? PendingBlobStatus.OfflinePendingUpload
603
- : PendingBlobStatus.OfflinePendingOp;
604
-
605
- entry.handleP.resolve(this.getBlobHandle(localId));
606
- }
607
-
608
585
  /**
609
586
  * Resubmit a BlobAttach op. Used to add storage IDs to ops that were
610
587
  * submitted to runtime while disconnected.
@@ -619,11 +596,10 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
619
596
  if (!blobId) {
620
597
  // We submitted this op while offline. The blob should have been uploaded by now.
621
598
  assert(
622
- pendingEntry?.status === PendingBlobStatus.OfflinePendingOp &&
623
- !!pendingEntry?.storageId,
599
+ pendingEntry?.opsent === true && !!pendingEntry?.storageId,
624
600
  0x38d /* blob must be uploaded before resubmitting BlobAttach op */,
625
601
  );
626
- return this.sendBlobAttachOp(localId, pendingEntry.storageId);
602
+ return this.sendBlobAttachOp(localId, pendingEntry?.storageId);
627
603
  }
628
604
  return this.sendBlobAttachOp(localId, blobId);
629
605
  }
@@ -631,6 +607,14 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
631
607
  public processBlobAttachOp(message: ISequencedDocumentMessage, local: boolean) {
632
608
  const localId = (message.metadata as IBlobMetadata | undefined)?.localId;
633
609
  const blobId = (message.metadata as IBlobMetadata | undefined)?.blobId;
610
+
611
+ if (localId) {
612
+ const pendingEntry = this.pendingBlobs.get(localId);
613
+ if (pendingEntry?.abortSignal?.aborted) {
614
+ this.deletePendingBlob(localId);
615
+ return;
616
+ }
617
+ }
634
618
  assert(blobId !== undefined, 0x12a /* "Missing blob id on metadata" */);
635
619
 
636
620
  // Set up a mapping from local ID to storage ID. This is crucial since without this the blob cannot be
@@ -656,22 +640,17 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
656
640
  entry !== undefined,
657
641
  0x38f /* local online BlobAttach op with no pending blob entry */,
658
642
  );
659
-
660
- // It's possible we transitioned to offline flow while waiting for this op.
661
- if (entry.status === PendingBlobStatus.OnlinePendingOp) {
662
- this.setRedirection(pendingLocalId, blobId);
663
- entry.acked = true;
664
- entry.handleP.resolve(this.getBlobHandle(pendingLocalId));
665
- this.deletePendingBlobMaybe(pendingLocalId);
666
- }
643
+ this.setRedirection(pendingLocalId, blobId);
644
+ entry.acked = true;
645
+ entry.handleP.resolve(this.getBlobHandle(pendingLocalId));
646
+ this.deletePendingBlobMaybe(pendingLocalId);
667
647
  });
668
648
  this.opsInFlight.delete(blobId);
669
649
  }
670
- // offline flow does not resolve the handle (since it was already resolved)
671
- // but we still need to delete the entry in case is acked and attached.
672
650
  const localEntry = this.pendingBlobs.get(localId);
673
651
  if (localEntry) {
674
652
  localEntry.acked = true;
653
+ localEntry.handleP.resolve(this.getBlobHandle(localId));
675
654
  this.deletePendingBlobMaybe(localId);
676
655
  }
677
656
  }
@@ -780,11 +759,11 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
780
759
  * Delete attachment blobs that are sweep ready.
781
760
  * @param sweepReadyBlobRoutes - The routes of blobs that are sweep ready and should be deleted. These routes will
782
761
  * be based off of local ids.
783
- * @returns - The routes of blobs that were deleted.
762
+ * @returns The routes of blobs that were deleted.
784
763
  */
785
764
  public deleteSweepReadyNodes(sweepReadyBlobRoutes: string[]): string[] {
786
765
  // If sweep for attachment blobs is not enabled, return empty list indicating nothing is deleted.
787
- if (this.mc.config.getBoolean(sweepAttachmentBlobsKey) !== true) {
766
+ if (this.mc.config.getBoolean(disableAttachmentBlobSweepKey) === true) {
788
767
  return [];
789
768
  }
790
769
 
@@ -943,18 +922,61 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
943
922
  }
944
923
  }
945
924
 
946
- public getPendingBlobs(): IPendingBlobs {
947
- const blobs = {};
948
- for (const [key, entry] of this.pendingBlobs) {
949
- blobs[key] = {
950
- blob: bufferToString(entry.blob, "base64"),
951
- attached: entry.attached,
952
- acked: entry.acked,
953
- minTTLInSeconds: entry.minTTLInSeconds,
954
- uploadTime: entry.uploadTime,
955
- };
956
- }
957
- return blobs;
925
+ public async getPendingBlobs(waitBlobsToAttach?: boolean): Promise<IPendingBlobs | undefined> {
926
+ return PerformanceEvent.timedExecAsync(
927
+ this.mc.logger,
928
+ { eventName: "GetPendingBlobs" },
929
+ async () => {
930
+ if (this.pendingBlobs.size === 0) {
931
+ return;
932
+ }
933
+ const blobs = {};
934
+ const localBlobs = new Set<PendingBlob>();
935
+ while (localBlobs.size < this.pendingBlobs.size) {
936
+ const attachBlobsP: Promise<void>[] = [];
937
+ for (const [id, entry] of this.pendingBlobs) {
938
+ if (!localBlobs.has(entry)) {
939
+ localBlobs.add(entry);
940
+ if (waitBlobsToAttach) {
941
+ if (!entry.opsent) {
942
+ this.sendBlobAttachOp(id, entry.storageId);
943
+ }
944
+ entry.handleP.resolve(this.getBlobHandle(id));
945
+ attachBlobsP.push(
946
+ new Promise<void>((resolve) => {
947
+ const onBlobAttached = (attachedEntry) => {
948
+ if (attachedEntry === entry) {
949
+ this.off("blobAttached", onBlobAttached);
950
+ resolve();
951
+ }
952
+ };
953
+ if (!entry.attached) {
954
+ this.on("blobAttached", onBlobAttached);
955
+ } else {
956
+ resolve();
957
+ }
958
+ }),
959
+ );
960
+ }
961
+ }
962
+ }
963
+ await Promise.all(attachBlobsP);
964
+ }
965
+ // another for is needed to correctly mark attach state
966
+ // future optimization won't add unattached blobs to the list
967
+ for (const [id, entry] of this.pendingBlobs) {
968
+ blobs[id] = {
969
+ blob: bufferToString(entry.blob, "base64"),
970
+ storageId: entry.storageId,
971
+ attached: entry.attached,
972
+ acked: entry.acked,
973
+ minTTLInSeconds: entry.minTTLInSeconds,
974
+ uploadTime: entry.uploadTime,
975
+ };
976
+ }
977
+ return blobs;
978
+ },
979
+ );
958
980
  }
959
981
  }
960
982
 
@@ -3,14 +3,19 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryLoggerExt, ChildLogger, TelemetryLogger } from "@fluidframework/telemetry-utils";
6
+ import {
7
+ ITelemetryLoggerExt,
8
+ createChildLogger,
9
+ formatTick,
10
+ } from "@fluidframework/telemetry-utils";
7
11
  import { IDeltaManager } from "@fluidframework/container-definitions";
8
12
  import {
9
13
  IDocumentMessage,
10
14
  ISequencedDocumentMessage,
11
15
  MessageType,
12
16
  } from "@fluidframework/protocol-definitions";
13
- import { assert, performance } from "@fluidframework/common-utils";
17
+ import { assert } from "@fluidframework/core-utils";
18
+ import { performance } from "@fluid-internal/client-utils";
14
19
 
15
20
  /**
16
21
  * We report various latency-related errors when waiting for op roundtrip takes longer than that amout of time.
@@ -75,7 +80,7 @@ class OpPerfTelemetry {
75
80
  private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
76
81
  logger: ITelemetryLoggerExt,
77
82
  ) {
78
- this.logger = ChildLogger.create(logger, "OpPerf");
83
+ this.logger = createChildLogger({ logger, namespace: "OpPerf" });
79
84
 
80
85
  this.deltaManager.on("pong", (latency) => this.recordPingTime(latency));
81
86
  this.deltaManager.on("submitOp", (message) => this.beforeOpSubmit(message));
@@ -179,7 +184,7 @@ class OpPerfTelemetry {
179
184
  ops: this.gap,
180
185
  // track time to connect only for first connection.
181
186
  timeToConnect: this.firstConnection
182
- ? TelemetryLogger.formatTick(this.connectionStartTime - this.bootTime)
187
+ ? formatTick(this.connectionStartTime - this.bootTime)
183
188
  : undefined,
184
189
  firstConnection: this.firstConnection,
185
190
  });