@fluidframework/container-runtime 2.13.0 → 2.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (489) hide show
  1. package/.eslintrc.cjs +71 -5
  2. package/CHANGELOG.md +84 -0
  3. package/api-report/container-runtime.legacy.alpha.api.md +38 -232
  4. package/dist/batchTracker.d.ts +1 -2
  5. package/dist/batchTracker.d.ts.map +1 -1
  6. package/dist/batchTracker.js +1 -1
  7. package/dist/batchTracker.js.map +1 -1
  8. package/dist/blobManager/blobManager.d.ts +5 -1
  9. package/dist/blobManager/blobManager.d.ts.map +1 -1
  10. package/dist/blobManager/blobManager.js +30 -13
  11. package/dist/blobManager/blobManager.js.map +1 -1
  12. package/dist/blobManager/blobManagerSnapSum.d.ts +1 -0
  13. package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  14. package/dist/blobManager/blobManagerSnapSum.js +7 -5
  15. package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
  16. package/dist/channelCollection.d.ts +23 -12
  17. package/dist/channelCollection.d.ts.map +1 -1
  18. package/dist/channelCollection.js +85 -53
  19. package/dist/channelCollection.js.map +1 -1
  20. package/dist/connectionTelemetry.d.ts +2 -2
  21. package/dist/connectionTelemetry.d.ts.map +1 -1
  22. package/dist/connectionTelemetry.js +10 -6
  23. package/dist/connectionTelemetry.js.map +1 -1
  24. package/dist/containerHandleContext.d.ts +1 -1
  25. package/dist/containerHandleContext.d.ts.map +1 -1
  26. package/dist/containerHandleContext.js.map +1 -1
  27. package/dist/containerRuntime.d.ts +87 -94
  28. package/dist/containerRuntime.d.ts.map +1 -1
  29. package/dist/containerRuntime.js +312 -226
  30. package/dist/containerRuntime.js.map +1 -1
  31. package/dist/dataStore.d.ts +7 -3
  32. package/dist/dataStore.d.ts.map +1 -1
  33. package/dist/dataStore.js +8 -4
  34. package/dist/dataStore.js.map +1 -1
  35. package/dist/dataStoreContext.d.ts +41 -25
  36. package/dist/dataStoreContext.d.ts.map +1 -1
  37. package/dist/dataStoreContext.js +47 -29
  38. package/dist/dataStoreContext.js.map +1 -1
  39. package/dist/dataStoreContexts.d.ts +6 -2
  40. package/dist/dataStoreContexts.d.ts.map +1 -1
  41. package/dist/dataStoreContexts.js +7 -2
  42. package/dist/dataStoreContexts.js.map +1 -1
  43. package/dist/dataStoreRegistry.d.ts +1 -1
  44. package/dist/dataStoreRegistry.d.ts.map +1 -1
  45. package/dist/dataStoreRegistry.js.map +1 -1
  46. package/dist/deltaManagerProxies.d.ts +1 -17
  47. package/dist/deltaManagerProxies.d.ts.map +1 -1
  48. package/dist/deltaManagerProxies.js.map +1 -1
  49. package/dist/deltaScheduler.d.ts +9 -6
  50. package/dist/deltaScheduler.d.ts.map +1 -1
  51. package/dist/deltaScheduler.js +95 -89
  52. package/dist/deltaScheduler.js.map +1 -1
  53. package/dist/gc/garbageCollection.d.ts +21 -7
  54. package/dist/gc/garbageCollection.d.ts.map +1 -1
  55. package/dist/gc/garbageCollection.js +48 -19
  56. package/dist/gc/garbageCollection.js.map +1 -1
  57. package/dist/gc/gcConfigs.d.ts +11 -0
  58. package/dist/gc/gcConfigs.d.ts.map +1 -1
  59. package/dist/gc/gcConfigs.js +5 -2
  60. package/dist/gc/gcConfigs.js.map +1 -1
  61. package/dist/gc/gcDefinitions.d.ts +218 -70
  62. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  63. package/dist/gc/gcDefinitions.js +40 -13
  64. package/dist/gc/gcDefinitions.js.map +1 -1
  65. package/dist/gc/gcHelpers.d.ts +6 -2
  66. package/dist/gc/gcHelpers.d.ts.map +1 -1
  67. package/dist/gc/gcHelpers.js +14 -7
  68. package/dist/gc/gcHelpers.js.map +1 -1
  69. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  70. package/dist/gc/gcSummaryDefinitions.d.ts +18 -6
  71. package/dist/gc/gcSummaryDefinitions.d.ts.map +1 -1
  72. package/dist/gc/gcSummaryDefinitions.js.map +1 -1
  73. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  74. package/dist/gc/gcSummaryStateTracker.js +2 -1
  75. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  76. package/dist/gc/gcTelemetry.d.ts +33 -11
  77. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  78. package/dist/gc/gcTelemetry.js +35 -17
  79. package/dist/gc/gcTelemetry.js.map +1 -1
  80. package/dist/gc/gcUnreferencedStateTracker.d.ts +42 -13
  81. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  82. package/dist/gc/gcUnreferencedStateTracker.js +27 -9
  83. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  84. package/dist/gc/index.d.ts +1 -0
  85. package/dist/gc/index.d.ts.map +1 -1
  86. package/dist/gc/index.js +3 -1
  87. package/dist/gc/index.js.map +1 -1
  88. package/dist/inboundBatchAggregator.d.ts +34 -0
  89. package/dist/inboundBatchAggregator.d.ts.map +1 -0
  90. package/dist/inboundBatchAggregator.js +185 -0
  91. package/dist/inboundBatchAggregator.js.map +1 -0
  92. package/dist/index.d.ts +1 -1
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js.map +1 -1
  95. package/dist/layerCompatState.d.ts +19 -0
  96. package/dist/layerCompatState.d.ts.map +1 -0
  97. package/dist/layerCompatState.js +64 -0
  98. package/dist/layerCompatState.js.map +1 -0
  99. package/dist/legacy.d.ts +0 -4
  100. package/dist/messageTypes.d.ts +14 -5
  101. package/dist/messageTypes.d.ts.map +1 -1
  102. package/dist/messageTypes.js.map +1 -1
  103. package/dist/metadata.d.ts +12 -4
  104. package/dist/metadata.d.ts.map +1 -1
  105. package/dist/metadata.js +6 -2
  106. package/dist/metadata.js.map +1 -1
  107. package/dist/opLifecycle/batchManager.d.ts +9 -3
  108. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  109. package/dist/opLifecycle/batchManager.js +3 -1
  110. package/dist/opLifecycle/batchManager.js.map +1 -1
  111. package/dist/opLifecycle/duplicateBatchDetector.d.ts +9 -3
  112. package/dist/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
  113. package/dist/opLifecycle/duplicateBatchDetector.js +11 -5
  114. package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
  115. package/dist/opLifecycle/opCompressor.d.ts +3 -2
  116. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  117. package/dist/opLifecycle/opCompressor.js +13 -19
  118. package/dist/opLifecycle/opCompressor.js.map +1 -1
  119. package/dist/opLifecycle/opDecompressor.d.ts +6 -1
  120. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  121. package/dist/opLifecycle/opDecompressor.js +16 -8
  122. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  123. package/dist/opLifecycle/opGroupingManager.d.ts +1 -2
  124. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  125. package/dist/opLifecycle/opGroupingManager.js +9 -6
  126. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  127. package/dist/opLifecycle/opSplitter.d.ts +13 -10
  128. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  129. package/dist/opLifecycle/opSplitter.js +16 -11
  130. package/dist/opLifecycle/opSplitter.js.map +1 -1
  131. package/dist/opLifecycle/outbox.d.ts +4 -4
  132. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  133. package/dist/opLifecycle/outbox.js +17 -16
  134. package/dist/opLifecycle/outbox.js.map +1 -1
  135. package/dist/opLifecycle/remoteMessageProcessor.d.ts +9 -3
  136. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  137. package/dist/opLifecycle/remoteMessageProcessor.js +3 -1
  138. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  139. package/dist/package.json +2 -1
  140. package/dist/packageVersion.d.ts +1 -1
  141. package/dist/packageVersion.js +1 -1
  142. package/dist/packageVersion.js.map +1 -1
  143. package/dist/pendingStateManager.d.ts +22 -11
  144. package/dist/pendingStateManager.d.ts.map +1 -1
  145. package/dist/pendingStateManager.js +24 -15
  146. package/dist/pendingStateManager.js.map +1 -1
  147. package/dist/summary/documentSchema.d.ts +7 -0
  148. package/dist/summary/documentSchema.d.ts.map +1 -1
  149. package/dist/summary/documentSchema.js +8 -4
  150. package/dist/summary/documentSchema.js.map +1 -1
  151. package/dist/summary/index.d.ts +1 -1
  152. package/dist/summary/index.d.ts.map +1 -1
  153. package/dist/summary/index.js.map +1 -1
  154. package/dist/summary/orderedClientElection.d.ts +94 -31
  155. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  156. package/dist/summary/orderedClientElection.js +28 -16
  157. package/dist/summary/orderedClientElection.js.map +1 -1
  158. package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -0
  159. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  160. package/dist/summary/runWhileConnectedCoordinator.js +7 -2
  161. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  162. package/dist/summary/runningSummarizer.d.ts +17 -6
  163. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  164. package/dist/summary/runningSummarizer.js +48 -19
  165. package/dist/summary/runningSummarizer.js.map +1 -1
  166. package/dist/summary/summarizer.d.ts +10 -5
  167. package/dist/summary/summarizer.d.ts.map +1 -1
  168. package/dist/summary/summarizer.js +26 -11
  169. package/dist/summary/summarizer.js.map +1 -1
  170. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  171. package/dist/summary/summarizerClientElection.js +1 -0
  172. package/dist/summary/summarizerClientElection.js.map +1 -1
  173. package/dist/summary/summarizerHeuristics.d.ts +6 -2
  174. package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
  175. package/dist/summary/summarizerHeuristics.js +13 -5
  176. package/dist/summary/summarizerHeuristics.js.map +1 -1
  177. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  178. package/dist/summary/summarizerNode/index.js.map +1 -1
  179. package/dist/summary/summarizerNode/summarizerNode.d.ts +24 -8
  180. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  181. package/dist/summary/summarizerNode/summarizerNode.js +45 -36
  182. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  183. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +48 -16
  184. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  185. package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -1
  186. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  187. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +13 -5
  188. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  189. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +15 -7
  190. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  191. package/dist/summary/summarizerTypes.d.ts +253 -135
  192. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  193. package/dist/summary/summarizerTypes.js.map +1 -1
  194. package/dist/summary/summaryCollection.d.ts +3 -4
  195. package/dist/summary/summaryCollection.d.ts.map +1 -1
  196. package/dist/summary/summaryCollection.js +10 -8
  197. package/dist/summary/summaryCollection.js.map +1 -1
  198. package/dist/summary/summaryFormat.d.ts +28 -9
  199. package/dist/summary/summaryFormat.d.ts.map +1 -1
  200. package/dist/summary/summaryFormat.js +3 -2
  201. package/dist/summary/summaryFormat.js.map +1 -1
  202. package/dist/summary/summaryGenerator.d.ts +9 -3
  203. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  204. package/dist/summary/summaryGenerator.js +22 -9
  205. package/dist/summary/summaryGenerator.js.map +1 -1
  206. package/dist/summary/summaryManager.d.ts +8 -4
  207. package/dist/summary/summaryManager.d.ts.map +1 -1
  208. package/dist/summary/summaryManager.js +20 -9
  209. package/dist/summary/summaryManager.js.map +1 -1
  210. package/dist/throttler.d.ts +26 -10
  211. package/dist/throttler.d.ts.map +1 -1
  212. package/dist/throttler.js +12 -4
  213. package/dist/throttler.js.map +1 -1
  214. package/lib/batchTracker.d.ts +1 -2
  215. package/lib/batchTracker.d.ts.map +1 -1
  216. package/lib/batchTracker.js +2 -2
  217. package/lib/batchTracker.js.map +1 -1
  218. package/lib/blobManager/blobManager.d.ts +5 -1
  219. package/lib/blobManager/blobManager.d.ts.map +1 -1
  220. package/lib/blobManager/blobManager.js +30 -13
  221. package/lib/blobManager/blobManager.js.map +1 -1
  222. package/lib/blobManager/blobManagerSnapSum.d.ts +1 -0
  223. package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  224. package/lib/blobManager/blobManagerSnapSum.js +7 -5
  225. package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
  226. package/lib/channelCollection.d.ts +23 -12
  227. package/lib/channelCollection.d.ts.map +1 -1
  228. package/lib/channelCollection.js +88 -54
  229. package/lib/channelCollection.js.map +1 -1
  230. package/lib/connectionTelemetry.d.ts +2 -2
  231. package/lib/connectionTelemetry.d.ts.map +1 -1
  232. package/lib/connectionTelemetry.js +11 -7
  233. package/lib/connectionTelemetry.js.map +1 -1
  234. package/lib/containerHandleContext.d.ts +1 -1
  235. package/lib/containerHandleContext.d.ts.map +1 -1
  236. package/lib/containerHandleContext.js.map +1 -1
  237. package/lib/containerRuntime.d.ts +87 -94
  238. package/lib/containerRuntime.d.ts.map +1 -1
  239. package/lib/containerRuntime.js +319 -228
  240. package/lib/containerRuntime.js.map +1 -1
  241. package/lib/dataStore.d.ts +7 -3
  242. package/lib/dataStore.d.ts.map +1 -1
  243. package/lib/dataStore.js +8 -4
  244. package/lib/dataStore.js.map +1 -1
  245. package/lib/dataStoreContext.d.ts +41 -25
  246. package/lib/dataStoreContext.d.ts.map +1 -1
  247. package/lib/dataStoreContext.js +47 -29
  248. package/lib/dataStoreContext.js.map +1 -1
  249. package/lib/dataStoreContexts.d.ts +6 -2
  250. package/lib/dataStoreContexts.d.ts.map +1 -1
  251. package/lib/dataStoreContexts.js +7 -2
  252. package/lib/dataStoreContexts.js.map +1 -1
  253. package/lib/dataStoreRegistry.d.ts +1 -1
  254. package/lib/dataStoreRegistry.d.ts.map +1 -1
  255. package/lib/dataStoreRegistry.js.map +1 -1
  256. package/lib/deltaManagerProxies.d.ts +1 -17
  257. package/lib/deltaManagerProxies.d.ts.map +1 -1
  258. package/lib/deltaManagerProxies.js.map +1 -1
  259. package/lib/deltaScheduler.d.ts +9 -6
  260. package/lib/deltaScheduler.d.ts.map +1 -1
  261. package/lib/deltaScheduler.js +96 -90
  262. package/lib/deltaScheduler.js.map +1 -1
  263. package/lib/gc/garbageCollection.d.ts +21 -7
  264. package/lib/gc/garbageCollection.d.ts.map +1 -1
  265. package/lib/gc/garbageCollection.js +51 -20
  266. package/lib/gc/garbageCollection.js.map +1 -1
  267. package/lib/gc/gcConfigs.d.ts +11 -0
  268. package/lib/gc/gcConfigs.d.ts.map +1 -1
  269. package/lib/gc/gcConfigs.js +4 -2
  270. package/lib/gc/gcConfigs.js.map +1 -1
  271. package/lib/gc/gcDefinitions.d.ts +218 -70
  272. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  273. package/lib/gc/gcDefinitions.js +40 -13
  274. package/lib/gc/gcDefinitions.js.map +1 -1
  275. package/lib/gc/gcHelpers.d.ts +6 -2
  276. package/lib/gc/gcHelpers.d.ts.map +1 -1
  277. package/lib/gc/gcHelpers.js +14 -7
  278. package/lib/gc/gcHelpers.js.map +1 -1
  279. package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  280. package/lib/gc/gcSummaryDefinitions.d.ts +18 -6
  281. package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -1
  282. package/lib/gc/gcSummaryDefinitions.js.map +1 -1
  283. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  284. package/lib/gc/gcSummaryStateTracker.js +2 -1
  285. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  286. package/lib/gc/gcTelemetry.d.ts +33 -11
  287. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  288. package/lib/gc/gcTelemetry.js +38 -18
  289. package/lib/gc/gcTelemetry.js.map +1 -1
  290. package/lib/gc/gcUnreferencedStateTracker.d.ts +42 -13
  291. package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  292. package/lib/gc/gcUnreferencedStateTracker.js +27 -9
  293. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
  294. package/lib/gc/index.d.ts +1 -0
  295. package/lib/gc/index.d.ts.map +1 -1
  296. package/lib/gc/index.js +1 -0
  297. package/lib/gc/index.js.map +1 -1
  298. package/lib/inboundBatchAggregator.d.ts +34 -0
  299. package/lib/inboundBatchAggregator.d.ts.map +1 -0
  300. package/lib/inboundBatchAggregator.js +181 -0
  301. package/lib/inboundBatchAggregator.js.map +1 -0
  302. package/lib/index.d.ts +1 -1
  303. package/lib/index.d.ts.map +1 -1
  304. package/lib/index.js.map +1 -1
  305. package/lib/layerCompatState.d.ts +19 -0
  306. package/lib/layerCompatState.d.ts.map +1 -0
  307. package/lib/layerCompatState.js +60 -0
  308. package/lib/layerCompatState.js.map +1 -0
  309. package/lib/legacy.d.ts +0 -4
  310. package/lib/messageTypes.d.ts +14 -5
  311. package/lib/messageTypes.d.ts.map +1 -1
  312. package/lib/messageTypes.js.map +1 -1
  313. package/lib/metadata.d.ts +12 -4
  314. package/lib/metadata.d.ts.map +1 -1
  315. package/lib/metadata.js +6 -2
  316. package/lib/metadata.js.map +1 -1
  317. package/lib/opLifecycle/batchManager.d.ts +9 -3
  318. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  319. package/lib/opLifecycle/batchManager.js +3 -1
  320. package/lib/opLifecycle/batchManager.js.map +1 -1
  321. package/lib/opLifecycle/duplicateBatchDetector.d.ts +9 -3
  322. package/lib/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
  323. package/lib/opLifecycle/duplicateBatchDetector.js +11 -5
  324. package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
  325. package/lib/opLifecycle/opCompressor.d.ts +3 -2
  326. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  327. package/lib/opLifecycle/opCompressor.js +14 -20
  328. package/lib/opLifecycle/opCompressor.js.map +1 -1
  329. package/lib/opLifecycle/opDecompressor.d.ts +6 -1
  330. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  331. package/lib/opLifecycle/opDecompressor.js +17 -9
  332. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  333. package/lib/opLifecycle/opGroupingManager.d.ts +1 -2
  334. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  335. package/lib/opLifecycle/opGroupingManager.js +10 -7
  336. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  337. package/lib/opLifecycle/opSplitter.d.ts +13 -10
  338. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  339. package/lib/opLifecycle/opSplitter.js +16 -11
  340. package/lib/opLifecycle/opSplitter.js.map +1 -1
  341. package/lib/opLifecycle/outbox.d.ts +4 -4
  342. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  343. package/lib/opLifecycle/outbox.js +17 -16
  344. package/lib/opLifecycle/outbox.js.map +1 -1
  345. package/lib/opLifecycle/remoteMessageProcessor.d.ts +9 -3
  346. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  347. package/lib/opLifecycle/remoteMessageProcessor.js +3 -1
  348. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  349. package/lib/packageVersion.d.ts +1 -1
  350. package/lib/packageVersion.js +1 -1
  351. package/lib/packageVersion.js.map +1 -1
  352. package/lib/pendingStateManager.d.ts +22 -11
  353. package/lib/pendingStateManager.d.ts.map +1 -1
  354. package/lib/pendingStateManager.js +25 -16
  355. package/lib/pendingStateManager.js.map +1 -1
  356. package/lib/summary/documentSchema.d.ts +7 -0
  357. package/lib/summary/documentSchema.d.ts.map +1 -1
  358. package/lib/summary/documentSchema.js +8 -4
  359. package/lib/summary/documentSchema.js.map +1 -1
  360. package/lib/summary/index.d.ts +1 -1
  361. package/lib/summary/index.d.ts.map +1 -1
  362. package/lib/summary/index.js.map +1 -1
  363. package/lib/summary/orderedClientElection.d.ts +94 -31
  364. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  365. package/lib/summary/orderedClientElection.js +28 -16
  366. package/lib/summary/orderedClientElection.js.map +1 -1
  367. package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -0
  368. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  369. package/lib/summary/runWhileConnectedCoordinator.js +7 -2
  370. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  371. package/lib/summary/runningSummarizer.d.ts +17 -6
  372. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  373. package/lib/summary/runningSummarizer.js +48 -19
  374. package/lib/summary/runningSummarizer.js.map +1 -1
  375. package/lib/summary/summarizer.d.ts +10 -5
  376. package/lib/summary/summarizer.d.ts.map +1 -1
  377. package/lib/summary/summarizer.js +26 -11
  378. package/lib/summary/summarizer.js.map +1 -1
  379. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  380. package/lib/summary/summarizerClientElection.js +1 -0
  381. package/lib/summary/summarizerClientElection.js.map +1 -1
  382. package/lib/summary/summarizerHeuristics.d.ts +6 -2
  383. package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
  384. package/lib/summary/summarizerHeuristics.js +13 -5
  385. package/lib/summary/summarizerHeuristics.js.map +1 -1
  386. package/lib/summary/summarizerNode/index.d.ts.map +1 -1
  387. package/lib/summary/summarizerNode/index.js.map +1 -1
  388. package/lib/summary/summarizerNode/summarizerNode.d.ts +24 -8
  389. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  390. package/lib/summary/summarizerNode/summarizerNode.js +45 -36
  391. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  392. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +48 -16
  393. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  394. package/lib/summary/summarizerNode/summarizerNodeUtils.js +3 -1
  395. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  396. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +13 -5
  397. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  398. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +15 -7
  399. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  400. package/lib/summary/summarizerTypes.d.ts +253 -135
  401. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  402. package/lib/summary/summarizerTypes.js.map +1 -1
  403. package/lib/summary/summaryCollection.d.ts +3 -4
  404. package/lib/summary/summaryCollection.d.ts.map +1 -1
  405. package/lib/summary/summaryCollection.js +10 -8
  406. package/lib/summary/summaryCollection.js.map +1 -1
  407. package/lib/summary/summaryFormat.d.ts +28 -9
  408. package/lib/summary/summaryFormat.d.ts.map +1 -1
  409. package/lib/summary/summaryFormat.js +2 -2
  410. package/lib/summary/summaryFormat.js.map +1 -1
  411. package/lib/summary/summaryGenerator.d.ts +9 -3
  412. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  413. package/lib/summary/summaryGenerator.js +22 -9
  414. package/lib/summary/summaryGenerator.js.map +1 -1
  415. package/lib/summary/summaryManager.d.ts +8 -4
  416. package/lib/summary/summaryManager.d.ts.map +1 -1
  417. package/lib/summary/summaryManager.js +20 -9
  418. package/lib/summary/summaryManager.js.map +1 -1
  419. package/lib/throttler.d.ts +26 -10
  420. package/lib/throttler.d.ts.map +1 -1
  421. package/lib/throttler.js +12 -4
  422. package/lib/throttler.js.map +1 -1
  423. package/package.json +22 -31
  424. package/src/batchTracker.ts +34 -36
  425. package/src/blobManager/blobManager.ts +54 -33
  426. package/src/blobManager/blobManagerSnapSum.ts +10 -10
  427. package/src/channelCollection.ts +108 -82
  428. package/src/connectionTelemetry.ts +43 -19
  429. package/src/containerHandleContext.ts +2 -2
  430. package/src/containerRuntime.ts +492 -364
  431. package/src/dataStore.ts +17 -9
  432. package/src/dataStoreContext.ts +94 -73
  433. package/src/dataStoreContexts.ts +17 -12
  434. package/src/dataStoreRegistry.ts +1 -1
  435. package/src/deltaManagerProxies.ts +5 -5
  436. package/src/deltaScheduler.ts +24 -18
  437. package/src/gc/garbageCollection.ts +89 -40
  438. package/src/gc/gcConfigs.ts +13 -5
  439. package/src/gc/gcDefinitions.ts +224 -70
  440. package/src/gc/gcHelpers.ts +22 -11
  441. package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
  442. package/src/gc/gcSummaryDefinitions.ts +18 -6
  443. package/src/gc/gcSummaryStateTracker.ts +7 -3
  444. package/src/gc/gcTelemetry.ts +73 -30
  445. package/src/gc/gcUnreferencedStateTracker.ts +40 -16
  446. package/src/gc/index.ts +1 -0
  447. package/src/{scheduleManager.ts → inboundBatchAggregator.ts} +55 -122
  448. package/src/index.ts +0 -3
  449. package/src/layerCompatState.ts +75 -0
  450. package/src/messageTypes.ts +16 -5
  451. package/src/metadata.ts +12 -4
  452. package/src/opLifecycle/README.md +43 -34
  453. package/src/opLifecycle/batchManager.ts +12 -6
  454. package/src/opLifecycle/duplicateBatchDetector.ts +12 -6
  455. package/src/opLifecycle/opCompressor.ts +22 -25
  456. package/src/opLifecycle/opDecompressor.ts +23 -11
  457. package/src/opLifecycle/opGroupingManager.ts +16 -11
  458. package/src/opLifecycle/opSplitter.ts +24 -18
  459. package/src/opLifecycle/outbox.ts +35 -33
  460. package/src/opLifecycle/remoteMessageProcessor.ts +13 -5
  461. package/src/packageVersion.ts +1 -1
  462. package/src/pendingStateManager.ts +49 -26
  463. package/src/summary/documentSchema.ts +41 -22
  464. package/src/summary/index.ts +0 -3
  465. package/src/summary/orderedClientElection.ts +114 -49
  466. package/src/summary/runWhileConnectedCoordinator.ts +12 -3
  467. package/src/summary/runningSummarizer.ts +79 -36
  468. package/src/summary/summarizer.ts +51 -25
  469. package/src/summary/summarizerClientElection.ts +4 -2
  470. package/src/summary/summarizerHeuristics.ts +23 -12
  471. package/src/summary/summarizerNode/index.ts +1 -0
  472. package/src/summary/summarizerNode/summarizerNode.ts +54 -43
  473. package/src/summary/summarizerNode/summarizerNodeUtils.ts +48 -16
  474. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +25 -15
  475. package/src/summary/summarizerTypes.ts +253 -139
  476. package/src/summary/summaryCollection.ts +41 -31
  477. package/src/summary/summaryFormat.ts +34 -13
  478. package/src/summary/summaryGenerator.ts +39 -18
  479. package/src/summary/summaryManager.ts +36 -24
  480. package/src/throttler.ts +23 -11
  481. package/container-runtime.test-files.tar +0 -0
  482. package/dist/scheduleManager.d.ts +0 -28
  483. package/dist/scheduleManager.d.ts.map +0 -1
  484. package/dist/scheduleManager.js +0 -233
  485. package/dist/scheduleManager.js.map +0 -1
  486. package/lib/scheduleManager.d.ts +0 -28
  487. package/lib/scheduleManager.d.ts.map +0 -1
  488. package/lib/scheduleManager.js +0 -229
  489. package/lib/scheduleManager.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
