@fluidframework/container-runtime 2.20.0 → 2.22.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 (337) hide show
  1. package/.eslintrc.cjs +36 -6
  2. package/.mocharc.cjs +3 -0
  3. package/CHANGELOG.md +42 -0
  4. package/README.md +1 -0
  5. package/api-report/container-runtime.legacy.alpha.api.md +31 -31
  6. package/dist/batchTracker.d.ts +1 -2
  7. package/dist/batchTracker.d.ts.map +1 -1
  8. package/dist/batchTracker.js +1 -1
  9. package/dist/batchTracker.js.map +1 -1
  10. package/dist/blobManager/blobManager.d.ts +0 -3
  11. package/dist/blobManager/blobManager.d.ts.map +1 -1
  12. package/dist/blobManager/blobManager.js +25 -19
  13. package/dist/blobManager/blobManager.js.map +1 -1
  14. package/dist/blobManager/blobManagerSnapSum.d.ts +1 -0
  15. package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  16. package/dist/blobManager/blobManagerSnapSum.js +7 -5
  17. package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
  18. package/dist/channelCollection.d.ts.map +1 -1
  19. package/dist/channelCollection.js +63 -41
  20. package/dist/channelCollection.js.map +1 -1
  21. package/dist/connectionTelemetry.d.ts +2 -2
  22. package/dist/connectionTelemetry.d.ts.map +1 -1
  23. package/dist/connectionTelemetry.js +4 -4
  24. package/dist/connectionTelemetry.js.map +1 -1
  25. package/dist/containerRuntime.d.ts +14 -30
  26. package/dist/containerRuntime.d.ts.map +1 -1
  27. package/dist/containerRuntime.js +265 -196
  28. package/dist/containerRuntime.js.map +1 -1
  29. package/dist/dataStore.js +6 -3
  30. package/dist/dataStore.js.map +1 -1
  31. package/dist/dataStoreContext.d.ts.map +1 -1
  32. package/dist/dataStoreContext.js +16 -11
  33. package/dist/dataStoreContext.js.map +1 -1
  34. package/dist/dataStoreContexts.d.ts.map +1 -1
  35. package/dist/dataStoreContexts.js +1 -0
  36. package/dist/dataStoreContexts.js.map +1 -1
  37. package/dist/deltaScheduler.d.ts.map +1 -1
  38. package/dist/deltaScheduler.js +5 -5
  39. package/dist/deltaScheduler.js.map +1 -1
  40. package/dist/gc/garbageCollection.d.ts.map +1 -1
  41. package/dist/gc/garbageCollection.js +36 -14
  42. package/dist/gc/garbageCollection.js.map +1 -1
  43. package/dist/gc/gcConfigs.d.ts.map +1 -1
  44. package/dist/gc/gcConfigs.js +2 -0
  45. package/dist/gc/gcConfigs.js.map +1 -1
  46. package/dist/gc/gcDefinitions.d.ts +8 -0
  47. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  48. package/dist/gc/gcDefinitions.js +1 -0
  49. package/dist/gc/gcDefinitions.js.map +1 -1
  50. package/dist/gc/gcHelpers.d.ts.map +1 -1
  51. package/dist/gc/gcHelpers.js +8 -5
  52. package/dist/gc/gcHelpers.js.map +1 -1
  53. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  54. package/dist/gc/gcSummaryStateTracker.js +2 -1
  55. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  56. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  57. package/dist/gc/gcTelemetry.js +29 -15
  58. package/dist/gc/gcTelemetry.js.map +1 -1
  59. package/dist/inboundBatchAggregator.js +3 -3
  60. package/dist/inboundBatchAggregator.js.map +1 -1
  61. package/dist/layerCompatState.d.ts +19 -0
  62. package/dist/layerCompatState.d.ts.map +1 -0
  63. package/dist/layerCompatState.js +64 -0
  64. package/dist/layerCompatState.js.map +1 -0
  65. package/dist/messageTypes.d.ts.map +1 -1
  66. package/dist/messageTypes.js.map +1 -1
  67. package/dist/opLifecycle/duplicateBatchDetector.js +2 -2
  68. package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
  69. package/dist/opLifecycle/opCompressor.d.ts +3 -2
  70. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  71. package/dist/opLifecycle/opCompressor.js +13 -19
  72. package/dist/opLifecycle/opCompressor.js.map +1 -1
  73. package/dist/opLifecycle/opDecompressor.d.ts +3 -0
  74. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  75. package/dist/opLifecycle/opDecompressor.js +4 -1
  76. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  77. package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
  78. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  79. package/dist/opLifecycle/opGroupingManager.js +5 -3
  80. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  81. package/dist/opLifecycle/opSplitter.d.ts +13 -10
  82. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  83. package/dist/opLifecycle/opSplitter.js +14 -11
  84. package/dist/opLifecycle/opSplitter.js.map +1 -1
  85. package/dist/opLifecycle/outbox.d.ts +3 -3
  86. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  87. package/dist/opLifecycle/outbox.js +11 -15
  88. package/dist/opLifecycle/outbox.js.map +1 -1
  89. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  90. package/dist/opLifecycle/remoteMessageProcessor.js +3 -1
  91. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  92. package/dist/packageVersion.d.ts +1 -1
  93. package/dist/packageVersion.js +1 -1
  94. package/dist/packageVersion.js.map +1 -1
  95. package/dist/pendingStateManager.d.ts +3 -4
  96. package/dist/pendingStateManager.d.ts.map +1 -1
  97. package/dist/pendingStateManager.js +11 -10
  98. package/dist/pendingStateManager.js.map +1 -1
  99. package/dist/summary/documentSchema.d.ts +7 -0
  100. package/dist/summary/documentSchema.d.ts.map +1 -1
  101. package/dist/summary/documentSchema.js +6 -4
  102. package/dist/summary/documentSchema.js.map +1 -1
  103. package/dist/summary/orderedClientElection.d.ts +1 -0
  104. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  105. package/dist/summary/orderedClientElection.js +13 -11
  106. package/dist/summary/orderedClientElection.js.map +1 -1
  107. package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -0
  108. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  109. package/dist/summary/runWhileConnectedCoordinator.js +7 -2
  110. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  111. package/dist/summary/runningSummarizer.d.ts +2 -2
  112. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  113. package/dist/summary/runningSummarizer.js +38 -17
  114. package/dist/summary/runningSummarizer.js.map +1 -1
  115. package/dist/summary/summarizer.d.ts +1 -0
  116. package/dist/summary/summarizer.d.ts.map +1 -1
  117. package/dist/summary/summarizer.js +18 -9
  118. package/dist/summary/summarizer.js.map +1 -1
  119. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  120. package/dist/summary/summarizerClientElection.js +1 -0
  121. package/dist/summary/summarizerClientElection.js.map +1 -1
  122. package/dist/summary/summarizerHeuristics.js +1 -1
  123. package/dist/summary/summarizerHeuristics.js.map +1 -1
  124. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  125. package/dist/summary/summarizerNode/index.js.map +1 -1
  126. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  127. package/dist/summary/summarizerNode/summarizerNode.js +30 -31
  128. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  129. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
  130. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
  131. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  132. package/dist/summary/summarizerTypes.d.ts +7 -0
  133. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  134. package/dist/summary/summarizerTypes.js.map +1 -1
  135. package/dist/summary/summaryCollection.d.ts +3 -4
  136. package/dist/summary/summaryCollection.d.ts.map +1 -1
  137. package/dist/summary/summaryCollection.js +9 -6
  138. package/dist/summary/summaryCollection.js.map +1 -1
  139. package/dist/summary/summaryFormat.d.ts +4 -1
  140. package/dist/summary/summaryFormat.d.ts.map +1 -1
  141. package/dist/summary/summaryFormat.js +3 -2
  142. package/dist/summary/summaryFormat.js.map +1 -1
  143. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  144. package/dist/summary/summaryGenerator.js +19 -8
  145. package/dist/summary/summaryGenerator.js.map +1 -1
  146. package/dist/summary/summaryManager.d.ts.map +1 -1
  147. package/dist/summary/summaryManager.js +12 -9
  148. package/dist/summary/summaryManager.js.map +1 -1
  149. package/lib/batchTracker.d.ts +1 -2
  150. package/lib/batchTracker.d.ts.map +1 -1
  151. package/lib/batchTracker.js +2 -2
  152. package/lib/batchTracker.js.map +1 -1
  153. package/lib/blobManager/blobManager.d.ts +0 -3
  154. package/lib/blobManager/blobManager.d.ts.map +1 -1
  155. package/lib/blobManager/blobManager.js +26 -20
  156. package/lib/blobManager/blobManager.js.map +1 -1
  157. package/lib/blobManager/blobManagerSnapSum.d.ts +1 -0
  158. package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  159. package/lib/blobManager/blobManagerSnapSum.js +7 -5
  160. package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
  161. package/lib/channelCollection.d.ts.map +1 -1
  162. package/lib/channelCollection.js +66 -42
  163. package/lib/channelCollection.js.map +1 -1
  164. package/lib/connectionTelemetry.d.ts +2 -2
  165. package/lib/connectionTelemetry.d.ts.map +1 -1
  166. package/lib/connectionTelemetry.js +5 -5
  167. package/lib/connectionTelemetry.js.map +1 -1
  168. package/lib/containerRuntime.d.ts +14 -30
  169. package/lib/containerRuntime.d.ts.map +1 -1
  170. package/lib/containerRuntime.js +272 -198
  171. package/lib/containerRuntime.js.map +1 -1
  172. package/lib/dataStore.js +6 -3
  173. package/lib/dataStore.js.map +1 -1
  174. package/lib/dataStoreContext.d.ts.map +1 -1
  175. package/lib/dataStoreContext.js +16 -11
  176. package/lib/dataStoreContext.js.map +1 -1
  177. package/lib/dataStoreContexts.d.ts.map +1 -1
  178. package/lib/dataStoreContexts.js +1 -0
  179. package/lib/dataStoreContexts.js.map +1 -1
  180. package/lib/deltaScheduler.d.ts.map +1 -1
  181. package/lib/deltaScheduler.js +6 -6
  182. package/lib/deltaScheduler.js.map +1 -1
  183. package/lib/gc/garbageCollection.d.ts.map +1 -1
  184. package/lib/gc/garbageCollection.js +39 -15
  185. package/lib/gc/garbageCollection.js.map +1 -1
  186. package/lib/gc/gcConfigs.d.ts.map +1 -1
  187. package/lib/gc/gcConfigs.js +2 -0
  188. package/lib/gc/gcConfigs.js.map +1 -1
  189. package/lib/gc/gcDefinitions.d.ts +8 -0
  190. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  191. package/lib/gc/gcDefinitions.js +1 -0
  192. package/lib/gc/gcDefinitions.js.map +1 -1
  193. package/lib/gc/gcHelpers.d.ts.map +1 -1
  194. package/lib/gc/gcHelpers.js +8 -5
  195. package/lib/gc/gcHelpers.js.map +1 -1
  196. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  197. package/lib/gc/gcSummaryStateTracker.js +2 -1
  198. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  199. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  200. package/lib/gc/gcTelemetry.js +32 -16
  201. package/lib/gc/gcTelemetry.js.map +1 -1
  202. package/lib/inboundBatchAggregator.js +4 -4
  203. package/lib/inboundBatchAggregator.js.map +1 -1
  204. package/lib/layerCompatState.d.ts +19 -0
  205. package/lib/layerCompatState.d.ts.map +1 -0
  206. package/lib/layerCompatState.js +60 -0
  207. package/lib/layerCompatState.js.map +1 -0
  208. package/lib/messageTypes.d.ts.map +1 -1
  209. package/lib/messageTypes.js.map +1 -1
  210. package/lib/opLifecycle/duplicateBatchDetector.js +2 -2
  211. package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
  212. package/lib/opLifecycle/opCompressor.d.ts +3 -2
  213. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  214. package/lib/opLifecycle/opCompressor.js +13 -19
  215. package/lib/opLifecycle/opCompressor.js.map +1 -1
  216. package/lib/opLifecycle/opDecompressor.d.ts +3 -0
  217. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  218. package/lib/opLifecycle/opDecompressor.js +4 -1
  219. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  220. package/lib/opLifecycle/opGroupingManager.d.ts +1 -1
  221. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  222. package/lib/opLifecycle/opGroupingManager.js +5 -3
  223. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  224. package/lib/opLifecycle/opSplitter.d.ts +13 -10
  225. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  226. package/lib/opLifecycle/opSplitter.js +14 -11
  227. package/lib/opLifecycle/opSplitter.js.map +1 -1
  228. package/lib/opLifecycle/outbox.d.ts +3 -3
  229. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  230. package/lib/opLifecycle/outbox.js +11 -15
  231. package/lib/opLifecycle/outbox.js.map +1 -1
  232. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  233. package/lib/opLifecycle/remoteMessageProcessor.js +3 -1
  234. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  235. package/lib/packageVersion.d.ts +1 -1
  236. package/lib/packageVersion.js +1 -1
  237. package/lib/packageVersion.js.map +1 -1
  238. package/lib/pendingStateManager.d.ts +3 -4
  239. package/lib/pendingStateManager.d.ts.map +1 -1
  240. package/lib/pendingStateManager.js +12 -11
  241. package/lib/pendingStateManager.js.map +1 -1
  242. package/lib/summary/documentSchema.d.ts +7 -0
  243. package/lib/summary/documentSchema.d.ts.map +1 -1
  244. package/lib/summary/documentSchema.js +6 -4
  245. package/lib/summary/documentSchema.js.map +1 -1
  246. package/lib/summary/orderedClientElection.d.ts +1 -0
  247. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  248. package/lib/summary/orderedClientElection.js +13 -11
  249. package/lib/summary/orderedClientElection.js.map +1 -1
  250. package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -0
  251. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  252. package/lib/summary/runWhileConnectedCoordinator.js +7 -2
  253. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  254. package/lib/summary/runningSummarizer.d.ts +2 -2
  255. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  256. package/lib/summary/runningSummarizer.js +38 -17
  257. package/lib/summary/runningSummarizer.js.map +1 -1
  258. package/lib/summary/summarizer.d.ts +1 -0
  259. package/lib/summary/summarizer.d.ts.map +1 -1
  260. package/lib/summary/summarizer.js +18 -9
  261. package/lib/summary/summarizer.js.map +1 -1
  262. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  263. package/lib/summary/summarizerClientElection.js +1 -0
  264. package/lib/summary/summarizerClientElection.js.map +1 -1
  265. package/lib/summary/summarizerHeuristics.js +1 -1
  266. package/lib/summary/summarizerHeuristics.js.map +1 -1
  267. package/lib/summary/summarizerNode/index.d.ts.map +1 -1
  268. package/lib/summary/summarizerNode/index.js.map +1 -1
  269. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  270. package/lib/summary/summarizerNode/summarizerNode.js +30 -31
  271. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  272. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
  273. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
  274. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  275. package/lib/summary/summarizerTypes.d.ts +7 -0
  276. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  277. package/lib/summary/summarizerTypes.js.map +1 -1
  278. package/lib/summary/summaryCollection.d.ts +3 -4
  279. package/lib/summary/summaryCollection.d.ts.map +1 -1
  280. package/lib/summary/summaryCollection.js +9 -6
  281. package/lib/summary/summaryCollection.js.map +1 -1
  282. package/lib/summary/summaryFormat.d.ts +4 -1
  283. package/lib/summary/summaryFormat.d.ts.map +1 -1
  284. package/lib/summary/summaryFormat.js +2 -2
  285. package/lib/summary/summaryFormat.js.map +1 -1
  286. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  287. package/lib/summary/summaryGenerator.js +19 -8
  288. package/lib/summary/summaryGenerator.js.map +1 -1
  289. package/lib/summary/summaryManager.d.ts.map +1 -1
  290. package/lib/summary/summaryManager.js +12 -9
  291. package/lib/summary/summaryManager.js.map +1 -1
  292. package/package.json +24 -46
  293. package/src/batchTracker.ts +3 -3
  294. package/src/blobManager/blobManager.ts +27 -28
  295. package/src/blobManager/blobManagerSnapSum.ts +8 -8
  296. package/src/channelCollection.ts +63 -44
  297. package/src/connectionTelemetry.ts +12 -6
  298. package/src/containerRuntime.ts +306 -236
  299. package/src/dataStore.ts +6 -3
  300. package/src/dataStoreContext.ts +16 -16
  301. package/src/dataStoreContexts.ts +1 -0
  302. package/src/deltaScheduler.ts +6 -6
  303. package/src/gc/garbageCollection.ts +47 -20
  304. package/src/gc/gcConfigs.ts +9 -1
  305. package/src/gc/gcDefinitions.ts +12 -0
  306. package/src/gc/gcHelpers.ts +9 -4
  307. package/src/gc/gcSummaryStateTracker.ts +3 -1
  308. package/src/gc/gcTelemetry.ts +26 -11
  309. package/src/inboundBatchAggregator.ts +4 -4
  310. package/src/layerCompatState.ts +75 -0
  311. package/src/messageTypes.ts +2 -0
  312. package/src/opLifecycle/README.md +43 -34
  313. package/src/opLifecycle/duplicateBatchDetector.ts +2 -2
  314. package/src/opLifecycle/opCompressor.ts +16 -23
  315. package/src/opLifecycle/opDecompressor.ts +4 -1
  316. package/src/opLifecycle/opGroupingManager.ts +5 -4
  317. package/src/opLifecycle/opSplitter.ts +14 -11
  318. package/src/opLifecycle/outbox.ts +13 -20
  319. package/src/opLifecycle/remoteMessageProcessor.ts +3 -1
  320. package/src/packageVersion.ts +1 -1
  321. package/src/pendingStateManager.ts +15 -10
  322. package/src/summary/documentSchema.ts +11 -4
  323. package/src/summary/orderedClientElection.ts +14 -11
  324. package/src/summary/runWhileConnectedCoordinator.ts +6 -0
  325. package/src/summary/runningSummarizer.ts +43 -19
  326. package/src/summary/summarizer.ts +24 -11
  327. package/src/summary/summarizerClientElection.ts +2 -0
  328. package/src/summary/summarizerHeuristics.ts +1 -1
  329. package/src/summary/summarizerNode/index.ts +1 -0
  330. package/src/summary/summarizerNode/summarizerNode.ts +32 -31
  331. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +4 -4
  332. package/src/summary/summarizerTypes.ts +7 -0
  333. package/src/summary/summaryCollection.ts +19 -8
  334. package/src/summary/summaryFormat.ts +10 -5
  335. package/src/summary/summaryGenerator.ts +25 -10
  336. package/src/summary/summaryManager.ts +14 -12
  337. 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
