@fluidframework/container-runtime 2.20.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 (333) hide show
  1. package/.eslintrc.cjs +36 -6
  2. package/CHANGELOG.md +38 -0
  3. package/api-report/container-runtime.legacy.alpha.api.md +31 -31
  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.map +1 -1
  9. package/dist/blobManager/blobManager.js +14 -11
  10. package/dist/blobManager/blobManager.js.map +1 -1
  11. package/dist/blobManager/blobManagerSnapSum.d.ts +1 -0
  12. package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  13. package/dist/blobManager/blobManagerSnapSum.js +7 -5
  14. package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
  15. package/dist/channelCollection.d.ts.map +1 -1
  16. package/dist/channelCollection.js +63 -41
  17. package/dist/channelCollection.js.map +1 -1
  18. package/dist/connectionTelemetry.d.ts +2 -2
  19. package/dist/connectionTelemetry.d.ts.map +1 -1
  20. package/dist/connectionTelemetry.js +4 -4
  21. package/dist/connectionTelemetry.js.map +1 -1
  22. package/dist/containerRuntime.d.ts +14 -30
  23. package/dist/containerRuntime.d.ts.map +1 -1
  24. package/dist/containerRuntime.js +264 -194
  25. package/dist/containerRuntime.js.map +1 -1
  26. package/dist/dataStore.js +6 -3
  27. package/dist/dataStore.js.map +1 -1
  28. package/dist/dataStoreContext.d.ts.map +1 -1
  29. package/dist/dataStoreContext.js +16 -11
  30. package/dist/dataStoreContext.js.map +1 -1
  31. package/dist/dataStoreContexts.d.ts.map +1 -1
  32. package/dist/dataStoreContexts.js +1 -0
  33. package/dist/dataStoreContexts.js.map +1 -1
  34. package/dist/deltaScheduler.d.ts.map +1 -1
  35. package/dist/deltaScheduler.js +5 -5
  36. package/dist/deltaScheduler.js.map +1 -1
  37. package/dist/gc/garbageCollection.d.ts.map +1 -1
  38. package/dist/gc/garbageCollection.js +36 -14
  39. package/dist/gc/garbageCollection.js.map +1 -1
  40. package/dist/gc/gcConfigs.d.ts.map +1 -1
  41. package/dist/gc/gcConfigs.js +2 -0
  42. package/dist/gc/gcConfigs.js.map +1 -1
  43. package/dist/gc/gcDefinitions.d.ts +8 -0
  44. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  45. package/dist/gc/gcDefinitions.js +1 -0
  46. package/dist/gc/gcDefinitions.js.map +1 -1
  47. package/dist/gc/gcHelpers.d.ts.map +1 -1
  48. package/dist/gc/gcHelpers.js +8 -5
  49. package/dist/gc/gcHelpers.js.map +1 -1
  50. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  51. package/dist/gc/gcSummaryStateTracker.js +2 -1
  52. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  53. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  54. package/dist/gc/gcTelemetry.js +29 -15
  55. package/dist/gc/gcTelemetry.js.map +1 -1
  56. package/dist/inboundBatchAggregator.js +3 -3
  57. package/dist/inboundBatchAggregator.js.map +1 -1
  58. package/dist/layerCompatState.d.ts +19 -0
  59. package/dist/layerCompatState.d.ts.map +1 -0
  60. package/dist/layerCompatState.js +64 -0
  61. package/dist/layerCompatState.js.map +1 -0
  62. package/dist/messageTypes.d.ts.map +1 -1
  63. package/dist/messageTypes.js.map +1 -1
  64. package/dist/opLifecycle/duplicateBatchDetector.js +2 -2
  65. package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
  66. package/dist/opLifecycle/opCompressor.d.ts +3 -2
  67. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  68. package/dist/opLifecycle/opCompressor.js +13 -19
  69. package/dist/opLifecycle/opCompressor.js.map +1 -1
  70. package/dist/opLifecycle/opDecompressor.d.ts +3 -0
  71. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  72. package/dist/opLifecycle/opDecompressor.js +4 -1
  73. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  74. package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
  75. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  76. package/dist/opLifecycle/opGroupingManager.js +5 -3
  77. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  78. package/dist/opLifecycle/opSplitter.d.ts +13 -10
  79. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  80. package/dist/opLifecycle/opSplitter.js +14 -11
  81. package/dist/opLifecycle/opSplitter.js.map +1 -1
  82. package/dist/opLifecycle/outbox.d.ts +3 -3
  83. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  84. package/dist/opLifecycle/outbox.js +11 -15
  85. package/dist/opLifecycle/outbox.js.map +1 -1
  86. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  87. package/dist/opLifecycle/remoteMessageProcessor.js +3 -1
  88. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  89. package/dist/packageVersion.d.ts +1 -1
  90. package/dist/packageVersion.js +1 -1
  91. package/dist/packageVersion.js.map +1 -1
  92. package/dist/pendingStateManager.d.ts +3 -4
  93. package/dist/pendingStateManager.d.ts.map +1 -1
  94. package/dist/pendingStateManager.js +11 -10
  95. package/dist/pendingStateManager.js.map +1 -1
  96. package/dist/summary/documentSchema.d.ts +7 -0
  97. package/dist/summary/documentSchema.d.ts.map +1 -1
  98. package/dist/summary/documentSchema.js +6 -4
  99. package/dist/summary/documentSchema.js.map +1 -1
  100. package/dist/summary/orderedClientElection.d.ts +1 -0
  101. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  102. package/dist/summary/orderedClientElection.js +13 -11
  103. package/dist/summary/orderedClientElection.js.map +1 -1
  104. package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -0
  105. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  106. package/dist/summary/runWhileConnectedCoordinator.js +7 -2
  107. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  108. package/dist/summary/runningSummarizer.d.ts +2 -2
  109. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  110. package/dist/summary/runningSummarizer.js +38 -17
  111. package/dist/summary/runningSummarizer.js.map +1 -1
  112. package/dist/summary/summarizer.d.ts +1 -0
  113. package/dist/summary/summarizer.d.ts.map +1 -1
  114. package/dist/summary/summarizer.js +18 -9
  115. package/dist/summary/summarizer.js.map +1 -1
  116. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  117. package/dist/summary/summarizerClientElection.js +1 -0
  118. package/dist/summary/summarizerClientElection.js.map +1 -1
  119. package/dist/summary/summarizerHeuristics.js +1 -1
  120. package/dist/summary/summarizerHeuristics.js.map +1 -1
  121. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  122. package/dist/summary/summarizerNode/index.js.map +1 -1
  123. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  124. package/dist/summary/summarizerNode/summarizerNode.js +30 -31
  125. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  126. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
  127. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
  128. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  129. package/dist/summary/summarizerTypes.d.ts +7 -0
  130. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  131. package/dist/summary/summarizerTypes.js.map +1 -1
  132. package/dist/summary/summaryCollection.d.ts +3 -4
  133. package/dist/summary/summaryCollection.d.ts.map +1 -1
  134. package/dist/summary/summaryCollection.js +9 -6
  135. package/dist/summary/summaryCollection.js.map +1 -1
  136. package/dist/summary/summaryFormat.d.ts +4 -1
  137. package/dist/summary/summaryFormat.d.ts.map +1 -1
  138. package/dist/summary/summaryFormat.js +3 -2
  139. package/dist/summary/summaryFormat.js.map +1 -1
  140. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  141. package/dist/summary/summaryGenerator.js +19 -8
  142. package/dist/summary/summaryGenerator.js.map +1 -1
  143. package/dist/summary/summaryManager.d.ts.map +1 -1
  144. package/dist/summary/summaryManager.js +12 -9
  145. package/dist/summary/summaryManager.js.map +1 -1
  146. package/lib/batchTracker.d.ts +1 -2
  147. package/lib/batchTracker.d.ts.map +1 -1
  148. package/lib/batchTracker.js +2 -2
  149. package/lib/batchTracker.js.map +1 -1
  150. package/lib/blobManager/blobManager.d.ts.map +1 -1
  151. package/lib/blobManager/blobManager.js +14 -11
  152. package/lib/blobManager/blobManager.js.map +1 -1
  153. package/lib/blobManager/blobManagerSnapSum.d.ts +1 -0
  154. package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  155. package/lib/blobManager/blobManagerSnapSum.js +7 -5
  156. package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
  157. package/lib/channelCollection.d.ts.map +1 -1
  158. package/lib/channelCollection.js +66 -42
  159. package/lib/channelCollection.js.map +1 -1
  160. package/lib/connectionTelemetry.d.ts +2 -2
  161. package/lib/connectionTelemetry.d.ts.map +1 -1
  162. package/lib/connectionTelemetry.js +5 -5
  163. package/lib/connectionTelemetry.js.map +1 -1
  164. package/lib/containerRuntime.d.ts +14 -30
  165. package/lib/containerRuntime.d.ts.map +1 -1
  166. package/lib/containerRuntime.js +271 -196
  167. package/lib/containerRuntime.js.map +1 -1
  168. package/lib/dataStore.js +6 -3
  169. package/lib/dataStore.js.map +1 -1
  170. package/lib/dataStoreContext.d.ts.map +1 -1
  171. package/lib/dataStoreContext.js +16 -11
  172. package/lib/dataStoreContext.js.map +1 -1
  173. package/lib/dataStoreContexts.d.ts.map +1 -1
  174. package/lib/dataStoreContexts.js +1 -0
  175. package/lib/dataStoreContexts.js.map +1 -1
  176. package/lib/deltaScheduler.d.ts.map +1 -1
  177. package/lib/deltaScheduler.js +6 -6
  178. package/lib/deltaScheduler.js.map +1 -1
  179. package/lib/gc/garbageCollection.d.ts.map +1 -1
  180. package/lib/gc/garbageCollection.js +39 -15
  181. package/lib/gc/garbageCollection.js.map +1 -1
  182. package/lib/gc/gcConfigs.d.ts.map +1 -1
  183. package/lib/gc/gcConfigs.js +2 -0
  184. package/lib/gc/gcConfigs.js.map +1 -1
  185. package/lib/gc/gcDefinitions.d.ts +8 -0
  186. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  187. package/lib/gc/gcDefinitions.js +1 -0
  188. package/lib/gc/gcDefinitions.js.map +1 -1
  189. package/lib/gc/gcHelpers.d.ts.map +1 -1
  190. package/lib/gc/gcHelpers.js +8 -5
  191. package/lib/gc/gcHelpers.js.map +1 -1
  192. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  193. package/lib/gc/gcSummaryStateTracker.js +2 -1
  194. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  195. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  196. package/lib/gc/gcTelemetry.js +32 -16
  197. package/lib/gc/gcTelemetry.js.map +1 -1
  198. package/lib/inboundBatchAggregator.js +4 -4
  199. package/lib/inboundBatchAggregator.js.map +1 -1
  200. package/lib/layerCompatState.d.ts +19 -0
  201. package/lib/layerCompatState.d.ts.map +1 -0
  202. package/lib/layerCompatState.js +60 -0
  203. package/lib/layerCompatState.js.map +1 -0
  204. package/lib/messageTypes.d.ts.map +1 -1
  205. package/lib/messageTypes.js.map +1 -1
  206. package/lib/opLifecycle/duplicateBatchDetector.js +2 -2
  207. package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
  208. package/lib/opLifecycle/opCompressor.d.ts +3 -2
  209. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  210. package/lib/opLifecycle/opCompressor.js +13 -19
  211. package/lib/opLifecycle/opCompressor.js.map +1 -1
  212. package/lib/opLifecycle/opDecompressor.d.ts +3 -0
  213. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  214. package/lib/opLifecycle/opDecompressor.js +4 -1
  215. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  216. package/lib/opLifecycle/opGroupingManager.d.ts +1 -1
  217. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  218. package/lib/opLifecycle/opGroupingManager.js +5 -3
  219. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  220. package/lib/opLifecycle/opSplitter.d.ts +13 -10
  221. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  222. package/lib/opLifecycle/opSplitter.js +14 -11
  223. package/lib/opLifecycle/opSplitter.js.map +1 -1
  224. package/lib/opLifecycle/outbox.d.ts +3 -3
  225. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  226. package/lib/opLifecycle/outbox.js +11 -15
  227. package/lib/opLifecycle/outbox.js.map +1 -1
  228. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  229. package/lib/opLifecycle/remoteMessageProcessor.js +3 -1
  230. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  231. package/lib/packageVersion.d.ts +1 -1
  232. package/lib/packageVersion.js +1 -1
  233. package/lib/packageVersion.js.map +1 -1
  234. package/lib/pendingStateManager.d.ts +3 -4
  235. package/lib/pendingStateManager.d.ts.map +1 -1
  236. package/lib/pendingStateManager.js +12 -11
  237. package/lib/pendingStateManager.js.map +1 -1
  238. package/lib/summary/documentSchema.d.ts +7 -0
  239. package/lib/summary/documentSchema.d.ts.map +1 -1
  240. package/lib/summary/documentSchema.js +6 -4
  241. package/lib/summary/documentSchema.js.map +1 -1
  242. package/lib/summary/orderedClientElection.d.ts +1 -0
  243. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  244. package/lib/summary/orderedClientElection.js +13 -11
  245. package/lib/summary/orderedClientElection.js.map +1 -1
  246. package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -0
  247. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  248. package/lib/summary/runWhileConnectedCoordinator.js +7 -2
  249. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  250. package/lib/summary/runningSummarizer.d.ts +2 -2
  251. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  252. package/lib/summary/runningSummarizer.js +38 -17
  253. package/lib/summary/runningSummarizer.js.map +1 -1
  254. package/lib/summary/summarizer.d.ts +1 -0
  255. package/lib/summary/summarizer.d.ts.map +1 -1
  256. package/lib/summary/summarizer.js +18 -9
  257. package/lib/summary/summarizer.js.map +1 -1
  258. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  259. package/lib/summary/summarizerClientElection.js +1 -0
  260. package/lib/summary/summarizerClientElection.js.map +1 -1
  261. package/lib/summary/summarizerHeuristics.js +1 -1
  262. package/lib/summary/summarizerHeuristics.js.map +1 -1
  263. package/lib/summary/summarizerNode/index.d.ts.map +1 -1
  264. package/lib/summary/summarizerNode/index.js.map +1 -1
  265. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  266. package/lib/summary/summarizerNode/summarizerNode.js +30 -31
  267. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  268. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
  269. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
  270. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  271. package/lib/summary/summarizerTypes.d.ts +7 -0
  272. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  273. package/lib/summary/summarizerTypes.js.map +1 -1
  274. package/lib/summary/summaryCollection.d.ts +3 -4
  275. package/lib/summary/summaryCollection.d.ts.map +1 -1
  276. package/lib/summary/summaryCollection.js +9 -6
  277. package/lib/summary/summaryCollection.js.map +1 -1
  278. package/lib/summary/summaryFormat.d.ts +4 -1
  279. package/lib/summary/summaryFormat.d.ts.map +1 -1
  280. package/lib/summary/summaryFormat.js +2 -2
  281. package/lib/summary/summaryFormat.js.map +1 -1
  282. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  283. package/lib/summary/summaryGenerator.js +19 -8
  284. package/lib/summary/summaryGenerator.js.map +1 -1
  285. package/lib/summary/summaryManager.d.ts.map +1 -1
  286. package/lib/summary/summaryManager.js +12 -9
  287. package/lib/summary/summaryManager.js.map +1 -1
  288. package/package.json +21 -43
  289. package/src/batchTracker.ts +3 -3
  290. package/src/blobManager/blobManager.ts +16 -14
  291. package/src/blobManager/blobManagerSnapSum.ts +8 -8
  292. package/src/channelCollection.ts +63 -44
  293. package/src/connectionTelemetry.ts +12 -6
  294. package/src/containerRuntime.ts +306 -235
  295. package/src/dataStore.ts +6 -3
  296. package/src/dataStoreContext.ts +16 -16
  297. package/src/dataStoreContexts.ts +1 -0
  298. package/src/deltaScheduler.ts +6 -6
  299. package/src/gc/garbageCollection.ts +47 -20
  300. package/src/gc/gcConfigs.ts +9 -1
  301. package/src/gc/gcDefinitions.ts +12 -0
  302. package/src/gc/gcHelpers.ts +9 -4
  303. package/src/gc/gcSummaryStateTracker.ts +3 -1
  304. package/src/gc/gcTelemetry.ts +26 -11
  305. package/src/inboundBatchAggregator.ts +4 -4
  306. package/src/layerCompatState.ts +75 -0
  307. package/src/messageTypes.ts +2 -0
  308. package/src/opLifecycle/README.md +43 -34
  309. package/src/opLifecycle/duplicateBatchDetector.ts +2 -2
  310. package/src/opLifecycle/opCompressor.ts +16 -23
  311. package/src/opLifecycle/opDecompressor.ts +4 -1
  312. package/src/opLifecycle/opGroupingManager.ts +5 -4
  313. package/src/opLifecycle/opSplitter.ts +14 -11
  314. package/src/opLifecycle/outbox.ts +13 -20
  315. package/src/opLifecycle/remoteMessageProcessor.ts +3 -1
  316. package/src/packageVersion.ts +1 -1
  317. package/src/pendingStateManager.ts +15 -10
  318. package/src/summary/documentSchema.ts +11 -4
  319. package/src/summary/orderedClientElection.ts +14 -11
  320. package/src/summary/runWhileConnectedCoordinator.ts +6 -0
  321. package/src/summary/runningSummarizer.ts +43 -19
  322. package/src/summary/summarizer.ts +24 -11
  323. package/src/summary/summarizerClientElection.ts +2 -0
  324. package/src/summary/summarizerHeuristics.ts +1 -1
  325. package/src/summary/summarizerNode/index.ts +1 -0
  326. package/src/summary/summarizerNode/summarizerNode.ts +32 -31
  327. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +4 -4
  328. package/src/summary/summarizerTypes.ts +7 -0
  329. package/src/summary/summaryCollection.ts +19 -8
  330. package/src/summary/summaryFormat.ts +10 -5
  331. package/src/summary/summaryGenerator.ts +25 -10
  332. package/src/summary/summaryManager.ts +14 -12
  333. package/container-runtime.test-files.tar +0 -0
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
5
+ import { Trace, TypedEventEmitter, } from "@fluid-internal/client-utils";
6
6
  import { AttachState, } from "@fluidframework/container-definitions";