5
+ import { Trace, TypedEventEmitter, } from "@fluid-internal/client-utils";
6
6
  import { AttachState, } from "@fluidframework/container-definitions";
7
7
  import { LoaderHeader, isIDeltaManagerFull, } from "@fluidframework/container-definitions/internal";
8
8
  import { assert, Deferred, LazyPromise, PromiseCache, delay, } from "@fluidframework/core-utils/internal";
@@ -23,13 +23,21 @@ import { ContainerFluidHandleContext } from "./containerHandleContext.js";
23
23
  import { channelToDataStore } from "./dataStore.js";
24
24
  import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
25
25
  import { DeltaManagerPendingOpsProxy, DeltaManagerSummarizerProxy, } from "./deltaManagerProxies.js";
26
- import { GCNodeType, GarbageCollector, gcGenerationOptionName, } from "./gc/index.js";
26
+ import { DeltaScheduler } from "./deltaScheduler.js";
27
+ import {
28
+ // eslint-disable-next-line import/no-deprecated
29
+ GCNodeType, GarbageCollector, gcGenerationOptionName, } from "./gc/index.js";
30
+ import { InboundBatchAggregator } from "./inboundBatchAggregator.js";
31
+ import { RuntimeCompatDetails, validateLoaderCompatibility } from "./layerCompatState.js";
27
32
  import { ContainerMessageType, } from "./messageTypes.js";