@@ -889,16 +914,15 @@ export class ContainerRuntime extends TypedEventEmitter {
889
914
  isBlobDeleted: (blobPath) => this.garbageCollector.isNodeDeleted(blobPath),
890
915
  runtime: this,
891
916
  stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
892
- closeContainer: (error) => this.closeFn(error),
893
917
  });
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" }));
918
+ this.deltaScheduler = new DeltaScheduler(this.innerDeltaManager, this, createChildLogger({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
919
+ this.inboundBatchAggregator = new InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, createChildLogger({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
896
920
  const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
897
- const legacySendBatchFn = makeLegacySendBatchFn(this.submitFn, this.innerDeltaManager);
921
+ const legacySendBatchFn = makeLegacySendBatchFn(submitFn, this.innerDeltaManager);
898
922
  this.outbox = new Outbox({
899
923
  shouldSend: () => this.canSendOps(),
900
924
  pendingStateManager: this.pendingStateManager,
901
- submitBatchFn: this.submitBatchFn,
925
+ submitBatchFn,
902
926
  legacySendBatchFn,
903
927
  compressor: new OpCompressor(this.mc.logger),
904
928
  splitter: opSplitter,
@@ -945,7 +969,7 @@ export class ContainerRuntime extends TypedEventEmitter {
945
969
  const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
946
970
  this.closeSummarizerDelayMs =
947
971
  closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
948
- this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
972
+ const summaryCollection = new SummaryCollection(this.deltaManager, this.baseLogger);
949
973
  this.dirtyContainer =
950
974
  this.attachState !== AttachState.Attached || this.hasPendingMessages();
951
975
  context.updateDirtyContainerState(this.dirtyContainer);
@@ -954,14 +978,17 @@ export class ContainerRuntime extends TypedEventEmitter {
954
978
  }
955
979
  else {
956
980
  const orderedClientLogger = createChildLogger({
957
- logger: this.logger,
981
+ logger: this.baseLogger,
958
982
  namespace: "OrderedClientElection",
959
983
  });
960
984
  const orderedClientCollection = new OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
961
985
  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,
986
+ this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary);
987
+ if (isSummarizerClient) {
988
+ // eslint-disable-next-line import/no-deprecated
989
+ this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, summaryCollection,
990
+ // eslint-disable-next-line import/no-deprecated
991
+ async (runtime) => RunWhileConnectedCoordinator.create(runtime,
965
992
  // Summarization runs in summarizer client and needs access to the real (non-proxy) active
966
993
  // information. The proxy delta manager would always return false for summarizer client.
967
994
  () => this.innerDeltaManager.active));
@@ -970,48 +997,49 @@ export class ContainerRuntime extends TypedEventEmitter {
970
997
  // Only create a SummaryManager and SummarizerClientElection
971
998
  // if summaries are enabled and we are not the summarizer client.
972
999
  const defaultAction = () => {
973
- if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
1000
+ if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
974
1001
  this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
975
1002
  // unregister default to no log on every op after falling behind
976
1003
  // and register summary ack handler to re-register this handler
977
1004
  // after successful summary
978
- this.summaryCollection.once(MessageType.SummaryAck, () => {
1005
+ summaryCollection.once(MessageType.SummaryAck, () => {
979
1006
  this.mc.logger.sendTelemetryEvent({
980
1007
  eventName: "SummaryStatus:CaughtUp",
981
1008
  });
982
1009
  // we've caught up, so re-register the default action to monitor for
983
1010
  // falling behind, and unregister ourself
984
- this.summaryCollection.on("default", defaultAction);
1011
+ summaryCollection.on("default", defaultAction);
985
1012
  });
986
- this.summaryCollection.off("default", defaultAction);
1013
+ summaryCollection.off("default", defaultAction);
987
1014
  }
988
1015
  };
989
- this.summaryCollection.on("default", defaultAction);
1016
+ summaryCollection.on("default", defaultAction);
990
1017
  // Create the SummaryManager and mark the initial state
991
1018
  this.summaryManager = new SummaryManager(this.summarizerClientElection, this, // IConnectedState
992
- this.summaryCollection, this.logger, this.formCreateSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
1019
+ summaryCollection, this.baseLogger, this.formCreateSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
993
1020
  30 * 1000, // 30 sec max delay
994
1021
  // throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
995
1022
  formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
996
- initialDelayMs: this.initialSummarizerDelayMs,
1023
+ initialDelayMs: initialSummarizerDelayMs,
997
1024
  });
998
1025
  // Forward events from SummaryManager
999
- [
1026
+ for (const eventName of [
1000
1027
  "summarize",
1001
1028
  "summarizeAllAttemptsFailed",
1002
1029
  "summarizerStop",
1003
1030
  "summarizerStart",
1004
1031
  "summarizerStartupFailed",
1005
- ].forEach((eventName) => {
1032
+ ]) {
1006
1033
  this.summaryManager?.on(eventName, (...args) => {
1007
1034
  this.emit(eventName, ...args);
1008
1035
  });
1009
- });
1036
+ }
1010
1037
  this.summaryManager.start();
1011
1038
  }
1012
1039
  }
1013
1040
  // logging hardware telemetry
1014
- this.logger.sendTelemetryEvent({
1041
+ this.baseLogger.send({
1042
+ category: "generic",
1015
1043
  eventName: "DeviceSpec",
1016
1044
  ...getDeviceSpec(),
1017
1045
  });
@@ -1023,13 +1051,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1023
1051
  summaryFormatVersion: metadata?.summaryFormatVersion,
1024
1052
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
1025
1053
  gcVersion: metadata?.gcFeature,
1026
- options: JSON.stringify(runtimeOptions),
1054
+ options: JSON.stringify(baseRuntimeOptions),
1027
1055
  idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
1028
- idCompressorMode: this.idCompressorMode,
1056
+ idCompressorMode: this.sessionSchema.idCompressorMode,
1029
1057
  sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
1030
1058
  featureGates: JSON.stringify({
1031
1059
  ...featureGatesForTelemetry,
1032
- disableAttachReorder: this.disableAttachReorder,
1033
1060
  disablePartialFlush,
1034
1061
  closeSummarizerDelayOverride,
1035
1062
  }),
@@ -1037,11 +1064,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1037
1064
  groupedBatchingEnabled: this.groupedBatchingEnabled,
1038
1065
  initialSequenceNumber: this.deltaManager.initialSequenceNumber,
1039
1066
  });
1040
- ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.logger);
1041
- BindBatchTracker(this, this.logger);
1067
+ ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
1068
+ BindBatchTracker(this, this.baseLogger);
1042
1069
  this.entryPoint = new LazyPromise(async () => {
1043
- if (this.isSummarizerClient) {
1044
- assert(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
1070
+ if (this._summarizer !== undefined) {
1045
1071
  return this._summarizer;
1046
1072
  }
1047
1073
  return provideEntryPoint(this);
@@ -1050,8 +1076,9 @@ export class ContainerRuntime extends TypedEventEmitter {
1050
1076
  // saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
1051
1077
  this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
1052
1078
  }
1079
+ // eslint-disable-next-line import/no-deprecated
1053
1080
  onSchemaChange(schema) {
1054
- this.logger.sendTelemetryEvent({
1081
+ this.mc.logger.sendTelemetryEvent({
1055
1082
  eventName: "SchemaChangeAccept",
1056
1083
  sessionRuntimeSchema: JSON.stringify(schema),
1057
1084
  });
@@ -1086,8 +1113,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1086
1113
  * Initializes the state from the base snapshot this container runtime loaded from.
1087
1114
  */
1088
1115
  async initializeBaseState() {
1089
- if (this.idCompressorMode === "on" ||
1090
- (this.idCompressorMode === "delayed" && this.connected)) {
1116
+ if (this.sessionSchema.idCompressorMode === "on" ||
1117
+ (this.sessionSchema.idCompressorMode === "delayed" && this.connected)) {
1091
1118
  this._idCompressor = await this.createIdCompressor();
1092
1119
  // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
1093
1120
  assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
@@ -1130,7 +1157,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1130
1157
  // Lookup up in the cache, if not present then make the network call as multiple datastores could
1131
1158
  // be in same loading group. So, once we have fetched the snapshot for that loading group on
1132
1159
  // any request, then cache that as same group could be requested in future too.
1133
- const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
1160
+ const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(","), async () => {
1134
1161
  assert(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
1135
1162
  loadedFromCache = false;
1136
1163
  return this.storage.getSnapshot({
@@ -1139,7 +1166,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1139
1166
  loadingGroupIds: sortedLoadingGroupIds,
1140
1167
  });
1141
1168
  });
1142
- this.logger.sendTelemetryEvent({
1169
+ this.mc.logger.sendTelemetryEvent({
1143
1170
  eventName: "GroupIdSnapshotFetched",
1144
1171
  details: JSON.stringify({
1145
1172
  fromCache: loadedFromCache,
@@ -1169,7 +1196,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1169
1196
  // another snapshot from which the summarizer loaded and it is behind, then just give up as
1170
1197
  // the summarizer state is not up to date.
1171
1198
  // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
1172
- if (this.isSummarizerClient) {
1199
+ if (this._summarizer !== undefined) {
1173
1200
  throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
1174
1201
  }
1175
1202
  // We want to catchup from sequenceNumber to targetSequenceNumber
@@ -1231,7 +1258,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1231
1258
  return {
1232
1259
  status: 200,
1233
1260
  mimeType: "fluid/object",
1234
- value: this.summarizer,
1261
+ value: this._summarizer,
1235
1262
  };
1236
1263
  }
1237
1264
  return create404Response(request);
@@ -1297,6 +1324,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1297
1324
  const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
1298
1325
  // Is document schema explicit control on?
1299
1326
  const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
1327
+ // eslint-disable-next-line import/no-deprecated
1300
1328
  const metadata = {
1301
1329
  ...this.createContainerMetadata,
1302
1330
  // Increment the summary number for the next summary that will be generated.
@@ -1310,7 +1338,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1310
1338
  // last message's sequence number.
1311
1339
  // See also lastMessageFromMetadata()
1312
1340
  message: explicitSchemaControl
1313
- ? { sequenceNumber: -1 }
1341
+ ? // eslint-disable-next-line import/no-deprecated
1342
+ { sequenceNumber: -1 }
1314
1343
  : message,
1315
1344
  lastMessage: explicitSchemaControl ? message : undefined,
1316
1345
  documentSchema,
@@ -1426,9 +1455,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1426
1455
  switch (opContents.type) {
1427
1456
  case ContainerMessageType.FluidDataStoreOp:
1428
1457
  case ContainerMessageType.Attach:
1429
- case ContainerMessageType.Alias:
1458
+ case ContainerMessageType.Alias: {
1430
1459
  return this.channelCollection.applyStashedOp(opContents);
1431
- case ContainerMessageType.IdAllocation:
1460
+ }
1461
+ case ContainerMessageType.IdAllocation: {
1432
1462
  // IDs allocation ops in stashed state are ignored because the tip state of the compressor
1433
1463
  // is serialized into the pending state. This is done because generation of new IDs during
1434
1464
  // stashed op application (or, later, resubmit) must generate new IDs and if the compressor
@@ -1438,17 +1468,22 @@ export class ContainerRuntime extends TypedEventEmitter {
1438
1468
  // and the runtime could filter out all ID allocation ops from the stashed state and apply them
1439
1469
  // before applying the rest of the stashed ops. This would accomplish the same thing but with
1440
1470
  // better performance in future incremental stashed state creation.
1441
- assert(this.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
1471
+ assert(this.sessionSchema.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
1442
1472
  return;
1443
- case ContainerMessageType.DocumentSchemaChange:
1473
+ }
1474
+ case ContainerMessageType.DocumentSchemaChange: {
1444
1475
  return;
1445
- case ContainerMessageType.BlobAttach:
1476
+ }
1477
+ case ContainerMessageType.BlobAttach: {
1446
1478
  return;
1447
- case ContainerMessageType.Rejoin:
1479
+ }
1480
+ case ContainerMessageType.Rejoin: {
1448
1481
  throw new Error("rejoin not expected here");
1449
- case ContainerMessageType.GC:
1482
+ }
1483
+ case ContainerMessageType.GC: {
1450
1484
  // GC op is only sent in summarizer which should never have stashed ops.
1451
1485
  throw new LoggingError("GC op not expected to be stashed in summarizer");
1486
+ }
1452
1487
  default: {
1453
1488
  const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
1454
1489
  this.closeFn(error);
@@ -1458,7 +1493,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1458
1493
  }
1459
1494
  async loadIdCompressor() {
1460
1495
  if (this._idCompressor === undefined &&
1461
- this.idCompressorMode !== undefined &&
1496
+ this.sessionSchema.idCompressorMode !== undefined &&
1462
1497
  this._loadIdCompressor === undefined) {
1463
1498
  this._loadIdCompressor = this.createIdCompressor()
1464
1499
  .then((compressor) => {
@@ -1472,7 +1507,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1472
1507
  this._idCompressor = compressor;
1473
1508
  })
1474
1509
  .catch((error) => {
1475
- this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
1510
+ this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
1476
1511
  throw error;
1477
1512
  });
1478
1513
  }
@@ -1483,7 +1518,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1483
1518
  const currentClientId = this._audience.getSelf()?.clientId;
1484
1519
  assert(clientId === currentClientId, 0x977 /* input clientId does not match Audience */);
1485
1520
  assert(this.clientId === currentClientId, 0x978 /* this.clientId does not match Audience */);
1486
- if (connected && this.idCompressorMode === "delayed") {
1521
+ if (connected && this.sessionSchema.idCompressorMode === "delayed") {
1487
1522
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1488
1523
  this.loadIdCompressor();
1489
1524
  }
@@ -1572,7 +1607,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1572
1607
  // or something different, like a system message.
1573
1608
  const hasModernRuntimeMessageEnvelope = messageCopy.type === MessageType.Operation;
1574
1609
  const savedOp = messageCopy.metadata?.savedOp;
1575
- const logLegacyCase = getSingleUseLegacyLogCallback(this.logger, messageCopy.type);
1610
+ const logLegacyCase = getSingleUseLegacyLogCallback(this.mc.logger, messageCopy.type);
1576
1611
  let runtimeBatch = hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
1577
1612
  if (runtimeBatch) {
1578
1613
  // We expect runtime messages to have JSON contents - deserialize it in place.
@@ -1674,11 +1709,11 @@ export class ContainerRuntime extends TypedEventEmitter {
1674
1709
  let error;
1675
1710
  try {
1676
1711
  if (!runtimeBatch) {
1677
- messagesWithMetadata.forEach(({ message }) => {
1712
+ for (const { message } of messagesWithMetadata) {
1678
1713
  this.ensureNoDataModelChanges(() => {
1679
1714
  this.observeNonRuntimeMessage(message);
1680
1715
  });
1681
- });
1716
+ }
1682
1717
  return;
1683
1718
  }
1684
1719
  // Updates a message's minimum sequence number to the minimum sequence number that container
@@ -1746,8 +1781,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1746
1781
  this.emit("op", message, true /* runtimeMessage */);
1747
1782
  }
1748
1783
  }
1749
- catch (e) {
1750
- error = e;
1784
+ catch (error_) {
1785
+ error = error_;
1751
1786
  throw error;
1752
1787
  }
1753
1788
  finally {
@@ -1804,30 +1839,39 @@ export class ContainerRuntime extends TypedEventEmitter {
1804
1839
  switch (message.type) {
1805
1840
  case ContainerMessageType.FluidDataStoreOp:
1806
1841
  case ContainerMessageType.Attach:
1807
- case ContainerMessageType.Alias:
1842
+ case ContainerMessageType.Alias: {
1808
1843
  // Remove the metadata from the message before sending it to the channel collection. The metadata
1809
1844
  // is added by the container runtime and is not part of the message that the channel collection and
1810
1845
  // layers below it expect.
1811
1846
  this.channelCollection.processMessages({ envelope: message, messagesContent, local });
1812
1847
  break;
1813
- case ContainerMessageType.BlobAttach:
1848
+ }
1849
+ case ContainerMessageType.BlobAttach: {
1814
1850
  this.blobManager.processBlobAttachMessage(message, local);
1815
1851
  break;
1816
- case ContainerMessageType.IdAllocation:
1852
+ }
1853
+ case ContainerMessageType.IdAllocation: {
1817
1854
  this.processIdCompressorMessages(contents, savedOp);
1818
1855
  break;
1819
- case ContainerMessageType.GC:
1856
+ }
1857
+ case ContainerMessageType.GC: {
1820
1858
  this.garbageCollector.processMessages(contents, message.timestamp, local);
1821
1859
  break;
1822
- case ContainerMessageType.ChunkedOp:
1860
+ }
1861
+ case ContainerMessageType.ChunkedOp: {
1823
1862
  // From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
1824
1863
  // Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
1825
1864
  assert(false, 0x93d /* should not even get here */);
1826
- case ContainerMessageType.Rejoin:
1865
+ }
1866
+ case ContainerMessageType.Rejoin: {
1827
1867
  break;
1828
- case ContainerMessageType.DocumentSchemaChange:
1829
- this.documentsSchemaController.processDocumentSchemaMessages(contents, local, message.sequenceNumber);
1868
+ }
1869
+ case ContainerMessageType.DocumentSchemaChange: {
1870
+ this.documentsSchemaController.processDocumentSchemaMessages(
1871
+ // eslint-disable-next-line import/no-deprecated
1872
+ contents, local, message.sequenceNumber);
1830
1873
  break;
1874
+ }
1831
1875
  default: {
1832
1876
  const error = getUnknownMessageTypeError(message.type, "validateAndProcessRuntimeMessage" /* codePath */, message);
1833
1877
  this.closeFn(error);
@@ -1845,7 +1889,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1845
1889
  // Some other client turned on the id compressor. If we have not turned it on,
1846
1890
  // put it in a pending queue and delay finalization.
1847
1891
  if (this._idCompressor === undefined) {
1848
- assert(this.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
1892
+ assert(this.sessionSchema.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
1849
1893
  this.pendingIdCompressorOps.push(range);
1850
1894
  }
1851
1895
  else {
@@ -1879,7 +1923,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1879
1923
  * Updates signal telemetry including emitting telemetry events.
1880
1924
  */
1881
1925
  processSignalForTelemetry(envelope) {
1882
- const { clientBroadcastSignalSequenceNumber } = envelope;
1926
+ const { clientBroadcastSignalSequenceNumber, contents: envelopeContents, address: envelopeAddress, } = envelope;
1883
1927
  if (clientBroadcastSignalSequenceNumber === undefined) {
1884
1928
  return;
1885
1929
  }
@@ -1917,8 +1961,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1917
1961
  };
1918
1962
  // Only log `contents.type` when address is for container to avoid
1919
1963
  // 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.
1964
+ if (envelopeAddress === undefined) {
1965
+ details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
1922
1966
  }
1923
1967
  this.mc.logger.sendTelemetryEvent({
1924
1968
  eventName: "SignalOutOfOrder",
@@ -1999,8 +2043,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1999
2043
  try {
2000
2044
  checkpoint.rollback((message) => this.rollback(message.contents, message.localOpMetadata));
2001
2045
  }
2002
- catch (err) {
2003
- const error2 = wrapError(err, (message) => {
2046
+ catch (error_) {
2047
+ const error2 = wrapError(error_, (message) => {
2004
2048
  return DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
2005
2049
  });
2006
2050
  this.closeFn(error2);
@@ -2111,8 +2155,9 @@ export class ContainerRuntime extends TypedEventEmitter {
2111
2155
  case ContainerMessageType.GC: {
2112
2156
  return false;
2113
2157
  }
2114
- default:
2158
+ default: {
2115
2159
  break;
2160
+ }
2116
2161
  }
2117
2162
  return true;
2118
2163
  }
@@ -2141,7 +2186,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2141
2186
  clientBroadcastSignalSequenceNumber;
2142
2187
  }
2143
2188
  // 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 &&
2189
+ if (clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
2145
2190
  this._signalTracking.roundTripSignalSequenceNumber === undefined) {
2146
2191
  this._signalTracking.signalTimestamp = Date.now();
2147
2192
  this._signalTracking.roundTripSignalSequenceNumber =
@@ -2207,6 +2252,12 @@ export class ContainerRuntime extends TypedEventEmitter {
2207
2252
  this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
2208
2253
  return summarizeResult.summary;
2209
2254
  }
2255
+ /**
2256
+ * Builds the Summary tree including all the channels and the container state.
2257
+ *
2258
+ * @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
2259
+ * so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
2260
+ */
2210
2261
  async summarizeInternal(fullTree, trackState, telemetryContext) {
2211
2262
  const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
2212
2263
  // Wrap data store summaries in .channels subtree.
@@ -2287,8 +2338,10 @@ export class ContainerRuntime extends TypedEventEmitter {
2287
2338
  */
2288
2339
  deleteSweepReadyNodes(sweepReadyRoutes) {
2289
2340
  const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
2290
- const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
2291
- return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
2341
+ return [
2342
+ ...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
2343
+ ...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
2344
+ ];
2292
2345
  }
2293
2346
  /**
2294
2347
  * This is called to update objects that are tombstones.
@@ -2314,10 +2367,13 @@ export class ContainerRuntime extends TypedEventEmitter {
2314
2367
  * Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
2315
2368
  * blob manager.
2316
2369
  */
2370
+ // eslint-disable-next-line import/no-deprecated
2317
2371
  getNodeType(nodePath) {
2318
2372
  if (isBlobPath(nodePath)) {
2373
+ // eslint-disable-next-line import/no-deprecated
2319
2374
  return GCNodeType.Blob;
2320
2375
  }
2376
+ // eslint-disable-next-line import/no-deprecated
2321
2377
  return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
2322
2378
  }
2323
2379
  /**
@@ -2331,13 +2387,19 @@ export class ContainerRuntime extends TypedEventEmitter {
2331
2387
  return ["_gcRoot"];
2332
2388
  }
2333
2389
  switch (this.getNodeType(nodePath)) {
2334
- case GCNodeType.Blob:
2390
+ // eslint-disable-next-line import/no-deprecated
2391
+ case GCNodeType.Blob: {
2335
2392
  return [blobManagerBasePath];
2393
+ }
2394
+ // eslint-disable-next-line import/no-deprecated
2336
2395
  case GCNodeType.DataStore:
2337
- case GCNodeType.SubDataStore:
2396
+ // eslint-disable-next-line import/no-deprecated
2397
+ case GCNodeType.SubDataStore: {
2338
2398
  return this.channelCollection.getDataStorePackagePath(nodePath);
2339
- default:
2399
+ }
2400
+ default: {
2340
2401
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
2402
+ }
2341
2403
  }
2342
2404
  }
2343
2405
  /**
@@ -2399,8 +2461,9 @@ export class ContainerRuntime extends TypedEventEmitter {
2399
2461
  * op processing, updating SummarizerNode state tracking, and garbage collection.
2400
2462
  * @param options - options controlling how the summary is generated or submitted
2401
2463
  */
2464
+ // eslint-disable-next-line import/no-deprecated
2402
2465
  async submitSummary(options) {
2403
- const { fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
2466
+ const { cancellationToken, fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
2404
2467
  // The summary number for this summary. This will be updated during the summary process, so get it now and
2405
2468
  // use it for all events logged during this summary.
2406
2469
  const summaryNumber = this.nextSummaryNumber;
@@ -2484,7 +2547,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2484
2547
  eventName: "LatestSummaryRefSeqNumMismatch",
2485
2548
  details: {
2486
2549
  ...startSummaryResult,
2487
- mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
2550
+ mismatchNumbers: [...startSummaryResult.mismatchNumbers],
2488
2551
  },
2489
2552
  });
2490
2553
  if (shouldValidatePreSummaryState && !finalAttempt) {
@@ -2504,7 +2567,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2504
2567
  // summarizer to reconnect in the future.
2505
2568
  // Also checking for cancellation is a must as summary process may be abandoned for other reasons,
2506
2569
  // like loss of connectivity for main (interactive) client.
2507
- if (options.cancellationToken.cancelled) {
2570
+ if (cancellationToken.cancelled) {
2508
2571
  return { continue: false, error: "disconnected" };
2509
2572
  }
2510
2573
  // That said, we rely on submitSystemMessage() that today only works in connected state.
@@ -2617,7 +2680,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2617
2680
  };
2618
2681
  let handle;
2619
2682
  try {
2620
- handle = await this.storage.uploadSummaryWithContext(summarizeResult.summary, summaryContext);
2683
+ handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
2621
2684
  }
2622
2685
  catch (error) {
2623
2686
  return {
@@ -2739,13 +2802,13 @@ export class ContainerRuntime extends TypedEventEmitter {
2739
2802
  return this.pendingMessagesCount !== 0;
2740
2803
  }
2741
2804
  updateDocumentDirtyState(dirty) {
2742
- if (this.attachState !== AttachState.Attached) {
2743
- assert(dirty, 0x3d2 /* Non-attached container is dirty */);
2744
- }
2745
- else {
2805
+ if (this.attachState === AttachState.Attached) {
2746
2806
  // Other way is not true = see this.isContainerMessageDirtyable()
2747
2807
  assert(!dirty || this.hasPendingMessages(), 0x3d3 /* if doc is dirty, there has to be pending ops */);
2748
2808
  }
2809
+ else {
2810
+ assert(dirty, 0x3d2 /* Non-attached container is dirty */);
2811
+ }
2749
2812
  if (this.dirtyContainer === dirty) {
2750
2813
  return;
2751
2814
  }
@@ -2807,7 +2870,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2807
2870
  // on this callback to do actual sending.
2808
2871
  const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
2809
2872
  if (schemaChangeMessage) {
2810
- this.logger.sendTelemetryEvent({
2873
+ this.mc.logger.sendTelemetryEvent({
2811
2874
  eventName: "SchemaChangeProposal",
2812
2875
  refSeq: schemaChangeMessage.refSeq,
2813
2876
  version: schemaChangeMessage.version,
@@ -2859,6 +2922,8 @@ export class ContainerRuntime extends TypedEventEmitter {
2859
2922
  return;
2860
2923
  }
2861
2924
  this.flushTaskExists = true;
2925
+ // TODO: hoist this out of the function scope to save unnecessary allocations
2926
+ // eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
2862
2927
  const flush = () => {
2863
2928
  this.flushTaskExists = false;
2864
2929
  try {
@@ -2869,22 +2934,25 @@ export class ContainerRuntime extends TypedEventEmitter {
2869
2934
  }
2870
2935
  };
2871
2936
  switch (this.flushMode) {
2872
- case FlushMode.TurnBased:
2937
+ case FlushMode.TurnBased: {
2873
2938
  // When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
2874
2939
  // batch at the end of the turn
2875
2940
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
2876
2941
  Promise.resolve().then(flush);
2877
2942
  break;
2943
+ }
2878
2944
  // FlushModeExperimental is experimental and not exposed directly in the runtime APIs
2879
- case FlushModeExperimental.Async:
2945
+ case FlushModeExperimental.Async: {
2880
2946
  // When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
2881
2947
  // batch when all micro-tasks are complete.
2882
2948
  // Compared to TurnBased, this flush mode will capture more ops into the same batch.
2883
2949
  setTimeout(flush, 0);
2884
2950
  break;
2885
- default:
2951
+ }
2952
+ default: {
2886
2953
  assert(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
2887
2954
  break;
2955
+ }
2888
2956
  }
2889
2957
  }
2890
2958
  submitSummaryMessage(contents, referenceSequenceNumber) {
@@ -2892,10 +2960,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2892
2960
  assert(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
2893
2961
  // System message should not be sent in the middle of the batch.
2894
2962
  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);
2963
+ return this.submitSummaryFn(contents, referenceSequenceNumber);
2899
2964
  }
2900
2965
  /**
2901
2966
  * Throw an error if the runtime is closed. Methods that are expected to potentially
@@ -2935,15 +3000,16 @@ export class ContainerRuntime extends TypedEventEmitter {
2935
3000
  * @param localOpMetadata - The local metadata associated with the original message.
2936
3001
  */
2937
3002
  reSubmitCore(message, localOpMetadata, opMetadata) {
2938
- assert(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
3003
+ assert(this._summarizer === undefined, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
2939
3004
  switch (message.type) {
2940
3005
  case ContainerMessageType.FluidDataStoreOp:
2941
3006
  case ContainerMessageType.Attach:
2942
- case ContainerMessageType.Alias:
3007
+ case ContainerMessageType.Alias: {
2943
3008
  // For Operations, call resubmitDataStoreOp which will find the right store
2944
3009
  // and trigger resubmission on it.
2945
3010
  this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
2946
3011
  break;
3012
+ }
2947
3013
  case ContainerMessageType.IdAllocation: {
2948
3014
  // Allocation ops are never resubmitted/rebased. This is because they require special handling to
2949
3015
  // avoid being submitted out of order. For example, if the pending state manager contained
@@ -2954,20 +3020,24 @@ export class ContainerRuntime extends TypedEventEmitter {
2954
3020
  // all pending IDs. The resubmitted allocation ops are then ignored here.
2955
3021
  break;
2956
3022
  }
2957
- case ContainerMessageType.BlobAttach:
3023
+ case ContainerMessageType.BlobAttach: {
2958
3024
  this.blobManager.reSubmit(opMetadata);
2959
3025
  break;
2960
- case ContainerMessageType.Rejoin:
3026
+ }
3027
+ case ContainerMessageType.Rejoin: {
2961
3028
  this.submit(message);
2962
3029
  break;
2963
- case ContainerMessageType.GC:
3030
+ }
3031
+ case ContainerMessageType.GC: {
2964
3032
  this.submit(message);
2965
3033
  break;
2966
- case ContainerMessageType.DocumentSchemaChange:
3034
+ }
3035
+ case ContainerMessageType.DocumentSchemaChange: {
2967
3036
  // There is no need to resend this message. Document schema controller will properly resend it again (if needed)
2968
3037
  // on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
2969
3038
  // send any ops, as some other client already changed schema.
2970
3039
  break;
3040
+ }
2971
3041
  default: {
2972
3042
  const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
2973
3043
  this.closeFn(error);
@@ -2979,18 +3049,21 @@ export class ContainerRuntime extends TypedEventEmitter {
2979
3049
  // Need to parse from string for back-compat
2980
3050
  const { type, contents } = this.parseLocalOpContent(content);
2981
3051
  switch (type) {
2982
- case ContainerMessageType.FluidDataStoreOp:
3052
+ case ContainerMessageType.FluidDataStoreOp: {
2983
3053
  // For operations, call rollbackDataStoreOp which will find the right store
2984
3054
  // and trigger rollback on it.
2985
3055
  this.channelCollection.rollback(type, contents, localOpMetadata);
2986
3056
  break;
2987
- default:
3057
+ }
3058
+ default: {
2988
3059
  throw new Error(`Can't rollback ${type}`);
3060
+ }
2989
3061
  }
2990
3062
  }
2991
3063
  /**
2992
3064
  * Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
2993
3065
  */
3066
+ // eslint-disable-next-line import/no-deprecated
2994
3067
  async refreshLatestSummaryAck(options) {
2995
3068
  const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
2996
3069
  // proposalHandle is always passed from RunningSummarizer.
@@ -3060,15 +3133,16 @@ export class ContainerRuntime extends TypedEventEmitter {
3060
3133
  snapshotTree = snapshot.snapshotTree;
3061
3134
  }
3062
3135
  else {
3063
- const versions = await this.storage.getVersions(null, 1, scenarioName, FetchSource.noCache);
3136
+ const versions = await this.storage.getVersions(
3137
+ // eslint-disable-next-line unicorn/no-null
3138
+ null, 1, scenarioName, FetchSource.noCache);
3064
3139
  assert(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
3065
3140
  snapshotTree = await this.storage.getSnapshotTree(versions[0]);
3066
3141
  assert(!!snapshotTree, 0x138 /* "Failed to get snapshot from storage" */);
3067
3142
  props.snapshotVersion = versions[0].id;
3068
3143
  }
3069
3144
  props.getSnapshotDuration = trace.trace().duration;
3070
- const readAndParseBlob = async (id) => readAndParse(this.storage, id);
3071
- const snapshotRefSeq = await seqFromTree(snapshotTree, readAndParseBlob);
3145
+ const snapshotRefSeq = await seqFromTree(snapshotTree, this.readAndParseBlob);
3072
3146
  props.snapshotRefSeq = snapshotRefSeq;
3073
3147
  props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
3074
3148
  perfEvent.end({ details: props });
@@ -3089,7 +3163,7 @@ export class ContainerRuntime extends TypedEventEmitter {
3089
3163
  if (this._orderSequentiallyCalls !== 0) {
3090
3164
  throw new UsageError("can't get state during orderSequentially");
3091
3165
  }
3092
- this.imminentClosure || (this.imminentClosure = props?.notifyImminentClosure ?? false);
3166
+ this.imminentClosure ||= props?.notifyImminentClosure ?? false;
3093
3167
  const getSyncState = (pendingAttachmentBlobs) => {
3094
3168
  const pending = this.pendingStateManager.getLocalState(props?.snapshotSequenceNumber);
3095
3169
  const sessionExpiryTimerStarted = props?.sessionExpiryTimerStarted ?? this.garbageCollector.sessionExpiryTimerStarted;
@@ -3121,32 +3195,32 @@ export class ContainerRuntime extends TypedEventEmitter {
3121
3195
  : PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
3122
3196
  }
3123
3197
  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);
3198
+ if (this._summarizer !== undefined) {
3199
+ return this._summarizer.summarizeOnDemand(options);
3129
3200
  }
3130
- else {
3201
+ else if (this.summaryManager === undefined) {
3131
3202
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
3132
3203
  // disableSummaries is turned on. We are throwing instead of returning a failure here,
3133
3204
  // because it is a misuse of the API rather than an expected failure.
3134
3205
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
3135
3206
  }
3207
+ else {
3208
+ return this.summaryManager.summarizeOnDemand(options);
3209
+ }
3136
3210
  }
3137
3211
  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);
3212
+ if (this._summarizer !== undefined) {
3213
+ return this._summarizer.enqueueSummarize(options);
3143
3214
  }
3144
- else {
3215
+ else if (this.summaryManager === undefined) {
3145
3216
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
3146
3217
  // generateSummaries is turned off. We are throwing instead of returning a failure here,
3147
3218
  // because it is a misuse of the API rather than an expected failure.
3148
3219
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
3149
3220
  }
3221
+ else {
3222
+ return this.summaryManager.enqueueSummarize(options);
3223
+ }
3150
3224
  }
3151
3225
  /**
3152
3226
  * Forms a function that will create and retrieve a Summarizer.