7
7
  import { LoaderHeader, isIDeltaManagerFull, } from "@fluidframework/container-definitions/internal";
8
8
  import { assert, Deferred, LazyPromise, PromiseCache, delay, } from "@fluidframework/core-utils/internal";
@@ -24,13 +24,20 @@ import { channelToDataStore } from "./dataStore.js";
24
24
  import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
25
25
  import { DeltaManagerPendingOpsProxy, DeltaManagerSummarizerProxy, } from "./deltaManagerProxies.js";
26
26
  import { DeltaScheduler } from "./deltaScheduler.js";
27
- import { GCNodeType, GarbageCollector, gcGenerationOptionName, } from "./gc/index.js";
27
+ import {
28
+ // eslint-disable-next-line import/no-deprecated
29
+ GCNodeType, GarbageCollector, gcGenerationOptionName, } from "./gc/index.js";
28
30
  import { InboundBatchAggregator } from "./inboundBatchAggregator.js";
31
+ import { RuntimeCompatDetails, validateLoaderCompatibility } from "./layerCompatState.js";
29
32
  import { ContainerMessageType, } from "./messageTypes.js";
30
33
  import { DuplicateBatchDetector, ensureContentsDeserialized, OpCompressor, OpDecompressor, OpGroupingManager, OpSplitter, Outbox, RemoteMessageProcessor, serializeOpContents, } from "./opLifecycle/index.js";