28
33
  import { DuplicateBatchDetector, ensureContentsDeserialized, OpCompressor, OpDecompressor, OpGroupingManager, OpSplitter, Outbox, RemoteMessageProcessor, serializeOpContents, } from "./opLifecycle/index.js";
29
34
  import { pkgVersion } from "./packageVersion.js";
30
35
  import { PendingStateManager, } from "./pendingStateManager.js";
31
- import { ScheduleManager } from "./scheduleManager.js";
32
- import { DocumentsSchemaController, OrderedClientCollection, OrderedClientElection, RetriableSummaryError, RunWhileConnectedCoordinator, Summarizer, SummarizerClientElection, SummaryCollection, SummaryManager, aliasBlobName, chunksBlobName, recentBatchInfoBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, rootHasIsolatedChannels, summarizerClientType, wrapSummaryInChannelsTree, } from "./summary/index.js";
36
+ import {
37
+ // eslint-disable-next-line import/no-deprecated
38
+ DocumentsSchemaController, OrderedClientCollection, OrderedClientElection, RetriableSummaryError, RunWhileConnectedCoordinator,
39
+ // eslint-disable-next-line import/no-deprecated
40
+ Summarizer, SummarizerClientElection, SummaryCollection, SummaryManager, aliasBlobName, chunksBlobName, recentBatchInfoBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, rootHasIsolatedChannels, summarizerClientType, wrapSummaryInChannelsTree, } from "./summary/index.js";
33
41
  import { Throttler, formExponentialFn } from "./throttler.js";
34
42
  /**
35
43
  * Creates an error object to be thrown / passed to Container's close fn in case of an unknown message type.
@@ -50,6 +58,9 @@ function getUnknownMessageTypeError(unknownContainerRuntimeMessageType, codePath
50
58
  },
51
59
  });
52
60
  }
61
+ export function isSummariesDisabled(config) {
62
+ return config.state === "disabled";
63
+ }
53
64
  /**
54
65
  * @legacy
55
66
  * @alpha
@@ -65,13 +76,14 @@ export const DefaultSummaryConfiguration = {
65
76
  maxOpsSinceLastSummary: 7000,
66
77
  initialSummarizerDelayMs: 5 * 1000, // 5 secs.
67
78
  nonRuntimeOpWeight: 0.1,
68
- runtimeOpWeight: 1.0,
79
+ runtimeOpWeight: 1,
69
80
  nonRuntimeHeuristicThreshold: 20,
70
81
  };
71
82
  /**
72
83
  * Error responses when requesting a deleted object will have this header set to true
73
84
  * @legacy
74
85
  * @alpha
86
+ * @deprecated This type will be moved to internal in 2.30. External usage is not necessary or supported.
75
87
  */
76
88
  export const DeletedResponseHeaderKey = "wasDeleted";
77
89
  /**
@@ -89,7 +101,9 @@ export const TombstoneResponseHeaderKey = "isTombstoned";
89
101
  * to this was experimental and is no longer supported.
90
102
  */
91
103
  export const InactiveResponseHeaderKey = "isInactive";
92
- /** Default values for Runtime Headers */
104
+ /**
105
+ * Default values for Runtime Headers
106
+ */
93
107
  export const defaultRuntimeHeaderData = {
94
108
  wait: true,
95
109
  viaHandle: false,
@@ -109,7 +123,7 @@ export var CompressionAlgorithms;
109
123
  * @alpha
110
124
  */
111
125
  export const disabledCompressionConfig = {
112
- minimumBatchSizeInBytes: Infinity,
126
+ minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
113
127
  compressionAlgorithm: CompressionAlgorithms.lz4,
114
128
  };
115
129
  const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
@@ -125,9 +139,13 @@ const defaultCompressionConfig = {
125
139
  compressionAlgorithm: CompressionAlgorithms.lz4,
126
140
  };
127
141
  const defaultChunkSizeInBytes = 204800;
128
- /** The default time to wait for pending ops to be processed during summarization */
142
+ /**
143
+ * The default time to wait for pending ops to be processed during summarization
144
+ */
129
145
  export const defaultPendingOpsWaitTimeoutMs = 1000;
130
- /** The default time to delay a summarization retry attempt when there are pending ops */
146
+ /**
147
+ * The default time to delay a summarization retry attempt when there are pending ops
148
+ */
131
149
  export const defaultPendingOpsRetryDelayMs = 1000;
132
150
  /**
133
151
  * Instead of refreshing from latest because we do not have 100% confidence in the state
@@ -153,12 +171,15 @@ export function getDeviceSpec() {
153
171
  try {
154
172
  if (typeof navigator === "object" && navigator !== null) {
155
173
  return {
174
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
156
175
  deviceMemory: navigator.deviceMemory,
157
176
  hardwareConcurrency: navigator.hardwareConcurrency,
158
177
  };
159
178
  }
160
179
  }
161
- catch { }
180
+ catch {
181
+ // Eat the error
182
+ }
162
183
  return {};
163
184
  }
164
185
  /**
@@ -199,18 +220,20 @@ async function createSummarizer(loader, url) {
199
220
  let fluidObject;
200
221
  // Older containers may not have the "getEntryPoint" API
201
222
  // ! This check will need to stay until LTS of loader moves past 2.0.0-internal.7.0.0
202
- if (resolvedContainer.getEntryPoint !== undefined) {
203
- fluidObject = await resolvedContainer.getEntryPoint();
204
- }
205
- else {
206
- const response = await resolvedContainer.request({
223
+ if (resolvedContainer.getEntryPoint === undefined) {
224
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
225
+ const response = (await resolvedContainer.request({
207
226
  url: `/${summarizerRequestUrl}`,
208
- });
227
+ }));
209
228
  if (response.status !== 200 || response.mimeType !== "fluid/object") {
210
229
  throw responseToException(response, request);
211
230
  }
231
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
212
232
  fluidObject = response.value;
213
233
  }
234
+ else {
235
+ fluidObject = await resolvedContainer.getEntryPoint();
236
+ }
214
237
  if (fluidObject?.ISummarizer === undefined) {
215
238
  throw new UsageError("Fluid object does not implement ISummarizer");
216
239
  }
@@ -222,7 +245,9 @@ async function createSummarizer(loader, url) {
222
245
  * This allows new runtime to make documents not openable for old runtimes, one explicit document schema control is enabled.
223
246
  * Please see addMetadataToSummary() as well
224
247
  */
225
- function lastMessageFromMetadata(metadata) {
248
+ function lastMessageFromMetadata(
249
+ // eslint-disable-next-line import/no-deprecated
250
+ metadata) {
226
251
  return metadata?.documentSchema?.runtime?.explicitSchemaControl
227
252
  ? metadata?.lastMessage
228
253
  : metadata?.message;
@@ -239,6 +264,7 @@ export let getSingleUseLegacyLogCallback = (logger, type) => {
239
264
  details: { codePath, type },
240
265
  });
241
266
  // Now that we've logged, prevent future logging (globally).
267
+ // eslint-disable-next-line unicorn/consistent-function-scoping
242
268
  getSingleUseLegacyLogCallback = () => () => { };
243
269
  };
244
270
  };
