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