31
34
  import { pkgVersion } from "./packageVersion.js";
32
35
  import { PendingStateManager, } from "./pendingStateManager.js";
33
- import { DocumentsSchemaController, OrderedClientCollection, OrderedClientElection, RetriableSummaryError, RunWhileConnectedCoordinator, Summarizer, SummarizerClientElection, SummaryCollection, SummaryManager, aliasBlobName, chunksBlobName, recentBatchInfoBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, rootHasIsolatedChannels, summarizerClientType, wrapSummaryInChannelsTree, } from "./summary/index.js";
36
+ import {
37
+ // eslint-disable-next-line import/no-deprecated
38
+ DocumentsSchemaController, OrderedClientCollection, OrderedClientElection, RetriableSummaryError, RunWhileConnectedCoordinator,
39
+ // eslint-disable-next-line import/no-deprecated
40
+ Summarizer, SummarizerClientElection, SummaryCollection, SummaryManager, aliasBlobName, chunksBlobName, recentBatchInfoBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, rootHasIsolatedChannels, summarizerClientType, wrapSummaryInChannelsTree, } from "./summary/index.js";
34
41
  import { Throttler, formExponentialFn } from "./throttler.js";
35
42
  /**
36
43
  * Creates an error object to be thrown / passed to Container's close fn in case of an unknown message type.
@@ -51,6 +58,9 @@ function getUnknownMessageTypeError(unknownContainerRuntimeMessageType, codePath
51
58
  },
52
59
  });
53
60
  }
61
+ export function isSummariesDisabled(config) {
62
+ return config.state === "disabled";
63
+ }
54
64
  /**
55
65
  * @legacy
56
66
  * @alpha
@@ -66,13 +76,14 @@ export const DefaultSummaryConfiguration = {
66
76
  maxOpsSinceLastSummary: 7000,
67
77
  initialSummarizerDelayMs: 5 * 1000, // 5 secs.
68
78
  nonRuntimeOpWeight: 0.1,
69
- runtimeOpWeight: 1.0,
79
+ runtimeOpWeight: 1,
70
80
  nonRuntimeHeuristicThreshold: 20,
71
81
  };
72
82
  /**
73
83
  * Error responses when requesting a deleted object will have this header set to true
74
84
  * @legacy
75
85
  * @alpha
86
+ * @deprecated This type will be moved to internal in 2.30. External usage is not necessary or supported.
76
87
  */
77
88
  export const DeletedResponseHeaderKey = "wasDeleted";
78
89
  /**
@@ -112,7 +123,7 @@ export var CompressionAlgorithms;
112
123
  * @alpha
113
124
  */
114
125
  export const disabledCompressionConfig = {
115
- minimumBatchSizeInBytes: Infinity,
126
+ minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
116
127
  compressionAlgorithm: CompressionAlgorithms.lz4,
117
128
  };
118
129
  const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
@@ -166,7 +177,9 @@ export function getDeviceSpec() {
166
177
  };
167
178
  }
168
179
  }
169
- catch { }
180
+ catch {
181
+ // Eat the error
182
+ }
170
183
  return {};
171
184
  }
172
185
  /**
@@ -207,21 +220,20 @@ async function createSummarizer(loader, url) {
207
220
  let fluidObject;
208
221
  // Older containers may not have the "getEntryPoint" API
209
222
  // ! This check will need to stay until LTS of loader moves past 2.0.0-internal.7.0.0
210
- if (resolvedContainer.getEntryPoint !== undefined) {
211
- fluidObject = await resolvedContainer.getEntryPoint();
212
- }
213
- else {
214
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment
215
- const response = await resolvedContainer.request({
223
+ if (resolvedContainer.getEntryPoint === undefined) {
224
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
225
+ const response = (await resolvedContainer.request({
216
226
  url: `/${summarizerRequestUrl}`,
217
- });
218
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
227
+ }));
219
228
  if (response.status !== 200 || response.mimeType !== "fluid/object") {
220
229
  throw responseToException(response, request);
221
230
  }
222
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
231
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
223
232
  fluidObject = response.value;
224
233
  }
234
+ else {
235
+ fluidObject = await resolvedContainer.getEntryPoint();
236
+ }
225
237
  if (fluidObject?.ISummarizer === undefined) {
226
238
  throw new UsageError("Fluid object does not implement ISummarizer");
227
239
  }
@@ -233,7 +245,9 @@ async function createSummarizer(loader, url) {
233
245
  * This allows new runtime to make documents not openable for old runtimes, one explicit document schema control is enabled.
234
246
  * Please see addMetadataToSummary() as well
235
247
  */
236
- function lastMessageFromMetadata(metadata) {
248
+ function lastMessageFromMetadata(
249
+ // eslint-disable-next-line import/no-deprecated
250
+ metadata) {
237
251
  return metadata?.documentSchema?.runtime?.explicitSchemaControl
238
252
  ? metadata?.lastMessage
239
253
  : metadata?.message;
@@ -250,6 +264,7 @@ export let getSingleUseLegacyLogCallback = (logger, type) => {
250
264
  details: { codePath, type },
251
265
  });
252
266
  // Now that we've logged, prevent future logging (globally).
267
+ // eslint-disable-next-line unicorn/consistent-function-scoping
253
268
  getSingleUseLegacyLogCallback = () => () => { };
254
269
  };
255
270
  };