@@ -252,15 +278,13 @@ export let getSingleUseLegacyLogCallback = (logger, type) => {
252
278
  export async function loadContainerRuntime(params) {
253
279
  return ContainerRuntime.loadRuntime(params);
254
280
  }
281
+ const defaultMaxConsecutiveReconnects = 7;
282
+ const defaultTelemetrySignalSampleCount = 100;
255
283
  /**
256
284
  * Represents the runtime of the container. Contains helper functions/state of the container.
257
285
  * It will define the store level mappings.
258
286
  *
259
- * @deprecated To be removed from the Legacy-Alpha API in version 2.20.0.
260
- * Use the loadContainerRuntime function and interfaces IContainerRuntime / IRuntime instead.
261
- *
262
- * @legacy
263
- * @alpha
287
+ * @internal
264
288
  */
265
289
  export class ContainerRuntime extends TypedEventEmitter {
266
290
  /**
@@ -295,7 +319,9 @@ export class ContainerRuntime extends TypedEventEmitter {
295
319
  },
296
320
  });
297
321
  const mc = loggerToMonitoringContext(logger);
298
- const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor, chunkSizeInBytes = defaultChunkSizeInBytes, enableGroupedBatching = true, explicitSchemaControl = false, } = runtimeOptions;
322
+ const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = runtimeOptions.enableGroupedBatching === false
323
+ ? disabledCompressionConfig // Compression must be disabled if Grouping is disabled
324
+ : defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor, chunkSizeInBytes = defaultChunkSizeInBytes, enableGroupedBatching = true, explicitSchemaControl = false, } = runtimeOptions;
299
325
  const registry = new FluidDataStoreRegistry(registryEntries);
300
326
  const tryFetchBlob = async (blobName) => {
301
327
  const blobId = context.baseSnapshot?.blobs[blobName];
@@ -309,7 +335,9 @@ export class ContainerRuntime extends TypedEventEmitter {
309
335
  const [chunks, recentBatchInfo, metadata, electedSummarizerData, aliases, serializedIdCompressor,] = await Promise.all([
310
336
  tryFetchBlob(chunksBlobName),
311
337
  tryFetchBlob(recentBatchInfoBlobName),
338
+ // eslint-disable-next-line import/no-deprecated
312
339
  tryFetchBlob(metadataBlobName),
340
+ // eslint-disable-next-line import/no-deprecated
313
341
  tryFetchBlob(electedSummarizerBlobName),
314
342
  tryFetchBlob(aliasBlobName),
315
343
  tryFetchBlob(idCompressorBlobName),
@@ -323,6 +351,7 @@ export class ContainerRuntime extends TypedEventEmitter {
323
351
  // When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
324
352
  if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
325
353
  // Unless bypass is explicitly set, then take action when sequence numbers mismatch.
354
+ // eslint-disable-next-line unicorn/no-lonely-if -- Separate if statements make flow easier to parse
326
355
  if (loadSequenceNumberVerification !== "bypass" &&
327
356
  runtimeSequenceNumber !== protocolSequenceNumber) {
328
357
  // Message to OCEs:
@@ -345,15 +374,18 @@ export class ContainerRuntime extends TypedEventEmitter {
345
374
  }
346
375
  let desiredIdCompressorMode;
347
376
  switch (mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) {
348
- case true:
377
+ case true: {
349
378
  desiredIdCompressorMode = "on";
350
379
  break;
351
- case false:
380
+ }
381
+ case false: {
352
382
  desiredIdCompressorMode = undefined;
353
383
  break;
354
- default:
384
+ }
385
+ default: {
355
386
  desiredIdCompressorMode = enableRuntimeIdCompressor;
356
387
  break;
388
+ }
357
389
  }
358
390
  // Enabling the IdCompressor is a one-way operation and we only want to
359
391
  // allow new containers to turn it on.
@@ -406,15 +438,16 @@ export class ContainerRuntime extends TypedEventEmitter {
406
438
  if (pendingLocalState?.pendingIdCompressorState !== undefined) {
407
439
  return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
408
440
  }
409
- else if (serializedIdCompressor !== undefined) {
410
- return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
441
+ else if (serializedIdCompressor === undefined) {
442
+ return createIdCompressor(compressorLogger);
411
443
  }
412
444
  else {
413
- return createIdCompressor(compressorLogger);
445
+ return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
414
446
  }
415
447
  };
416
- const compressionLz4 = compressionOptions.minimumBatchSizeInBytes !== Infinity &&
448
+ const compressionLz4 = compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY &&
417
449
  compressionOptions.compressionAlgorithm === "lz4";
450
+ // eslint-disable-next-line import/no-deprecated
418
451
  const documentSchemaController = new DocumentsSchemaController(existing, protocolSequenceNumber, metadata?.documentSchema, {
419
452
  explicitSchemaControl,
420
453
  compressionLz4,
@@ -424,6 +457,9 @@ export class ContainerRuntime extends TypedEventEmitter {
424
457
  }, (schema) => {
425
458
  runtime.onSchemaChange(schema);
426
459
  });
460
+ if (compressionLz4 && !enableGroupedBatching) {
461
+ throw new UsageError("If compression is enabled, op grouping must be enabled too");
462
+ }
427
463
  const featureGatesForTelemetry = {};
428
464
  // Make sure we've got all the options including internal ones
429
465
  const internalRuntimeOptions = {
@@ -484,29 +520,26 @@ export class ContainerRuntime extends TypedEventEmitter {
484
520
  * has to deal with compressed ops as other clients might send them.
485
521
  * And in reverse, session schema can have compression Off, but feature gates / runtime options want it On.
486
522
  * In such case it will be off in session schema, however this client will propose change to schema, and once / if
487
- * this op rountrips, compression will be On. Client can't send compressed ops until it's change in schema.
523
+ * this op roundtrips, compression will be On. Client can't send compressed ops until it's change in schema.
488
524
  */
489
525
  get sessionSchema() {
490
526
  return this.documentsSchemaController.sessionSchema.runtime;
491
527
  }
492
- get idCompressorMode() {
493
- return this.sessionSchema.idCompressorMode;
494
- }
495
528
  /**
496
- * See IContainerRuntimeBase.idCompressor() for details.
529
+ * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor}
497
530
  */
498
531
  get idCompressor() {
499
532
  // Expose ID Compressor only if it's On from the start.
500
533
  // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
501
534
  // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
502
535
  // to reason over such things as session ID space.
503
- if (this.idCompressorMode === "on") {
536
+ if (this.sessionSchema.idCompressorMode === "on") {
504
537
  assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
505
538
  return this._idCompressor;
506
539
  }
507
540
  }
508
541
  /**
509
- * See IContainerRuntimeBase.generateDocumentUniqueId() for details.
542
+ * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.generateDocumentUniqueId}
510
543
  */
511
544
  generateDocumentUniqueId() {
512
545
  return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
@@ -542,35 +575,15 @@ export class ContainerRuntime extends TypedEventEmitter {
542
575
  get connected() {
543
576
  return this._connected;
544
577
  }
545
- /** clientId of parent (non-summarizing) container that owns summarizer container */
578
+ /**
579
+ * clientId of parent (non-summarizing) container that owns summarizer container
580
+ */
546
581
  get summarizerClientId() {
547
582
  return this.summarizerClientElection?.electedClientId;
548
583
  }
549
584
  get disposed() {
550
585
  return this._disposed;
551
586
  }
552
- get summarizer() {
553
- assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
554
- return this._summarizer;
555
- }
556
- isSummariesDisabled() {
557
- return this.summaryConfiguration.state === "disabled";
558
- }
559
- getMaxOpsSinceLastSummary() {
560
- return this.summaryConfiguration.state !== "disabled"
561
- ? this.summaryConfiguration.maxOpsSinceLastSummary
562
- : 0;
563
- }
564
- getInitialSummarizerDelayMs() {
565
- // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
566
- // to ISummaryConfiguration in 0.60.
567
- if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
568
- return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
569
- }
570
- return this.summaryConfiguration.state !== "disabled"
571
- ? this.summaryConfiguration.initialSummarizerDelayMs
572
- : 0;
573
- }
574
587
  /**
575
588
  * If false, loading or using a Tombstoned object should merely log, not fail.
576
589
  * @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
@@ -587,14 +600,27 @@ export class ContainerRuntime extends TypedEventEmitter {
587
600
  get gcThrowOnTombstoneUsage() {
588
601
  return false;
589
602
  }
603
+ get ILayerCompatDetails() {
604
+ return RuntimeCompatDetails;
605
+ }
590
606
  /***/
591
- constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope,
607
+ constructor(context, registry,
608
+ // eslint-disable-next-line import/no-deprecated
609
+ metadata,
610
+ // eslint-disable-next-line import/no-deprecated
611
+ electedSummarizerData, chunks, dataStoreAliasMap, baseRuntimeOptions, containerScope,
592
612
  // Create a custom ITelemetryBaseLogger to output telemetry events.
593
- baseLogger, existing, blobManagerSnapshot, _storage, createIdCompressor, documentsSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler, summaryConfiguration = {
613
+ baseLogger, existing,
614
+ // eslint-disable-next-line import/no-deprecated
615
+ blobManagerSnapshot, _storage, createIdCompressor,
616
+ // eslint-disable-next-line import/no-deprecated
617
+ documentsSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler,
618
+ // eslint-disable-next-line unicorn/no-object-as-default-parameter
619
+ summaryConfiguration = {
594
620
  // the defaults
595
621
  ...DefaultSummaryConfiguration,
596
622
  // the runtime configuration overrides
597
- ...runtimeOptions.summaryOptions?.summaryConfigOverrides,
623
+ ...baseRuntimeOptions.summaryOptions?.summaryConfigOverrides,
598
624
  }, recentBatchInfo) {
599
625
  super();
600
626
  this.registry = registry;
@@ -605,19 +631,16 @@ export class ContainerRuntime extends TypedEventEmitter {
605
631
  this.createIdCompressor = createIdCompressor;
606
632
  this.documentsSchemaController = documentsSchemaController;
607
633
  this.requestHandler = requestHandler;
608
- this.summaryConfiguration = summaryConfiguration;
609
634
  this.imminentClosure = false;
610
635
  // We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
611
636
  // Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
612
637
  this.pendingIdCompressorOps = [];
613
- this.defaultMaxConsecutiveReconnects = 7;
614
638
  this._orderSequentiallyCalls = 0;
615
639
  this.flushTaskExists = false;
616
640
  this.consecutiveReconnects = 0;
617
641
  this.ensureNoDataModelChangesCalls = 0;
618
642
  this._disposed = false;
619
643
  this.emitDirtyDocumentEvent = true;
620
- this.defaultTelemetrySignalSampleCount = 100;
621
644
  this._signalTracking = {
622
645
  totalSignalsSentInLatencyWindow: 0,
623
646
  signalsLost: 0,
@@ -636,16 +659,19 @@ export class ContainerRuntime extends TypedEventEmitter {
636
659
  this.snapshotCacheForLoadingGroupIds = new PromiseCache({
637
660
  expiry: { policy: "absolute", durationMs: 60000 },
638
661
  });
662
+ this.readAndParseBlob = async (id) => readAndParse(this.storage, id);
639
663
  const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, snapshotWithContents, } = context;
664
+ // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
665
+ this.disposeFn = disposeFn ?? closeFn;
666
+ const maybeLoaderCompatDetails = context;
667
+ validateLoaderCompatibility(maybeLoaderCompatDetails.ILayerCompatDetails, this.disposeFn);
640
668
  // Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
641
- this.runtimeOptions = {
669
+ const runtimeOptions = {
642
670
  flushMode: defaultFlushMode,
643
- enableGroupedBatching: true,
644
- ...runtimeOptions,
671
+ ...baseRuntimeOptions,
645
672
  };
646
- this.logger = createChildLogger({ logger: this.baseLogger });
647
673
  this.mc = createChildMonitoringContext({
648
- logger: this.logger,
674
+ logger: this.baseLogger,
649
675
  namespace: "ContainerRuntime",
650
676
  });
651
677
  // If we support multiple algorithms in the future, then we would need to manage it here carefully.
@@ -662,19 +688,23 @@ export class ContainerRuntime extends TypedEventEmitter {
662
688
  this.innerDeltaManager = deltaManager;
663
689
  // Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
664
690
  // This makes ContainerRuntime the final gatekeeper for outgoing messages.
665
- this.submitFn = submitFn;
666
- this.submitBatchFn = submitBatchFn;
667
- this.submitSummaryFn = submitSummaryFn;
691
+ // back-compat: ADO #1385: Make this call unconditional in the future
692
+ this.submitSummaryFn =
693
+ submitSummaryFn ??
694
+ ((summaryOp, refseq) => submitFn(MessageType.Summarize, summaryOp, false));
668
695
  this.submitSignalFn = submitSignalFn;
669
696
  // TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
670
697
  // Values are generally expected to be set from the runtime side.
671
698
  this.options = options ?? {};
672
699
  this.clientDetails = clientDetails;
673
- this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
700
+ const isSummarizerClient = this.clientDetails.type === summarizerClientType;
674
701
  this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
702
+ // eslint-disable-next-line unicorn/consistent-destructuring
675
703
  this._getClientId = () => context.clientId;
704
+ // eslint-disable-next-line unicorn/consistent-destructuring
676
705
  this._getAttachState = () => context.attachState;
677
706
  this.getAbsoluteUrl = async (relativeUrl) => {
707
+ // eslint-disable-next-line unicorn/consistent-destructuring
678
708
  if (context.getAbsoluteUrl === undefined) {
679
709
  throw new Error("Driver does not implement getAbsoluteUrl");
680
710
  }
@@ -687,10 +717,8 @@ export class ContainerRuntime extends TypedEventEmitter {
687
717
  // customer should observe dirty state on the runtime (the owner of dirty state) directly, rather than on the IContainer.
688
718
  this.on("dirty", () => context.updateDirtyContainerState(true));
689
719
  this.on("saved", () => context.updateDirtyContainerState(false));
690
- // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
691
- this.disposeFn = disposeFn ?? closeFn;
692
720
  // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
693
- this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
721
+ this.closeFn = isSummarizerClient ? this.disposeFn : closeFn;
694
722
  let loadSummaryNumber;
695
723
  // Get the container creation metadata. For new container, we initialize these. For existing containers,
696
724
  // get the values from the metadata blob.
@@ -719,18 +747,15 @@ export class ContainerRuntime extends TypedEventEmitter {
719
747
  eventName: "GCFeatureMatrix",
720
748
  metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
721
749
  inputs: JSON.stringify({
722
- gcOptions_gcGeneration: this.runtimeOptions.gcOptions[gcGenerationOptionName],
750
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
751
+ gcOptions_gcGeneration: runtimeOptions.gcOptions[gcGenerationOptionName],
723
752
  }),
724
753
  });
725
754
  this.telemetryDocumentId = metadata?.telemetryDocumentId ?? uuid();
726
- this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
727
755
  const opGroupingManager = new OpGroupingManager({
728
756
  groupedBatchingEnabled: this.groupedBatchingEnabled,
729
- opCountThreshold: this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
730
- reentrantBatchGroupingEnabled: this.mc.config.getBoolean("Fluid.ContainerRuntime.GroupedBatchingReentrancy") ??
731
- true,
732
757
  }, this.mc.logger);
733
- const opSplitter = new OpSplitter(chunks, this.submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
758
+ const opSplitter = new OpSplitter(chunks, submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
734
759
  this.remoteMessageProcessor = new RemoteMessageProcessor(opSplitter, new OpDecompressor(this.mc.logger), opGroupingManager);
735
760
  const pendingRuntimeState = pendingLocalState;
736
761
  this.pendingStateManager = new PendingStateManager({
@@ -740,7 +765,7 @@ export class ContainerRuntime extends TypedEventEmitter {
740
765
  reSubmitBatch: this.reSubmitBatch.bind(this),
741
766
  isActiveConnection: () => this.innerDeltaManager.active,
742
767
  isAttached: () => this.attachState !== AttachState.Detached,
743
- }, pendingRuntimeState?.pending, this.logger);
768
+ }, pendingRuntimeState?.pending, this.baseLogger);
744
769
  let outerDeltaManager;
745
770
  this.useDeltaManagerOpsProxy =
746
771
  this.mc.config.getBoolean("Fluid.ContainerRuntime.DeltaManagerOpsProxy") === true;
@@ -755,24 +780,35 @@ export class ContainerRuntime extends TypedEventEmitter {
755
780
  }
756
781
  this._deltaManager = outerDeltaManager;
757
782
  this.handleContext = new ContainerFluidHandleContext("", this);
758
- if (this.summaryConfiguration.state === "enabled") {
759
- this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
760
- }
761
- this.summariesDisabled = this.isSummariesDisabled();
762
- this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
763
- this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
783
+ if (summaryConfiguration.state === "enabled") {
784
+ this.validateSummaryHeuristicConfiguration(summaryConfiguration);
785
+ }
786
+ this.summariesDisabled = isSummariesDisabled(summaryConfiguration);
787
+ const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = isSummariesDisabled(summaryConfiguration)
788
+ ? {}
789
+ : {
790
+ ...summaryConfiguration,
791
+ initialSummarizerDelayMs:
792
+ // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
793
+ // to ISummaryConfiguration in 0.60.
794
+ runtimeOptions.summaryOptions.initialSummarizerDelayMs ??
795
+ summaryConfiguration.initialSummarizerDelayMs,
796
+ };
764
797
  this.maxConsecutiveReconnects =
765
- this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
766
- this.defaultMaxConsecutiveReconnects;
767
- if (this.runtimeOptions.flushMode ===
768
- FlushModeExperimental.Async &&
769
- supportedFeatures?.get("referenceSequenceNumbers") !== true) {
798
+ this.mc.config.getNumber(maxConsecutiveReconnectsKey) ?? defaultMaxConsecutiveReconnects;
799
+ // If the context has ILayerCompatDetails, it supports referenceSequenceNumbers since that features
800
+ // predates ILayerCompatDetails.
801
+ const referenceSequenceNumbersSupported = maybeLoaderCompatDetails.ILayerCompatDetails === undefined
802
+ ? supportedFeatures?.get("referenceSequenceNumbers") === true
803
+ : true;
804
+ if (runtimeOptions.flushMode === FlushModeExperimental.Async &&
805
+ !referenceSequenceNumbersSupported) {
770
806
  // The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
771
807
  this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
772
808
  this._flushMode = FlushMode.TurnBased;
773
809
  }
774
810
  else {
775
- this._flushMode = this.runtimeOptions.flushMode;
811
+ this._flushMode = runtimeOptions.flushMode;
776
812
  }
777
813
  this.offlineEnabled =
778
814
  this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
@@ -787,6 +823,7 @@ export class ContainerRuntime extends TypedEventEmitter {
787
823
  if (this.offlineEnabled) {
788
824
  this.duplicateBatchDetector = new DuplicateBatchDetector(recentBatchInfo);
789
825
  }
826
+ // eslint-disable-next-line unicorn/consistent-destructuring
790
827
  if (context.attachState === AttachState.Attached) {
791
828
  const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
792
829
  if (maxSnapshotCacheDurationMs !== undefined &&
@@ -799,13 +836,13 @@ export class ContainerRuntime extends TypedEventEmitter {
799
836
  }
800
837
  this.garbageCollector = GarbageCollector.create({
801
838
  runtime: this,
802
- gcOptions: this.runtimeOptions.gcOptions,
839
+ gcOptions: runtimeOptions.gcOptions,
803
840
  baseSnapshot,
804
841
  baseLogger: this.mc.logger,
805
842
  existing,
806
843
  metadata,
807
844
  createContainerMetadata: this.createContainerMetadata,
808
- isSummarizerClient: this.isSummarizerClient,
845
+ isSummarizerClient,
809
846
  getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
810
847
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
811
848
  readAndParseBlob: async (id) => readAndParse(this.storage, id),
@@ -819,7 +856,7 @@ export class ContainerRuntime extends TypedEventEmitter {
819
856
  const summaryReferenceSequenceNumber = baseSnapshot === undefined || metadata?.disableIsolatedChannels === true
820
857
  ? undefined
821
858
  : loadedFromSequenceNumber;
822
- this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
859
+ this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.baseLogger, namespace: "SummarizerNode" }),
823
860
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
824
861
  async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
825
862
  // Latest change sequence number, no changes since summary applied yet
@@ -879,13 +916,14 @@ export class ContainerRuntime extends TypedEventEmitter {
879
916
  stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
880
917
  closeContainer: (error) => this.closeFn(error),
881
918
  });
882
- this.scheduleManager = new ScheduleManager(this.innerDeltaManager, this, () => this.clientId, createChildLogger({ logger: this.logger, namespace: "ScheduleManager" }));
919
+ this.deltaScheduler = new DeltaScheduler(this.innerDeltaManager, this, createChildLogger({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
920
+ this.inboundBatchAggregator = new InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, createChildLogger({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
883
921
  const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
884
- const legacySendBatchFn = makeLegacySendBatchFn(this.submitFn, this.innerDeltaManager);
922
+ const legacySendBatchFn = makeLegacySendBatchFn(submitFn, this.innerDeltaManager);
885
923
  this.outbox = new Outbox({
886
924
  shouldSend: () => this.canSendOps(),
887
925
  pendingStateManager: this.pendingStateManager,
888
- submitBatchFn: this.submitBatchFn,
926
+ submitBatchFn,
889
927
  legacySendBatchFn,
890
928
  compressor: new OpCompressor(this.mc.logger),
891
929
  splitter: opSplitter,
@@ -932,7 +970,7 @@ export class ContainerRuntime extends TypedEventEmitter {
932
970
  const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
933
971
  this.closeSummarizerDelayMs =
934
972
  closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
935
- this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
973
+ const summaryCollection = new SummaryCollection(this.deltaManager, this.baseLogger);
936
974
  this.dirtyContainer =
937
975
  this.attachState !== AttachState.Attached || this.hasPendingMessages();
938
976
  context.updateDirtyContainerState(this.dirtyContainer);
@@ -941,14 +979,17 @@ export class ContainerRuntime extends TypedEventEmitter {
941
979
  }
942
980
  else {
943
981
  const orderedClientLogger = createChildLogger({
944
- logger: this.logger,
982
+ logger: this.baseLogger,
945
983
  namespace: "OrderedClientElection",
946
984
  });
947
985
  const orderedClientCollection = new OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
948
986
  const orderedClientElectionForSummarizer = new OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, SummarizerClientElection.isClientEligible, this.mc.config.getBoolean("Fluid.ContainerRuntime.OrderedClientElection.EnablePerformanceEvents"));
949
- this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
950
- if (this.isSummarizerClient) {
951
- this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => RunWhileConnectedCoordinator.create(runtime,
987
+ this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary);
988
+ if (isSummarizerClient) {
989
+ // eslint-disable-next-line import/no-deprecated
990
+ this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, summaryCollection,
991
+ // eslint-disable-next-line import/no-deprecated
992
+ async (runtime) => RunWhileConnectedCoordinator.create(runtime,
952
993
  // Summarization runs in summarizer client and needs access to the real (non-proxy) active
953
994
  // information. The proxy delta manager would always return false for summarizer client.
954
995
  () => this.innerDeltaManager.active));
@@ -957,48 +998,49 @@ export class ContainerRuntime extends TypedEventEmitter {
957
998
  // Only create a SummaryManager and SummarizerClientElection
958
999
  // if summaries are enabled and we are not the summarizer client.
959
1000
  const defaultAction = () => {
960
- if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
1001
+ if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
961
1002
  this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
962
1003
  // unregister default to no log on every op after falling behind
963
1004
  // and register summary ack handler to re-register this handler
964
1005
  // after successful summary
965
- this.summaryCollection.once(MessageType.SummaryAck, () => {
1006
+ summaryCollection.once(MessageType.SummaryAck, () => {
966
1007
  this.mc.logger.sendTelemetryEvent({
967
1008
  eventName: "SummaryStatus:CaughtUp",
968
1009
  });
969
1010
  // we've caught up, so re-register the default action to monitor for
970
1011
  // falling behind, and unregister ourself
971
- this.summaryCollection.on("default", defaultAction);
1012
+ summaryCollection.on("default", defaultAction);
972
1013
  });
973
- this.summaryCollection.off("default", defaultAction);
1014
+ summaryCollection.off("default", defaultAction);
974
1015
  }
975
1016
  };
976
- this.summaryCollection.on("default", defaultAction);
1017
+ summaryCollection.on("default", defaultAction);
977
1018
  // Create the SummaryManager and mark the initial state
978
1019
  this.summaryManager = new SummaryManager(this.summarizerClientElection, this, // IConnectedState
979
- this.summaryCollection, this.logger, this.formCreateSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
1020
+ summaryCollection, this.baseLogger, this.formCreateSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
980
1021
  30 * 1000, // 30 sec max delay
981
1022
  // throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
982
1023
  formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
983
- initialDelayMs: this.initialSummarizerDelayMs,
1024
+ initialDelayMs: initialSummarizerDelayMs,
984
1025
  });
985
1026
  // Forward events from SummaryManager
986
- [
1027
+ for (const eventName of [
987
1028
  "summarize",
988
1029
  "summarizeAllAttemptsFailed",
989
1030
  "summarizerStop",
990
1031
  "summarizerStart",
991
1032
  "summarizerStartupFailed",
992
- ].forEach((eventName) => {
1033
+ ]) {
993
1034
  this.summaryManager?.on(eventName, (...args) => {
994
1035
  this.emit(eventName, ...args);
995
1036
  });
996
- });
1037
+ }
997
1038
  this.summaryManager.start();
998
1039
  }
999
1040
  }
1000
1041
  // logging hardware telemetry
1001
- this.logger.sendTelemetryEvent({
1042
+ this.baseLogger.send({
1043
+ category: "generic",
1002
1044
  eventName: "DeviceSpec",
1003
1045
  ...getDeviceSpec(),
1004
1046
  });
@@ -1010,13 +1052,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1010
1052
  summaryFormatVersion: metadata?.summaryFormatVersion,
1011
1053
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
1012
1054
  gcVersion: metadata?.gcFeature,
1013
- options: JSON.stringify(runtimeOptions),
1055
+ options: JSON.stringify(baseRuntimeOptions),
1014
1056
  idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
1015
- idCompressorMode: this.idCompressorMode,
1057
+ idCompressorMode: this.sessionSchema.idCompressorMode,
1016
1058
  sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
1017
1059
  featureGates: JSON.stringify({
1018
1060
  ...featureGatesForTelemetry,
1019
- disableAttachReorder: this.disableAttachReorder,
1020
1061
  disablePartialFlush,
1021
1062
  closeSummarizerDelayOverride,
1022
1063
  }),
@@ -1024,11 +1065,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1024
1065
  groupedBatchingEnabled: this.groupedBatchingEnabled,
1025
1066
  initialSequenceNumber: this.deltaManager.initialSequenceNumber,
1026
1067
  });
1027
- ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.logger);
1028
- BindBatchTracker(this, this.logger);
1068
+ ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
1069
+ BindBatchTracker(this, this.baseLogger);
1029
1070
  this.entryPoint = new LazyPromise(async () => {
1030
- if (this.isSummarizerClient) {
1031
- assert(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
1071
+ if (this._summarizer !== undefined) {
1032
1072
  return this._summarizer;
1033
1073
  }
1034
1074
  return provideEntryPoint(this);
@@ -1037,8 +1077,9 @@ export class ContainerRuntime extends TypedEventEmitter {
1037
1077
  // saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
1038
1078
  this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
1039
1079
  }
1080
+ // eslint-disable-next-line import/no-deprecated
1040
1081
  onSchemaChange(schema) {
1041
- this.logger.sendTelemetryEvent({
1082
+ this.mc.logger.sendTelemetryEvent({
1042
1083
  eventName: "SchemaChangeAccept",
1043
1084
  sessionRuntimeSchema: JSON.stringify(schema),
1044
1085
  });
@@ -1061,19 +1102,20 @@ export class ContainerRuntime extends TypedEventEmitter {
1061
1102
  deleteChildSummarizerNode(id) {
1062
1103
  return this.summarizerNode.deleteChild(id);
1063
1104
  }
1064
- /* IFluidParentContext APIs that should not be called on Root */
1105
+ // #region `IFluidParentContext` APIs that should not be called on Root
1065
1106
  makeLocallyVisible() {
1066
1107
  assert(false, 0x8eb /* should not be called */);
1067
1108
  }
1068
1109
  setChannelDirty(address) {
1069
1110
  assert(false, 0x909 /* should not be called */);
1070
1111
  }
1112
+ // #endregion
1071
1113
  /**
1072
1114
  * Initializes the state from the base snapshot this container runtime loaded from.
1073
1115
  */
1074
1116
  async initializeBaseState() {
1075
- if (this.idCompressorMode === "on" ||
1076
- (this.idCompressorMode === "delayed" && this.connected)) {
1117
+ if (this.sessionSchema.idCompressorMode === "on" ||
1118
+ (this.sessionSchema.idCompressorMode === "delayed" && this.connected)) {
1077
1119
  this._idCompressor = await this.createIdCompressor();
1078
1120
  // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
1079
1121
  assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
@@ -1098,6 +1140,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1098
1140
  this._summarizer?.dispose();
1099
1141
  this.channelCollection.dispose();
1100
1142
  this.pendingStateManager.dispose();
1143
+ this.inboundBatchAggregator.dispose();
1144
+ this.deltaScheduler.dispose();
1101
1145
  this.emit("dispose");
1102
1146
  this.removeAllListeners();
1103
1147
  }
@@ -1114,7 +1158,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1114
1158
  // Lookup up in the cache, if not present then make the network call as multiple datastores could
1115
1159
  // be in same loading group. So, once we have fetched the snapshot for that loading group on
1116
1160
  // any request, then cache that as same group could be requested in future too.
1117
- const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
1161
+ const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(","), async () => {
1118
1162
  assert(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
1119
1163
  loadedFromCache = false;
1120
1164
  return this.storage.getSnapshot({
@@ -1123,7 +1167,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1123
1167
  loadingGroupIds: sortedLoadingGroupIds,
1124
1168
  });
1125
1169
  });
1126
- this.logger.sendTelemetryEvent({
1170
+ this.mc.logger.sendTelemetryEvent({
1127
1171
  eventName: "GroupIdSnapshotFetched",
1128
1172
  details: JSON.stringify({
1129
1173
  fromCache: loadedFromCache,
@@ -1153,7 +1197,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1153
1197
  // another snapshot from which the summarizer loaded and it is behind, then just give up as
1154
1198
  // the summarizer state is not up to date.
1155
1199
  // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
1156
- if (this.isSummarizerClient) {
1200
+ if (this._summarizer !== undefined) {
1157
1201
  throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
1158
1202
  }
1159
1203
  // We want to catchup from sequenceNumber to targetSequenceNumber
@@ -1215,7 +1259,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1215
1259
  return {
1216
1260
  status: 200,
1217
1261
  mimeType: "fluid/object",
1218
- value: this.summarizer,
1262
+ value: this._summarizer,
1219
1263
  };
1220
1264
  }
1221
1265
  return create404Response(request);
@@ -1270,7 +1314,9 @@ export class ContainerRuntime extends TypedEventEmitter {
1270
1314
  internalId(maybeAlias) {
1271
1315
  return this.channelCollection.internalId(maybeAlias);
1272
1316
  }
1273
- /** Adds the container's metadata to the given summary tree. */
1317
+ /**
1318
+ * Adds the container's metadata to the given summary tree.
1319
+ */
1274
1320
  addMetadataToSummary(summaryTree) {
1275
1321
  // The last message processed at the time of summary. If there are no new messages, use the message from the
1276
1322
  // last summary.
@@ -1279,6 +1325,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1279
1325
  const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
1280
1326
  // Is document schema explicit control on?
1281
1327
  const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
1328
+ // eslint-disable-next-line import/no-deprecated
1282
1329
  const metadata = {
1283
1330
  ...this.createContainerMetadata,
1284
1331
  // Increment the summary number for the next summary that will be generated.
@@ -1292,7 +1339,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1292
1339
  // last message's sequence number.
1293
1340
  // See also lastMessageFromMetadata()
1294
1341
  message: explicitSchemaControl
1295
- ? { sequenceNumber: -1 }
1342
+ ? // eslint-disable-next-line import/no-deprecated
1343
+ { sequenceNumber: -1 }
1296
1344
  : message,
1297
1345
  lastMessage: explicitSchemaControl ? message : undefined,
1298
1346
  documentSchema,
@@ -1408,9 +1456,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1408
1456
  switch (opContents.type) {
1409
1457
  case ContainerMessageType.FluidDataStoreOp:
1410
1458
  case ContainerMessageType.Attach:
1411
- case ContainerMessageType.Alias:
1459
+ case ContainerMessageType.Alias: {
1412
1460
  return this.channelCollection.applyStashedOp(opContents);
1413
- case ContainerMessageType.IdAllocation:
1461
+ }
1462
+ case ContainerMessageType.IdAllocation: {
1414
1463
  // IDs allocation ops in stashed state are ignored because the tip state of the compressor
1415
1464
  // is serialized into the pending state. This is done because generation of new IDs during
1416
1465
  // stashed op application (or, later, resubmit) must generate new IDs and if the compressor
@@ -1420,17 +1469,22 @@ export class ContainerRuntime extends TypedEventEmitter {
1420
1469
  // and the runtime could filter out all ID allocation ops from the stashed state and apply them
1421
1470
  // before applying the rest of the stashed ops. This would accomplish the same thing but with
1422
1471
  // better performance in future incremental stashed state creation.
1423
- assert(this.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
1472
+ assert(this.sessionSchema.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
1424
1473
  return;
1425
- case ContainerMessageType.DocumentSchemaChange:
1474
+ }
1475
+ case ContainerMessageType.DocumentSchemaChange: {
1426
1476
  return;
1427
- case ContainerMessageType.BlobAttach:
1477
+ }
1478
+ case ContainerMessageType.BlobAttach: {
1428
1479
  return;
1429
- case ContainerMessageType.Rejoin:
1480
+ }
1481
+ case ContainerMessageType.Rejoin: {
1430
1482
  throw new Error("rejoin not expected here");
1431
- case ContainerMessageType.GC:
1483
+ }
1484
+ case ContainerMessageType.GC: {
1432
1485
  // GC op is only sent in summarizer which should never have stashed ops.
1433
1486
  throw new LoggingError("GC op not expected to be stashed in summarizer");
1487
+ }
1434
1488
  default: {
1435
1489
  const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
1436
1490
  this.closeFn(error);
@@ -1440,7 +1494,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1440
1494
  }
1441
1495
  async loadIdCompressor() {
1442
1496
  if (this._idCompressor === undefined &&
1443
- this.idCompressorMode !== undefined &&
1497
+ this.sessionSchema.idCompressorMode !== undefined &&
1444
1498
  this._loadIdCompressor === undefined) {
1445
1499
  this._loadIdCompressor = this.createIdCompressor()
1446
1500
  .then((compressor) => {
@@ -1454,7 +1508,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1454
1508
  this._idCompressor = compressor;
1455
1509
  })
1456
1510
  .catch((error) => {
1457
- this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
1511
+ this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
1458
1512
  throw error;
1459
1513
  });
1460
1514
  }
@@ -1465,7 +1519,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1465
1519
  const currentClientId = this._audience.getSelf()?.clientId;
1466
1520
  assert(clientId === currentClientId, 0x977 /* input clientId does not match Audience */);
1467
1521
  assert(this.clientId === currentClientId, 0x978 /* this.clientId does not match Audience */);
1468
- if (connected && this.idCompressorMode === "delayed") {
1522
+ if (connected && this.sessionSchema.idCompressorMode === "delayed") {
1469
1523
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1470
1524
  this.loadIdCompressor();
1471
1525
  }
@@ -1554,7 +1608,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1554
1608
  // or something different, like a system message.
1555
1609
  const hasModernRuntimeMessageEnvelope = messageCopy.type === MessageType.Operation;
1556
1610
  const savedOp = messageCopy.metadata?.savedOp;
1557
- const logLegacyCase = getSingleUseLegacyLogCallback(this.logger, messageCopy.type);
1611
+ const logLegacyCase = getSingleUseLegacyLogCallback(this.mc.logger, messageCopy.type);
1558
1612
  let runtimeBatch = hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
1559
1613
  if (runtimeBatch) {
1560
1614
  // We expect runtime messages to have JSON contents - deserialize it in place.
@@ -1639,7 +1693,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1639
1693
  }
1640
1694
  }
1641
1695
  /**
1642
- * Processes inbound message(s). It calls schedule manager according to the messages' location in the batch.
1696
+ * Processes inbound message(s). It calls delta scheduler according to the messages' location in the batch.
1643
1697
  * @param messagesWithMetadata - messages to process along with their metadata.
1644
1698
  * @param locationInBatch - Are we processing the start and/or end of a batch?
1645
1699
  * @param local - true if the messages were originally generated by the client receiving it.
@@ -1651,19 +1705,19 @@ export class ContainerRuntime extends TypedEventEmitter {
1651
1705
  if (locationInBatch.batchStart) {
1652
1706
  const firstMessage = messagesWithMetadata[0]?.message;
1653
1707
  assert(firstMessage !== undefined, 0xa31 /* Batch must have at least one message */);
1654
- this.scheduleManager.batchBegin(firstMessage);
1708
+ this.emit("batchBegin", firstMessage);
1655
1709
  }
1656
1710
  let error;
1657
1711
  try {
1658
1712
  if (!runtimeBatch) {
1659
- messagesWithMetadata.forEach(({ message }) => {
1713
+ for (const { message } of messagesWithMetadata) {
1660
1714
  this.ensureNoDataModelChanges(() => {
1661
1715
  this.observeNonRuntimeMessage(message);
1662
1716
  });
1663
- });
1717
+ }
1664
1718
  return;
1665
1719
  }
1666
- // Helper that updates a message's minimum sequence number to the minimum sequence number that container
1720
+ // Updates a message's minimum sequence number to the minimum sequence number that container
1667
1721
  // runtime is tracking and sets _processedClientSequenceNumber. It returns the updated message.
1668
1722
  const updateSequenceNumbers = (message) => {
1669
1723
  // Set the minimum sequence number to the containerRuntime's understanding of minimum sequence number.
@@ -1694,7 +1748,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1694
1748
  }
1695
1749
  let bunchedMessagesContent = [];
1696
1750
  let previousMessage;
1697
- // Helper that processes the previous bunch of messages.
1751
+ // Process the previous bunch of messages.
1698
1752
  const sendBunchedMessages = () => {
1699
1753
  assert(previousMessage !== undefined, 0xa67 /* previous message must exist */);
1700
1754
  this.ensureNoDataModelChanges(() => {
@@ -1728,15 +1782,15 @@ export class ContainerRuntime extends TypedEventEmitter {
1728
1782
  this.emit("op", message, true /* runtimeMessage */);
1729
1783
  }
1730
1784
  }
1731
- catch (e) {
1732
- error = e;
1785
+ catch (error_) {
1786
+ error = error_;
1733
1787
  throw error;
1734
1788
  }
1735
1789
  finally {
1736
1790
  if (locationInBatch.batchEnd) {
1737
1791
  const lastMessage = messagesWithMetadata[messagesWithMetadata.length - 1]?.message;
1738
1792
  assert(lastMessage !== undefined, 0xa32 /* Batch must have at least one message */);
1739
- this.scheduleManager.batchEnd(error, lastMessage);
1793
+ this.emit("batchEnd", error, lastMessage);
1740
1794
  }
1741
1795
  }
1742
1796
  }
@@ -1786,30 +1840,39 @@ export class ContainerRuntime extends TypedEventEmitter {
1786
1840
  switch (message.type) {
1787
1841
  case ContainerMessageType.FluidDataStoreOp:
1788
1842
  case ContainerMessageType.Attach:
1789
- case ContainerMessageType.Alias:
1843
+ case ContainerMessageType.Alias: {
1790
1844
  // Remove the metadata from the message before sending it to the channel collection. The metadata
1791
1845
  // is added by the container runtime and is not part of the message that the channel collection and
1792
1846
  // layers below it expect.
1793
1847
  this.channelCollection.processMessages({ envelope: message, messagesContent, local });
1794
1848
  break;
1795
- case ContainerMessageType.BlobAttach:
1849
+ }
1850
+ case ContainerMessageType.BlobAttach: {
1796
1851
  this.blobManager.processBlobAttachMessage(message, local);
1797
1852
  break;
1798
- case ContainerMessageType.IdAllocation:
1853
+ }
1854
+ case ContainerMessageType.IdAllocation: {
1799
1855
  this.processIdCompressorMessages(contents, savedOp);
1800
1856
  break;
1801
- case ContainerMessageType.GC:
1857
+ }
1858
+ case ContainerMessageType.GC: {
1802
1859
  this.garbageCollector.processMessages(contents, message.timestamp, local);
1803
1860
  break;
1804
- case ContainerMessageType.ChunkedOp:
1861
+ }
1862
+ case ContainerMessageType.ChunkedOp: {
1805
1863
  // From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
1806
1864
  // Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
1807
1865
  assert(false, 0x93d /* should not even get here */);
1808
- case ContainerMessageType.Rejoin:
1866
+ }
1867
+ case ContainerMessageType.Rejoin: {
1809
1868
  break;
1810
- case ContainerMessageType.DocumentSchemaChange:
1811
- this.documentsSchemaController.processDocumentSchemaMessages(contents, local, message.sequenceNumber);
1869
+ }
1870
+ case ContainerMessageType.DocumentSchemaChange: {
1871
+ this.documentsSchemaController.processDocumentSchemaMessages(
1872
+ // eslint-disable-next-line import/no-deprecated
1873
+ contents, local, message.sequenceNumber);
1812
1874
  break;
1875
+ }
1813
1876
  default: {
1814
1877
  const error = getUnknownMessageTypeError(message.type, "validateAndProcessRuntimeMessage" /* codePath */, message);
1815
1878
  this.closeFn(error);
@@ -1827,7 +1890,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1827
1890
  // Some other client turned on the id compressor. If we have not turned it on,
1828
1891
  // put it in a pending queue and delay finalization.
1829
1892
  if (this._idCompressor === undefined) {
1830
- assert(this.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
1893
+ assert(this.sessionSchema.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
1831
1894
  this.pendingIdCompressorOps.push(range);
1832
1895
  }
1833
1896
  else {
@@ -1861,7 +1924,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1861
1924
  * Updates signal telemetry including emitting telemetry events.
1862
1925
  */
1863
1926
  processSignalForTelemetry(envelope) {
1864
- const { clientBroadcastSignalSequenceNumber } = envelope;
1927
+ const { clientBroadcastSignalSequenceNumber, contents: envelopeContents, address: envelopeAddress, } = envelope;
1865
1928
  if (clientBroadcastSignalSequenceNumber === undefined) {
1866
1929
  return;
1867
1930
  }
@@ -1899,8 +1962,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1899
1962
  };
1900
1963
  // Only log `contents.type` when address is for container to avoid
1901
1964
  // chance that contents type is customer data.
1902
- if (envelope.address === undefined) {
1903
- details.contentsType = envelope.contents.type; // Type of signal that was received out of order.
1965
+ if (envelopeAddress === undefined) {
1966
+ details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
1904
1967
  }
1905
1968
  this.mc.logger.sendTelemetryEvent({
1906
1969
  eventName: "SignalOutOfOrder",
@@ -1981,8 +2044,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1981
2044
  try {
1982
2045
  checkpoint.rollback((message) => this.rollback(message.contents, message.localOpMetadata));
1983
2046
  }
1984
- catch (err) {
1985
- const error2 = wrapError(err, (message) => {
2047
+ catch (error_) {
2048
+ const error2 = wrapError(error_, (message) => {
1986
2049
  return DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
1987
2050
  });
1988
2051
  this.closeFn(error2);
@@ -2043,15 +2106,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2043
2106
  return this.channelCollection.createDetachedDataStore(pkg, loadingGroupId);
2044
2107
  }
2045
2108
  async createDataStore(pkg, loadingGroupId) {
2046
- const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], undefined, // props
2047
- loadingGroupId);
2048
- return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
2049
- }
2050
- /**
2051
- * @deprecated 0.16 Issue #1537, #3631
2052
- */
2053
- async _createDataStoreWithProps(pkg, props) {
2054
- const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], props);
2109
+ const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], loadingGroupId);
2055
2110
  return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
2056
2111
  }
2057
2112
  canSendOps() {
@@ -2078,7 +2133,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2078
2133
  get isDirty() {
2079
2134
  return this.dirtyContainer;
2080
2135
  }
2081
- isContainerMessageDirtyable({ type, contents }) {
2136
+ isContainerMessageDirtyable({ type, contents, }) {
2082
2137
  // Certain container runtime messages should not mark the container dirty such as the old built-in
2083
2138
  // AgentScheduler and Garbage collector messages.
2084
2139
  switch (type) {
@@ -2101,8 +2156,9 @@ export class ContainerRuntime extends TypedEventEmitter {
2101
2156
  case ContainerMessageType.GC: {
2102
2157
  return false;
2103
2158
  }
2104
- default:
2159
+ default: {
2105
2160
  break;
2161
+ }
2106
2162
  }
2107
2163
  return true;
2108
2164
  }
@@ -2131,7 +2187,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2131
2187
  clientBroadcastSignalSequenceNumber;
2132
2188
  }
2133
2189
  // We should not track the round trip of a new signal in the case we are already tracking one.
2134
- if (clientBroadcastSignalSequenceNumber % this.defaultTelemetrySignalSampleCount === 1 &&
2190
+ if (clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
2135
2191
  this._signalTracking.roundTripSignalSequenceNumber === undefined) {
2136
2192
  this._signalTracking.signalTimestamp = Date.now();
2137
2193
  this._signalTracking.roundTripSignalSequenceNumber =
@@ -2197,6 +2253,12 @@ export class ContainerRuntime extends TypedEventEmitter {
2197
2253
  this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
2198
2254
  return summarizeResult.summary;
2199
2255
  }
2256
+ /**
2257
+ * Builds the Summary tree including all the channels and the container state.
2258
+ *
2259
+ * @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
2260
+ * so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
2261
+ */
2200
2262
  async summarizeInternal(fullTree, trackState, telemetryContext) {
2201
2263
  const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
2202
2264
  // Wrap data store summaries in .channels subtree.
@@ -2277,8 +2339,10 @@ export class ContainerRuntime extends TypedEventEmitter {
2277
2339
  */
2278
2340
  deleteSweepReadyNodes(sweepReadyRoutes) {
2279
2341
  const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
2280
- const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
2281
- return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
2342
+ return [
2343
+ ...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
2344
+ ...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
2345
+ ];
2282
2346
  }
2283
2347
  /**
2284
2348
  * This is called to update objects that are tombstones.
@@ -2304,10 +2368,13 @@ export class ContainerRuntime extends TypedEventEmitter {
2304
2368
  * Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
2305
2369
  * blob manager.
2306
2370
  */
2371
+ // eslint-disable-next-line import/no-deprecated
2307
2372
  getNodeType(nodePath) {
2308
2373
  if (isBlobPath(nodePath)) {
2374
+ // eslint-disable-next-line import/no-deprecated
2309
2375
  return GCNodeType.Blob;
2310
2376
  }
2377
+ // eslint-disable-next-line import/no-deprecated
2311
2378
  return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
2312
2379
  }
2313
2380
  /**
@@ -2321,13 +2388,19 @@ export class ContainerRuntime extends TypedEventEmitter {
2321
2388
  return ["_gcRoot"];
2322
2389
  }
2323
2390
  switch (this.getNodeType(nodePath)) {
2324
- case GCNodeType.Blob:
2391
+ // eslint-disable-next-line import/no-deprecated
2392
+ case GCNodeType.Blob: {
2325
2393
  return [blobManagerBasePath];
2394
+ }
2395
+ // eslint-disable-next-line import/no-deprecated
2326
2396
  case GCNodeType.DataStore:
2327
- case GCNodeType.SubDataStore:
2397
+ // eslint-disable-next-line import/no-deprecated
2398
+ case GCNodeType.SubDataStore: {
2328
2399
  return this.channelCollection.getDataStorePackagePath(nodePath);
2329
- default:
2400
+ }
2401
+ default: {
2330
2402
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
2403
+ }
2331
2404
  }
2332
2405
  }
2333
2406
  /**
@@ -2389,8 +2462,9 @@ export class ContainerRuntime extends TypedEventEmitter {
2389
2462
  * op processing, updating SummarizerNode state tracking, and garbage collection.
2390
2463
  * @param options - options controlling how the summary is generated or submitted
2391
2464
  */
2465
+ // eslint-disable-next-line import/no-deprecated
2392
2466
  async submitSummary(options) {
2393
- const { fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
2467
+ const { cancellationToken, fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
2394
2468
  // The summary number for this summary. This will be updated during the summary process, so get it now and
2395
2469
  // use it for all events logged during this summary.
2396
2470
  const summaryNumber = this.nextSummaryNumber;
@@ -2474,7 +2548,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2474
2548
  eventName: "LatestSummaryRefSeqNumMismatch",
2475
2549
  details: {
2476
2550
  ...startSummaryResult,
2477
- mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
2551
+ mismatchNumbers: [...startSummaryResult.mismatchNumbers],
2478
2552
  },
2479
2553
  });
2480
2554
  if (shouldValidatePreSummaryState && !finalAttempt) {
@@ -2494,7 +2568,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2494
2568
  // summarizer to reconnect in the future.
2495
2569
  // Also checking for cancellation is a must as summary process may be abandoned for other reasons,
2496
2570
  // like loss of connectivity for main (interactive) client.
2497
- if (options.cancellationToken.cancelled) {
2571
+ if (cancellationToken.cancelled) {
2498
2572
  return { continue: false, error: "disconnected" };
2499
2573
  }
2500
2574
  // That said, we rely on submitSystemMessage() that today only works in connected state.
@@ -2607,7 +2681,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2607
2681
  };
2608
2682
  let handle;
2609
2683
  try {
2610
- handle = await this.storage.uploadSummaryWithContext(summarizeResult.summary, summaryContext);
2684
+ handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
2611
2685
  }
2612
2686
  catch (error) {
2613
2687
  return {
@@ -2729,13 +2803,13 @@ export class ContainerRuntime extends TypedEventEmitter {
2729
2803
  return this.pendingMessagesCount !== 0;
2730
2804
  }
2731
2805
  updateDocumentDirtyState(dirty) {
2732
- if (this.attachState !== AttachState.Attached) {
2733
- assert(dirty, 0x3d2 /* Non-attached container is dirty */);
2734
- }
2735
- else {
2806
+ if (this.attachState === AttachState.Attached) {
2736
2807
  // Other way is not true = see this.isContainerMessageDirtyable()
2737
2808
  assert(!dirty || this.hasPendingMessages(), 0x3d3 /* if doc is dirty, there has to be pending ops */);
2738
2809
  }
2810
+ else {
2811
+ assert(dirty, 0x3d2 /* Non-attached container is dirty */);
2812
+ }
2739
2813
  if (this.dirtyContainer === dirty) {
2740
2814
  return;
2741
2815
  }
@@ -2744,7 +2818,11 @@ export class ContainerRuntime extends TypedEventEmitter {
2744
2818
  this.emit(dirty ? "dirty" : "saved");
2745
2819
  }
2746
2820
  }
2747
- submitMessage(type, contents, localOpMetadata = undefined) {
2821
+ submitMessage(type,
2822
+ // TODO: better typing
2823
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
2824
+ contents, localOpMetadata = undefined) {
2825
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2748
2826
  this.submit({ type, contents }, localOpMetadata);
2749
2827
  }
2750
2828
  async uploadBlob(blob, signal) {
@@ -2793,7 +2871,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2793
2871
  // on this callback to do actual sending.
2794
2872
  const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
2795
2873
  if (schemaChangeMessage) {
2796
- this.logger.sendTelemetryEvent({
2874
+ this.mc.logger.sendTelemetryEvent({
2797
2875
  eventName: "SchemaChangeProposal",
2798
2876
  refSeq: schemaChangeMessage.refSeq,
2799
2877
  version: schemaChangeMessage.version,
@@ -2845,6 +2923,8 @@ export class ContainerRuntime extends TypedEventEmitter {
2845
2923
  return;
2846
2924
  }
2847
2925
  this.flushTaskExists = true;
2926
+ // TODO: hoist this out of the function scope to save unnecessary allocations
2927
+ // eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
2848
2928
  const flush = () => {
2849
2929
  this.flushTaskExists = false;
2850
2930
  try {
@@ -2855,22 +2935,25 @@ export class ContainerRuntime extends TypedEventEmitter {
2855
2935
  }
2856
2936
  };
2857
2937
  switch (this.flushMode) {
2858
- case FlushMode.TurnBased:
2938
+ case FlushMode.TurnBased: {
2859
2939
  // When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
2860
2940
  // batch at the end of the turn
2861
2941
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
2862
2942
  Promise.resolve().then(flush);
2863
2943
  break;
2944
+ }
2864
2945
  // FlushModeExperimental is experimental and not exposed directly in the runtime APIs
2865
- case FlushModeExperimental.Async:
2946
+ case FlushModeExperimental.Async: {
2866
2947
  // When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
2867
2948
  // batch when all micro-tasks are complete.
2868
2949
  // Compared to TurnBased, this flush mode will capture more ops into the same batch.
2869
2950
  setTimeout(flush, 0);
2870
2951
  break;
2871
- default:
2952
+ }
2953
+ default: {
2872
2954
  assert(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
2873
2955
  break;
2956
+ }
2874
2957
  }
2875
2958
  }
2876
2959
  submitSummaryMessage(contents, referenceSequenceNumber) {
@@ -2878,10 +2961,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2878
2961
  assert(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
2879
2962
  // System message should not be sent in the middle of the batch.
2880
2963
  assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
2881
- // back-compat: ADO #1385: Make this call unconditional in the future
2882
- return this.submitSummaryFn !== undefined
2883
- ? this.submitSummaryFn(contents, referenceSequenceNumber)
2884
- : this.submitFn(MessageType.Summarize, contents, false);
2964
+ return this.submitSummaryFn(contents, referenceSequenceNumber);
2885
2965
  }
2886
2966
  /**
2887
2967
  * Throw an error if the runtime is closed. Methods that are expected to potentially
@@ -2921,15 +3001,16 @@ export class ContainerRuntime extends TypedEventEmitter {
2921
3001
  * @param localOpMetadata - The local metadata associated with the original message.
2922
3002
  */
2923
3003
  reSubmitCore(message, localOpMetadata, opMetadata) {
2924
- assert(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
3004
+ assert(this._summarizer === undefined, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
2925
3005
  switch (message.type) {
2926
3006
  case ContainerMessageType.FluidDataStoreOp:
2927
3007
  case ContainerMessageType.Attach:
2928
- case ContainerMessageType.Alias:
3008
+ case ContainerMessageType.Alias: {
2929
3009
  // For Operations, call resubmitDataStoreOp which will find the right store
2930
3010
  // and trigger resubmission on it.
2931
3011
  this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
2932
3012
  break;
3013
+ }
2933
3014
  case ContainerMessageType.IdAllocation: {
2934
3015
  // Allocation ops are never resubmitted/rebased. This is because they require special handling to
2935
3016
  // avoid being submitted out of order. For example, if the pending state manager contained
@@ -2940,20 +3021,24 @@ export class ContainerRuntime extends TypedEventEmitter {
2940
3021
  // all pending IDs. The resubmitted allocation ops are then ignored here.
2941
3022
  break;
2942
3023
  }
2943
- case ContainerMessageType.BlobAttach:
3024
+ case ContainerMessageType.BlobAttach: {
2944
3025
  this.blobManager.reSubmit(opMetadata);
2945
3026
  break;
2946
- case ContainerMessageType.Rejoin:
3027
+ }
3028
+ case ContainerMessageType.Rejoin: {
2947
3029
  this.submit(message);
2948
3030
  break;
2949
- case ContainerMessageType.GC:
3031
+ }
3032
+ case ContainerMessageType.GC: {
2950
3033
  this.submit(message);
2951
3034
  break;
2952
- case ContainerMessageType.DocumentSchemaChange:
3035
+ }
3036
+ case ContainerMessageType.DocumentSchemaChange: {
2953
3037
  // There is no need to resend this message. Document schema controller will properly resend it again (if needed)
2954
3038
  // on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
2955
3039
  // send any ops, as some other client already changed schema.
2956
3040
  break;
3041
+ }
2957
3042
  default: {
2958
3043
  const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
2959
3044
  this.closeFn(error);
@@ -2965,16 +3050,21 @@ export class ContainerRuntime extends TypedEventEmitter {
2965
3050
  // Need to parse from string for back-compat
2966
3051
  const { type, contents } = this.parseLocalOpContent(content);
2967
3052
  switch (type) {
2968
- case ContainerMessageType.FluidDataStoreOp:
3053
+ case ContainerMessageType.FluidDataStoreOp: {
2969
3054
  // For operations, call rollbackDataStoreOp which will find the right store
2970
3055
  // and trigger rollback on it.
2971
3056
  this.channelCollection.rollback(type, contents, localOpMetadata);
2972
3057
  break;
2973
- default:
3058
+ }
3059
+ default: {
2974
3060
  throw new Error(`Can't rollback ${type}`);
3061
+ }
2975
3062
  }
2976
3063
  }
2977
- /** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
3064
+ /**
3065
+ * Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
3066
+ */
3067
+ // eslint-disable-next-line import/no-deprecated
2978
3068
  async refreshLatestSummaryAck(options) {
2979
3069
  const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
2980
3070
  // proposalHandle is always passed from RunningSummarizer.
@@ -3044,15 +3134,16 @@ export class ContainerRuntime extends TypedEventEmitter {
3044
3134
  snapshotTree = snapshot.snapshotTree;
3045
3135
  }
3046
3136
  else {
3047
- const versions = await this.storage.getVersions(null, 1, scenarioName, FetchSource.noCache);
3137
+ const versions = await this.storage.getVersions(
3138
+ // eslint-disable-next-line unicorn/no-null
3139
+ null, 1, scenarioName, FetchSource.noCache);
3048
3140
  assert(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
3049
3141
  snapshotTree = await this.storage.getSnapshotTree(versions[0]);
3050
3142
  assert(!!snapshotTree, 0x138 /* "Failed to get snapshot from storage" */);
3051
3143
  props.snapshotVersion = versions[0].id;
3052
3144
  }
3053
3145
  props.getSnapshotDuration = trace.trace().duration;
3054
- const readAndParseBlob = async (id) => readAndParse(this.storage, id);
3055
- const snapshotRefSeq = await seqFromTree(snapshotTree, readAndParseBlob);
3146
+ const snapshotRefSeq = await seqFromTree(snapshotTree, this.readAndParseBlob);
3056
3147
  props.snapshotRefSeq = snapshotRefSeq;
3057
3148
  props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
3058
3149
  perfEvent.end({ details: props });
@@ -3105,32 +3196,32 @@ export class ContainerRuntime extends TypedEventEmitter {
3105
3196
  : PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
3106
3197
  }
3107
3198
  summarizeOnDemand(options) {
3108
- if (this.isSummarizerClient) {
3109
- return this.summarizer.summarizeOnDemand(options);
3199
+ if (this._summarizer !== undefined) {
3200
+ return this._summarizer.summarizeOnDemand(options);
3110
3201
  }
3111
- else if (this.summaryManager !== undefined) {
3112
- return this.summaryManager.summarizeOnDemand(options);
3113
- }
3114
- else {
3202
+ else if (this.summaryManager === undefined) {
3115
3203
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
3116
3204
  // disableSummaries is turned on. We are throwing instead of returning a failure here,
3117
3205
  // because it is a misuse of the API rather than an expected failure.
3118
3206
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
3119
3207
  }
3208
+ else {
3209
+ return this.summaryManager.summarizeOnDemand(options);
3210
+ }
3120
3211
  }
3121
3212
  enqueueSummarize(options) {
3122
- if (this.isSummarizerClient) {
3123
- return this.summarizer.enqueueSummarize(options);
3124
- }
3125
- else if (this.summaryManager !== undefined) {
3126
- return this.summaryManager.enqueueSummarize(options);
3213
+ if (this._summarizer !== undefined) {
3214
+ return this._summarizer.enqueueSummarize(options);
3127
3215
  }
3128
- else {
3216
+ else if (this.summaryManager === undefined) {
3129
3217
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
3130
3218
  // generateSummaries is turned off. We are throwing instead of returning a failure here,
3131
3219
  // because it is a misuse of the API rather than an expected failure.
3132
3220
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
3133
3221
  }
3222
+ else {
3223
+ return this.summaryManager.enqueueSummarize(options);
3224
+ }
3134
3225
  }
3135
3226
  /**
3136
3227
  * Forms a function that will create and retrieve a Summarizer.