@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
@@ -3,7 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
6
+ import {
7
+ Trace,
8
+ TypedEventEmitter,
9
+ type ILayerCompatDetails,
10
+ type IProvideLayerCompatDetails,
11
+ } from "@fluid-internal/client-utils";
7
12
  import {
8
13
  AttachState,
9
14
  IAudience,
@@ -12,7 +17,6 @@ import {
12
17
  type IAudienceEvents,
13
18
  } from "@fluidframework/container-definitions";
14
19
  import {
15
- IBatchMessage,
16
20
  IContainerContext,
17
21
  IGetPendingLocalStateProps,
18
22
  ILoader,
@@ -34,6 +38,7 @@ import {
34
38
  ITelemetryBaseLogger,
35
39
  } from "@fluidframework/core-interfaces";
36
40
  import {
41
+ type IErrorBase,
37
42
  IFluidHandleContext,
38
43
  type IFluidHandleInternal,
39
44
  IProvideFluidHandleContext,
@@ -64,7 +69,6 @@ import {
64
69
  ISequencedDocumentMessage,
65
70
  ISignalMessage,
66
71
  type ISummaryContext,
67
- type SummaryObject,
68
72
  } from "@fluidframework/driver-definitions/internal";
69
73
  import { readAndParse } from "@fluidframework/driver-utils/internal";
70
74
  import type { IIdCompressor } from "@fluidframework/id-compressor";
@@ -93,6 +97,7 @@ import {
93
97
  gcTreeKey,
94
98
  IInboundSignalMessage,
95
99
  type IRuntimeMessagesContent,
100
+ type ISummarizerNodeWithGC,
96
101
  } from "@fluidframework/runtime-definitions/internal";
97
102
  import {
98
103
  GCDataBuilder,
@@ -142,6 +147,7 @@ import {
142
147
  blobsTreeName,
143
148
  isBlobPath,
144
149
  loadBlobManagerLoadInfo,
150
+ // eslint-disable-next-line import/no-deprecated
145
151
  type IBlobManagerLoadInfo,
146
152
  } from "./blobManager/index.js";
147
153
  import {
@@ -157,15 +163,20 @@ import {
157
163
  DeltaManagerPendingOpsProxy,
158
164
  DeltaManagerSummarizerProxy,
159
165
  } from "./deltaManagerProxies.js";
166
+ import { DeltaScheduler } from "./deltaScheduler.js";
160
167
  import {
168
+ // eslint-disable-next-line import/no-deprecated
161
169
  GCNodeType,
162
170
  GarbageCollector,
163
171
  IGCRuntimeOptions,
172
+ // eslint-disable-next-line import/no-deprecated
164
173
  IGCStats,
165
174
  IGarbageCollector,
166
175
  gcGenerationOptionName,
167
176
  type GarbageCollectionMessage,
168
177
  } from "./gc/index.js";
178
+ import { InboundBatchAggregator } from "./inboundBatchAggregator.js";
179
+ import { RuntimeCompatDetails, validateLoaderCompatibility } from "./layerCompatState.js";
169
180
  import {
170
181
  ContainerMessageType,
171
182
  type ContainerRuntimeDocumentSchemaMessage,
@@ -199,28 +210,39 @@ import {
199
210
  IPendingLocalState,
200
211
  PendingStateManager,
201
212
  } from "./pendingStateManager.js";
202
- import { ScheduleManager } from "./scheduleManager.js";
203
213
  import {
214
+ // eslint-disable-next-line import/no-deprecated
204
215
  DocumentsSchemaController,
205
216
  EnqueueSummarizeResult,
206
217
  IBaseSummarizeResult,
218
+ // eslint-disable-next-line import/no-deprecated
207
219
  IConnectableRuntime,
220
+ // eslint-disable-next-line import/no-deprecated
208
221
  IContainerRuntimeMetadata,
222
+ // eslint-disable-next-line import/no-deprecated
209
223
  ICreateContainerMetadata,
224
+ // eslint-disable-next-line import/no-deprecated
210
225
  type IDocumentSchemaChangeMessage,
226
+ // eslint-disable-next-line import/no-deprecated
211
227
  type IDocumentSchemaCurrent,
212
228
  IEnqueueSummarizeOptions,
213
229
  IGenerateSummaryTreeResult,
214
230
  IGeneratedSummaryStats,
215
231
  IOnDemandSummarizeOptions,
232
+ // eslint-disable-next-line import/no-deprecated
216
233
  IRefreshSummaryAckOptions,
217
234
  IRootSummarizerNodeWithGC,
235
+ // eslint-disable-next-line import/no-deprecated
218
236
  ISerializedElection,
237
+ // eslint-disable-next-line import/no-deprecated
219
238
  ISubmitSummaryOptions,
220
239
  ISummarizeResults,
221
240
  ISummarizer,
241
+ // eslint-disable-next-line import/no-deprecated
222
242
  ISummarizerInternalsProvider,
243
+ // eslint-disable-next-line import/no-deprecated
223
244
  ISummarizerRuntime,
245
+ // eslint-disable-next-line import/no-deprecated
224
246
  ISummaryMetadataMessage,
225
247
  IdCompressorMode,
226
248
  OrderedClientCollection,
@@ -228,6 +250,7 @@ import {
228
250
  RetriableSummaryError,
229
251
  RunWhileConnectedCoordinator,
230
252
  SubmitSummaryResult,
253
+ // eslint-disable-next-line import/no-deprecated
231
254
  Summarizer,
232
255
  SummarizerClientElection,
233
256
  SummaryCollection,
@@ -243,6 +266,8 @@ import {
243
266
  rootHasIsolatedChannels,
244
267
  summarizerClientType,
245
268
  wrapSummaryInChannelsTree,
269
+ // eslint-disable-next-line import/no-deprecated
270
+ type IDocumentSchemaFeatures,
246
271
  } from "./summary/index.js";
247
272
  import { Throttler, formExponentialFn } from "./throttler.js";
248
273
 
@@ -387,6 +412,12 @@ export type ISummaryConfiguration =
387
412
  | ISummaryConfigurationDisableHeuristics
388
413
  | ISummaryConfigurationHeuristics;
389
414
 
415
+ export function isSummariesDisabled(
416
+ config: ISummaryConfiguration,
417
+ ): config is ISummaryConfigurationDisableSummarizer {
418
+ return config.state === "disabled";
419
+ }
420
+
390
421
  /**
391
422
  * @legacy
392
423
  * @alpha
@@ -412,7 +443,7 @@ export const DefaultSummaryConfiguration: ISummaryConfiguration = {
412
443
 
413
444
  nonRuntimeOpWeight: 0.1,
414
445
 
415
- runtimeOpWeight: 1.0,
446
+ runtimeOpWeight: 1,
416
447
 
417
448
  nonRuntimeHeuristicThreshold: 20,
418
449
  };
@@ -422,7 +453,9 @@ export const DefaultSummaryConfiguration: ISummaryConfiguration = {
422
453
  * @alpha
423
454
  */
424
455
  export interface ISummaryRuntimeOptions {
425
- /** Override summary configurations set by the server. */
456
+ /**
457
+ * Override summary configurations set by the server.
458
+ */
426
459
  summaryConfigOverrides?: ISummaryConfiguration;
427
460
 
428
461
  /**
@@ -470,15 +503,7 @@ export interface IContainerRuntimeOptions {
470
503
  * 3. "bypass" will skip the check entirely. This is not recommended.
471
504
  */
472
505
  readonly loadSequenceNumberVerification?: "close" | "log" | "bypass";
473
- /**
474
- * Sets the flush mode for the runtime. In Immediate flush mode the runtime will immediately
475
- * send all operations to the driver layer, while in TurnBased the operations will be buffered
476
- * and then sent them as a single batch at the end of the turn.
477
- * By default, flush mode is TurnBased.
478
- *
479
- * @deprecated Only the default value TurnBased is supported. This option will be removed in the future.
480
- */
481
- readonly flushMode?: FlushMode;
506
+
482
507
  /**
483
508
  * Enables the runtime to compress ops. See {@link ICompressionRuntimeOptions}.
484
509
  */
@@ -520,8 +545,8 @@ export interface IContainerRuntimeOptions {
520
545
  * message to be sent to the service.
521
546
  * The grouping and ungrouping of such messages is handled by the "OpGroupingManager".
522
547
  *
523
- * By default, the feature is enabled.
524
- * @deprecated The ability to disable Grouped Batching is deprecated and will be removed in v2.20.0. This feature is required for the proper functioning of the Fluid Framework.
548
+ * By default, the feature is enabled. This feature can only be disabled when compression is also disabled.
549
+ * @deprecated The ability to disable Grouped Batching is deprecated and will be removed in a future release. This feature is required for the proper functioning of the Fluid Framework.
525
550
  */
526
551
  readonly enableGroupedBatching?: boolean;
527
552
 
@@ -564,6 +589,7 @@ export interface IContainerRuntimeOptionsInternal extends IContainerRuntimeOptio
564
589
  * Error responses when requesting a deleted object will have this header set to true
565
590
  * @legacy
566
591
  * @alpha
592
+ * @deprecated This type will be moved to internal in 2.30. External usage is not necessary or supported.
567
593
  */
568
594
  export const DeletedResponseHeaderKey = "wasDeleted";
569
595
  /**
@@ -592,7 +618,9 @@ export interface RuntimeHeaderData {
592
618
  allowTombstone?: boolean;
593
619
  }
594
620
 
595
- /** Default values for Runtime Headers */
621
+ /**
622
+ * Default values for Runtime Headers
623
+ */
596
624
  export const defaultRuntimeHeaderData: Required<RuntimeHeaderData> = {
597
625
  wait: true,
598
626
  viaHandle: false,
@@ -613,7 +641,7 @@ export enum CompressionAlgorithms {
613
641
  * @alpha
614
642
  */
615
643
  export const disabledCompressionConfig: ICompressionRuntimeOptions = {
616
- minimumBatchSizeInBytes: Infinity,
644
+ minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
617
645
  compressionAlgorithm: CompressionAlgorithms.lz4,
618
646
  };
619
647
 
@@ -671,9 +699,13 @@ const defaultCompressionConfig = {
671
699
 
672
700
  const defaultChunkSizeInBytes = 204800;
673
701
 
674
- /** The default time to wait for pending ops to be processed during summarization */
702
+ /**
703
+ * The default time to wait for pending ops to be processed during summarization
704
+ */
675
705
  export const defaultPendingOpsWaitTimeoutMs = 1000;
676
- /** The default time to delay a summarization retry attempt when there are pending ops */
706
+ /**
707
+ * The default time to delay a summarization retry attempt when there are pending ops
708
+ */
677
709
  export const defaultPendingOpsRetryDelayMs = 1000;
678
710
 
679
711
  /**
@@ -699,15 +731,21 @@ export function isUnpackedRuntimeMessage(message: ISequencedDocumentMessage): bo
699
731
  export const agentSchedulerId = "_scheduler";
700
732
 
701
733
  // safely check navigator and get the hardware spec value
702
- export function getDeviceSpec() {
734
+ export function getDeviceSpec(): {
735
+ deviceMemory?: number | undefined;
736
+ hardwareConcurrency?: number | undefined;
737
+ } {
703
738
  try {
704
739
  if (typeof navigator === "object" && navigator !== null) {
705
740
  return {
741
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
706
742
  deviceMemory: (navigator as any).deviceMemory,
707
743
  hardwareConcurrency: navigator.hardwareConcurrency,
708
744
  };
709
745
  }
710
- } catch {}
746
+ } catch {
747
+ // Eat the error
748
+ }
711
749
  return {};
712
750
  }
713
751
 
@@ -718,10 +756,15 @@ export function getDeviceSpec() {
718
756
  */
719
757
  export const makeLegacySendBatchFn =
720
758
  (
721
- submitFn: (type: MessageType, contents: any, batch: boolean, appData?: any) => number,
759
+ submitFn: (
760
+ type: MessageType,
761
+ contents: unknown,
762
+ batch: boolean,
763
+ appData?: unknown,
764
+ ) => number,
722
765
  deltaManager: Pick<IDeltaManager<unknown, unknown>, "flush">,
723
766
  ) =>
724
- (batch: IBatch) => {
767
+ (batch: IBatch): number => {
725
768
  // Default to negative one to match Container.submitBatch behavior
726
769
  let clientSequenceNumber: number = -1;
727
770
  for (const message of batch.messages) {
@@ -763,16 +806,18 @@ async function createSummarizer(loader: ILoader, url: string): Promise<ISummariz
763
806
 
764
807
  // Older containers may not have the "getEntryPoint" API
765
808
  // ! This check will need to stay until LTS of loader moves past 2.0.0-internal.7.0.0
766
- if (resolvedContainer.getEntryPoint !== undefined) {
767
- fluidObject = await resolvedContainer.getEntryPoint();
768
- } else {
769
- const response = await (resolvedContainer as any).request({
809
+ if (resolvedContainer.getEntryPoint === undefined) {
810
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
811
+ const response = (await (resolvedContainer as any).request({
770
812
  url: `/${summarizerRequestUrl}`,
771
- });
813
+ })) as IResponse;
772
814
  if (response.status !== 200 || response.mimeType !== "fluid/object") {
773
815
  throw responseToException(response, request);
774
816
  }
817
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
775
818
  fluidObject = response.value;
819
+ } else {
820
+ fluidObject = await resolvedContainer.getEntryPoint();
776
821
  }
777
822
 
778
823
  if (fluidObject?.ISummarizer === undefined) {
@@ -787,7 +832,11 @@ async function createSummarizer(loader: ILoader, url: string): Promise<ISummariz
787
832
  * This allows new runtime to make documents not openable for old runtimes, one explicit document schema control is enabled.
788
833
  * Please see addMetadataToSummary() as well
789
834
  */
790
- function lastMessageFromMetadata(metadata: IContainerRuntimeMetadata | undefined) {
835
+ function lastMessageFromMetadata(
836
+ // eslint-disable-next-line import/no-deprecated
837
+ metadata: IContainerRuntimeMetadata | undefined,
838
+ // eslint-disable-next-line import/no-deprecated
839
+ ): ISummaryMetadataMessage | undefined {
791
840
  return metadata?.documentSchema?.runtime?.explicitSchemaControl
792
841
  ? metadata?.lastMessage
793
842
  : metadata?.message;
@@ -799,13 +848,14 @@ function lastMessageFromMetadata(metadata: IContainerRuntimeMetadata | undefined
799
848
  * We only want to log this once, to avoid spamming telemetry if we are wrong and these cases are hit commonly.
800
849
  */
801
850
  export let getSingleUseLegacyLogCallback = (logger: ITelemetryLoggerExt, type: string) => {
802
- return (codePath: string) => {
851
+ return (codePath: string): void => {
803
852
  logger.sendTelemetryEvent({
804
853
  eventName: "LegacyMessageFormat",
805
854
  details: { codePath, type },
806
855
  });
807
856
 
808
857
  // Now that we've logged, prevent future logging (globally).
858
+ // eslint-disable-next-line unicorn/consistent-function-scoping
809
859
  getSingleUseLegacyLogCallback = () => () => {};
810
860
  };
811
861
  };
@@ -861,24 +911,27 @@ export async function loadContainerRuntime(
861
911
  return ContainerRuntime.loadRuntime(params);
862
912
  }
863
913
 
914
+ const defaultMaxConsecutiveReconnects = 7;
915
+
916
+ const defaultTelemetrySignalSampleCount = 100;
917
+
864
918
  /**
865
919
  * Represents the runtime of the container. Contains helper functions/state of the container.
866
920
  * It will define the store level mappings.
867
921
  *
868
- * @deprecated To be removed from the Legacy-Alpha API in version 2.20.0.
869
- * Use the loadContainerRuntime function and interfaces IContainerRuntime / IRuntime instead.
870
- *
871
- * @legacy
872
- * @alpha
922
+ * @internal
873
923
  */
874
924
  export class ContainerRuntime
875
925
  extends TypedEventEmitter<IContainerRuntimeEvents>
876
926
  implements
877
927
  IContainerRuntime,
878
928
  IRuntime,
929
+ // eslint-disable-next-line import/no-deprecated
879
930
  ISummarizerRuntime,
931
+ // eslint-disable-next-line import/no-deprecated
880
932
  ISummarizerInternalsProvider,
881
- IProvideFluidHandleContext
933
+ IProvideFluidHandleContext,
934
+ IProvideLayerCompatDetails
882
935
  {
883
936
  /**
884
937
  * Load the stores from a snapshot and returns the runtime.
@@ -902,7 +955,9 @@ export class ContainerRuntime
902
955
  runtimeOptions?: IContainerRuntimeOptions; // May also include options from IContainerRuntimeOptionsInternal
903
956
  containerScope?: FluidObject;
904
957
  containerRuntimeCtor?: typeof ContainerRuntime;
905
- /** @deprecated Will be removed once Loader LTS version is "2.0.0-internal.7.0.0". Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md */
958
+ /**
959
+ * @deprecated Will be removed once Loader LTS version is "2.0.0-internal.7.0.0". Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
960
+ */
906
961
  requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;
907
962
  provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;
908
963
  }): Promise<ContainerRuntime> {
@@ -940,7 +995,9 @@ export class ContainerRuntime
940
995
  gcOptions = {},
941
996
  loadSequenceNumberVerification = "close",
942
997
  flushMode = defaultFlushMode,
943
- compressionOptions = defaultCompressionConfig,
998
+ compressionOptions = runtimeOptions.enableGroupedBatching === false
999
+ ? disabledCompressionConfig // Compression must be disabled if Grouping is disabled
1000
+ : defaultCompressionConfig,
944
1001
  maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
945
1002
  enableRuntimeIdCompressor,
946
1003
  chunkSizeInBytes = defaultChunkSizeInBytes,
@@ -975,7 +1032,9 @@ export class ContainerRuntime
975
1032
  tryFetchBlob<ReturnType<DuplicateBatchDetector["getRecentBatchInfoForSummary"]>>(
976
1033
  recentBatchInfoBlobName,
977
1034
  ),
1035
+ // eslint-disable-next-line import/no-deprecated
978
1036
  tryFetchBlob<IContainerRuntimeMetadata>(metadataBlobName),
1037
+ // eslint-disable-next-line import/no-deprecated
979
1038
  tryFetchBlob<ISerializedElection>(electedSummarizerBlobName),
980
1039
  tryFetchBlob<[string, string][]>(aliasBlobName),
981
1040
  tryFetchBlob<SerializedIdCompressorWithNoSession>(idCompressorBlobName),
@@ -992,6 +1051,7 @@ export class ContainerRuntime
992
1051
  // When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
993
1052
  if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
994
1053
  // Unless bypass is explicitly set, then take action when sequence numbers mismatch.
1054
+ // eslint-disable-next-line unicorn/no-lonely-if -- Separate if statements make flow easier to parse
995
1055
  if (
996
1056
  loadSequenceNumberVerification !== "bypass" &&
997
1057
  runtimeSequenceNumber !== protocolSequenceNumber
@@ -1020,15 +1080,18 @@ export class ContainerRuntime
1020
1080
 
1021
1081
  let desiredIdCompressorMode: IdCompressorMode;
1022
1082
  switch (mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) {
1023
- case true:
1083
+ case true: {
1024
1084
  desiredIdCompressorMode = "on";
1025
1085
  break;
1026
- case false:
1086
+ }
1087
+ case false: {
1027
1088
  desiredIdCompressorMode = undefined;
1028
1089
  break;
1029
- default:
1090
+ }
1091
+ default: {
1030
1092
  desiredIdCompressorMode = enableRuntimeIdCompressor;
1031
1093
  break;
1094
+ }
1032
1095
  }
1033
1096
 
1034
1097
  // Enabling the IdCompressor is a one-way operation and we only want to
@@ -1066,7 +1129,7 @@ export class ContainerRuntime
1066
1129
  idCompressorMode = desiredIdCompressorMode;
1067
1130
  }
1068
1131
 
1069
- const createIdCompressorFn = async () => {
1132
+ const createIdCompressorFn = async (): Promise<IIdCompressor & IIdCompressorCore> => {
1070
1133
  const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import(
1071
1134
  "@fluidframework/id-compressor/internal"
1072
1135
  );
@@ -1092,21 +1155,22 @@ export class ContainerRuntime
1092
1155
  pendingLocalState.pendingIdCompressorState,
1093
1156
  compressorLogger,
1094
1157
  );
1095
- } else if (serializedIdCompressor !== undefined) {
1158
+ } else if (serializedIdCompressor === undefined) {
1159
+ return createIdCompressor(compressorLogger);
1160
+ } else {
1096
1161
  return deserializeIdCompressor(
1097
1162
  serializedIdCompressor,
1098
1163
  createSessionId(),
1099
1164
  compressorLogger,
1100
1165
  );
1101
- } else {
1102
- return createIdCompressor(compressorLogger);
1103
1166
  }
1104
1167
  };
1105
1168
 
1106
1169
  const compressionLz4 =
1107
- compressionOptions.minimumBatchSizeInBytes !== Infinity &&
1170
+ compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY &&
1108
1171
  compressionOptions.compressionAlgorithm === "lz4";
1109
1172
 
1173
+ // eslint-disable-next-line import/no-deprecated
1110
1174
  const documentSchemaController = new DocumentsSchemaController(
1111
1175
  existing,
1112
1176
  protocolSequenceNumber,
@@ -1123,6 +1187,10 @@ export class ContainerRuntime
1123
1187
  },
1124
1188
  );
1125
1189
 
1190
+ if (compressionLz4 && !enableGroupedBatching) {
1191
+ throw new UsageError("If compression is enabled, op grouping must be enabled too");
1192
+ }
1193
+
1126
1194
  const featureGatesForTelemetry: Record<string, boolean | number | undefined> = {};
1127
1195
 
1128
1196
  // Make sure we've got all the options including internal ones
@@ -1170,7 +1238,7 @@ export class ContainerRuntime
1170
1238
  runtime.setConnectionStateCore(true, runtime.delayConnectClientId);
1171
1239
  }
1172
1240
  },
1173
- (error) => runtime.closeFn(error),
1241
+ (error: IErrorBase) => runtime.closeFn(error),
1174
1242
  );
1175
1243
 
1176
1244
  // Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
@@ -1183,7 +1251,7 @@ export class ContainerRuntime
1183
1251
  return runtime;
1184
1252
  }
1185
1253
 
1186
- public readonly options: Record<string | number, any>;
1254
+ public readonly options: Record<string | number, unknown>;
1187
1255
  private imminentClosure: boolean = false;
1188
1256
 
1189
1257
  private readonly _getClientId: () => string | undefined;
@@ -1197,22 +1265,10 @@ export class ContainerRuntime
1197
1265
  return this._storage;
1198
1266
  }
1199
1267
 
1200
- public get containerRuntime() {
1268
+ public get containerRuntime(): ContainerRuntime {
1201
1269
  return this;
1202
1270
  }
1203
1271
 
1204
- private readonly submitFn: (
1205
- type: MessageType,
1206
- contents: any,
1207
- batch: boolean,
1208
- appData?: any,
1209
- ) => number;
1210
- /**
1211
- * Although current IContainerContext guarantees submitBatchFn, it is not available on older loaders.
1212
- */
1213
- private readonly submitBatchFn:
1214
- | ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)
1215
- | undefined;
1216
1272
  private readonly submitSummaryFn: (
1217
1273
  summaryOp: ISummaryContent,
1218
1274
  referenceSequenceNumber?: number,
@@ -1249,9 +1305,15 @@ export class ContainerRuntime
1249
1305
  * has to deal with compressed ops as other clients might send them.
1250
1306
  * And in reverse, session schema can have compression Off, but feature gates / runtime options want it On.
1251
1307
  * In such case it will be off in session schema, however this client will propose change to schema, and once / if
1252
- * this op rountrips, compression will be On. Client can't send compressed ops until it's change in schema.
1308
+ * this op roundtrips, compression will be On. Client can't send compressed ops until it's change in schema.
1253
1309
  */
1254
- public get sessionSchema() {
1310
+ public get sessionSchema(): {
1311
+ // eslint-disable-next-line import/no-deprecated
1312
+ [P in keyof IDocumentSchemaFeatures]?: IDocumentSchemaFeatures[P] extends boolean
1313
+ ? true
1314
+ : // eslint-disable-next-line import/no-deprecated
1315
+ IDocumentSchemaFeatures[P];
1316
+ } {
1255
1317
  return this.documentsSchemaController.sessionSchema.runtime;
1256
1318
  }
1257
1319
 
@@ -1267,18 +1329,15 @@ export class ContainerRuntime
1267
1329
  // In such case we have to process all ops, including those marked with savedOp === true.
1268
1330
  private readonly skipSavedCompressorOps: boolean;
1269
1331
 
1270
- public get idCompressorMode() {
1271
- return this.sessionSchema.idCompressorMode;
1272
- }
1273
1332
  /**
1274
- * See IContainerRuntimeBase.idCompressor() for details.
1333
+ * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor}
1275
1334
  */
1276
- public get idCompressor() {
1335
+ public get idCompressor(): (IIdCompressor & IIdCompressorCore) | undefined {
1277
1336
  // Expose ID Compressor only if it's On from the start.
1278
1337
  // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
1279
1338
  // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
1280
1339
  // to reason over such things as session ID space.
1281
- if (this.idCompressorMode === "on") {
1340
+ if (this.sessionSchema.idCompressorMode === "on") {
1282
1341
  assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
1283
1342
  return this._idCompressor;
1284
1343
  }
@@ -1286,14 +1345,14 @@ export class ContainerRuntime
1286
1345
 
1287
1346
  /**
1288
1347
  * True if we have ID compressor loading in-flight (async operation). Useful only for
1289
- * this.idCompressorMode === "delayed" mode
1348
+ * this.sessionSchema.idCompressorMode === "delayed" mode
1290
1349
  */
1291
1350
  protected _loadIdCompressor: Promise<void> | undefined;
1292
1351
 
1293
1352
  /**
1294
- * See IContainerRuntimeBase.generateDocumentUniqueId() for details.
1353
+ * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.generateDocumentUniqueId}
1295
1354
  */
1296
- public generateDocumentUniqueId() {
1355
+ public generateDocumentUniqueId(): string | number {
1297
1356
  return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
1298
1357
  }
1299
1358
 
@@ -1330,14 +1389,10 @@ export class ContainerRuntime
1330
1389
  * do not create it (see SummarizerClientElection.clientDetailsPermitElection() for details)
1331
1390
  */
1332
1391
  private readonly summaryManager?: SummaryManager;
1333
- private readonly summaryCollection: SummaryCollection;
1334
1392
 
1335
1393
  private readonly summarizerNode: IRootSummarizerNodeWithGC;
1336
1394
 
1337
- private readonly logger: ITelemetryLoggerExt;
1338
-
1339
1395
  private readonly maxConsecutiveReconnects: number;
1340
- private readonly defaultMaxConsecutiveReconnects = 7;
1341
1396
 
1342
1397
  private _orderSequentiallyCalls: number = 0;
1343
1398
  private readonly _flushMode: FlushMode;
@@ -1377,22 +1432,22 @@ export class ContainerRuntime
1377
1432
  return this._connected;
1378
1433
  }
1379
1434
 
1380
- /** clientId of parent (non-summarizing) container that owns summarizer container */
1435
+ /**
1436
+ * clientId of parent (non-summarizing) container that owns summarizer container
1437
+ */
1381
1438
  public get summarizerClientId(): string | undefined {
1382
1439
  return this.summarizerClientElection?.electedClientId;
1383
1440
  }
1384
1441
 
1385
1442
  private _disposed = false;
1386
- public get disposed() {
1443
+ public get disposed(): boolean {
1387
1444
  return this._disposed;
1388
1445
  }
1389
1446
 
1390
1447
  private dirtyContainer: boolean;
1391
1448
  private emitDirtyDocumentEvent = true;
1392
- private readonly disableAttachReorder: boolean | undefined;
1393
1449
  private readonly useDeltaManagerOpsProxy: boolean;
1394
1450
  private readonly closeSummarizerDelayMs: number;
1395
- private readonly defaultTelemetrySignalSampleCount = 100;
1396
1451
  private readonly _signalTracking: IPerfSignalReport = {
1397
1452
  totalSignalsSentInLatencyWindow: 0,
1398
1453
  signalsLost: 0,
@@ -1410,8 +1465,10 @@ export class ContainerRuntime
1410
1465
  * It is the main entry point for summary work.
1411
1466
  * It is created only by summarizing container (i.e. one with clientType === "summarizer")
1412
1467
  */
1468
+ // eslint-disable-next-line import/no-deprecated
1413
1469
  private readonly _summarizer?: Summarizer;
1414
- private readonly scheduleManager: ScheduleManager;
1470
+ private readonly deltaScheduler: DeltaScheduler;
1471
+ private readonly inboundBatchAggregator: InboundBatchAggregator;
1415
1472
  private readonly blobManager: BlobManager;
1416
1473
  private readonly pendingStateManager: PendingStateManager;
1417
1474
  private readonly duplicateBatchDetector: DuplicateBatchDetector | undefined;
@@ -1421,38 +1478,15 @@ export class ContainerRuntime
1421
1478
  private readonly channelCollection: ChannelCollection;
1422
1479
  private readonly remoteMessageProcessor: RemoteMessageProcessor;
1423
1480
 
1424
- /** The last message processed at the time of the last summary. */
1481
+ /**
1482
+ * The last message processed at the time of the last summary.
1483
+ */
1484
+ // eslint-disable-next-line import/no-deprecated
1425
1485
  private messageAtLastSummary: ISummaryMetadataMessage | undefined;
1426
1486
 
1427
- private get summarizer(): Summarizer {
1428
- assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
1429
- return this._summarizer;
1430
- }
1431
-
1432
1487
  private readonly summariesDisabled: boolean;
1433
- private isSummariesDisabled(): boolean {
1434
- return this.summaryConfiguration.state === "disabled";
1435
- }
1436
-
1437
- private readonly maxOpsSinceLastSummary: number;
1438
- private getMaxOpsSinceLastSummary(): number {
1439
- return this.summaryConfiguration.state !== "disabled"
1440
- ? this.summaryConfiguration.maxOpsSinceLastSummary
1441
- : 0;
1442
- }
1443
-
1444
- private readonly initialSummarizerDelayMs: number;
1445
- private getInitialSummarizerDelayMs(): number {
1446
- // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
1447
- // to ISummaryConfiguration in 0.60.
1448
- if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
1449
- return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
1450
- }
1451
- return this.summaryConfiguration.state !== "disabled"
1452
- ? this.summaryConfiguration.initialSummarizerDelayMs
1453
- : 0;
1454
- }
1455
1488
 
1489
+ // eslint-disable-next-line import/no-deprecated
1456
1490
  private readonly createContainerMetadata: ICreateContainerMetadata;
1457
1491
  /**
1458
1492
  * The summary number of the next summary that will be generated for this container. This is incremented every time
@@ -1484,11 +1518,6 @@ export class ContainerRuntime
1484
1518
  */
1485
1519
  private readonly telemetryDocumentId: string;
1486
1520
 
1487
- /**
1488
- * Whether this client is the summarizer client itself (type is summarizerClientType)
1489
- */
1490
- private readonly isSummarizerClient: boolean;
1491
-
1492
1521
  /**
1493
1522
  * The id of the version used to initially load this runtime, or undefined if it's newly created.
1494
1523
  */
@@ -1509,30 +1538,30 @@ export class ContainerRuntime
1509
1538
  expiry: { policy: "absolute", durationMs: 60000 },
1510
1539
  });
1511
1540
 
1512
- /**
1513
- * The options to apply to this ContainerRuntime instance (including internal options hidden from the public API)
1514
- */
1515
- private readonly runtimeOptions: Readonly<Required<IContainerRuntimeOptionsInternal>>;
1541
+ public get ILayerCompatDetails(): ILayerCompatDetails {
1542
+ return RuntimeCompatDetails;
1543
+ }
1516
1544
 
1517
1545
  /***/
1518
1546
  protected constructor(
1519
1547
  context: IContainerContext,
1520
1548
  private readonly registry: IFluidDataStoreRegistry,
1549
+ // eslint-disable-next-line import/no-deprecated
1521
1550
  private readonly metadata: IContainerRuntimeMetadata | undefined,
1551
+ // eslint-disable-next-line import/no-deprecated
1522
1552
  electedSummarizerData: ISerializedElection | undefined,
1523
1553
  chunks: [string, string[]][],
1524
1554
  dataStoreAliasMap: [string, string][],
1525
- runtimeOptions: Readonly<
1526
- Required<Omit<IContainerRuntimeOptions, "flushMode" | "enableGroupedBatching">> &
1527
- IContainerRuntimeOptions // Let flushMode and enabledGroupedBatching be optional now since they're soon to be removed
1528
- >,
1555
+ baseRuntimeOptions: Readonly<Required<IContainerRuntimeOptions>>,
1529
1556
  private readonly containerScope: FluidObject,
1530
1557
  // Create a custom ITelemetryBaseLogger to output telemetry events.
1531
1558
  public readonly baseLogger: ITelemetryBaseLogger,
1532
1559
  existing: boolean,
1560
+ // eslint-disable-next-line import/no-deprecated
1533
1561
  blobManagerSnapshot: IBlobManagerLoadInfo,
1534
1562
  private readonly _storage: IDocumentStorageService,
1535
1563
  private readonly createIdCompressor: () => Promise<IIdCompressor & IIdCompressorCore>,
1564
+ // eslint-disable-next-line import/no-deprecated
1536
1565
  private readonly documentsSchemaController: DocumentsSchemaController,
1537
1566
  featureGatesForTelemetry: Record<string, boolean | number | undefined>,
1538
1567
  provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
@@ -1540,11 +1569,12 @@ export class ContainerRuntime
1540
1569
  request: IRequest,
1541
1570
  runtime: IContainerRuntime,
1542
1571
  ) => Promise<IResponse>,
1543
- private readonly summaryConfiguration: ISummaryConfiguration = {
1572
+ // eslint-disable-next-line unicorn/no-object-as-default-parameter
1573
+ summaryConfiguration: ISummaryConfiguration = {
1544
1574
  // the defaults
1545
1575
  ...DefaultSummaryConfiguration,
1546
1576
  // the runtime configuration overrides
1547
- ...runtimeOptions.summaryOptions?.summaryConfigOverrides,
1577
+ ...baseRuntimeOptions.summaryOptions?.summaryConfigOverrides,
1548
1578
  },
1549
1579
  recentBatchInfo?: [number, string][],
1550
1580
  ) {
@@ -1570,15 +1600,19 @@ export class ContainerRuntime
1570
1600
  snapshotWithContents,
1571
1601
  } = context;
1572
1602
 
1603
+ // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
1604
+ this.disposeFn = disposeFn ?? closeFn;
1605
+
1606
+ const maybeLoaderCompatDetails = context as FluidObject<ILayerCompatDetails>;
1607
+ validateLoaderCompatibility(maybeLoaderCompatDetails.ILayerCompatDetails, this.disposeFn);
1608
+
1573
1609
  // Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
1574
- this.runtimeOptions = {
1610
+ const runtimeOptions = {
1575
1611
  flushMode: defaultFlushMode,
1576
- enableGroupedBatching: true,
1577
- ...runtimeOptions,
1612
+ ...baseRuntimeOptions,
1578
1613
  };
1579
- this.logger = createChildLogger({ logger: this.baseLogger });
1580
1614
  this.mc = createChildMonitoringContext({
1581
- logger: this.logger,
1615
+ logger: this.baseLogger,
1582
1616
  namespace: "ContainerRuntime",
1583
1617
  });
1584
1618
 
@@ -1598,20 +1632,24 @@ export class ContainerRuntime
1598
1632
 
1599
1633
  // Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
1600
1634
  // This makes ContainerRuntime the final gatekeeper for outgoing messages.
1601
- this.submitFn = submitFn;
1602
- this.submitBatchFn = submitBatchFn;
1603
- this.submitSummaryFn = submitSummaryFn;
1635
+ // back-compat: ADO #1385: Make this call unconditional in the future
1636
+ this.submitSummaryFn =
1637
+ submitSummaryFn ??
1638
+ ((summaryOp, refseq) => submitFn(MessageType.Summarize, summaryOp, false));
1604
1639
  this.submitSignalFn = submitSignalFn;
1605
1640
 
1606
1641
  // TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
1607
1642
  // Values are generally expected to be set from the runtime side.
1608
1643
  this.options = options ?? {};
1609
1644
  this.clientDetails = clientDetails;
1610
- this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
1645
+ const isSummarizerClient = this.clientDetails.type === summarizerClientType;
1611
1646
  this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
1647
+ // eslint-disable-next-line unicorn/consistent-destructuring
1612
1648
  this._getClientId = () => context.clientId;
1649
+ // eslint-disable-next-line unicorn/consistent-destructuring
1613
1650
  this._getAttachState = () => context.attachState;
1614
1651
  this.getAbsoluteUrl = async (relativeUrl: string) => {
1652
+ // eslint-disable-next-line unicorn/consistent-destructuring
1615
1653
  if (context.getAbsoluteUrl === undefined) {
1616
1654
  throw new Error("Driver does not implement getAbsoluteUrl");
1617
1655
  }
@@ -1625,10 +1663,8 @@ export class ContainerRuntime
1625
1663
  this.on("dirty", () => context.updateDirtyContainerState(true));
1626
1664
  this.on("saved", () => context.updateDirtyContainerState(false));
1627
1665
 
1628
- // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
1629
- this.disposeFn = disposeFn ?? closeFn;
1630
1666
  // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
1631
- this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
1667
+ this.closeFn = isSummarizerClient ? this.disposeFn : closeFn;
1632
1668
 
1633
1669
  let loadSummaryNumber: number;
1634
1670
  // Get the container creation metadata. For new container, we initialize these. For existing containers,
@@ -1660,31 +1696,23 @@ export class ContainerRuntime
1660
1696
  eventName: "GCFeatureMatrix",
1661
1697
  metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
1662
1698
  inputs: JSON.stringify({
1663
- gcOptions_gcGeneration: this.runtimeOptions.gcOptions[gcGenerationOptionName],
1699
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1700
+ gcOptions_gcGeneration: runtimeOptions.gcOptions[gcGenerationOptionName],
1664
1701
  }),
1665
1702
  });
1666
1703
 
1667
1704
  this.telemetryDocumentId = metadata?.telemetryDocumentId ?? uuid();
1668
1705
 
1669
- this.disableAttachReorder = this.mc.config.getBoolean(
1670
- "Fluid.ContainerRuntime.disableAttachOpReorder",
1671
- );
1672
-
1673
1706
  const opGroupingManager = new OpGroupingManager(
1674
1707
  {
1675
1708
  groupedBatchingEnabled: this.groupedBatchingEnabled,
1676
- opCountThreshold:
1677
- this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
1678
- reentrantBatchGroupingEnabled:
1679
- this.mc.config.getBoolean("Fluid.ContainerRuntime.GroupedBatchingReentrancy") ??
1680
- true,
1681
1709
  },
1682
1710
  this.mc.logger,
1683
1711
  );
1684
1712
 
1685
1713
  const opSplitter = new OpSplitter(
1686
1714
  chunks,
1687
- this.submitBatchFn,
1715
+ submitBatchFn,
1688
1716
  runtimeOptions.chunkSizeInBytes,
1689
1717
  runtimeOptions.maxBatchSizeInBytes,
1690
1718
  this.mc.logger,
@@ -1707,7 +1735,7 @@ export class ContainerRuntime
1707
1735
  isAttached: () => this.attachState !== AttachState.Detached,
1708
1736
  },
1709
1737
  pendingRuntimeState?.pending,
1710
- this.logger,
1738
+ this.baseLogger,
1711
1739
  );
1712
1740
 
1713
1741
  let outerDeltaManager: IDeltaManagerFull;
@@ -1733,28 +1761,42 @@ export class ContainerRuntime
1733
1761
 
1734
1762
  this.handleContext = new ContainerFluidHandleContext("", this);
1735
1763
 
1736
- if (this.summaryConfiguration.state === "enabled") {
1737
- this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
1764
+ if (summaryConfiguration.state === "enabled") {
1765
+ this.validateSummaryHeuristicConfiguration(summaryConfiguration);
1738
1766
  }
1739
1767
 
1740
- this.summariesDisabled = this.isSummariesDisabled();
1741
- this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
1742
- this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
1768
+ this.summariesDisabled = isSummariesDisabled(summaryConfiguration);
1769
+ const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = isSummariesDisabled(
1770
+ summaryConfiguration,
1771
+ )
1772
+ ? {}
1773
+ : {
1774
+ ...summaryConfiguration,
1775
+ initialSummarizerDelayMs:
1776
+ // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
1777
+ // to ISummaryConfiguration in 0.60.
1778
+ runtimeOptions.summaryOptions.initialSummarizerDelayMs ??
1779
+ summaryConfiguration.initialSummarizerDelayMs,
1780
+ };
1743
1781
 
1744
1782
  this.maxConsecutiveReconnects =
1745
- this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
1746
- this.defaultMaxConsecutiveReconnects;
1747
-
1783
+ this.mc.config.getNumber(maxConsecutiveReconnectsKey) ?? defaultMaxConsecutiveReconnects;
1784
+
1785
+ // If the context has ILayerCompatDetails, it supports referenceSequenceNumbers since that features
1786
+ // predates ILayerCompatDetails.
1787
+ const referenceSequenceNumbersSupported =
1788
+ maybeLoaderCompatDetails.ILayerCompatDetails === undefined
1789
+ ? supportedFeatures?.get("referenceSequenceNumbers") === true
1790
+ : true;
1748
1791
  if (
1749
- this.runtimeOptions.flushMode ===
1750
- (FlushModeExperimental.Async as unknown as FlushMode) &&
1751
- supportedFeatures?.get("referenceSequenceNumbers") !== true
1792
+ runtimeOptions.flushMode === (FlushModeExperimental.Async as unknown as FlushMode) &&
1793
+ !referenceSequenceNumbersSupported
1752
1794
  ) {
1753
1795
  // The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
1754
1796
  this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
1755
1797
  this._flushMode = FlushMode.TurnBased;
1756
1798
  } else {
1757
- this._flushMode = this.runtimeOptions.flushMode;
1799
+ this._flushMode = runtimeOptions.flushMode;
1758
1800
  }
1759
1801
  this.offlineEnabled =
1760
1802
  this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
@@ -1772,6 +1814,7 @@ export class ContainerRuntime
1772
1814
  this.duplicateBatchDetector = new DuplicateBatchDetector(recentBatchInfo);
1773
1815
  }
1774
1816
 
1817
+ // eslint-disable-next-line unicorn/consistent-destructuring
1775
1818
  if (context.attachState === AttachState.Attached) {
1776
1819
  const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
1777
1820
  if (
@@ -1787,13 +1830,13 @@ export class ContainerRuntime
1787
1830
 
1788
1831
  this.garbageCollector = GarbageCollector.create({
1789
1832
  runtime: this,
1790
- gcOptions: this.runtimeOptions.gcOptions,
1833
+ gcOptions: runtimeOptions.gcOptions,
1791
1834
  baseSnapshot,
1792
1835
  baseLogger: this.mc.logger,
1793
1836
  existing,
1794
1837
  metadata,
1795
1838
  createContainerMetadata: this.createContainerMetadata,
1796
- isSummarizerClient: this.isSummarizerClient,
1839
+ isSummarizerClient,
1797
1840
  getNodePackagePath: async (nodePath: string) => this.getGCNodePackagePath(nodePath),
1798
1841
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
1799
1842
  readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
@@ -1810,7 +1853,7 @@ export class ContainerRuntime
1810
1853
  ? undefined
1811
1854
  : loadedFromSequenceNumber;
1812
1855
  this.summarizerNode = createRootSummarizerNodeWithGC(
1813
- createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
1856
+ createChildLogger({ logger: this.baseLogger, namespace: "SummarizerNode" }),
1814
1857
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
1815
1858
  async (fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext) =>
1816
1859
  this.summarizeInternal(fullTree, trackState, telemetryContext),
@@ -1902,23 +1945,28 @@ export class ContainerRuntime
1902
1945
  closeContainer: (error?: ICriticalContainerError) => this.closeFn(error),
1903
1946
  });
1904
1947
 
1905
- this.scheduleManager = new ScheduleManager(
1948
+ this.deltaScheduler = new DeltaScheduler(
1906
1949
  this.innerDeltaManager,
1907
1950
  this,
1951
+ createChildLogger({ logger: this.baseLogger, namespace: "DeltaScheduler" }),
1952
+ );
1953
+
1954
+ this.inboundBatchAggregator = new InboundBatchAggregator(
1955
+ this.innerDeltaManager,
1908
1956
  () => this.clientId,
1909
- createChildLogger({ logger: this.logger, namespace: "ScheduleManager" }),
1957
+ createChildLogger({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }),
1910
1958
  );
1911
1959
 
1912
1960
  const disablePartialFlush = this.mc.config.getBoolean(
1913
1961
  "Fluid.ContainerRuntime.DisablePartialFlush",
1914
1962
  );
1915
1963
 
1916
- const legacySendBatchFn = makeLegacySendBatchFn(this.submitFn, this.innerDeltaManager);
1964
+ const legacySendBatchFn = makeLegacySendBatchFn(submitFn, this.innerDeltaManager);
1917
1965
 
1918
1966
  this.outbox = new Outbox({
1919
1967
  shouldSend: () => this.canSendOps(),
1920
1968
  pendingStateManager: this.pendingStateManager,
1921
- submitBatchFn: this.submitBatchFn,
1969
+ submitBatchFn,
1922
1970
  legacySendBatchFn,
1923
1971
  compressor: new OpCompressor(this.mc.logger),
1924
1972
  splitter: opSplitter,
@@ -1975,7 +2023,7 @@ export class ContainerRuntime
1975
2023
  );
1976
2024
  this.closeSummarizerDelayMs =
1977
2025
  closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
1978
- this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
2026
+ const summaryCollection = new SummaryCollection(this.deltaManager, this.baseLogger);
1979
2027
 
1980
2028
  this.dirtyContainer =
1981
2029
  this.attachState !== AttachState.Attached || this.hasPendingMessages();
@@ -1985,7 +2033,7 @@ export class ContainerRuntime
1985
2033
  this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
1986
2034
  } else {
1987
2035
  const orderedClientLogger = createChildLogger({
1988
- logger: this.logger,
2036
+ logger: this.baseLogger,
1989
2037
  namespace: "OrderedClientElection",
1990
2038
  });
1991
2039
  const orderedClientCollection = new OrderedClientCollection(
@@ -2005,18 +2053,20 @@ export class ContainerRuntime
2005
2053
 
2006
2054
  this.summarizerClientElection = new SummarizerClientElection(
2007
2055
  orderedClientLogger,
2008
- this.summaryCollection,
2056
+ summaryCollection,
2009
2057
  orderedClientElectionForSummarizer,
2010
- this.maxOpsSinceLastSummary,
2058
+ maxOpsSinceLastSummary,
2011
2059
  );
2012
2060
 
2013
- if (this.isSummarizerClient) {
2061
+ if (isSummarizerClient) {
2062
+ // eslint-disable-next-line import/no-deprecated
2014
2063
  this._summarizer = new Summarizer(
2015
2064
  this /* ISummarizerRuntime */,
2016
- () => this.summaryConfiguration,
2065
+ () => summaryConfiguration,
2017
2066
  this /* ISummarizerInternalsProvider */,
2018
2067
  this.handleContext,
2019
- this.summaryCollection,
2068
+ summaryCollection,
2069
+ // eslint-disable-next-line import/no-deprecated
2020
2070
  async (runtime: IConnectableRuntime) =>
2021
2071
  RunWhileConnectedCoordinator.create(
2022
2072
  runtime,
@@ -2028,32 +2078,32 @@ export class ContainerRuntime
2028
2078
  } else if (SummarizerClientElection.clientDetailsPermitElection(this.clientDetails)) {
2029
2079
  // Only create a SummaryManager and SummarizerClientElection
2030
2080
  // if summaries are enabled and we are not the summarizer client.
2031
- const defaultAction = () => {
2032
- if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
2081
+ const defaultAction = (): void => {
2082
+ if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
2033
2083
  this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
2034
2084
  // unregister default to no log on every op after falling behind
2035
2085
  // and register summary ack handler to re-register this handler
2036
2086
  // after successful summary
2037
- this.summaryCollection.once(MessageType.SummaryAck, () => {
2087
+ summaryCollection.once(MessageType.SummaryAck, () => {
2038
2088
  this.mc.logger.sendTelemetryEvent({
2039
2089
  eventName: "SummaryStatus:CaughtUp",
2040
2090
  });
2041
2091
  // we've caught up, so re-register the default action to monitor for
2042
2092
  // falling behind, and unregister ourself
2043
- this.summaryCollection.on("default", defaultAction);
2093
+ summaryCollection.on("default", defaultAction);
2044
2094
  });
2045
- this.summaryCollection.off("default", defaultAction);
2095
+ summaryCollection.off("default", defaultAction);
2046
2096
  }
2047
2097
  };
2048
2098
 
2049
- this.summaryCollection.on("default", defaultAction);
2099
+ summaryCollection.on("default", defaultAction);
2050
2100
 
2051
2101
  // Create the SummaryManager and mark the initial state
2052
2102
  this.summaryManager = new SummaryManager(
2053
2103
  this.summarizerClientElection,
2054
2104
  this, // IConnectedState
2055
- this.summaryCollection,
2056
- this.logger,
2105
+ summaryCollection,
2106
+ this.baseLogger,
2057
2107
  this.formCreateSummarizerFn(loader),
2058
2108
  new Throttler(
2059
2109
  60 * 1000, // 60 sec delay window
@@ -2062,28 +2112,29 @@ export class ContainerRuntime
2062
2112
  formExponentialFn({ coefficient: 20, initialDelay: 0 }),
2063
2113
  ),
2064
2114
  {
2065
- initialDelayMs: this.initialSummarizerDelayMs,
2115
+ initialDelayMs: initialSummarizerDelayMs,
2066
2116
  },
2067
2117
  );
2068
2118
  // Forward events from SummaryManager
2069
- [
2119
+ for (const eventName of [
2070
2120
  "summarize",
2071
2121
  "summarizeAllAttemptsFailed",
2072
2122
  "summarizerStop",
2073
2123
  "summarizerStart",
2074
2124
  "summarizerStartupFailed",
2075
- ].forEach((eventName) => {
2076
- this.summaryManager?.on(eventName, (...args: any[]) => {
2125
+ ]) {
2126
+ this.summaryManager?.on(eventName, (...args: unknown[]) => {
2077
2127
  this.emit(eventName, ...args);
2078
2128
  });
2079
- });
2129
+ }
2080
2130
 
2081
2131
  this.summaryManager.start();
2082
2132
  }
2083
2133
  }
2084
2134
 
2085
2135
  // logging hardware telemetry
2086
- this.logger.sendTelemetryEvent({
2136
+ this.baseLogger.send({
2137
+ category: "generic",
2087
2138
  eventName: "DeviceSpec",
2088
2139
  ...getDeviceSpec(),
2089
2140
  });
@@ -2096,13 +2147,12 @@ export class ContainerRuntime
2096
2147
  summaryFormatVersion: metadata?.summaryFormatVersion,
2097
2148
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
2098
2149
  gcVersion: metadata?.gcFeature,
2099
- options: JSON.stringify(runtimeOptions),
2150
+ options: JSON.stringify(baseRuntimeOptions),
2100
2151
  idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
2101
- idCompressorMode: this.idCompressorMode,
2152
+ idCompressorMode: this.sessionSchema.idCompressorMode,
2102
2153
  sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
2103
2154
  featureGates: JSON.stringify({
2104
2155
  ...featureGatesForTelemetry,
2105
- disableAttachReorder: this.disableAttachReorder,
2106
2156
  disablePartialFlush,
2107
2157
  closeSummarizerDelayOverride,
2108
2158
  }),
@@ -2111,15 +2161,11 @@ export class ContainerRuntime
2111
2161
  initialSequenceNumber: this.deltaManager.initialSequenceNumber,
2112
2162
  });
2113
2163
 
2114
- ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.logger);
2115
- BindBatchTracker(this, this.logger);
2164
+ ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
2165
+ BindBatchTracker(this, this.baseLogger);
2116
2166
 
2117
2167
  this.entryPoint = new LazyPromise(async () => {
2118
- if (this.isSummarizerClient) {
2119
- assert(
2120
- this._summarizer !== undefined,
2121
- 0x5bf /* Summarizer object is undefined in a summarizer client */,
2122
- );
2168
+ if (this._summarizer !== undefined) {
2123
2169
  return this._summarizer;
2124
2170
  }
2125
2171
  return provideEntryPoint(this);
@@ -2130,8 +2176,9 @@ export class ContainerRuntime
2130
2176
  this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
2131
2177
  }
2132
2178
 
2133
- public onSchemaChange(schema: IDocumentSchemaCurrent) {
2134
- this.logger.sendTelemetryEvent({
2179
+ // eslint-disable-next-line import/no-deprecated
2180
+ public onSchemaChange(schema: IDocumentSchemaCurrent): void {
2181
+ this.mc.logger.sendTelemetryEvent({
2135
2182
  eventName: "SchemaChangeAccept",
2136
2183
  sessionRuntimeSchema: JSON.stringify(schema),
2137
2184
  });
@@ -2157,7 +2204,7 @@ export class ContainerRuntime
2157
2204
  return (
2158
2205
  summarizeInternal: SummarizeInternalFn,
2159
2206
  getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
2160
- ) =>
2207
+ ): ISummarizerNodeWithGC =>
2161
2208
  this.summarizerNode.createChild(
2162
2209
  summarizeInternal,
2163
2210
  id,
@@ -2167,26 +2214,29 @@ export class ContainerRuntime
2167
2214
  );
2168
2215
  }
2169
2216
 
2170
- public deleteChildSummarizerNode(id: string) {
2217
+ public deleteChildSummarizerNode(id: string): void {
2171
2218
  return this.summarizerNode.deleteChild(id);
2172
2219
  }
2173
2220
 
2174
- /* IFluidParentContext APIs that should not be called on Root */
2175
- public makeLocallyVisible() {
2221
+ // #region `IFluidParentContext` APIs that should not be called on Root
2222
+
2223
+ public makeLocallyVisible(): void {
2176
2224
  assert(false, 0x8eb /* should not be called */);
2177
2225
  }
2178
2226
 
2179
- public setChannelDirty(address: string) {
2227
+ public setChannelDirty(address: string): void {
2180
2228
  assert(false, 0x909 /* should not be called */);
2181
2229
  }
2182
2230
 
2231
+ // #endregion
2232
+
2183
2233
  /**
2184
2234
  * Initializes the state from the base snapshot this container runtime loaded from.
2185
2235
  */
2186
2236
  private async initializeBaseState(): Promise<void> {
2187
2237
  if (
2188
- this.idCompressorMode === "on" ||
2189
- (this.idCompressorMode === "delayed" && this.connected)
2238
+ this.sessionSchema.idCompressorMode === "on" ||
2239
+ (this.sessionSchema.idCompressorMode === "delayed" && this.connected)
2190
2240
  ) {
2191
2241
  this._idCompressor = await this.createIdCompressor();
2192
2242
  // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
@@ -2219,6 +2269,8 @@ export class ContainerRuntime
2219
2269
  this._summarizer?.dispose();
2220
2270
  this.channelCollection.dispose();
2221
2271
  this.pendingStateManager.dispose();
2272
+ this.inboundBatchAggregator.dispose();
2273
+ this.deltaScheduler.dispose();
2222
2274
  this.emit("dispose");
2223
2275
  this.removeAllListeners();
2224
2276
  }
@@ -2243,7 +2295,7 @@ export class ContainerRuntime
2243
2295
  // be in same loading group. So, once we have fetched the snapshot for that loading group on
2244
2296
  // any request, then cache that as same group could be requested in future too.
2245
2297
  const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(
2246
- sortedLoadingGroupIds.join(),
2298
+ sortedLoadingGroupIds.join(","),
2247
2299
  async () => {
2248
2300
  assert(
2249
2301
  this.storage.getSnapshot !== undefined,
@@ -2258,7 +2310,7 @@ export class ContainerRuntime
2258
2310
  },
2259
2311
  );
2260
2312
 
2261
- this.logger.sendTelemetryEvent({
2313
+ this.mc.logger.sendTelemetryEvent({
2262
2314
  eventName: "GroupIdSnapshotFetched",
2263
2315
  details: JSON.stringify({
2264
2316
  fromCache: loadedFromCache,
@@ -2299,7 +2351,7 @@ export class ContainerRuntime
2299
2351
  // another snapshot from which the summarizer loaded and it is behind, then just give up as
2300
2352
  // the summarizer state is not up to date.
2301
2353
  // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
2302
- if (this.isSummarizerClient) {
2354
+ if (this._summarizer !== undefined) {
2303
2355
  throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
2304
2356
  }
2305
2357
 
@@ -2370,7 +2422,7 @@ export class ContainerRuntime
2370
2422
  return {
2371
2423
  status: 200,
2372
2424
  mimeType: "fluid/object",
2373
- value: this.summarizer,
2425
+ value: this._summarizer,
2374
2426
  };
2375
2427
  }
2376
2428
  return create404Response(request);
@@ -2431,8 +2483,10 @@ export class ContainerRuntime
2431
2483
  return this.channelCollection.internalId(maybeAlias);
2432
2484
  }
2433
2485
 
2434
- /** Adds the container's metadata to the given summary tree. */
2435
- private addMetadataToSummary(summaryTree: ISummaryTreeWithStats) {
2486
+ /**
2487
+ * Adds the container's metadata to the given summary tree.
2488
+ */
2489
+ private addMetadataToSummary(summaryTree: ISummaryTreeWithStats): void {
2436
2490
  // The last message processed at the time of summary. If there are no new messages, use the message from the
2437
2491
  // last summary.
2438
2492
  const message =
@@ -2446,6 +2500,7 @@ export class ContainerRuntime
2446
2500
  // Is document schema explicit control on?
2447
2501
  const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
2448
2502
 
2503
+ // eslint-disable-next-line import/no-deprecated
2449
2504
  const metadata: IContainerRuntimeMetadata = {
2450
2505
  ...this.createContainerMetadata,
2451
2506
  // Increment the summary number for the next summary that will be generated.
@@ -2459,7 +2514,8 @@ export class ContainerRuntime
2459
2514
  // last message's sequence number.
2460
2515
  // See also lastMessageFromMetadata()
2461
2516
  message: explicitSchemaControl
2462
- ? ({ sequenceNumber: -1 } as any as ISummaryMetadataMessage)
2517
+ ? // eslint-disable-next-line import/no-deprecated
2518
+ ({ sequenceNumber: -1 } as unknown as ISummaryMetadataMessage)
2463
2519
  : message,
2464
2520
  lastMessage: explicitSchemaControl ? message : undefined,
2465
2521
  documentSchema,
@@ -2473,7 +2529,7 @@ export class ContainerRuntime
2473
2529
  fullTree: boolean,
2474
2530
  trackState: boolean,
2475
2531
  telemetryContext?: ITelemetryContext,
2476
- ) {
2532
+ ): void {
2477
2533
  this.addMetadataToSummary(summaryTree);
2478
2534
 
2479
2535
  if (this._idCompressor) {
@@ -2549,11 +2605,11 @@ export class ContainerRuntime
2549
2605
  return this.consecutiveReconnects < this.maxConsecutiveReconnects;
2550
2606
  }
2551
2607
 
2552
- private resetReconnectCount() {
2608
+ private resetReconnectCount(): void {
2553
2609
  this.consecutiveReconnects = 0;
2554
2610
  }
2555
2611
 
2556
- private replayPendingStates() {
2612
+ private replayPendingStates(): void {
2557
2613
  // We need to be able to send ops to replay states
2558
2614
  if (!this.canSendOps()) {
2559
2615
  return;
@@ -2593,7 +2649,7 @@ export class ContainerRuntime
2593
2649
  // TODO: markfields: confirm Local- versus Outbound- ContainerRuntimeMessage typing
2594
2650
  private parseLocalOpContent(serializedContents?: string): LocalContainerRuntimeMessage {
2595
2651
  assert(serializedContents !== undefined, 0x6d5 /* content must be defined */);
2596
- const message: LocalContainerRuntimeMessage = JSON.parse(serializedContents);
2652
+ const message = JSON.parse(serializedContents) as LocalContainerRuntimeMessage;
2597
2653
  assert(message.type !== undefined, 0x6d6 /* incorrect op content format */);
2598
2654
  return message;
2599
2655
  }
@@ -2604,9 +2660,10 @@ export class ContainerRuntime
2604
2660
  switch (opContents.type) {
2605
2661
  case ContainerMessageType.FluidDataStoreOp:
2606
2662
  case ContainerMessageType.Attach:
2607
- case ContainerMessageType.Alias:
2663
+ case ContainerMessageType.Alias: {
2608
2664
  return this.channelCollection.applyStashedOp(opContents);
2609
- case ContainerMessageType.IdAllocation:
2665
+ }
2666
+ case ContainerMessageType.IdAllocation: {
2610
2667
  // IDs allocation ops in stashed state are ignored because the tip state of the compressor
2611
2668
  // is serialized into the pending state. This is done because generation of new IDs during
2612
2669
  // stashed op application (or, later, resubmit) must generate new IDs and if the compressor
@@ -2617,19 +2674,24 @@ export class ContainerRuntime
2617
2674
  // before applying the rest of the stashed ops. This would accomplish the same thing but with
2618
2675
  // better performance in future incremental stashed state creation.
2619
2676
  assert(
2620
- this.idCompressorMode !== undefined,
2677
+ this.sessionSchema.idCompressorMode !== undefined,
2621
2678
  0x8f1 /* ID compressor should be in use */,
2622
2679
  );
2623
2680
  return;
2624
- case ContainerMessageType.DocumentSchemaChange:
2681
+ }
2682
+ case ContainerMessageType.DocumentSchemaChange: {
2625
2683
  return;
2626
- case ContainerMessageType.BlobAttach:
2684
+ }
2685
+ case ContainerMessageType.BlobAttach: {
2627
2686
  return;
2628
- case ContainerMessageType.Rejoin:
2687
+ }
2688
+ case ContainerMessageType.Rejoin: {
2629
2689
  throw new Error("rejoin not expected here");
2630
- case ContainerMessageType.GC:
2690
+ }
2691
+ case ContainerMessageType.GC: {
2631
2692
  // GC op is only sent in summarizer which should never have stashed ops.
2632
2693
  throw new LoggingError("GC op not expected to be stashed in summarizer");
2694
+ }
2633
2695
  default: {
2634
2696
  const error = getUnknownMessageTypeError(
2635
2697
  opContents.type,
@@ -2641,10 +2703,10 @@ export class ContainerRuntime
2641
2703
  }
2642
2704
  }
2643
2705
 
2644
- private async loadIdCompressor() {
2706
+ private async loadIdCompressor(): Promise<void | undefined> {
2645
2707
  if (
2646
2708
  this._idCompressor === undefined &&
2647
- this.idCompressorMode !== undefined &&
2709
+ this.sessionSchema.idCompressorMode !== undefined &&
2648
2710
  this._loadIdCompressor === undefined
2649
2711
  ) {
2650
2712
  this._loadIdCompressor = this.createIdCompressor()
@@ -2659,14 +2721,14 @@ export class ContainerRuntime
2659
2721
  this._idCompressor = compressor;
2660
2722
  })
2661
2723
  .catch((error) => {
2662
- this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
2724
+ this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
2663
2725
  throw error;
2664
2726
  });
2665
2727
  }
2666
2728
  return this._loadIdCompressor;
2667
2729
  }
2668
2730
 
2669
- public setConnectionState(connected: boolean, clientId?: string) {
2731
+ public setConnectionState(connected: boolean, clientId?: string): void {
2670
2732
  // Validate we have consistent state
2671
2733
  const currentClientId = this._audience.getSelf()?.clientId;
2672
2734
  assert(clientId === currentClientId, 0x977 /* input clientId does not match Audience */);
@@ -2675,7 +2737,7 @@ export class ContainerRuntime
2675
2737
  0x978 /* this.clientId does not match Audience */,
2676
2738
  );
2677
2739
 
2678
- if (connected && this.idCompressorMode === "delayed") {
2740
+ if (connected && this.sessionSchema.idCompressorMode === "delayed") {
2679
2741
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
2680
2742
  this.loadIdCompressor();
2681
2743
  }
@@ -2709,7 +2771,7 @@ export class ContainerRuntime
2709
2771
  this.setConnectionStateCore(connected, clientId);
2710
2772
  }
2711
2773
 
2712
- private setConnectionStateCore(connected: boolean, clientId?: string) {
2774
+ private setConnectionStateCore(connected: boolean, clientId?: string): void {
2713
2775
  assert(
2714
2776
  !this.delayConnectClientId,
2715
2777
  0x394 /* connect event delay must be cleared before propagating connect event */,
@@ -2777,7 +2839,7 @@ export class ContainerRuntime
2777
2839
  raiseConnectedEvent(this.mc.logger, this, connected, clientId);
2778
2840
  }
2779
2841
 
2780
- public async notifyOpReplay(message: ISequencedDocumentMessage) {
2842
+ public async notifyOpReplay(message: ISequencedDocumentMessage): Promise<void> {
2781
2843
  await this.pendingStateManager.applyStashedOpsAt(message.sequenceNumber);
2782
2844
  }
2783
2845
 
@@ -2786,7 +2848,7 @@ export class ContainerRuntime
2786
2848
  * @param messageCopy - Sequenced message for a distributed document.
2787
2849
  * @param local - true if the message was originally generated by the client receiving it.
2788
2850
  */
2789
- public process({ ...messageCopy }: ISequencedDocumentMessage, local: boolean) {
2851
+ public process({ ...messageCopy }: ISequencedDocumentMessage, local: boolean): void {
2790
2852
  // spread operator above ensure we make a shallow copy of message, as the processing flow will modify it.
2791
2853
  // There might be multiple container instances receiving the same message.
2792
2854
 
@@ -2797,7 +2859,7 @@ export class ContainerRuntime
2797
2859
  // or something different, like a system message.
2798
2860
  const hasModernRuntimeMessageEnvelope = messageCopy.type === MessageType.Operation;
2799
2861
  const savedOp = (messageCopy.metadata as ISavedOpMetadata)?.savedOp;
2800
- const logLegacyCase = getSingleUseLegacyLogCallback(this.logger, messageCopy.type);
2862
+ const logLegacyCase = getSingleUseLegacyLogCallback(this.mc.logger, messageCopy.type);
2801
2863
 
2802
2864
  let runtimeBatch: boolean =
2803
2865
  hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
@@ -2924,7 +2986,7 @@ export class ContainerRuntime
2924
2986
  private _processedClientSequenceNumber: number | undefined;
2925
2987
 
2926
2988
  /**
2927
- * Processes inbound message(s). It calls schedule manager according to the messages' location in the batch.
2989
+ * Processes inbound message(s). It calls delta scheduler according to the messages' location in the batch.
2928
2990
  * @param messagesWithMetadata - messages to process along with their metadata.
2929
2991
  * @param locationInBatch - Are we processing the start and/or end of a batch?
2930
2992
  * @param local - true if the messages were originally generated by the client receiving it.
@@ -2942,27 +3004,29 @@ export class ContainerRuntime
2942
3004
  savedOp: boolean | undefined,
2943
3005
  runtimeBatch: boolean,
2944
3006
  groupedBatch: boolean,
2945
- ) {
3007
+ ): void {
2946
3008
  if (locationInBatch.batchStart) {
2947
3009
  const firstMessage = messagesWithMetadata[0]?.message;
2948
3010
  assert(firstMessage !== undefined, 0xa31 /* Batch must have at least one message */);
2949
- this.scheduleManager.batchBegin(firstMessage);
3011
+ this.emit("batchBegin", firstMessage);
2950
3012
  }
2951
3013
 
2952
3014
  let error: unknown;
2953
3015
  try {
2954
3016
  if (!runtimeBatch) {
2955
- messagesWithMetadata.forEach(({ message }) => {
3017
+ for (const { message } of messagesWithMetadata) {
2956
3018
  this.ensureNoDataModelChanges(() => {
2957
3019
  this.observeNonRuntimeMessage(message);
2958
3020
  });
2959
- });
3021
+ }
2960
3022
  return;
2961
3023
  }
2962
3024
 
2963
- // Helper that updates a message's minimum sequence number to the minimum sequence number that container
3025
+ // Updates a message's minimum sequence number to the minimum sequence number that container
2964
3026
  // runtime is tracking and sets _processedClientSequenceNumber. It returns the updated message.
2965
- const updateSequenceNumbers = (message: ISequencedDocumentMessage) => {
3027
+ const updateSequenceNumbers = (
3028
+ message: ISequencedDocumentMessage,
3029
+ ): InboundSequencedContainerRuntimeMessage => {
2966
3030
  // Set the minimum sequence number to the containerRuntime's understanding of minimum sequence number.
2967
3031
  message.minimumSequenceNumber =
2968
3032
  this.useDeltaManagerOpsProxy &&
@@ -2999,8 +3063,8 @@ export class ContainerRuntime
2999
3063
  let bunchedMessagesContent: IRuntimeMessagesContent[] = [];
3000
3064
  let previousMessage: InboundSequencedContainerRuntimeMessage | undefined;
3001
3065
 
3002
- // Helper that processes the previous bunch of messages.
3003
- const sendBunchedMessages = () => {
3066
+ // Process the previous bunch of messages.
3067
+ const sendBunchedMessages = (): void => {
3004
3068
  assert(previousMessage !== undefined, 0xa67 /* previous message must exist */);
3005
3069
  this.ensureNoDataModelChanges(() => {
3006
3070
  this.validateAndProcessRuntimeMessages(
@@ -3039,14 +3103,14 @@ export class ContainerRuntime
3039
3103
  for (const { message } of messagesWithMetadata) {
3040
3104
  this.emit("op", message, true /* runtimeMessage */);
3041
3105
  }
3042
- } catch (e) {
3043
- error = e;
3106
+ } catch (error_) {
3107
+ error = error_;
3044
3108
  throw error;
3045
3109
  } finally {
3046
3110
  if (locationInBatch.batchEnd) {
3047
3111
  const lastMessage = messagesWithMetadata[messagesWithMetadata.length - 1]?.message;
3048
3112
  assert(lastMessage !== undefined, 0xa32 /* Batch must have at least one message */);
3049
- this.scheduleManager.batchEnd(error, lastMessage);
3113
+ this.emit("batchEnd", error, lastMessage);
3050
3114
  }
3051
3115
  }
3052
3116
  }
@@ -3055,7 +3119,7 @@ export class ContainerRuntime
3055
3119
  * Observes messages that are not intended for the runtime layer, updating/notifying Runtime systems as needed.
3056
3120
  * @param message - non-runtime message to process.
3057
3121
  */
3058
- private observeNonRuntimeMessage(message: ISequencedDocumentMessage) {
3122
+ private observeNonRuntimeMessage(message: ISequencedDocumentMessage): void {
3059
3123
  // Set the minimum sequence number to the containerRuntime's understanding of minimum sequence number.
3060
3124
  if (this.deltaManager.minimumSequenceNumber < message.minimumSequenceNumber) {
3061
3125
  message.minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
@@ -3111,38 +3175,46 @@ export class ContainerRuntime
3111
3175
  switch (message.type) {
3112
3176
  case ContainerMessageType.FluidDataStoreOp:
3113
3177
  case ContainerMessageType.Attach:
3114
- case ContainerMessageType.Alias:
3178
+ case ContainerMessageType.Alias: {
3115
3179
  // Remove the metadata from the message before sending it to the channel collection. The metadata
3116
3180
  // is added by the container runtime and is not part of the message that the channel collection and
3117
3181
  // layers below it expect.
3118
3182
  this.channelCollection.processMessages({ envelope: message, messagesContent, local });
3119
3183
  break;
3120
- case ContainerMessageType.BlobAttach:
3184
+ }
3185
+ case ContainerMessageType.BlobAttach: {
3121
3186
  this.blobManager.processBlobAttachMessage(message, local);
3122
3187
  break;
3123
- case ContainerMessageType.IdAllocation:
3188
+ }
3189
+ case ContainerMessageType.IdAllocation: {
3124
3190
  this.processIdCompressorMessages(contents as IdCreationRange[], savedOp);
3125
3191
  break;
3126
- case ContainerMessageType.GC:
3192
+ }
3193
+ case ContainerMessageType.GC: {
3127
3194
  this.garbageCollector.processMessages(
3128
3195
  contents as GarbageCollectionMessage[],
3129
3196
  message.timestamp,
3130
3197
  local,
3131
3198
  );
3132
3199
  break;
3133
- case ContainerMessageType.ChunkedOp:
3200
+ }
3201
+ case ContainerMessageType.ChunkedOp: {
3134
3202
  // From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
3135
3203
  // Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
3136
3204
  assert(false, 0x93d /* should not even get here */);
3137
- case ContainerMessageType.Rejoin:
3205
+ }
3206
+ case ContainerMessageType.Rejoin: {
3138
3207
  break;
3139
- case ContainerMessageType.DocumentSchemaChange:
3208
+ }
3209
+ case ContainerMessageType.DocumentSchemaChange: {
3140
3210
  this.documentsSchemaController.processDocumentSchemaMessages(
3211
+ // eslint-disable-next-line import/no-deprecated
3141
3212
  contents as IDocumentSchemaChangeMessage[],
3142
3213
  local,
3143
3214
  message.sequenceNumber,
3144
3215
  );
3145
3216
  break;
3217
+ }
3146
3218
  default: {
3147
3219
  const error = getUnknownMessageTypeError(
3148
3220
  message.type,
@@ -3155,7 +3227,10 @@ export class ContainerRuntime
3155
3227
  }
3156
3228
  }
3157
3229
 
3158
- private processIdCompressorMessages(messageContents: IdCreationRange[], savedOp?: boolean) {
3230
+ private processIdCompressorMessages(
3231
+ messageContents: IdCreationRange[],
3232
+ savedOp?: boolean,
3233
+ ): void {
3159
3234
  for (const range of messageContents) {
3160
3235
  // Don't re-finalize the range if we're processing a "savedOp" in
3161
3236
  // stashed ops flow. The compressor is stashed with these ops already processed.
@@ -3166,7 +3241,7 @@ export class ContainerRuntime
3166
3241
  // put it in a pending queue and delay finalization.
3167
3242
  if (this._idCompressor === undefined) {
3168
3243
  assert(
3169
- this.idCompressorMode !== undefined,
3244
+ this.sessionSchema.idCompressorMode !== undefined,
3170
3245
  0x93c /* id compressor should be enabled */,
3171
3246
  );
3172
3247
  this.pendingIdCompressorOps.push(range);
@@ -3184,7 +3259,7 @@ export class ContainerRuntime
3184
3259
  /**
3185
3260
  * Emits the Signal event and update the perf signal data.
3186
3261
  */
3187
- private sendSignalTelemetryEvent() {
3262
+ private sendSignalTelemetryEvent(): void {
3188
3263
  const duration = Date.now() - this._signalTracking.signalTimestamp;
3189
3264
  this.mc.logger.sendPerformanceEvent({
3190
3265
  eventName: "SignalLatency",
@@ -3206,7 +3281,11 @@ export class ContainerRuntime
3206
3281
  * Updates signal telemetry including emitting telemetry events.
3207
3282
  */
3208
3283
  private processSignalForTelemetry(envelope: ISignalEnvelope): void {
3209
- const { clientBroadcastSignalSequenceNumber } = envelope;
3284
+ const {
3285
+ clientBroadcastSignalSequenceNumber,
3286
+ contents: envelopeContents,
3287
+ address: envelopeAddress,
3288
+ } = envelope;
3210
3289
  if (clientBroadcastSignalSequenceNumber === undefined) {
3211
3290
  return;
3212
3291
  }
@@ -3251,8 +3330,8 @@ export class ContainerRuntime
3251
3330
  };
3252
3331
  // Only log `contents.type` when address is for container to avoid
3253
3332
  // chance that contents type is customer data.
3254
- if (envelope.address === undefined) {
3255
- details.contentsType = envelope.contents.type; // Type of signal that was received out of order.
3333
+ if (envelopeAddress === undefined) {
3334
+ details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
3256
3335
  }
3257
3336
  this.mc.logger.sendTelemetryEvent({
3258
3337
  eventName: "SignalOutOfOrder",
@@ -3278,7 +3357,7 @@ export class ContainerRuntime
3278
3357
  }
3279
3358
  }
3280
3359
 
3281
- public processSignal(message: ISignalMessage, local: boolean) {
3360
+ public processSignal(message: ISignalMessage, local: boolean): void {
3282
3361
  const envelope = message.content as ISignalEnvelope;
3283
3362
  const transformed: IInboundSignalMessage = {
3284
3363
  clientId: message.clientId,
@@ -3348,8 +3427,8 @@ export class ContainerRuntime
3348
3427
  checkpoint.rollback((message: BatchMessage) =>
3349
3428
  this.rollback(message.contents, message.localOpMetadata),
3350
3429
  );
3351
- } catch (err) {
3352
- const error2 = wrapError(err, (message) => {
3430
+ } catch (error_) {
3431
+ const error2 = wrapError(error_, (message) => {
3353
3432
  return DataProcessingError.create(
3354
3433
  `RollbackError: ${message}`,
3355
3434
  "checkpointRollback",
@@ -3440,7 +3519,6 @@ export class ContainerRuntime
3440
3519
  ): Promise<IDataStore> {
3441
3520
  const context = this.channelCollection.createDataStoreContext(
3442
3521
  Array.isArray(pkg) ? pkg : [pkg],
3443
- undefined, // props
3444
3522
  loadingGroupId,
3445
3523
  );
3446
3524
  return channelToDataStore(
@@ -3451,26 +3529,7 @@ export class ContainerRuntime
3451
3529
  );
3452
3530
  }
3453
3531
 
3454
- /**
3455
- * @deprecated 0.16 Issue #1537, #3631
3456
- */
3457
- public async _createDataStoreWithProps(
3458
- pkg: Readonly<string | string[]>,
3459
- props?: any,
3460
- ): Promise<IDataStore> {
3461
- const context = this.channelCollection.createDataStoreContext(
3462
- Array.isArray(pkg) ? pkg : [pkg],
3463
- props,
3464
- );
3465
- return channelToDataStore(
3466
- await context.realize(),
3467
- context.id,
3468
- this.channelCollection,
3469
- this.mc.logger,
3470
- );
3471
- }
3472
-
3473
- private canSendOps() {
3532
+ private canSendOps(): boolean {
3474
3533
  // Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
3475
3534
  // container runtime's ability to send ops depend on the actual readonly state of the delta manager.
3476
3535
  return (
@@ -3481,7 +3540,7 @@ export class ContainerRuntime
3481
3540
  /**
3482
3541
  * Typically ops are batched and later flushed together, but in some cases we want to flush immediately.
3483
3542
  */
3484
- private currentlyBatching() {
3543
+ private currentlyBatching(): boolean {
3485
3544
  return this.flushMode !== FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
3486
3545
  }
3487
3546
 
@@ -3503,7 +3562,10 @@ export class ContainerRuntime
3503
3562
  return this.dirtyContainer;
3504
3563
  }
3505
3564
 
3506
- private isContainerMessageDirtyable({ type, contents }: OutboundContainerRuntimeMessage) {
3565
+ private isContainerMessageDirtyable({
3566
+ type,
3567
+ contents,
3568
+ }: OutboundContainerRuntimeMessage): boolean {
3507
3569
  // Certain container runtime messages should not mark the container dirty such as the old built-in
3508
3570
  // AgentScheduler and Garbage collector messages.
3509
3571
  switch (type) {
@@ -3526,8 +3588,9 @@ export class ContainerRuntime
3526
3588
  case ContainerMessageType.GC: {
3527
3589
  return false;
3528
3590
  }
3529
- default:
3591
+ default: {
3530
3592
  break;
3593
+ }
3531
3594
  }
3532
3595
  return true;
3533
3596
  }
@@ -3535,7 +3598,7 @@ export class ContainerRuntime
3535
3598
  private createNewSignalEnvelope(
3536
3599
  address: string | undefined,
3537
3600
  type: string,
3538
- content: any,
3601
+ content: unknown,
3539
3602
  ): Omit<ISignalEnvelope, "broadcastSignalSequenceNumber"> {
3540
3603
  const newEnvelope: Omit<ISignalEnvelope, "broadcastSignalSequenceNumber"> = {
3541
3604
  address,
@@ -3545,7 +3608,7 @@ export class ContainerRuntime
3545
3608
  return newEnvelope;
3546
3609
  }
3547
3610
 
3548
- private submitEnvelopedSignal(envelope: ISignalEnvelope, targetClientId?: string) {
3611
+ private submitEnvelopedSignal(envelope: ISignalEnvelope, targetClientId?: string): void {
3549
3612
  const isBroadcastSignal = targetClientId === undefined;
3550
3613
 
3551
3614
  if (isBroadcastSignal) {
@@ -3570,7 +3633,7 @@ export class ContainerRuntime
3570
3633
 
3571
3634
  // We should not track the round trip of a new signal in the case we are already tracking one.
3572
3635
  if (
3573
- clientBroadcastSignalSequenceNumber % this.defaultTelemetrySignalSampleCount === 1 &&
3636
+ clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
3574
3637
  this._signalTracking.roundTripSignalSequenceNumber === undefined
3575
3638
  ) {
3576
3639
  this._signalTracking.signalTimestamp = Date.now();
@@ -3597,7 +3660,7 @@ export class ContainerRuntime
3597
3660
  * Support for this option at container runtime is planned to be deprecated in the future.
3598
3661
  *
3599
3662
  */
3600
- public submitSignal(type: string, content: unknown, targetClientId?: string) {
3663
+ public submitSignal(type: string, content: unknown, targetClientId?: string): void {
3601
3664
  this.verifyNotClosed();
3602
3665
  const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
3603
3666
  return this.submitEnvelopedSignal(envelope, targetClientId);
@@ -3664,6 +3727,12 @@ export class ContainerRuntime
3664
3727
 
3665
3728
  public readonly getAbsoluteUrl: (relativeUrl: string) => Promise<string | undefined>;
3666
3729
 
3730
+ /**
3731
+ * Builds the Summary tree including all the channels and the container state.
3732
+ *
3733
+ * @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
3734
+ * so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
3735
+ */
3667
3736
  private async summarizeInternal(
3668
3737
  fullTree: boolean,
3669
3738
  trackState: boolean,
@@ -3694,17 +3763,29 @@ export class ContainerRuntime
3694
3763
  * Returns a summary of the runtime at the current sequence number.
3695
3764
  */
3696
3765
  public async summarize(options: {
3697
- /** True to generate the full tree with no handle reuse optimizations; defaults to false */
3766
+ /**
3767
+ * True to generate the full tree with no handle reuse optimizations; defaults to false
3768
+ */
3698
3769
  fullTree?: boolean;
3699
- /** True to track the state for this summary in the SummarizerNodes; defaults to true */
3770
+ /**
3771
+ * True to track the state for this summary in the SummarizerNodes; defaults to true
3772
+ */
3700
3773
  trackState?: boolean;
3701
- /** Logger to use for correlated summary events */
3774
+ /**
3775
+ * Logger to use for correlated summary events
3776
+ */
3702
3777
  summaryLogger?: ITelemetryLoggerExt;
3703
- /** True to run garbage collection before summarizing; defaults to true */
3778
+ /**
3779
+ * True to run garbage collection before summarizing; defaults to true
3780
+ */
3704
3781
  runGC?: boolean;
3705
- /** True to generate full GC data */
3782
+ /**
3783
+ * True to generate full GC data
3784
+ */
3706
3785
  fullGC?: boolean;
3707
- /** True to run GC sweep phase after the mark phase */
3786
+ /**
3787
+ * True to run GC sweep phase after the mark phase
3788
+ */
3708
3789
  runSweep?: boolean;
3709
3790
  }): Promise<ISummaryTreeWithStats> {
3710
3791
  this.verifyNotClosed();
@@ -3780,7 +3861,7 @@ export class ContainerRuntime
3780
3861
  * @param usedRoutes - The routes that are used in all nodes in this Container.
3781
3862
  * @see IGarbageCollectionRuntime.updateUsedRoutes
3782
3863
  */
3783
- public updateUsedRoutes(usedRoutes: readonly string[]) {
3864
+ public updateUsedRoutes(usedRoutes: readonly string[]): void {
3784
3865
  // Update our summarizer node's used routes. Updating used routes in summarizer node before
3785
3866
  // summarizing is required and asserted by the the summarizer node. We are the root and are
3786
3867
  // always referenced, so the used routes is only self-route (empty string).
@@ -3799,8 +3880,10 @@ export class ContainerRuntime
3799
3880
  const { dataStoreRoutes, blobManagerRoutes } =
3800
3881
  this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
3801
3882
 
3802
- const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
3803
- return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
3883
+ return [
3884
+ ...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
3885
+ ...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
3886
+ ];
3804
3887
  }
3805
3888
 
3806
3889
  /**
@@ -3811,7 +3894,7 @@ export class ContainerRuntime
3811
3894
  *
3812
3895
  * @param tombstonedRoutes - Data store and attachment blob routes that are tombstones in this Container.
3813
3896
  */
3814
- public updateTombstonedRoutes(tombstonedRoutes: readonly string[]) {
3897
+ public updateTombstonedRoutes(tombstonedRoutes: readonly string[]): void {
3815
3898
  const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
3816
3899
  this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
3817
3900
  }
@@ -3829,10 +3912,13 @@ export class ContainerRuntime
3829
3912
  * Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
3830
3913
  * blob manager.
3831
3914
  */
3915
+ // eslint-disable-next-line import/no-deprecated
3832
3916
  public getNodeType(nodePath: string): GCNodeType {
3833
3917
  if (isBlobPath(nodePath)) {
3918
+ // eslint-disable-next-line import/no-deprecated
3834
3919
  return GCNodeType.Blob;
3835
3920
  }
3921
+ // eslint-disable-next-line import/no-deprecated
3836
3922
  return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
3837
3923
  }
3838
3924
 
@@ -3848,13 +3934,19 @@ export class ContainerRuntime
3848
3934
  }
3849
3935
 
3850
3936
  switch (this.getNodeType(nodePath)) {
3851
- case GCNodeType.Blob:
3937
+ // eslint-disable-next-line import/no-deprecated
3938
+ case GCNodeType.Blob: {
3852
3939
  return [blobManagerBasePath];
3940
+ }
3941
+ // eslint-disable-next-line import/no-deprecated
3853
3942
  case GCNodeType.DataStore:
3854
- case GCNodeType.SubDataStore:
3943
+ // eslint-disable-next-line import/no-deprecated
3944
+ case GCNodeType.SubDataStore: {
3855
3945
  return this.channelCollection.getDataStorePackagePath(nodePath);
3856
- default:
3946
+ }
3947
+ default: {
3857
3948
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
3949
+ }
3858
3950
  }
3859
3951
  }
3860
3952
 
@@ -3864,7 +3956,10 @@ export class ContainerRuntime
3864
3956
  * @returns Two route lists - One that contains routes for blob manager and another one that contains routes
3865
3957
  * for data stores.
3866
3958
  */
3867
- private getDataStoreAndBlobManagerRoutes(routes: readonly string[]) {
3959
+ private getDataStoreAndBlobManagerRoutes(routes: readonly string[]): {
3960
+ blobManagerRoutes: string[];
3961
+ dataStoreRoutes: string[];
3962
+ } {
3868
3963
  const blobManagerRoutes: string[] = [];
3869
3964
  const dataStoreRoutes: string[] = [];
3870
3965
  for (const route of routes) {
@@ -3883,14 +3978,21 @@ export class ContainerRuntime
3883
3978
  */
3884
3979
  public async collectGarbage(
3885
3980
  options: {
3886
- /** Logger to use for logging GC events */
3981
+ /**
3982
+ * Logger to use for logging GC events
3983
+ */
3887
3984
  logger?: ITelemetryLoggerExt;
3888
- /** True to run GC sweep phase after the mark phase */
3985
+ /**
3986
+ * True to run GC sweep phase after the mark phase
3987
+ */
3889
3988
  runSweep?: boolean;
3890
- /** True to generate full GC data */
3989
+ /**
3990
+ * True to generate full GC data
3991
+ */
3891
3992
  fullGC?: boolean;
3892
3993
  },
3893
3994
  telemetryContext?: ITelemetryContext,
3995
+ // eslint-disable-next-line import/no-deprecated
3894
3996
  ): Promise<IGCStats | undefined> {
3895
3997
  return this.garbageCollector.collectGarbage(options, telemetryContext);
3896
3998
  }
@@ -3902,7 +4004,11 @@ export class ContainerRuntime
3902
4004
  * @param toPath - The absolute path of the outbound node that is referenced.
3903
4005
  * @param messageTimestampMs - The timestamp of the message that added the reference.
3904
4006
  */
3905
- public addedGCOutboundRoute(fromPath: string, toPath: string, messageTimestampMs?: number) {
4007
+ public addedGCOutboundRoute(
4008
+ fromPath: string,
4009
+ toPath: string,
4010
+ messageTimestampMs?: number,
4011
+ ): void {
3906
4012
  // This is always called when processing an op so messageTimestampMs should exist. Due to back-compat
3907
4013
  // across the data store runtime / container runtime boundary, this may be undefined and if so, get
3908
4014
  // the timestamp from the last processed message which should exist.
@@ -3929,8 +4035,10 @@ export class ContainerRuntime
3929
4035
  * op processing, updating SummarizerNode state tracking, and garbage collection.
3930
4036
  * @param options - options controlling how the summary is generated or submitted
3931
4037
  */
4038
+ // eslint-disable-next-line import/no-deprecated
3932
4039
  public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
3933
4040
  const {
4041
+ cancellationToken,
3934
4042
  fullTree = false,
3935
4043
  finalAttempt = false,
3936
4044
  summaryLogger,
@@ -4050,7 +4158,7 @@ export class ContainerRuntime
4050
4158
  eventName: "LatestSummaryRefSeqNumMismatch",
4051
4159
  details: {
4052
4160
  ...startSummaryResult,
4053
- mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
4161
+ mismatchNumbers: [...startSummaryResult.mismatchNumbers],
4054
4162
  },
4055
4163
  });
4056
4164
 
@@ -4074,7 +4182,7 @@ export class ContainerRuntime
4074
4182
  // summarizer to reconnect in the future.
4075
4183
  // Also checking for cancellation is a must as summary process may be abandoned for other reasons,
4076
4184
  // like loss of connectivity for main (interactive) client.
4077
- if (options.cancellationToken.cancelled) {
4185
+ if (cancellationToken.cancelled) {
4078
4186
  return { continue: false, error: "disconnected" };
4079
4187
  }
4080
4188
  // That said, we rely on submitSystemMessage() that today only works in connected state.
@@ -4171,7 +4279,7 @@ export class ContainerRuntime
4171
4279
  // Counting dataStores and handles
4172
4280
  // Because handles are unchanged dataStores in the current logic,
4173
4281
  // summarized dataStore count is total dataStore count minus handle count
4174
- const dataStoreTree: SummaryObject | undefined = summaryTree.tree[channelsTreeName];
4282
+ const dataStoreTree = summaryTree.tree[channelsTreeName];
4175
4283
 
4176
4284
  assert(dataStoreTree.type === SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
4177
4285
  const handleCount = Object.values(dataStoreTree.tree).filter(
@@ -4215,10 +4323,7 @@ export class ContainerRuntime
4215
4323
 
4216
4324
  let handle: string;
4217
4325
  try {
4218
- handle = await this.storage.uploadSummaryWithContext(
4219
- summarizeResult.summary,
4220
- summaryContext,
4221
- );
4326
+ handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
4222
4327
  } catch (error) {
4223
4328
  return {
4224
4329
  stage: "generate",
@@ -4363,19 +4468,19 @@ export class ContainerRuntime
4363
4468
  return this.pendingStateManager.pendingMessagesCount + this.outbox.messageCount;
4364
4469
  }
4365
4470
 
4366
- private hasPendingMessages() {
4471
+ private hasPendingMessages(): boolean {
4367
4472
  return this.pendingMessagesCount !== 0;
4368
4473
  }
4369
4474
 
4370
- private updateDocumentDirtyState(dirty: boolean) {
4371
- if (this.attachState !== AttachState.Attached) {
4372
- assert(dirty, 0x3d2 /* Non-attached container is dirty */);
4373
- } else {
4475
+ private updateDocumentDirtyState(dirty: boolean): void {
4476
+ if (this.attachState === AttachState.Attached) {
4374
4477
  // Other way is not true = see this.isContainerMessageDirtyable()
4375
4478
  assert(
4376
4479
  !dirty || this.hasPendingMessages(),
4377
4480
  0x3d3 /* if doc is dirty, there has to be pending ops */,
4378
4481
  );
4482
+ } else {
4483
+ assert(dirty, 0x3d2 /* Non-attached container is dirty */);
4379
4484
  }
4380
4485
 
4381
4486
  if (this.dirtyContainer === dirty) {
@@ -4393,9 +4498,12 @@ export class ContainerRuntime
4393
4498
  | ContainerMessageType.FluidDataStoreOp
4394
4499
  | ContainerMessageType.Alias
4395
4500
  | ContainerMessageType.Attach,
4501
+ // TODO: better typing
4502
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
4396
4503
  contents: any,
4397
4504
  localOpMetadata: unknown = undefined,
4398
4505
  ): void {
4506
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
4399
4507
  this.submit({ type, contents }, localOpMetadata);
4400
4508
  }
4401
4509
 
@@ -4469,7 +4577,7 @@ export class ContainerRuntime
4469
4577
  // on this callback to do actual sending.
4470
4578
  const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
4471
4579
  if (schemaChangeMessage) {
4472
- this.logger.sendTelemetryEvent({
4580
+ this.mc.logger.sendTelemetryEvent({
4473
4581
  eventName: "SchemaChangeProposal",
4474
4582
  refSeq: schemaChangeMessage.refSeq,
4475
4583
  version: schemaChangeMessage.version,
@@ -4517,13 +4625,16 @@ export class ContainerRuntime
4517
4625
  }
4518
4626
  }
4519
4627
 
4520
- private scheduleFlush() {
4628
+ private scheduleFlush(): void {
4521
4629
  if (this.flushTaskExists) {
4522
4630
  return;
4523
4631
  }
4524
4632
 
4525
4633
  this.flushTaskExists = true;
4526
- const flush = () => {
4634
+
4635
+ // TODO: hoist this out of the function scope to save unnecessary allocations
4636
+ // eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
4637
+ const flush = (): void => {
4527
4638
  this.flushTaskExists = false;
4528
4639
  try {
4529
4640
  this.flush();
@@ -4533,31 +4644,37 @@ export class ContainerRuntime
4533
4644
  };
4534
4645
 
4535
4646
  switch (this.flushMode) {
4536
- case FlushMode.TurnBased:
4647
+ case FlushMode.TurnBased: {
4537
4648
  // When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
4538
4649
  // batch at the end of the turn
4539
4650
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
4540
4651
  Promise.resolve().then(flush);
4541
4652
  break;
4653
+ }
4542
4654
 
4543
4655
  // FlushModeExperimental is experimental and not exposed directly in the runtime APIs
4544
- case FlushModeExperimental.Async as unknown as FlushMode:
4656
+ case FlushModeExperimental.Async as unknown as FlushMode: {
4545
4657
  // When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
4546
4658
  // batch when all micro-tasks are complete.
4547
4659
  // Compared to TurnBased, this flush mode will capture more ops into the same batch.
4548
4660
  setTimeout(flush, 0);
4549
4661
  break;
4662
+ }
4550
4663
 
4551
- default:
4664
+ default: {
4552
4665
  assert(
4553
4666
  this._orderSequentiallyCalls > 0,
4554
4667
  0x587 /* Unreachable unless running under orderSequentially */,
4555
4668
  );
4556
4669
  break;
4670
+ }
4557
4671
  }
4558
4672
  }
4559
4673
 
4560
- private submitSummaryMessage(contents: ISummaryContent, referenceSequenceNumber: number) {
4674
+ private submitSummaryMessage(
4675
+ contents: ISummaryContent,
4676
+ referenceSequenceNumber: number,
4677
+ ): number {
4561
4678
  this.verifyNotClosed();
4562
4679
  assert(
4563
4680
  this.connected,
@@ -4567,17 +4684,14 @@ export class ContainerRuntime
4567
4684
  // System message should not be sent in the middle of the batch.
4568
4685
  assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
4569
4686
 
4570
- // back-compat: ADO #1385: Make this call unconditional in the future
4571
- return this.submitSummaryFn !== undefined
4572
- ? this.submitSummaryFn(contents, referenceSequenceNumber)
4573
- : this.submitFn(MessageType.Summarize, contents, false);
4687
+ return this.submitSummaryFn(contents, referenceSequenceNumber);
4574
4688
  }
4575
4689
 
4576
4690
  /**
4577
4691
  * Throw an error if the runtime is closed. Methods that are expected to potentially
4578
4692
  * be called after dispose due to asynchrony should not call this.
4579
4693
  */
4580
- private verifyNotClosed() {
4694
+ private verifyNotClosed(): void {
4581
4695
  if (this._disposed) {
4582
4696
  throw new Error("Runtime is closed");
4583
4697
  }
@@ -4589,7 +4703,7 @@ export class ContainerRuntime
4589
4703
  * @remarks - If the "Offline Load" feature is enabled, the batchId is included in the resubmitted messages,
4590
4704
  * for correlation to detect container forking.
4591
4705
  */
4592
- private reSubmitBatch(batch: PendingMessageResubmitData[], batchId: BatchId) {
4706
+ private reSubmitBatch(batch: PendingMessageResubmitData[], batchId: BatchId): void {
4593
4707
  this.orderSequentially(() => {
4594
4708
  for (const message of batch) {
4595
4709
  this.reSubmit(message);
@@ -4601,7 +4715,7 @@ export class ContainerRuntime
4601
4715
  this.flush(this.offlineEnabled ? batchId : undefined);
4602
4716
  }
4603
4717
 
4604
- private reSubmit(message: PendingMessageResubmitData) {
4718
+ private reSubmit(message: PendingMessageResubmitData): void {
4605
4719
  // Need to parse from string for back-compat
4606
4720
  const containerRuntimeMessage = this.parseLocalOpContent(message.content);
4607
4721
  this.reSubmitCore(containerRuntimeMessage, message.localOpMetadata, message.opMetadata);
@@ -4618,19 +4732,20 @@ export class ContainerRuntime
4618
4732
  message: LocalContainerRuntimeMessage,
4619
4733
  localOpMetadata: unknown,
4620
4734
  opMetadata: Record<string, unknown> | undefined,
4621
- ) {
4735
+ ): void {
4622
4736
  assert(
4623
- !this.isSummarizerClient,
4737
+ this._summarizer === undefined,
4624
4738
  0x8f2 /* Summarizer never reconnects so should never resubmit */,
4625
4739
  );
4626
4740
  switch (message.type) {
4627
4741
  case ContainerMessageType.FluidDataStoreOp:
4628
4742
  case ContainerMessageType.Attach:
4629
- case ContainerMessageType.Alias:
4743
+ case ContainerMessageType.Alias: {
4630
4744
  // For Operations, call resubmitDataStoreOp which will find the right store
4631
4745
  // and trigger resubmission on it.
4632
4746
  this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
4633
4747
  break;
4748
+ }
4634
4749
  case ContainerMessageType.IdAllocation: {
4635
4750
  // Allocation ops are never resubmitted/rebased. This is because they require special handling to
4636
4751
  // avoid being submitted out of order. For example, if the pending state manager contained
@@ -4641,20 +4756,24 @@ export class ContainerRuntime
4641
4756
  // all pending IDs. The resubmitted allocation ops are then ignored here.
4642
4757
  break;
4643
4758
  }
4644
- case ContainerMessageType.BlobAttach:
4759
+ case ContainerMessageType.BlobAttach: {
4645
4760
  this.blobManager.reSubmit(opMetadata);
4646
4761
  break;
4647
- case ContainerMessageType.Rejoin:
4762
+ }
4763
+ case ContainerMessageType.Rejoin: {
4648
4764
  this.submit(message);
4649
4765
  break;
4650
- case ContainerMessageType.GC:
4766
+ }
4767
+ case ContainerMessageType.GC: {
4651
4768
  this.submit(message);
4652
4769
  break;
4653
- case ContainerMessageType.DocumentSchemaChange:
4770
+ }
4771
+ case ContainerMessageType.DocumentSchemaChange: {
4654
4772
  // There is no need to resend this message. Document schema controller will properly resend it again (if needed)
4655
4773
  // on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
4656
4774
  // send any ops, as some other client already changed schema.
4657
4775
  break;
4776
+ }
4658
4777
  default: {
4659
4778
  const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
4660
4779
  this.closeFn(error);
@@ -4663,22 +4782,27 @@ export class ContainerRuntime
4663
4782
  }
4664
4783
  }
4665
4784
 
4666
- private rollback(content: string | undefined, localOpMetadata: unknown) {
4785
+ private rollback(content: string | undefined, localOpMetadata: unknown): void {
4667
4786
  // Need to parse from string for back-compat
4668
4787
  const { type, contents } = this.parseLocalOpContent(content);
4669
4788
  switch (type) {
4670
- case ContainerMessageType.FluidDataStoreOp:
4789
+ case ContainerMessageType.FluidDataStoreOp: {
4671
4790
  // For operations, call rollbackDataStoreOp which will find the right store
4672
4791
  // and trigger rollback on it.
4673
4792
  this.channelCollection.rollback(type, contents, localOpMetadata);
4674
4793
  break;
4675
- default:
4794
+ }
4795
+ default: {
4676
4796
  throw new Error(`Can't rollback ${type}`);
4797
+ }
4677
4798
  }
4678
4799
  }
4679
4800
 
4680
- /** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
4681
- public async refreshLatestSummaryAck(options: IRefreshSummaryAckOptions) {
4801
+ /**
4802
+ * Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
4803
+ */
4804
+ // eslint-disable-next-line import/no-deprecated
4805
+ public async refreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise<void> {
4682
4806
  const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
4683
4807
  // proposalHandle is always passed from RunningSummarizer.
4684
4808
  assert(proposalHandle !== undefined, 0x766 /* proposalHandle should be available */);
@@ -4724,6 +4848,9 @@ export class ContainerRuntime
4724
4848
  };
4725
4849
  }
4726
4850
 
4851
+ private readonly readAndParseBlob = async <T>(id: string): Promise<T> =>
4852
+ readAndParse<T>(this.storage, id);
4853
+
4727
4854
  /**
4728
4855
  * Fetches the latest snapshot from storage. If the fetched snapshot is same or newer than the one for which ack
4729
4856
  * was received, close this client. Fetching the snapshot will update the cache for this client so if it's
@@ -4735,7 +4862,7 @@ export class ContainerRuntime
4735
4862
  targetRefSeq: number,
4736
4863
  targetAckHandle: string,
4737
4864
  logger: ITelemetryLoggerExt,
4738
- ) {
4865
+ ): Promise<void> {
4739
4866
  const fetchedSnapshotRefSeq = await PerformanceEvent.timedExecAsync(
4740
4867
  logger,
4741
4868
  { eventName: "RefreshLatestSummaryAckFetch" },
@@ -4784,6 +4911,7 @@ export class ContainerRuntime
4784
4911
  snapshotTree = snapshot.snapshotTree;
4785
4912
  } else {
4786
4913
  const versions = await this.storage.getVersions(
4914
+ // eslint-disable-next-line unicorn/no-null
4787
4915
  null,
4788
4916
  1,
4789
4917
  scenarioName,
@@ -4799,8 +4927,8 @@ export class ContainerRuntime
4799
4927
  }
4800
4928
 
4801
4929
  props.getSnapshotDuration = trace.trace().duration;
4802
- const readAndParseBlob = async <T>(id: string) => readAndParse<T>(this.storage, id);
4803
- const snapshotRefSeq = await seqFromTree(snapshotTree, readAndParseBlob);
4930
+
4931
+ const snapshotRefSeq = await seqFromTree(snapshotTree, this.readAndParseBlob);
4804
4932
  props.snapshotRefSeq = snapshotRefSeq;
4805
4933
  props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
4806
4934
 
@@ -4852,7 +4980,7 @@ export class ContainerRuntime
4852
4980
  const logAndReturnPendingState = (
4853
4981
  event: PerformanceEvent,
4854
4982
  pendingState?: IPendingRuntimeState,
4855
- ) => {
4983
+ ): IPendingRuntimeState | undefined => {
4856
4984
  event.end({
4857
4985
  attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
4858
4986
  pendingOpsSize: pendingState?.pending?.pendingStates.length,
@@ -4880,28 +5008,28 @@ export class ContainerRuntime
4880
5008
  }
4881
5009
 
4882
5010
  public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {
4883
- if (this.isSummarizerClient) {
4884
- return this.summarizer.summarizeOnDemand(options);
4885
- } else if (this.summaryManager !== undefined) {
4886
- return this.summaryManager.summarizeOnDemand(options);
4887
- } else {
5011
+ if (this._summarizer !== undefined) {
5012
+ return this._summarizer.summarizeOnDemand(options);
5013
+ } else if (this.summaryManager === undefined) {
4888
5014
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
4889
5015
  // disableSummaries is turned on. We are throwing instead of returning a failure here,
4890
5016
  // because it is a misuse of the API rather than an expected failure.
4891
5017
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
5018
+ } else {
5019
+ return this.summaryManager.summarizeOnDemand(options);
4892
5020
  }
4893
5021
  }
4894
5022
 
4895
5023
  public enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult {
4896
- if (this.isSummarizerClient) {
4897
- return this.summarizer.enqueueSummarize(options);
4898
- } else if (this.summaryManager !== undefined) {
4899
- return this.summaryManager.enqueueSummarize(options);
4900
- } else {
5024
+ if (this._summarizer !== undefined) {
5025
+ return this._summarizer.enqueueSummarize(options);
5026
+ } else if (this.summaryManager === undefined) {
4901
5027
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
4902
5028
  // generateSummaries is turned off. We are throwing instead of returning a failure here,
4903
5029
  // because it is a misuse of the API rather than an expected failure.
4904
5030
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
5031
+ } else {
5032
+ return this.summaryManager.enqueueSummarize(options);
4905
5033
  }
4906
5034
  }
4907
5035
 
@@ -4916,7 +5044,7 @@ export class ContainerRuntime
4916
5044
 
4917
5045
  private validateSummaryHeuristicConfiguration(
4918
5046
  configuration: ISummaryConfigurationHeuristics,
4919
- ) {
5047
+ ): void {
4920
5048
  // eslint-disable-next-line no-restricted-syntax
4921
5049
  for (const prop in configuration) {
4922
5050
  if (typeof configuration[prop] === "number" && configuration[prop] < 0) {