@@ -263,6 +278,8 @@ export let getSingleUseLegacyLogCallback = (logger, type) => {
263
278
  export async function loadContainerRuntime(params) {
264
279
  return ContainerRuntime.loadRuntime(params);
265
280
  }
281
+ const defaultMaxConsecutiveReconnects = 7;
282
+ const defaultTelemetrySignalSampleCount = 100;
266
283
  /**
267
284
  * Represents the runtime of the container. Contains helper functions/state of the container.
268
285
  * It will define the store level mappings.
@@ -318,7 +335,9 @@ export class ContainerRuntime extends TypedEventEmitter {
318
335
  const [chunks, recentBatchInfo, metadata, electedSummarizerData, aliases, serializedIdCompressor,] = await Promise.all([
319
336
  tryFetchBlob(chunksBlobName),
320
337
  tryFetchBlob(recentBatchInfoBlobName),
338
+ // eslint-disable-next-line import/no-deprecated
321
339
  tryFetchBlob(metadataBlobName),
340
+ // eslint-disable-next-line import/no-deprecated
322
341
  tryFetchBlob(electedSummarizerBlobName),
323
342
  tryFetchBlob(aliasBlobName),
324
343
  tryFetchBlob(idCompressorBlobName),
@@ -332,6 +351,7 @@ export class ContainerRuntime extends TypedEventEmitter {
332
351
  // When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
333
352
  if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
334
353
  // Unless bypass is explicitly set, then take action when sequence numbers mismatch.
354
+ // eslint-disable-next-line unicorn/no-lonely-if -- Separate if statements make flow easier to parse
335
355
  if (loadSequenceNumberVerification !== "bypass" &&
336
356
  runtimeSequenceNumber !== protocolSequenceNumber) {
337
357
  // Message to OCEs:
@@ -354,15 +374,18 @@ export class ContainerRuntime extends TypedEventEmitter {
354
374
  }
355
375
  let desiredIdCompressorMode;
356
376
  switch (mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) {
357
- case true:
377
+ case true: {
358
378
  desiredIdCompressorMode = "on";
359
379
  break;
360
- case false:
380
+ }
381
+ case false: {
361
382
  desiredIdCompressorMode = undefined;
362
383
  break;
363
- default:
384
+ }
385
+ default: {
364
386
  desiredIdCompressorMode = enableRuntimeIdCompressor;
365
387
  break;
388
+ }
366
389
  }
367
390
  // Enabling the IdCompressor is a one-way operation and we only want to
368
391
  // allow new containers to turn it on.
@@ -415,15 +438,16 @@ export class ContainerRuntime extends TypedEventEmitter {
415
438
  if (pendingLocalState?.pendingIdCompressorState !== undefined) {
416
439
  return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
417
440
  }
418
- else if (serializedIdCompressor !== undefined) {
419
- return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
441
+ else if (serializedIdCompressor === undefined) {
442
+ return createIdCompressor(compressorLogger);
420
443
  }
421
444
  else {
422
- return createIdCompressor(compressorLogger);
445
+ return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
423
446
  }
424
447
  };
425
- const compressionLz4 = compressionOptions.minimumBatchSizeInBytes !== Infinity &&
448
+ const compressionLz4 = compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY &&
426
449
  compressionOptions.compressionAlgorithm === "lz4";
450
+ // eslint-disable-next-line import/no-deprecated
427
451
  const documentSchemaController = new DocumentsSchemaController(existing, protocolSequenceNumber, metadata?.documentSchema, {
428
452
  explicitSchemaControl,
429
453
  compressionLz4,
@@ -501,9 +525,6 @@ export class ContainerRuntime extends TypedEventEmitter {
501
525
  get sessionSchema() {
502
526
  return this.documentsSchemaController.sessionSchema.runtime;
503
527
  }
504
- get idCompressorMode() {
505
- return this.sessionSchema.idCompressorMode;
506
- }
507
528
  /**
508
529
  * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor}
509
530
  */
@@ -512,7 +533,7 @@ export class ContainerRuntime extends TypedEventEmitter {
512
533
  // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
513
534
  // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
514
535
  // to reason over such things as session ID space.
515
- if (this.idCompressorMode === "on") {
536
+ if (this.sessionSchema.idCompressorMode === "on") {
516
537
  assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
517
538
  return this._idCompressor;
518
539
  }
@@ -563,28 +584,6 @@ export class ContainerRuntime extends TypedEventEmitter {
563
584
  get disposed() {
564
585
  return this._disposed;
565
586
  }
566
- get summarizer() {
567
- assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
568
- return this._summarizer;
569
- }
570
- isSummariesDisabled() {
571
- return this.summaryConfiguration.state === "disabled";
572
- }
573
- getMaxOpsSinceLastSummary() {
574
- return this.summaryConfiguration.state !== "disabled"
575
- ? this.summaryConfiguration.maxOpsSinceLastSummary
576
- : 0;
577
- }
578
- getInitialSummarizerDelayMs() {
579
- // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
580
- // to ISummaryConfiguration in 0.60.
581
- if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
582
- return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
583
- }
584
- return this.summaryConfiguration.state !== "disabled"
585
- ? this.summaryConfiguration.initialSummarizerDelayMs
586
- : 0;
587
- }
588
587
  /**
589
588
  * If false, loading or using a Tombstoned object should merely log, not fail.
590
589
  * @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
@@ -601,14 +600,27 @@ export class ContainerRuntime extends TypedEventEmitter {
601
600
  get gcThrowOnTombstoneUsage() {
602
601
  return false;
603
602
  }
603
+ get ILayerCompatDetails() {
604
+ return RuntimeCompatDetails;
605
+ }
604
606
  /***/
605
- constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope,
607
+ constructor(context, registry,
608
+ // eslint-disable-next-line import/no-deprecated
609
+ metadata,
610
+ // eslint-disable-next-line import/no-deprecated
611
+ electedSummarizerData, chunks, dataStoreAliasMap, baseRuntimeOptions, containerScope,
606
612
  // Create a custom ITelemetryBaseLogger to output telemetry events.
607
- baseLogger, existing, blobManagerSnapshot, _storage, createIdCompressor, documentsSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler, summaryConfiguration = {
613
+ baseLogger, existing,
614
+ // eslint-disable-next-line import/no-deprecated
615
+ blobManagerSnapshot, _storage, createIdCompressor,
616
+ // eslint-disable-next-line import/no-deprecated
617
+ documentsSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler,
618
+ // eslint-disable-next-line unicorn/no-object-as-default-parameter
619
+ summaryConfiguration = {
608
620
  // the defaults
609
621
  ...DefaultSummaryConfiguration,
610
622
  // the runtime configuration overrides
611
- ...runtimeOptions.summaryOptions?.summaryConfigOverrides,
623
+ ...baseRuntimeOptions.summaryOptions?.summaryConfigOverrides,
612
624
  }, recentBatchInfo) {
613
625
  super();
614
626
  this.registry = registry;
@@ -619,19 +631,16 @@ export class ContainerRuntime extends TypedEventEmitter {
619
631
  this.createIdCompressor = createIdCompressor;
620
632
  this.documentsSchemaController = documentsSchemaController;
621
633
  this.requestHandler = requestHandler;
622
- this.summaryConfiguration = summaryConfiguration;
623
634
  this.imminentClosure = false;
624
635
  // We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
625
636
  // Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
626
637
  this.pendingIdCompressorOps = [];
627
- this.defaultMaxConsecutiveReconnects = 7;
628
638
  this._orderSequentiallyCalls = 0;
629
639
  this.flushTaskExists = false;
630
640
  this.consecutiveReconnects = 0;
631
641
  this.ensureNoDataModelChangesCalls = 0;
632
642
  this._disposed = false;
633
643
  this.emitDirtyDocumentEvent = true;
634
- this.defaultTelemetrySignalSampleCount = 100;
635
644
  this._signalTracking = {
636
645
  totalSignalsSentInLatencyWindow: 0,
637
646
  signalsLost: 0,
@@ -650,15 +659,19 @@ export class ContainerRuntime extends TypedEventEmitter {
650
659
  this.snapshotCacheForLoadingGroupIds = new PromiseCache({
651
660
  expiry: { policy: "absolute", durationMs: 60000 },
652
661
  });
662
+ this.readAndParseBlob = async (id) => readAndParse(this.storage, id);
653
663
  const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, snapshotWithContents, } = context;
664
+ // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
665
+ this.disposeFn = disposeFn ?? closeFn;
666
+ const maybeLoaderCompatDetails = context;
667
+ validateLoaderCompatibility(maybeLoaderCompatDetails.ILayerCompatDetails, this.disposeFn);
654
668
  // Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
655
- this.runtimeOptions = {
669
+ const runtimeOptions = {
656
670
  flushMode: defaultFlushMode,
657
- ...runtimeOptions,
671
+ ...baseRuntimeOptions,
658
672
  };
659
- this.logger = createChildLogger({ logger: this.baseLogger });
660
673
  this.mc = createChildMonitoringContext({
661
- logger: this.logger,
674
+ logger: this.baseLogger,
662
675
  namespace: "ContainerRuntime",
663
676
  });
664
677
  // If we support multiple algorithms in the future, then we would need to manage it here carefully.
@@ -675,19 +688,23 @@ export class ContainerRuntime extends TypedEventEmitter {
675
688
  this.innerDeltaManager = deltaManager;
676
689
  // Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
677
690
  // This makes ContainerRuntime the final gatekeeper for outgoing messages.
678
- this.submitFn = submitFn;
679
- this.submitBatchFn = submitBatchFn;
680
- this.submitSummaryFn = submitSummaryFn;
691
+ // back-compat: ADO #1385: Make this call unconditional in the future
692
+ this.submitSummaryFn =
693
+ submitSummaryFn ??
694
+ ((summaryOp, refseq) => submitFn(MessageType.Summarize, summaryOp, false));
681
695
  this.submitSignalFn = submitSignalFn;
682
696
  // TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
683
697
  // Values are generally expected to be set from the runtime side.
684
698
  this.options = options ?? {};
685
699
  this.clientDetails = clientDetails;
686
- this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
700
+ const isSummarizerClient = this.clientDetails.type === summarizerClientType;
687
701
  this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
702
+ // eslint-disable-next-line unicorn/consistent-destructuring
688
703
  this._getClientId = () => context.clientId;
704
+ // eslint-disable-next-line unicorn/consistent-destructuring
689
705
  this._getAttachState = () => context.attachState;
690
706
  this.getAbsoluteUrl = async (relativeUrl) => {
707
+ // eslint-disable-next-line unicorn/consistent-destructuring
691
708
  if (context.getAbsoluteUrl === undefined) {
692
709
  throw new Error("Driver does not implement getAbsoluteUrl");
693
710
  }
@@ -700,10 +717,8 @@ export class ContainerRuntime extends TypedEventEmitter {
700
717
  // customer should observe dirty state on the runtime (the owner of dirty state) directly, rather than on the IContainer.
701
718
  this.on("dirty", () => context.updateDirtyContainerState(true));
702
719
  this.on("saved", () => context.updateDirtyContainerState(false));
703
- // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
704
- this.disposeFn = disposeFn ?? closeFn;
705
720
  // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
706
- this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
721
+ this.closeFn = isSummarizerClient ? this.disposeFn : closeFn;
707
722
  let loadSummaryNumber;
708
723
  // Get the container creation metadata. For new container, we initialize these. For existing containers,
709
724
  // get the values from the metadata blob.
@@ -733,16 +748,14 @@ export class ContainerRuntime extends TypedEventEmitter {
733
748
  metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
734
749
  inputs: JSON.stringify({
735
750
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
736
- gcOptions_gcGeneration: this.runtimeOptions.gcOptions[gcGenerationOptionName],
751
+ gcOptions_gcGeneration: runtimeOptions.gcOptions[gcGenerationOptionName],
737
752
  }),
738
753
  });
739
754
  this.telemetryDocumentId = metadata?.telemetryDocumentId ?? uuid();
740
- this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
741
755
  const opGroupingManager = new OpGroupingManager({
742
756
  groupedBatchingEnabled: this.groupedBatchingEnabled,
743
- opCountThreshold: this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
744
757
  }, this.mc.logger);
745
- const opSplitter = new OpSplitter(chunks, this.submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
758
+ const opSplitter = new OpSplitter(chunks, submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
746
759
  this.remoteMessageProcessor = new RemoteMessageProcessor(opSplitter, new OpDecompressor(this.mc.logger), opGroupingManager);
747
760
  const pendingRuntimeState = pendingLocalState;
748
761
  this.pendingStateManager = new PendingStateManager({
@@ -752,7 +765,7 @@ export class ContainerRuntime extends TypedEventEmitter {
752
765
  reSubmitBatch: this.reSubmitBatch.bind(this),
753
766
  isActiveConnection: () => this.innerDeltaManager.active,
754
767
  isAttached: () => this.attachState !== AttachState.Detached,
755
- }, pendingRuntimeState?.pending, this.logger);
768
+ }, pendingRuntimeState?.pending, this.baseLogger);
756
769
  let outerDeltaManager;
757
770
  this.useDeltaManagerOpsProxy =
758
771
  this.mc.config.getBoolean("Fluid.ContainerRuntime.DeltaManagerOpsProxy") === true;
@@ -767,24 +780,35 @@ export class ContainerRuntime extends TypedEventEmitter {
767
780
  }
768
781
  this._deltaManager = outerDeltaManager;
769
782
  this.handleContext = new ContainerFluidHandleContext("", this);
770
- if (this.summaryConfiguration.state === "enabled") {
771
- this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
772
- }
773
- this.summariesDisabled = this.isSummariesDisabled();
774
- this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
775
- this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
783
+ if (summaryConfiguration.state === "enabled") {
784
+ this.validateSummaryHeuristicConfiguration(summaryConfiguration);
785
+ }
786
+ this.summariesDisabled = isSummariesDisabled(summaryConfiguration);
787
+ const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = isSummariesDisabled(summaryConfiguration)
788
+ ? {}
789
+ : {
790
+ ...summaryConfiguration,
791
+ initialSummarizerDelayMs:
792
+ // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
793
+ // to ISummaryConfiguration in 0.60.
794
+ runtimeOptions.summaryOptions.initialSummarizerDelayMs ??
795
+ summaryConfiguration.initialSummarizerDelayMs,
796
+ };
776
797
  this.maxConsecutiveReconnects =
777
- this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
778
- this.defaultMaxConsecutiveReconnects;
779
- if (this.runtimeOptions.flushMode ===
780
- FlushModeExperimental.Async &&
781
- supportedFeatures?.get("referenceSequenceNumbers") !== true) {
798
+ this.mc.config.getNumber(maxConsecutiveReconnectsKey) ?? defaultMaxConsecutiveReconnects;
799
+ // If the context has ILayerCompatDetails, it supports referenceSequenceNumbers since that features
800
+ // predates ILayerCompatDetails.
801
+ const referenceSequenceNumbersSupported = maybeLoaderCompatDetails.ILayerCompatDetails === undefined
802
+ ? supportedFeatures?.get("referenceSequenceNumbers") === true
803
+ : true;
804
+ if (runtimeOptions.flushMode === FlushModeExperimental.Async &&
805
+ !referenceSequenceNumbersSupported) {
782
806
  // The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
783
807
  this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
784
808
  this._flushMode = FlushMode.TurnBased;
785
809
  }
786
810
  else {
787
- this._flushMode = this.runtimeOptions.flushMode;
811
+ this._flushMode = runtimeOptions.flushMode;
788
812
  }
789
813
  this.offlineEnabled =
790
814
  this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
@@ -799,6 +823,7 @@ export class ContainerRuntime extends TypedEventEmitter {
799
823
  if (this.offlineEnabled) {
800
824
  this.duplicateBatchDetector = new DuplicateBatchDetector(recentBatchInfo);
801
825
  }
826
+ // eslint-disable-next-line unicorn/consistent-destructuring
802
827
  if (context.attachState === AttachState.Attached) {
803
828
  const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
804
829
  if (maxSnapshotCacheDurationMs !== undefined &&
@@ -811,13 +836,13 @@ export class ContainerRuntime extends TypedEventEmitter {
811
836
  }
812
837
  this.garbageCollector = GarbageCollector.create({
813
838
  runtime: this,
814
- gcOptions: this.runtimeOptions.gcOptions,
839
+ gcOptions: runtimeOptions.gcOptions,
815
840
  baseSnapshot,
816
841
  baseLogger: this.mc.logger,
817
842
  existing,
818
843
  metadata,
819
844
  createContainerMetadata: this.createContainerMetadata,
820
- isSummarizerClient: this.isSummarizerClient,
845
+ isSummarizerClient,
821
846
  getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
822
847
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
823
848
  readAndParseBlob: async (id) => readAndParse(this.storage, id),
@@ -831,7 +856,7 @@ export class ContainerRuntime extends TypedEventEmitter {
831
856
  const summaryReferenceSequenceNumber = baseSnapshot === undefined || metadata?.disableIsolatedChannels === true
832
857
  ? undefined
833
858
  : loadedFromSequenceNumber;
834
- this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
859
+ this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.baseLogger, namespace: "SummarizerNode" }),
835
860
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
836
861
  async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
837
862
  // Latest change sequence number, no changes since summary applied yet
@@ -891,14 +916,14 @@ export class ContainerRuntime extends TypedEventEmitter {
891
916
  stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
892
917
  closeContainer: (error) => this.closeFn(error),
893
918
  });
894
- this.deltaScheduler = new DeltaScheduler(this.innerDeltaManager, this, createChildLogger({ logger: this.logger, namespace: "DeltaScheduler" }));
895
- this.inboundBatchAggregator = new InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, createChildLogger({ logger: this.logger, namespace: "InboundBatchAggregator" }));
919
+ this.deltaScheduler = new DeltaScheduler(this.innerDeltaManager, this, createChildLogger({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
920
+ this.inboundBatchAggregator = new InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, createChildLogger({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
896
921
  const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
897
- const legacySendBatchFn = makeLegacySendBatchFn(this.submitFn, this.innerDeltaManager);
922
+ const legacySendBatchFn = makeLegacySendBatchFn(submitFn, this.innerDeltaManager);
898
923
  this.outbox = new Outbox({
899
924
  shouldSend: () => this.canSendOps(),
900
925
  pendingStateManager: this.pendingStateManager,
901
- submitBatchFn: this.submitBatchFn,
926
+ submitBatchFn,
902
927
  legacySendBatchFn,
903
928
  compressor: new OpCompressor(this.mc.logger),
904
929
  splitter: opSplitter,
@@ -945,7 +970,7 @@ export class ContainerRuntime extends TypedEventEmitter {
945
970
  const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
946
971
  this.closeSummarizerDelayMs =
947
972
  closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
948
- this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
973
+ const summaryCollection = new SummaryCollection(this.deltaManager, this.baseLogger);
949
974
  this.dirtyContainer =
950
975
  this.attachState !== AttachState.Attached || this.hasPendingMessages();
951
976
  context.updateDirtyContainerState(this.dirtyContainer);
@@ -954,14 +979,17 @@ export class ContainerRuntime extends TypedEventEmitter {
954
979
  }
955
980
  else {
956
981
  const orderedClientLogger = createChildLogger({
957
- logger: this.logger,
982
+ logger: this.baseLogger,
958
983
  namespace: "OrderedClientElection",
959
984
  });
960
985
  const orderedClientCollection = new OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
961
986
  const orderedClientElectionForSummarizer = new OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, SummarizerClientElection.isClientEligible, this.mc.config.getBoolean("Fluid.ContainerRuntime.OrderedClientElection.EnablePerformanceEvents"));
962
- this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
963
- if (this.isSummarizerClient) {
964
- this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => RunWhileConnectedCoordinator.create(runtime,
987
+ this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary);
988
+ if (isSummarizerClient) {
989
+ // eslint-disable-next-line import/no-deprecated
990
+ this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, summaryCollection,
991
+ // eslint-disable-next-line import/no-deprecated
992
+ async (runtime) => RunWhileConnectedCoordinator.create(runtime,
965
993
  // Summarization runs in summarizer client and needs access to the real (non-proxy) active
966
994
  // information. The proxy delta manager would always return false for summarizer client.
967
995
  () => this.innerDeltaManager.active));
@@ -970,48 +998,49 @@ export class ContainerRuntime extends TypedEventEmitter {
970
998
  // Only create a SummaryManager and SummarizerClientElection
971
999
  // if summaries are enabled and we are not the summarizer client.
972
1000
  const defaultAction = () => {
973
- if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
1001
+ if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
974
1002
  this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
975
1003
  // unregister default to no log on every op after falling behind
976
1004
  // and register summary ack handler to re-register this handler
977
1005
  // after successful summary
978
- this.summaryCollection.once(MessageType.SummaryAck, () => {
1006
+ summaryCollection.once(MessageType.SummaryAck, () => {
979
1007
  this.mc.logger.sendTelemetryEvent({
980
1008
  eventName: "SummaryStatus:CaughtUp",
981
1009
  });
982
1010
  // we've caught up, so re-register the default action to monitor for
983
1011
  // falling behind, and unregister ourself
984
- this.summaryCollection.on("default", defaultAction);
1012
+ summaryCollection.on("default", defaultAction);
985
1013
  });
986
- this.summaryCollection.off("default", defaultAction);
1014
+ summaryCollection.off("default", defaultAction);
987
1015
  }
988
1016
  };
989
- this.summaryCollection.on("default", defaultAction);
1017
+ summaryCollection.on("default", defaultAction);
990
1018
  // Create the SummaryManager and mark the initial state
991
1019
  this.summaryManager = new SummaryManager(this.summarizerClientElection, this, // IConnectedState
992
- this.summaryCollection, this.logger, this.formCreateSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
1020
+ summaryCollection, this.baseLogger, this.formCreateSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
993
1021
  30 * 1000, // 30 sec max delay
994
1022
  // throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
995
1023
  formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
996
- initialDelayMs: this.initialSummarizerDelayMs,
1024
+ initialDelayMs: initialSummarizerDelayMs,
997
1025
  });
998
1026
  // Forward events from SummaryManager
999
- [
1027
+ for (const eventName of [
1000
1028
  "summarize",
1001
1029
  "summarizeAllAttemptsFailed",
1002
1030
  "summarizerStop",
1003
1031
  "summarizerStart",
1004
1032
  "summarizerStartupFailed",
1005
- ].forEach((eventName) => {
1033
+ ]) {
1006
1034
  this.summaryManager?.on(eventName, (...args) => {
1007
1035
  this.emit(eventName, ...args);
1008
1036
  });
1009
- });
1037
+ }
1010
1038
  this.summaryManager.start();
1011
1039
  }
1012
1040
  }
1013
1041
  // logging hardware telemetry
1014
- this.logger.sendTelemetryEvent({
1042
+ this.baseLogger.send({
1043
+ category: "generic",
1015
1044
  eventName: "DeviceSpec",
1016
1045
  ...getDeviceSpec(),
1017
1046
  });
@@ -1023,13 +1052,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1023
1052
  summaryFormatVersion: metadata?.summaryFormatVersion,
1024
1053
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
1025
1054
  gcVersion: metadata?.gcFeature,
1026
- options: JSON.stringify(runtimeOptions),
1055
+ options: JSON.stringify(baseRuntimeOptions),
1027
1056
  idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
1028
- idCompressorMode: this.idCompressorMode,
1057
+ idCompressorMode: this.sessionSchema.idCompressorMode,
1029
1058
  sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
1030
1059
  featureGates: JSON.stringify({
1031
1060
  ...featureGatesForTelemetry,
1032
- disableAttachReorder: this.disableAttachReorder,
1033
1061
  disablePartialFlush,
1034
1062
  closeSummarizerDelayOverride,
1035
1063
  }),
@@ -1037,11 +1065,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1037
1065
  groupedBatchingEnabled: this.groupedBatchingEnabled,
1038
1066
  initialSequenceNumber: this.deltaManager.initialSequenceNumber,
1039
1067
  });
1040
- ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.logger);
1041
- BindBatchTracker(this, this.logger);
1068
+ ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
1069
+ BindBatchTracker(this, this.baseLogger);
1042
1070
  this.entryPoint = new LazyPromise(async () => {
1043
- if (this.isSummarizerClient) {
1044
- assert(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
1071
+ if (this._summarizer !== undefined) {
1045
1072
  return this._summarizer;
1046
1073
  }
1047
1074
  return provideEntryPoint(this);
@@ -1050,8 +1077,9 @@ export class ContainerRuntime extends TypedEventEmitter {
1050
1077
  // saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
1051
1078
  this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
1052
1079
  }
1080
+ // eslint-disable-next-line import/no-deprecated
1053
1081
  onSchemaChange(schema) {
1054
- this.logger.sendTelemetryEvent({
1082
+ this.mc.logger.sendTelemetryEvent({
1055
1083
  eventName: "SchemaChangeAccept",
1056
1084
  sessionRuntimeSchema: JSON.stringify(schema),
1057
1085
  });
@@ -1086,8 +1114,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1086
1114
  * Initializes the state from the base snapshot this container runtime loaded from.
1087
1115
  */
1088
1116
  async initializeBaseState() {
1089
- if (this.idCompressorMode === "on" ||
1090
- (this.idCompressorMode === "delayed" && this.connected)) {
1117
+ if (this.sessionSchema.idCompressorMode === "on" ||
1118
+ (this.sessionSchema.idCompressorMode === "delayed" && this.connected)) {
1091
1119
  this._idCompressor = await this.createIdCompressor();
1092
1120
  // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
1093
1121
  assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
@@ -1130,7 +1158,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1130
1158
  // Lookup up in the cache, if not present then make the network call as multiple datastores could
1131
1159
  // be in same loading group. So, once we have fetched the snapshot for that loading group on
1132
1160
  // any request, then cache that as same group could be requested in future too.
1133
- const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
1161
+ const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(","), async () => {
1134
1162
  assert(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
1135
1163
  loadedFromCache = false;
1136
1164
  return this.storage.getSnapshot({
@@ -1139,7 +1167,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1139
1167
  loadingGroupIds: sortedLoadingGroupIds,
1140
1168
  });
1141
1169
  });
1142
- this.logger.sendTelemetryEvent({
1170
+ this.mc.logger.sendTelemetryEvent({
1143
1171
  eventName: "GroupIdSnapshotFetched",
1144
1172
  details: JSON.stringify({
1145
1173
  fromCache: loadedFromCache,
@@ -1169,7 +1197,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1169
1197
  // another snapshot from which the summarizer loaded and it is behind, then just give up as
1170
1198
  // the summarizer state is not up to date.
1171
1199
  // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
1172
- if (this.isSummarizerClient) {
1200
+ if (this._summarizer !== undefined) {
1173
1201
  throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
1174
1202
  }
1175
1203
  // We want to catchup from sequenceNumber to targetSequenceNumber
@@ -1231,7 +1259,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1231
1259
  return {
1232
1260
  status: 200,
1233
1261
  mimeType: "fluid/object",
1234
- value: this.summarizer,
1262
+ value: this._summarizer,
1235
1263
  };
1236
1264
  }
1237
1265
  return create404Response(request);
@@ -1297,6 +1325,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1297
1325
  const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
1298
1326
  // Is document schema explicit control on?
1299
1327
  const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
1328
+ // eslint-disable-next-line import/no-deprecated
1300
1329
  const metadata = {
1301
1330
  ...this.createContainerMetadata,
1302
1331
  // Increment the summary number for the next summary that will be generated.
@@ -1310,7 +1339,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1310
1339
  // last message's sequence number.
1311
1340
  // See also lastMessageFromMetadata()
1312
1341
  message: explicitSchemaControl
1313
- ? { sequenceNumber: -1 }
1342
+ ? // eslint-disable-next-line import/no-deprecated
1343
+ { sequenceNumber: -1 }
1314
1344
  : message,
1315
1345
  lastMessage: explicitSchemaControl ? message : undefined,
1316
1346
  documentSchema,
@@ -1426,9 +1456,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1426
1456
  switch (opContents.type) {
1427
1457
  case ContainerMessageType.FluidDataStoreOp:
1428
1458
  case ContainerMessageType.Attach:
1429
- case ContainerMessageType.Alias:
1459
+ case ContainerMessageType.Alias: {
1430
1460
  return this.channelCollection.applyStashedOp(opContents);
1431
- case ContainerMessageType.IdAllocation:
1461
+ }
1462
+ case ContainerMessageType.IdAllocation: {
1432
1463
  // IDs allocation ops in stashed state are ignored because the tip state of the compressor
1433
1464
  // is serialized into the pending state. This is done because generation of new IDs during
1434
1465
  // stashed op application (or, later, resubmit) must generate new IDs and if the compressor
@@ -1438,17 +1469,22 @@ export class ContainerRuntime extends TypedEventEmitter {
1438
1469
  // and the runtime could filter out all ID allocation ops from the stashed state and apply them
1439
1470
  // before applying the rest of the stashed ops. This would accomplish the same thing but with
1440
1471
  // better performance in future incremental stashed state creation.
1441
- assert(this.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
1472
+ assert(this.sessionSchema.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
1442
1473
  return;
1443
- case ContainerMessageType.DocumentSchemaChange:
1474
+ }
1475
+ case ContainerMessageType.DocumentSchemaChange: {
1444
1476
  return;
1445
- case ContainerMessageType.BlobAttach:
1477
+ }
1478
+ case ContainerMessageType.BlobAttach: {
1446
1479
  return;
1447
- case ContainerMessageType.Rejoin:
1480
+ }
1481
+ case ContainerMessageType.Rejoin: {
1448
1482
  throw new Error("rejoin not expected here");
1449
- case ContainerMessageType.GC:
1483
+ }
1484
+ case ContainerMessageType.GC: {
1450
1485
  // GC op is only sent in summarizer which should never have stashed ops.
1451
1486
  throw new LoggingError("GC op not expected to be stashed in summarizer");
1487
+ }
1452
1488
  default: {
1453
1489
  const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
1454
1490
  this.closeFn(error);
@@ -1458,7 +1494,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1458
1494
  }
1459
1495
  async loadIdCompressor() {
1460
1496
  if (this._idCompressor === undefined &&
1461
- this.idCompressorMode !== undefined &&
1497
+ this.sessionSchema.idCompressorMode !== undefined &&
1462
1498
  this._loadIdCompressor === undefined) {
1463
1499
  this._loadIdCompressor = this.createIdCompressor()
1464
1500
  .then((compressor) => {
@@ -1472,7 +1508,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1472
1508
  this._idCompressor = compressor;
1473
1509
  })
1474
1510
  .catch((error) => {
1475
- this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
1511
+ this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
1476
1512
  throw error;
1477
1513
  });
1478
1514
  }
@@ -1483,7 +1519,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1483
1519
  const currentClientId = this._audience.getSelf()?.clientId;
1484
1520
  assert(clientId === currentClientId, 0x977 /* input clientId does not match Audience */);
1485
1521
  assert(this.clientId === currentClientId, 0x978 /* this.clientId does not match Audience */);
1486
- if (connected && this.idCompressorMode === "delayed") {
1522
+ if (connected && this.sessionSchema.idCompressorMode === "delayed") {
1487
1523
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1488
1524
  this.loadIdCompressor();
1489
1525
  }
@@ -1572,7 +1608,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1572
1608
  // or something different, like a system message.
1573
1609
  const hasModernRuntimeMessageEnvelope = messageCopy.type === MessageType.Operation;
1574
1610
  const savedOp = messageCopy.metadata?.savedOp;
1575
- const logLegacyCase = getSingleUseLegacyLogCallback(this.logger, messageCopy.type);
1611
+ const logLegacyCase = getSingleUseLegacyLogCallback(this.mc.logger, messageCopy.type);
1576
1612
  let runtimeBatch = hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
1577
1613
  if (runtimeBatch) {
1578
1614
  // We expect runtime messages to have JSON contents - deserialize it in place.
@@ -1674,11 +1710,11 @@ export class ContainerRuntime extends TypedEventEmitter {
1674
1710
  let error;
1675
1711
  try {
1676
1712
  if (!runtimeBatch) {
1677
- messagesWithMetadata.forEach(({ message }) => {
1713
+ for (const { message } of messagesWithMetadata) {
1678
1714
  this.ensureNoDataModelChanges(() => {
1679
1715
  this.observeNonRuntimeMessage(message);
1680
1716
  });
1681
- });
1717
+ }
1682
1718
  return;
1683
1719
  }
1684
1720
  // Updates a message's minimum sequence number to the minimum sequence number that container
@@ -1746,8 +1782,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1746
1782
  this.emit("op", message, true /* runtimeMessage */);
1747
1783
  }
1748
1784
  }
1749
- catch (e) {
1750
- error = e;
1785
+ catch (error_) {
1786
+ error = error_;
1751
1787
  throw error;
1752
1788
  }
1753
1789
  finally {
@@ -1804,30 +1840,39 @@ export class ContainerRuntime extends TypedEventEmitter {
1804
1840
  switch (message.type) {
1805
1841
  case ContainerMessageType.FluidDataStoreOp:
1806
1842
  case ContainerMessageType.Attach:
1807
- case ContainerMessageType.Alias:
1843
+ case ContainerMessageType.Alias: {
1808
1844
  // Remove the metadata from the message before sending it to the channel collection. The metadata
1809
1845
  // is added by the container runtime and is not part of the message that the channel collection and
1810
1846
  // layers below it expect.
1811
1847
  this.channelCollection.processMessages({ envelope: message, messagesContent, local });
1812
1848
  break;
1813
- case ContainerMessageType.BlobAttach:
1849
+ }
1850
+ case ContainerMessageType.BlobAttach: {
1814
1851
  this.blobManager.processBlobAttachMessage(message, local);
1815
1852
  break;
1816
- case ContainerMessageType.IdAllocation:
1853
+ }
1854
+ case ContainerMessageType.IdAllocation: {
1817
1855
  this.processIdCompressorMessages(contents, savedOp);
1818
1856
  break;
1819
- case ContainerMessageType.GC:
1857
+ }
1858
+ case ContainerMessageType.GC: {
1820
1859
  this.garbageCollector.processMessages(contents, message.timestamp, local);
1821
1860
  break;
1822
- case ContainerMessageType.ChunkedOp:
1861
+ }
1862
+ case ContainerMessageType.ChunkedOp: {
1823
1863
  // From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
1824
1864
  // Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
1825
1865
  assert(false, 0x93d /* should not even get here */);
1826
- case ContainerMessageType.Rejoin:
1866
+ }
1867
+ case ContainerMessageType.Rejoin: {
1827
1868
  break;
1828
- case ContainerMessageType.DocumentSchemaChange:
1829
- this.documentsSchemaController.processDocumentSchemaMessages(contents, local, message.sequenceNumber);
1869
+ }
1870
+ case ContainerMessageType.DocumentSchemaChange: {
1871
+ this.documentsSchemaController.processDocumentSchemaMessages(
1872
+ // eslint-disable-next-line import/no-deprecated
1873
+ contents, local, message.sequenceNumber);
1830
1874
  break;
1875
+ }
1831
1876
  default: {
1832
1877
  const error = getUnknownMessageTypeError(message.type, "validateAndProcessRuntimeMessage" /* codePath */, message);
1833
1878
  this.closeFn(error);
@@ -1845,7 +1890,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1845
1890
  // Some other client turned on the id compressor. If we have not turned it on,
1846
1891
  // put it in a pending queue and delay finalization.
1847
1892
  if (this._idCompressor === undefined) {
1848
- assert(this.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
1893
+ assert(this.sessionSchema.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
1849
1894
  this.pendingIdCompressorOps.push(range);
1850
1895
  }
1851
1896
  else {
@@ -1879,7 +1924,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1879
1924
  * Updates signal telemetry including emitting telemetry events.
1880
1925
  */
1881
1926
  processSignalForTelemetry(envelope) {
1882
- const { clientBroadcastSignalSequenceNumber } = envelope;
1927
+ const { clientBroadcastSignalSequenceNumber, contents: envelopeContents, address: envelopeAddress, } = envelope;
1883
1928
  if (clientBroadcastSignalSequenceNumber === undefined) {
1884
1929
  return;
1885
1930
  }
@@ -1917,8 +1962,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1917
1962
  };
1918
1963
  // Only log `contents.type` when address is for container to avoid
1919
1964
  // chance that contents type is customer data.
1920
- if (envelope.address === undefined) {
1921
- details.contentsType = envelope.contents.type; // Type of signal that was received out of order.
1965
+ if (envelopeAddress === undefined) {
1966
+ details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
1922
1967
  }
1923
1968
  this.mc.logger.sendTelemetryEvent({
1924
1969
  eventName: "SignalOutOfOrder",
@@ -1999,8 +2044,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1999
2044
  try {
2000
2045
  checkpoint.rollback((message) => this.rollback(message.contents, message.localOpMetadata));
2001
2046
  }
2002
- catch (err) {
2003
- const error2 = wrapError(err, (message) => {
2047
+ catch (error_) {
2048
+ const error2 = wrapError(error_, (message) => {
2004
2049
  return DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
2005
2050
  });
2006
2051
  this.closeFn(error2);
@@ -2111,8 +2156,9 @@ export class ContainerRuntime extends TypedEventEmitter {
2111
2156
  case ContainerMessageType.GC: {
2112
2157
  return false;
2113
2158
  }
2114
- default:
2159
+ default: {
2115
2160
  break;
2161
+ }
2116
2162
  }
2117
2163
  return true;
2118
2164
  }
@@ -2141,7 +2187,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2141
2187
  clientBroadcastSignalSequenceNumber;
2142
2188
  }
2143
2189
  // We should not track the round trip of a new signal in the case we are already tracking one.
2144
- if (clientBroadcastSignalSequenceNumber % this.defaultTelemetrySignalSampleCount === 1 &&
2190
+ if (clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
2145
2191
  this._signalTracking.roundTripSignalSequenceNumber === undefined) {
2146
2192
  this._signalTracking.signalTimestamp = Date.now();
2147
2193
  this._signalTracking.roundTripSignalSequenceNumber =
@@ -2207,6 +2253,12 @@ export class ContainerRuntime extends TypedEventEmitter {
2207
2253
  this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
2208
2254
  return summarizeResult.summary;
2209
2255
  }
2256
+ /**
2257
+ * Builds the Summary tree including all the channels and the container state.
2258
+ *
2259
+ * @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
2260
+ * so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
2261
+ */
2210
2262
  async summarizeInternal(fullTree, trackState, telemetryContext) {
2211
2263
  const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
2212
2264
  // Wrap data store summaries in .channels subtree.
@@ -2287,8 +2339,10 @@ export class ContainerRuntime extends TypedEventEmitter {
2287
2339
  */
2288
2340
  deleteSweepReadyNodes(sweepReadyRoutes) {
2289
2341
  const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
2290
- const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
2291
- return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
2342
+ return [
2343
+ ...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
2344
+ ...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
2345
+ ];
2292
2346
  }
2293
2347
  /**
2294
2348
  * This is called to update objects that are tombstones.
@@ -2314,10 +2368,13 @@ export class ContainerRuntime extends TypedEventEmitter {
2314
2368
  * Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
2315
2369
  * blob manager.
2316
2370
  */
2371
+ // eslint-disable-next-line import/no-deprecated
2317
2372
  getNodeType(nodePath) {
2318
2373
  if (isBlobPath(nodePath)) {
2374
+ // eslint-disable-next-line import/no-deprecated
2319
2375
  return GCNodeType.Blob;
2320
2376
  }
2377
+ // eslint-disable-next-line import/no-deprecated
2321
2378
  return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
2322
2379
  }
2323
2380
  /**
@@ -2331,13 +2388,19 @@ export class ContainerRuntime extends TypedEventEmitter {
2331
2388
  return ["_gcRoot"];
2332
2389
  }
2333
2390
  switch (this.getNodeType(nodePath)) {
2334
- case GCNodeType.Blob:
2391
+ // eslint-disable-next-line import/no-deprecated
2392
+ case GCNodeType.Blob: {
2335
2393
  return [blobManagerBasePath];
2394
+ }
2395
+ // eslint-disable-next-line import/no-deprecated
2336
2396
  case GCNodeType.DataStore:
2337
- case GCNodeType.SubDataStore:
2397
+ // eslint-disable-next-line import/no-deprecated
2398
+ case GCNodeType.SubDataStore: {
2338
2399
  return this.channelCollection.getDataStorePackagePath(nodePath);
2339
- default:
2400
+ }
2401
+ default: {
2340
2402
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
2403
+ }
2341
2404
  }
2342
2405
  }
2343
2406
  /**
@@ -2399,8 +2462,9 @@ export class ContainerRuntime extends TypedEventEmitter {
2399
2462
  * op processing, updating SummarizerNode state tracking, and garbage collection.
2400
2463
  * @param options - options controlling how the summary is generated or submitted
2401
2464
  */
2465
+ // eslint-disable-next-line import/no-deprecated
2402
2466
  async submitSummary(options) {
2403
- const { fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
2467
+ const { cancellationToken, fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
2404
2468
  // The summary number for this summary. This will be updated during the summary process, so get it now and
2405
2469
  // use it for all events logged during this summary.
2406
2470
  const summaryNumber = this.nextSummaryNumber;
@@ -2484,7 +2548,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2484
2548
  eventName: "LatestSummaryRefSeqNumMismatch",
2485
2549
  details: {
2486
2550
  ...startSummaryResult,
2487
- mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
2551
+ mismatchNumbers: [...startSummaryResult.mismatchNumbers],
2488
2552
  },
2489
2553
  });
2490
2554
  if (shouldValidatePreSummaryState && !finalAttempt) {
@@ -2504,7 +2568,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2504
2568
  // summarizer to reconnect in the future.
2505
2569
  // Also checking for cancellation is a must as summary process may be abandoned for other reasons,
2506
2570
  // like loss of connectivity for main (interactive) client.
2507
- if (options.cancellationToken.cancelled) {
2571
+ if (cancellationToken.cancelled) {
2508
2572
  return { continue: false, error: "disconnected" };
2509
2573
  }
2510
2574
  // That said, we rely on submitSystemMessage() that today only works in connected state.
@@ -2617,7 +2681,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2617
2681
  };
2618
2682
  let handle;
2619
2683
  try {
2620
- handle = await this.storage.uploadSummaryWithContext(summarizeResult.summary, summaryContext);
2684
+ handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
2621
2685
  }
2622
2686
  catch (error) {
2623
2687
  return {
@@ -2739,13 +2803,13 @@ export class ContainerRuntime extends TypedEventEmitter {
2739
2803
  return this.pendingMessagesCount !== 0;
2740
2804
  }
2741
2805
  updateDocumentDirtyState(dirty) {
2742
- if (this.attachState !== AttachState.Attached) {
2743
- assert(dirty, 0x3d2 /* Non-attached container is dirty */);
2744
- }
2745
- else {
2806
+ if (this.attachState === AttachState.Attached) {
2746
2807
  // Other way is not true = see this.isContainerMessageDirtyable()
2747
2808
  assert(!dirty || this.hasPendingMessages(), 0x3d3 /* if doc is dirty, there has to be pending ops */);
2748
2809
  }
2810
+ else {
2811
+ assert(dirty, 0x3d2 /* Non-attached container is dirty */);
2812
+ }
2749
2813
  if (this.dirtyContainer === dirty) {
2750
2814
  return;
2751
2815
  }
@@ -2807,7 +2871,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2807
2871
  // on this callback to do actual sending.
2808
2872
  const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
2809
2873
  if (schemaChangeMessage) {
2810
- this.logger.sendTelemetryEvent({
2874
+ this.mc.logger.sendTelemetryEvent({
2811
2875
  eventName: "SchemaChangeProposal",
2812
2876
  refSeq: schemaChangeMessage.refSeq,
2813
2877
  version: schemaChangeMessage.version,
@@ -2859,6 +2923,8 @@ export class ContainerRuntime extends TypedEventEmitter {
2859
2923
  return;
2860
2924
  }
2861
2925
  this.flushTaskExists = true;
2926
+ // TODO: hoist this out of the function scope to save unnecessary allocations
2927
+ // eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
2862
2928
  const flush = () => {
2863
2929
  this.flushTaskExists = false;
2864
2930
  try {
@@ -2869,22 +2935,25 @@ export class ContainerRuntime extends TypedEventEmitter {
2869
2935
  }
2870
2936
  };
2871
2937
  switch (this.flushMode) {
2872
- case FlushMode.TurnBased:
2938
+ case FlushMode.TurnBased: {
2873
2939
  // When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
2874
2940
  // batch at the end of the turn
2875
2941
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
2876
2942
  Promise.resolve().then(flush);
2877
2943
  break;
2944
+ }
2878
2945
  // FlushModeExperimental is experimental and not exposed directly in the runtime APIs
2879
- case FlushModeExperimental.Async:
2946
+ case FlushModeExperimental.Async: {
2880
2947
  // When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
2881
2948
  // batch when all micro-tasks are complete.
2882
2949
  // Compared to TurnBased, this flush mode will capture more ops into the same batch.
2883
2950
  setTimeout(flush, 0);
2884
2951
  break;
2885
- default:
2952
+ }
2953
+ default: {
2886
2954
  assert(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
2887
2955
  break;
2956
+ }
2888
2957
  }
2889
2958
  }
2890
2959
  submitSummaryMessage(contents, referenceSequenceNumber) {
@@ -2892,10 +2961,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2892
2961
  assert(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
2893
2962
  // System message should not be sent in the middle of the batch.
2894
2963
  assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
2895
- // back-compat: ADO #1385: Make this call unconditional in the future
2896
- return this.submitSummaryFn !== undefined
2897
- ? this.submitSummaryFn(contents, referenceSequenceNumber)
2898
- : this.submitFn(MessageType.Summarize, contents, false);
2964
+ return this.submitSummaryFn(contents, referenceSequenceNumber);
2899
2965
  }
2900
2966
  /**
2901
2967
  * Throw an error if the runtime is closed. Methods that are expected to potentially
@@ -2935,15 +3001,16 @@ export class ContainerRuntime extends TypedEventEmitter {
2935
3001
  * @param localOpMetadata - The local metadata associated with the original message.
2936
3002
  */
2937
3003
  reSubmitCore(message, localOpMetadata, opMetadata) {
2938
- assert(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
3004
+ assert(this._summarizer === undefined, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
2939
3005
  switch (message.type) {
2940
3006
  case ContainerMessageType.FluidDataStoreOp:
2941
3007
  case ContainerMessageType.Attach:
2942
- case ContainerMessageType.Alias:
3008
+ case ContainerMessageType.Alias: {
2943
3009
  // For Operations, call resubmitDataStoreOp which will find the right store
2944
3010
  // and trigger resubmission on it.
2945
3011
  this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
2946
3012
  break;
3013
+ }
2947
3014
  case ContainerMessageType.IdAllocation: {
2948
3015
  // Allocation ops are never resubmitted/rebased. This is because they require special handling to
2949
3016
  // avoid being submitted out of order. For example, if the pending state manager contained
@@ -2954,20 +3021,24 @@ export class ContainerRuntime extends TypedEventEmitter {
2954
3021
  // all pending IDs. The resubmitted allocation ops are then ignored here.
2955
3022
  break;
2956
3023
  }
2957
- case ContainerMessageType.BlobAttach:
3024
+ case ContainerMessageType.BlobAttach: {
2958
3025
  this.blobManager.reSubmit(opMetadata);
2959
3026
  break;
2960
- case ContainerMessageType.Rejoin:
3027
+ }
3028
+ case ContainerMessageType.Rejoin: {
2961
3029
  this.submit(message);
2962
3030
  break;
2963
- case ContainerMessageType.GC:
3031
+ }
3032
+ case ContainerMessageType.GC: {
2964
3033
  this.submit(message);
2965
3034
  break;
2966
- case ContainerMessageType.DocumentSchemaChange:
3035
+ }
3036
+ case ContainerMessageType.DocumentSchemaChange: {
2967
3037
  // There is no need to resend this message. Document schema controller will properly resend it again (if needed)
2968
3038
  // on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
2969
3039
  // send any ops, as some other client already changed schema.
2970
3040
  break;
3041
+ }
2971
3042
  default: {
2972
3043
  const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
2973
3044
  this.closeFn(error);
@@ -2979,18 +3050,21 @@ export class ContainerRuntime extends TypedEventEmitter {
2979
3050
  // Need to parse from string for back-compat
2980
3051
  const { type, contents } = this.parseLocalOpContent(content);
2981
3052
  switch (type) {
2982
- case ContainerMessageType.FluidDataStoreOp:
3053
+ case ContainerMessageType.FluidDataStoreOp: {
2983
3054
  // For operations, call rollbackDataStoreOp which will find the right store
2984
3055
  // and trigger rollback on it.
2985
3056
  this.channelCollection.rollback(type, contents, localOpMetadata);
2986
3057
  break;
2987
- default:
3058
+ }
3059
+ default: {
2988
3060
  throw new Error(`Can't rollback ${type}`);
3061
+ }
2989
3062
  }
2990
3063
  }
2991
3064
  /**
2992
3065
  * Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
2993
3066
  */
3067
+ // eslint-disable-next-line import/no-deprecated
2994
3068
  async refreshLatestSummaryAck(options) {
2995
3069
  const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
2996
3070
  // proposalHandle is always passed from RunningSummarizer.
@@ -3060,15 +3134,16 @@ export class ContainerRuntime extends TypedEventEmitter {
3060
3134
  snapshotTree = snapshot.snapshotTree;
3061
3135
  }
3062
3136
  else {
3063
- const versions = await this.storage.getVersions(null, 1, scenarioName, FetchSource.noCache);
3137
+ const versions = await this.storage.getVersions(
3138
+ // eslint-disable-next-line unicorn/no-null
3139
+ null, 1, scenarioName, FetchSource.noCache);
3064
3140
  assert(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
3065
3141
  snapshotTree = await this.storage.getSnapshotTree(versions[0]);
3066
3142
  assert(!!snapshotTree, 0x138 /* "Failed to get snapshot from storage" */);
3067
3143
  props.snapshotVersion = versions[0].id;
3068
3144
  }
3069
3145
  props.getSnapshotDuration = trace.trace().duration;
3070
- const readAndParseBlob = async (id) => readAndParse(this.storage, id);
3071
- const snapshotRefSeq = await seqFromTree(snapshotTree, readAndParseBlob);
3146
+ const snapshotRefSeq = await seqFromTree(snapshotTree, this.readAndParseBlob);
3072
3147
  props.snapshotRefSeq = snapshotRefSeq;
3073
3148
  props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
3074
3149
  perfEvent.end({ details: props });
@@ -3121,32 +3196,32 @@ export class ContainerRuntime extends TypedEventEmitter {
3121
3196
  : PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
3122
3197
  }
3123
3198
  summarizeOnDemand(options) {
3124
- if (this.isSummarizerClient) {
3125
- return this.summarizer.summarizeOnDemand(options);
3126
- }
3127
- else if (this.summaryManager !== undefined) {
3128
- return this.summaryManager.summarizeOnDemand(options);
3199
+ if (this._summarizer !== undefined) {
3200
+ return this._summarizer.summarizeOnDemand(options);
3129
3201
  }
3130
- else {
3202
+ else if (this.summaryManager === undefined) {
3131
3203
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
3132
3204
  // disableSummaries is turned on. We are throwing instead of returning a failure here,
3133
3205
  // because it is a misuse of the API rather than an expected failure.
3134
3206
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
3135
3207
  }
3208
+ else {
3209
+ return this.summaryManager.summarizeOnDemand(options);
3210
+ }
3136
3211
  }
3137
3212
  enqueueSummarize(options) {
3138
- if (this.isSummarizerClient) {
3139
- return this.summarizer.enqueueSummarize(options);
3140
- }
3141
- else if (this.summaryManager !== undefined) {
3142
- return this.summaryManager.enqueueSummarize(options);
3213
+ if (this._summarizer !== undefined) {
3214
+ return this._summarizer.enqueueSummarize(options);
3143
3215
  }
3144
- else {
3216
+ else if (this.summaryManager === undefined) {
3145
3217
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
3146
3218
  // generateSummaries is turned off. We are throwing instead of returning a failure here,
3147
3219
  // because it is a misuse of the API rather than an expected failure.
3148
3220
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
3149
3221
  }
3222
+ else {
3223
+ return this.summaryManager.enqueueSummarize(options);
3224
+ }
3150
3225
  }
3151
3226
  /**
3152
3227
  * Forms a function that will create and retrieve a Summarizer.