@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
@@ -3,7 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
6
+ import {
7
+ Trace,
8
+ TypedEventEmitter,
9
+ type ILayerCompatDetails,
10
+ type IProvideLayerCompatDetails,
11
+ } from "@fluid-internal/client-utils";
7
12
  import {
8
13
  AttachState,
9
14
  IAudience,
@@ -12,7 +17,6 @@ import {
12
17
  type IAudienceEvents,
13
18
  } from "@fluidframework/container-definitions";
14
19
  import {
15
- IBatchMessage,
16
20
  IContainerContext,
17
21
  IGetPendingLocalStateProps,
18
22
  ILoader,
@@ -34,6 +38,7 @@ import {
34
38
  ITelemetryBaseLogger,
35
39
  } from "@fluidframework/core-interfaces";
36
40
  import {
41
+ type IErrorBase,
37
42
  IFluidHandleContext,
38
43
  type IFluidHandleInternal,
39
44
  IProvideFluidHandleContext,
@@ -142,6 +147,7 @@ import {
142
147
  blobsTreeName,
143
148
  isBlobPath,
144
149
  loadBlobManagerLoadInfo,
150
+ // eslint-disable-next-line import/no-deprecated
145
151
  type IBlobManagerLoadInfo,
146
152
  } from "./blobManager/index.js";
147
153
  import {
@@ -159,15 +165,18 @@ import {
159
165
  } from "./deltaManagerProxies.js";
160
166
  import { DeltaScheduler } from "./deltaScheduler.js";
161
167
  import {
168
+ // eslint-disable-next-line import/no-deprecated
162
169
  GCNodeType,
163
170
  GarbageCollector,
164
171
  IGCRuntimeOptions,
172
+ // eslint-disable-next-line import/no-deprecated
165
173
  IGCStats,
166
174
  IGarbageCollector,
167
175
  gcGenerationOptionName,
168
176
  type GarbageCollectionMessage,
169
177
  } from "./gc/index.js";
170
178
  import { InboundBatchAggregator } from "./inboundBatchAggregator.js";
179
+ import { RuntimeCompatDetails, validateLoaderCompatibility } from "./layerCompatState.js";
171
180
  import {
172
181
  ContainerMessageType,
173
182
  type ContainerRuntimeDocumentSchemaMessage,
@@ -202,26 +211,38 @@ import {
202
211
  PendingStateManager,
203
212
  } from "./pendingStateManager.js";
204
213
  import {
214
+ // eslint-disable-next-line import/no-deprecated
205
215
  DocumentsSchemaController,
206
216
  EnqueueSummarizeResult,
207
217
  IBaseSummarizeResult,
218
+ // eslint-disable-next-line import/no-deprecated
208
219
  IConnectableRuntime,
220
+ // eslint-disable-next-line import/no-deprecated
209
221
  IContainerRuntimeMetadata,
222
+ // eslint-disable-next-line import/no-deprecated
210
223
  ICreateContainerMetadata,
224
+ // eslint-disable-next-line import/no-deprecated
211
225
  type IDocumentSchemaChangeMessage,
226
+ // eslint-disable-next-line import/no-deprecated
212
227
  type IDocumentSchemaCurrent,
213
228
  IEnqueueSummarizeOptions,
214
229
  IGenerateSummaryTreeResult,
215
230
  IGeneratedSummaryStats,
216
231
  IOnDemandSummarizeOptions,
232
+ // eslint-disable-next-line import/no-deprecated
217
233
  IRefreshSummaryAckOptions,
218
234
  IRootSummarizerNodeWithGC,
235
+ // eslint-disable-next-line import/no-deprecated
219
236
  ISerializedElection,
237
+ // eslint-disable-next-line import/no-deprecated
220
238
  ISubmitSummaryOptions,
221
239
  ISummarizeResults,
222
240
  ISummarizer,
241
+ // eslint-disable-next-line import/no-deprecated
223
242
  ISummarizerInternalsProvider,
243
+ // eslint-disable-next-line import/no-deprecated
224
244
  ISummarizerRuntime,
245
+ // eslint-disable-next-line import/no-deprecated
225
246
  ISummaryMetadataMessage,
226
247
  IdCompressorMode,
227
248
  OrderedClientCollection,
@@ -229,6 +250,7 @@ import {
229
250
  RetriableSummaryError,
230
251
  RunWhileConnectedCoordinator,
231
252
  SubmitSummaryResult,
253
+ // eslint-disable-next-line import/no-deprecated
232
254
  Summarizer,
233
255
  SummarizerClientElection,
234
256
  SummaryCollection,
@@ -244,6 +266,7 @@ import {
244
266
  rootHasIsolatedChannels,
245
267
  summarizerClientType,
246
268
  wrapSummaryInChannelsTree,
269
+ // eslint-disable-next-line import/no-deprecated
247
270
  type IDocumentSchemaFeatures,
248
271
  } from "./summary/index.js";
249
272
  import { Throttler, formExponentialFn } from "./throttler.js";
@@ -389,6 +412,12 @@ export type ISummaryConfiguration =
389
412
  | ISummaryConfigurationDisableHeuristics
390
413
  | ISummaryConfigurationHeuristics;
391
414
 
415
+ export function isSummariesDisabled(
416
+ config: ISummaryConfiguration,
417
+ ): config is ISummaryConfigurationDisableSummarizer {
418
+ return config.state === "disabled";
419
+ }
420
+
392
421
  /**
393
422
  * @legacy
394
423
  * @alpha
@@ -414,7 +443,7 @@ export const DefaultSummaryConfiguration: ISummaryConfiguration = {
414
443
 
415
444
  nonRuntimeOpWeight: 0.1,
416
445
 
417
- runtimeOpWeight: 1.0,
446
+ runtimeOpWeight: 1,
418
447
 
419
448
  nonRuntimeHeuristicThreshold: 20,
420
449
  };
@@ -560,6 +589,7 @@ export interface IContainerRuntimeOptionsInternal extends IContainerRuntimeOptio
560
589
  * Error responses when requesting a deleted object will have this header set to true
561
590
  * @legacy
562
591
  * @alpha
592
+ * @deprecated This type will be moved to internal in 2.30. External usage is not necessary or supported.
563
593
  */
564
594
  export const DeletedResponseHeaderKey = "wasDeleted";
565
595
  /**
@@ -611,7 +641,7 @@ export enum CompressionAlgorithms {
611
641
  * @alpha
612
642
  */
613
643
  export const disabledCompressionConfig: ICompressionRuntimeOptions = {
614
- minimumBatchSizeInBytes: Infinity,
644
+ minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
615
645
  compressionAlgorithm: CompressionAlgorithms.lz4,
616
646
  };
617
647
 
@@ -713,7 +743,9 @@ export function getDeviceSpec(): {
713
743
  hardwareConcurrency: navigator.hardwareConcurrency,
714
744
  };
715
745
  }
716
- } catch {}
746
+ } catch {
747
+ // Eat the error
748
+ }
717
749
  return {};
718
750
  }
719
751
 
@@ -774,19 +806,18 @@ async function createSummarizer(loader: ILoader, url: string): Promise<ISummariz
774
806
 
775
807
  // Older containers may not have the "getEntryPoint" API
776
808
  // ! This check will need to stay until LTS of loader moves past 2.0.0-internal.7.0.0
777
- if (resolvedContainer.getEntryPoint !== undefined) {
778
- fluidObject = await resolvedContainer.getEntryPoint();
779
- } else {
780
- // 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
781
- const response = await (resolvedContainer as any).request({
809
+ if (resolvedContainer.getEntryPoint === undefined) {
810
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
811
+ const response = (await (resolvedContainer as any).request({
782
812
  url: `/${summarizerRequestUrl}`,
783
- });
784
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
813
+ })) as IResponse;
785
814
  if (response.status !== 200 || response.mimeType !== "fluid/object") {
786
815
  throw responseToException(response, request);
787
816
  }
788
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
817
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
789
818
  fluidObject = response.value;
819
+ } else {
820
+ fluidObject = await resolvedContainer.getEntryPoint();
790
821
  }
791
822
 
792
823
  if (fluidObject?.ISummarizer === undefined) {
@@ -802,7 +833,9 @@ async function createSummarizer(loader: ILoader, url: string): Promise<ISummariz
802
833
  * Please see addMetadataToSummary() as well
803
834
  */
804
835
  function lastMessageFromMetadata(
836
+ // eslint-disable-next-line import/no-deprecated
805
837
  metadata: IContainerRuntimeMetadata | undefined,
838
+ // eslint-disable-next-line import/no-deprecated
806
839
  ): ISummaryMetadataMessage | undefined {
807
840
  return metadata?.documentSchema?.runtime?.explicitSchemaControl
808
841
  ? metadata?.lastMessage
@@ -822,6 +855,7 @@ export let getSingleUseLegacyLogCallback = (logger: ITelemetryLoggerExt, type: s
822
855
  });
823
856
 
824
857
  // Now that we've logged, prevent future logging (globally).
858
+ // eslint-disable-next-line unicorn/consistent-function-scoping
825
859
  getSingleUseLegacyLogCallback = () => () => {};
826
860
  };
827
861
  };
@@ -877,6 +911,10 @@ export async function loadContainerRuntime(
877
911
  return ContainerRuntime.loadRuntime(params);
878
912
  }
879
913
 
914
+ const defaultMaxConsecutiveReconnects = 7;
915
+
916
+ const defaultTelemetrySignalSampleCount = 100;
917
+
880
918
  /**
881
919
  * Represents the runtime of the container. Contains helper functions/state of the container.
882
920
  * It will define the store level mappings.
@@ -888,9 +926,12 @@ export class ContainerRuntime
888
926
  implements
889
927
  IContainerRuntime,
890
928
  IRuntime,
929
+ // eslint-disable-next-line import/no-deprecated
891
930
  ISummarizerRuntime,
931
+ // eslint-disable-next-line import/no-deprecated
892
932
  ISummarizerInternalsProvider,
893
- IProvideFluidHandleContext
933
+ IProvideFluidHandleContext,
934
+ IProvideLayerCompatDetails
894
935
  {
895
936
  /**
896
937
  * Load the stores from a snapshot and returns the runtime.
@@ -991,7 +1032,9 @@ export class ContainerRuntime
991
1032
  tryFetchBlob<ReturnType<DuplicateBatchDetector["getRecentBatchInfoForSummary"]>>(
992
1033
  recentBatchInfoBlobName,
993
1034
  ),
1035
+ // eslint-disable-next-line import/no-deprecated
994
1036
  tryFetchBlob<IContainerRuntimeMetadata>(metadataBlobName),
1037
+ // eslint-disable-next-line import/no-deprecated
995
1038
  tryFetchBlob<ISerializedElection>(electedSummarizerBlobName),
996
1039
  tryFetchBlob<[string, string][]>(aliasBlobName),
997
1040
  tryFetchBlob<SerializedIdCompressorWithNoSession>(idCompressorBlobName),
@@ -1008,6 +1051,7 @@ export class ContainerRuntime
1008
1051
  // When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
1009
1052
  if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
1010
1053
  // Unless bypass is explicitly set, then take action when sequence numbers mismatch.
1054
+ // eslint-disable-next-line unicorn/no-lonely-if -- Separate if statements make flow easier to parse
1011
1055
  if (
1012
1056
  loadSequenceNumberVerification !== "bypass" &&
1013
1057
  runtimeSequenceNumber !== protocolSequenceNumber
@@ -1036,15 +1080,18 @@ export class ContainerRuntime
1036
1080
 
1037
1081
  let desiredIdCompressorMode: IdCompressorMode;
1038
1082
  switch (mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) {
1039
- case true:
1083
+ case true: {
1040
1084
  desiredIdCompressorMode = "on";
1041
1085
  break;
1042
- case false:
1086
+ }
1087
+ case false: {
1043
1088
  desiredIdCompressorMode = undefined;
1044
1089
  break;
1045
- default:
1090
+ }
1091
+ default: {
1046
1092
  desiredIdCompressorMode = enableRuntimeIdCompressor;
1047
1093
  break;
1094
+ }
1048
1095
  }
1049
1096
 
1050
1097
  // Enabling the IdCompressor is a one-way operation and we only want to
@@ -1108,21 +1155,22 @@ export class ContainerRuntime
1108
1155
  pendingLocalState.pendingIdCompressorState,
1109
1156
  compressorLogger,
1110
1157
  );
1111
- } else if (serializedIdCompressor !== undefined) {
1158
+ } else if (serializedIdCompressor === undefined) {
1159
+ return createIdCompressor(compressorLogger);
1160
+ } else {
1112
1161
  return deserializeIdCompressor(
1113
1162
  serializedIdCompressor,
1114
1163
  createSessionId(),
1115
1164
  compressorLogger,
1116
1165
  );
1117
- } else {
1118
- return createIdCompressor(compressorLogger);
1119
1166
  }
1120
1167
  };
1121
1168
 
1122
1169
  const compressionLz4 =
1123
- compressionOptions.minimumBatchSizeInBytes !== Infinity &&
1170
+ compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY &&
1124
1171
  compressionOptions.compressionAlgorithm === "lz4";
1125
1172
 
1173
+ // eslint-disable-next-line import/no-deprecated
1126
1174
  const documentSchemaController = new DocumentsSchemaController(
1127
1175
  existing,
1128
1176
  protocolSequenceNumber,
@@ -1190,7 +1238,7 @@ export class ContainerRuntime
1190
1238
  runtime.setConnectionStateCore(true, runtime.delayConnectClientId);
1191
1239
  }
1192
1240
  },
1193
- (error) => runtime.closeFn(error),
1241
+ (error: IErrorBase) => runtime.closeFn(error),
1194
1242
  );
1195
1243
 
1196
1244
  // Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
@@ -1221,18 +1269,6 @@ export class ContainerRuntime
1221
1269
  return this;
1222
1270
  }
1223
1271
 
1224
- private readonly submitFn: (
1225
- type: MessageType,
1226
- contents: unknown,
1227
- batch: boolean,
1228
- appData?: unknown,
1229
- ) => number;
1230
- /**
1231
- * Although current IContainerContext guarantees submitBatchFn, it is not available on older loaders.
1232
- */
1233
- private readonly submitBatchFn:
1234
- | ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)
1235
- | undefined;
1236
1272
  private readonly submitSummaryFn: (
1237
1273
  summaryOp: ISummaryContent,
1238
1274
  referenceSequenceNumber?: number,
@@ -1272,9 +1308,11 @@ export class ContainerRuntime
1272
1308
  * this op roundtrips, compression will be On. Client can't send compressed ops until it's change in schema.
1273
1309
  */
1274
1310
  public get sessionSchema(): {
1311
+ // eslint-disable-next-line import/no-deprecated
1275
1312
  [P in keyof IDocumentSchemaFeatures]?: IDocumentSchemaFeatures[P] extends boolean
1276
1313
  ? true
1277
- : IDocumentSchemaFeatures[P];
1314
+ : // eslint-disable-next-line import/no-deprecated
1315
+ IDocumentSchemaFeatures[P];
1278
1316
  } {
1279
1317
  return this.documentsSchemaController.sessionSchema.runtime;
1280
1318
  }
@@ -1291,9 +1329,6 @@ export class ContainerRuntime
1291
1329
  // In such case we have to process all ops, including those marked with savedOp === true.
1292
1330
  private readonly skipSavedCompressorOps: boolean;
1293
1331
 
1294
- public get idCompressorMode(): IdCompressorMode {
1295
- return this.sessionSchema.idCompressorMode;
1296
- }
1297
1332
  /**
1298
1333
  * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor}
1299
1334
  */
@@ -1302,7 +1337,7 @@ export class ContainerRuntime
1302
1337
  // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
1303
1338
  // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
1304
1339
  // to reason over such things as session ID space.
1305
- if (this.idCompressorMode === "on") {
1340
+ if (this.sessionSchema.idCompressorMode === "on") {
1306
1341
  assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
1307
1342
  return this._idCompressor;
1308
1343
  }
@@ -1310,7 +1345,7 @@ export class ContainerRuntime
1310
1345
 
1311
1346
  /**
1312
1347
  * True if we have ID compressor loading in-flight (async operation). Useful only for
1313
- * this.idCompressorMode === "delayed" mode
1348
+ * this.sessionSchema.idCompressorMode === "delayed" mode
1314
1349
  */
1315
1350
  protected _loadIdCompressor: Promise<void> | undefined;
1316
1351
 
@@ -1354,14 +1389,10 @@ export class ContainerRuntime
1354
1389
  * do not create it (see SummarizerClientElection.clientDetailsPermitElection() for details)
1355
1390
  */
1356
1391
  private readonly summaryManager?: SummaryManager;
1357
- private readonly summaryCollection: SummaryCollection;
1358
1392
 
1359
1393
  private readonly summarizerNode: IRootSummarizerNodeWithGC;
1360
1394
 
1361
- private readonly logger: ITelemetryLoggerExt;
1362
-
1363
1395
  private readonly maxConsecutiveReconnects: number;
1364
- private readonly defaultMaxConsecutiveReconnects = 7;
1365
1396
 
1366
1397
  private _orderSequentiallyCalls: number = 0;
1367
1398
  private readonly _flushMode: FlushMode;
@@ -1415,10 +1446,8 @@ export class ContainerRuntime
1415
1446
 
1416
1447
  private dirtyContainer: boolean;
1417
1448
  private emitDirtyDocumentEvent = true;
1418
- private readonly disableAttachReorder: boolean | undefined;
1419
1449
  private readonly useDeltaManagerOpsProxy: boolean;
1420
1450
  private readonly closeSummarizerDelayMs: number;
1421
- private readonly defaultTelemetrySignalSampleCount = 100;
1422
1451
  private readonly _signalTracking: IPerfSignalReport = {
1423
1452
  totalSignalsSentInLatencyWindow: 0,
1424
1453
  signalsLost: 0,
@@ -1436,6 +1465,7 @@ export class ContainerRuntime
1436
1465
  * It is the main entry point for summary work.
1437
1466
  * It is created only by summarizing container (i.e. one with clientType === "summarizer")
1438
1467
  */
1468
+ // eslint-disable-next-line import/no-deprecated
1439
1469
  private readonly _summarizer?: Summarizer;
1440
1470
  private readonly deltaScheduler: DeltaScheduler;
1441
1471
  private readonly inboundBatchAggregator: InboundBatchAggregator;
@@ -1451,37 +1481,12 @@ export class ContainerRuntime
1451
1481
  /**
1452
1482
  * The last message processed at the time of the last summary.
1453
1483
  */
1484
+ // eslint-disable-next-line import/no-deprecated
1454
1485
  private messageAtLastSummary: ISummaryMetadataMessage | undefined;
1455
1486
 
1456
- private get summarizer(): Summarizer {
1457
- assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
1458
- return this._summarizer;
1459
- }
1460
-
1461
1487
  private readonly summariesDisabled: boolean;
1462
- private isSummariesDisabled(): boolean {
1463
- return this.summaryConfiguration.state === "disabled";
1464
- }
1465
-
1466
- private readonly maxOpsSinceLastSummary: number;
1467
- private getMaxOpsSinceLastSummary(): number {
1468
- return this.summaryConfiguration.state !== "disabled"
1469
- ? this.summaryConfiguration.maxOpsSinceLastSummary
1470
- : 0;
1471
- }
1472
-
1473
- private readonly initialSummarizerDelayMs: number;
1474
- private getInitialSummarizerDelayMs(): number {
1475
- // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
1476
- // to ISummaryConfiguration in 0.60.
1477
- if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
1478
- return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
1479
- }
1480
- return this.summaryConfiguration.state !== "disabled"
1481
- ? this.summaryConfiguration.initialSummarizerDelayMs
1482
- : 0;
1483
- }
1484
1488
 
1489
+ // eslint-disable-next-line import/no-deprecated
1485
1490
  private readonly createContainerMetadata: ICreateContainerMetadata;
1486
1491
  /**
1487
1492
  * The summary number of the next summary that will be generated for this container. This is incremented every time
@@ -1513,11 +1518,6 @@ export class ContainerRuntime
1513
1518
  */
1514
1519
  private readonly telemetryDocumentId: string;
1515
1520
 
1516
- /**
1517
- * Whether this client is the summarizer client itself (type is summarizerClientType)
1518
- */
1519
- private readonly isSummarizerClient: boolean;
1520
-
1521
1521
  /**
1522
1522
  * The id of the version used to initially load this runtime, or undefined if it's newly created.
1523
1523
  */
@@ -1538,27 +1538,30 @@ export class ContainerRuntime
1538
1538
  expiry: { policy: "absolute", durationMs: 60000 },
1539
1539
  });
1540
1540
 
1541
- /**
1542
- * The options to apply to this ContainerRuntime instance (including internal options hidden from the public API)
1543
- */
1544
- private readonly runtimeOptions: Readonly<Required<IContainerRuntimeOptionsInternal>>;
1541
+ public get ILayerCompatDetails(): ILayerCompatDetails {
1542
+ return RuntimeCompatDetails;
1543
+ }
1545
1544
 
1546
1545
  /***/
1547
1546
  protected constructor(
1548
1547
  context: IContainerContext,
1549
1548
  private readonly registry: IFluidDataStoreRegistry,
1549
+ // eslint-disable-next-line import/no-deprecated
1550
1550
  private readonly metadata: IContainerRuntimeMetadata | undefined,
1551
+ // eslint-disable-next-line import/no-deprecated
1551
1552
  electedSummarizerData: ISerializedElection | undefined,
1552
1553
  chunks: [string, string[]][],
1553
1554
  dataStoreAliasMap: [string, string][],
1554
- runtimeOptions: Readonly<Required<IContainerRuntimeOptions>>,
1555
+ baseRuntimeOptions: Readonly<Required<IContainerRuntimeOptions>>,
1555
1556
  private readonly containerScope: FluidObject,
1556
1557
  // Create a custom ITelemetryBaseLogger to output telemetry events.
1557
1558
  public readonly baseLogger: ITelemetryBaseLogger,
1558
1559
  existing: boolean,
1560
+ // eslint-disable-next-line import/no-deprecated
1559
1561
  blobManagerSnapshot: IBlobManagerLoadInfo,
1560
1562
  private readonly _storage: IDocumentStorageService,
1561
1563
  private readonly createIdCompressor: () => Promise<IIdCompressor & IIdCompressorCore>,
1564
+ // eslint-disable-next-line import/no-deprecated
1562
1565
  private readonly documentsSchemaController: DocumentsSchemaController,
1563
1566
  featureGatesForTelemetry: Record<string, boolean | number | undefined>,
1564
1567
  provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
@@ -1566,11 +1569,12 @@ export class ContainerRuntime
1566
1569
  request: IRequest,
1567
1570
  runtime: IContainerRuntime,
1568
1571
  ) => Promise<IResponse>,
1569
- private readonly summaryConfiguration: ISummaryConfiguration = {
1572
+ // eslint-disable-next-line unicorn/no-object-as-default-parameter
1573
+ summaryConfiguration: ISummaryConfiguration = {
1570
1574
  // the defaults
1571
1575
  ...DefaultSummaryConfiguration,
1572
1576
  // the runtime configuration overrides
1573
- ...runtimeOptions.summaryOptions?.summaryConfigOverrides,
1577
+ ...baseRuntimeOptions.summaryOptions?.summaryConfigOverrides,
1574
1578
  },
1575
1579
  recentBatchInfo?: [number, string][],
1576
1580
  ) {
@@ -1596,14 +1600,19 @@ export class ContainerRuntime
1596
1600
  snapshotWithContents,
1597
1601
  } = context;
1598
1602
 
1603
+ // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
1604
+ this.disposeFn = disposeFn ?? closeFn;
1605
+
1606
+ const maybeLoaderCompatDetails = context as FluidObject<ILayerCompatDetails>;
1607
+ validateLoaderCompatibility(maybeLoaderCompatDetails.ILayerCompatDetails, this.disposeFn);
1608
+
1599
1609
  // Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
1600
- this.runtimeOptions = {
1610
+ const runtimeOptions = {
1601
1611
  flushMode: defaultFlushMode,
1602
- ...runtimeOptions,
1612
+ ...baseRuntimeOptions,
1603
1613
  };
1604
- this.logger = createChildLogger({ logger: this.baseLogger });
1605
1614
  this.mc = createChildMonitoringContext({
1606
- logger: this.logger,
1615
+ logger: this.baseLogger,
1607
1616
  namespace: "ContainerRuntime",
1608
1617
  });
1609
1618
 
@@ -1623,20 +1632,24 @@ export class ContainerRuntime
1623
1632
 
1624
1633
  // Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
1625
1634
  // This makes ContainerRuntime the final gatekeeper for outgoing messages.
1626
- this.submitFn = submitFn;
1627
- this.submitBatchFn = submitBatchFn;
1628
- this.submitSummaryFn = submitSummaryFn;
1635
+ // back-compat: ADO #1385: Make this call unconditional in the future
1636
+ this.submitSummaryFn =
1637
+ submitSummaryFn ??
1638
+ ((summaryOp, refseq) => submitFn(MessageType.Summarize, summaryOp, false));
1629
1639
  this.submitSignalFn = submitSignalFn;
1630
1640
 
1631
1641
  // TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
1632
1642
  // Values are generally expected to be set from the runtime side.
1633
1643
  this.options = options ?? {};
1634
1644
  this.clientDetails = clientDetails;
1635
- this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
1645
+ const isSummarizerClient = this.clientDetails.type === summarizerClientType;
1636
1646
  this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
1647
+ // eslint-disable-next-line unicorn/consistent-destructuring
1637
1648
  this._getClientId = () => context.clientId;
1649
+ // eslint-disable-next-line unicorn/consistent-destructuring
1638
1650
  this._getAttachState = () => context.attachState;
1639
1651
  this.getAbsoluteUrl = async (relativeUrl: string) => {
1652
+ // eslint-disable-next-line unicorn/consistent-destructuring
1640
1653
  if (context.getAbsoluteUrl === undefined) {
1641
1654
  throw new Error("Driver does not implement getAbsoluteUrl");
1642
1655
  }
@@ -1650,10 +1663,8 @@ export class ContainerRuntime
1650
1663
  this.on("dirty", () => context.updateDirtyContainerState(true));
1651
1664
  this.on("saved", () => context.updateDirtyContainerState(false));
1652
1665
 
1653
- // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
1654
- this.disposeFn = disposeFn ?? closeFn;
1655
1666
  // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
1656
- this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
1667
+ this.closeFn = isSummarizerClient ? this.disposeFn : closeFn;
1657
1668
 
1658
1669
  let loadSummaryNumber: number;
1659
1670
  // Get the container creation metadata. For new container, we initialize these. For existing containers,
@@ -1686,28 +1697,22 @@ export class ContainerRuntime
1686
1697
  metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
1687
1698
  inputs: JSON.stringify({
1688
1699
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1689
- gcOptions_gcGeneration: this.runtimeOptions.gcOptions[gcGenerationOptionName],
1700
+ gcOptions_gcGeneration: runtimeOptions.gcOptions[gcGenerationOptionName],
1690
1701
  }),
1691
1702
  });
1692
1703
 
1693
1704
  this.telemetryDocumentId = metadata?.telemetryDocumentId ?? uuid();
1694
1705
 
1695
- this.disableAttachReorder = this.mc.config.getBoolean(
1696
- "Fluid.ContainerRuntime.disableAttachOpReorder",
1697
- );
1698
-
1699
1706
  const opGroupingManager = new OpGroupingManager(
1700
1707
  {
1701
1708
  groupedBatchingEnabled: this.groupedBatchingEnabled,
1702
- opCountThreshold:
1703
- this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
1704
1709
  },
1705
1710
  this.mc.logger,
1706
1711
  );
1707
1712
 
1708
1713
  const opSplitter = new OpSplitter(
1709
1714
  chunks,
1710
- this.submitBatchFn,
1715
+ submitBatchFn,
1711
1716
  runtimeOptions.chunkSizeInBytes,
1712
1717
  runtimeOptions.maxBatchSizeInBytes,
1713
1718
  this.mc.logger,
@@ -1730,7 +1735,7 @@ export class ContainerRuntime
1730
1735
  isAttached: () => this.attachState !== AttachState.Detached,
1731
1736
  },
1732
1737
  pendingRuntimeState?.pending,
1733
- this.logger,
1738
+ this.baseLogger,
1734
1739
  );
1735
1740
 
1736
1741
  let outerDeltaManager: IDeltaManagerFull;
@@ -1756,28 +1761,42 @@ export class ContainerRuntime
1756
1761
 
1757
1762
  this.handleContext = new ContainerFluidHandleContext("", this);
1758
1763
 
1759
- if (this.summaryConfiguration.state === "enabled") {
1760
- this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
1764
+ if (summaryConfiguration.state === "enabled") {
1765
+ this.validateSummaryHeuristicConfiguration(summaryConfiguration);
1761
1766
  }
1762
1767
 
1763
- this.summariesDisabled = this.isSummariesDisabled();
1764
- this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
1765
- this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
1768
+ this.summariesDisabled = isSummariesDisabled(summaryConfiguration);
1769
+ const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = isSummariesDisabled(
1770
+ summaryConfiguration,
1771
+ )
1772
+ ? {}
1773
+ : {
1774
+ ...summaryConfiguration,
1775
+ initialSummarizerDelayMs:
1776
+ // back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
1777
+ // to ISummaryConfiguration in 0.60.
1778
+ runtimeOptions.summaryOptions.initialSummarizerDelayMs ??
1779
+ summaryConfiguration.initialSummarizerDelayMs,
1780
+ };
1766
1781
 
1767
1782
  this.maxConsecutiveReconnects =
1768
- this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
1769
- this.defaultMaxConsecutiveReconnects;
1770
-
1783
+ this.mc.config.getNumber(maxConsecutiveReconnectsKey) ?? defaultMaxConsecutiveReconnects;
1784
+
1785
+ // If the context has ILayerCompatDetails, it supports referenceSequenceNumbers since that features
1786
+ // predates ILayerCompatDetails.
1787
+ const referenceSequenceNumbersSupported =
1788
+ maybeLoaderCompatDetails.ILayerCompatDetails === undefined
1789
+ ? supportedFeatures?.get("referenceSequenceNumbers") === true
1790
+ : true;
1771
1791
  if (
1772
- this.runtimeOptions.flushMode ===
1773
- (FlushModeExperimental.Async as unknown as FlushMode) &&
1774
- supportedFeatures?.get("referenceSequenceNumbers") !== true
1792
+ runtimeOptions.flushMode === (FlushModeExperimental.Async as unknown as FlushMode) &&
1793
+ !referenceSequenceNumbersSupported
1775
1794
  ) {
1776
1795
  // The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
1777
1796
  this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
1778
1797
  this._flushMode = FlushMode.TurnBased;
1779
1798
  } else {
1780
- this._flushMode = this.runtimeOptions.flushMode;
1799
+ this._flushMode = runtimeOptions.flushMode;
1781
1800
  }
1782
1801
  this.offlineEnabled =
1783
1802
  this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
@@ -1795,6 +1814,7 @@ export class ContainerRuntime
1795
1814
  this.duplicateBatchDetector = new DuplicateBatchDetector(recentBatchInfo);
1796
1815
  }
1797
1816
 
1817
+ // eslint-disable-next-line unicorn/consistent-destructuring
1798
1818
  if (context.attachState === AttachState.Attached) {
1799
1819
  const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
1800
1820
  if (
@@ -1810,13 +1830,13 @@ export class ContainerRuntime
1810
1830
 
1811
1831
  this.garbageCollector = GarbageCollector.create({
1812
1832
  runtime: this,
1813
- gcOptions: this.runtimeOptions.gcOptions,
1833
+ gcOptions: runtimeOptions.gcOptions,
1814
1834
  baseSnapshot,
1815
1835
  baseLogger: this.mc.logger,
1816
1836
  existing,
1817
1837
  metadata,
1818
1838
  createContainerMetadata: this.createContainerMetadata,
1819
- isSummarizerClient: this.isSummarizerClient,
1839
+ isSummarizerClient,
1820
1840
  getNodePackagePath: async (nodePath: string) => this.getGCNodePackagePath(nodePath),
1821
1841
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
1822
1842
  readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
@@ -1833,7 +1853,7 @@ export class ContainerRuntime
1833
1853
  ? undefined
1834
1854
  : loadedFromSequenceNumber;
1835
1855
  this.summarizerNode = createRootSummarizerNodeWithGC(
1836
- createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
1856
+ createChildLogger({ logger: this.baseLogger, namespace: "SummarizerNode" }),
1837
1857
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
1838
1858
  async (fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext) =>
1839
1859
  this.summarizeInternal(fullTree, trackState, telemetryContext),
@@ -1922,31 +1942,30 @@ export class ContainerRuntime
1922
1942
  isBlobDeleted: (blobPath: string) => this.garbageCollector.isNodeDeleted(blobPath),
1923
1943
  runtime: this,
1924
1944
  stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
1925
- closeContainer: (error?: ICriticalContainerError) => this.closeFn(error),
1926
1945
  });
1927
1946
 
1928
1947
  this.deltaScheduler = new DeltaScheduler(
1929
1948
  this.innerDeltaManager,
1930
1949
  this,
1931
- createChildLogger({ logger: this.logger, namespace: "DeltaScheduler" }),
1950
+ createChildLogger({ logger: this.baseLogger, namespace: "DeltaScheduler" }),
1932
1951
  );
1933
1952
 
1934
1953
  this.inboundBatchAggregator = new InboundBatchAggregator(
1935
1954
  this.innerDeltaManager,
1936
1955
  () => this.clientId,
1937
- createChildLogger({ logger: this.logger, namespace: "InboundBatchAggregator" }),
1956
+ createChildLogger({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }),
1938
1957
  );
1939
1958
 
1940
1959
  const disablePartialFlush = this.mc.config.getBoolean(
1941
1960
  "Fluid.ContainerRuntime.DisablePartialFlush",
1942
1961
  );
1943
1962
 
1944
- const legacySendBatchFn = makeLegacySendBatchFn(this.submitFn, this.innerDeltaManager);
1963
+ const legacySendBatchFn = makeLegacySendBatchFn(submitFn, this.innerDeltaManager);
1945
1964
 
1946
1965
  this.outbox = new Outbox({
1947
1966
  shouldSend: () => this.canSendOps(),
1948
1967
  pendingStateManager: this.pendingStateManager,
1949
- submitBatchFn: this.submitBatchFn,
1968
+ submitBatchFn,
1950
1969
  legacySendBatchFn,
1951
1970
  compressor: new OpCompressor(this.mc.logger),
1952
1971
  splitter: opSplitter,
@@ -2003,7 +2022,7 @@ export class ContainerRuntime
2003
2022
  );
2004
2023
  this.closeSummarizerDelayMs =
2005
2024
  closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
2006
- this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
2025
+ const summaryCollection = new SummaryCollection(this.deltaManager, this.baseLogger);
2007
2026
 
2008
2027
  this.dirtyContainer =
2009
2028
  this.attachState !== AttachState.Attached || this.hasPendingMessages();
@@ -2013,7 +2032,7 @@ export class ContainerRuntime
2013
2032
  this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
2014
2033
  } else {
2015
2034
  const orderedClientLogger = createChildLogger({
2016
- logger: this.logger,
2035
+ logger: this.baseLogger,
2017
2036
  namespace: "OrderedClientElection",
2018
2037
  });
2019
2038
  const orderedClientCollection = new OrderedClientCollection(
@@ -2033,18 +2052,20 @@ export class ContainerRuntime
2033
2052
 
2034
2053
  this.summarizerClientElection = new SummarizerClientElection(
2035
2054
  orderedClientLogger,
2036
- this.summaryCollection,
2055
+ summaryCollection,
2037
2056
  orderedClientElectionForSummarizer,
2038
- this.maxOpsSinceLastSummary,
2057
+ maxOpsSinceLastSummary,
2039
2058
  );
2040
2059
 
2041
- if (this.isSummarizerClient) {
2060
+ if (isSummarizerClient) {
2061
+ // eslint-disable-next-line import/no-deprecated
2042
2062
  this._summarizer = new Summarizer(
2043
2063
  this /* ISummarizerRuntime */,
2044
- () => this.summaryConfiguration,
2064
+ () => summaryConfiguration,
2045
2065
  this /* ISummarizerInternalsProvider */,
2046
2066
  this.handleContext,
2047
- this.summaryCollection,
2067
+ summaryCollection,
2068
+ // eslint-disable-next-line import/no-deprecated
2048
2069
  async (runtime: IConnectableRuntime) =>
2049
2070
  RunWhileConnectedCoordinator.create(
2050
2071
  runtime,
@@ -2057,31 +2078,31 @@ export class ContainerRuntime
2057
2078
  // Only create a SummaryManager and SummarizerClientElection
2058
2079
  // if summaries are enabled and we are not the summarizer client.
2059
2080
  const defaultAction = (): void => {
2060
- if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
2081
+ if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
2061
2082
  this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
2062
2083
  // unregister default to no log on every op after falling behind
2063
2084
  // and register summary ack handler to re-register this handler
2064
2085
  // after successful summary
2065
- this.summaryCollection.once(MessageType.SummaryAck, () => {
2086
+ summaryCollection.once(MessageType.SummaryAck, () => {
2066
2087
  this.mc.logger.sendTelemetryEvent({
2067
2088
  eventName: "SummaryStatus:CaughtUp",
2068
2089
  });
2069
2090
  // we've caught up, so re-register the default action to monitor for
2070
2091
  // falling behind, and unregister ourself
2071
- this.summaryCollection.on("default", defaultAction);
2092
+ summaryCollection.on("default", defaultAction);
2072
2093
  });
2073
- this.summaryCollection.off("default", defaultAction);
2094
+ summaryCollection.off("default", defaultAction);
2074
2095
  }
2075
2096
  };
2076
2097
 
2077
- this.summaryCollection.on("default", defaultAction);
2098
+ summaryCollection.on("default", defaultAction);
2078
2099
 
2079
2100
  // Create the SummaryManager and mark the initial state
2080
2101
  this.summaryManager = new SummaryManager(
2081
2102
  this.summarizerClientElection,
2082
2103
  this, // IConnectedState
2083
- this.summaryCollection,
2084
- this.logger,
2104
+ summaryCollection,
2105
+ this.baseLogger,
2085
2106
  this.formCreateSummarizerFn(loader),
2086
2107
  new Throttler(
2087
2108
  60 * 1000, // 60 sec delay window
@@ -2090,28 +2111,29 @@ export class ContainerRuntime
2090
2111
  formExponentialFn({ coefficient: 20, initialDelay: 0 }),
2091
2112
  ),
2092
2113
  {
2093
- initialDelayMs: this.initialSummarizerDelayMs,
2114
+ initialDelayMs: initialSummarizerDelayMs,
2094
2115
  },
2095
2116
  );
2096
2117
  // Forward events from SummaryManager
2097
- [
2118
+ for (const eventName of [
2098
2119
  "summarize",
2099
2120
  "summarizeAllAttemptsFailed",
2100
2121
  "summarizerStop",
2101
2122
  "summarizerStart",
2102
2123
  "summarizerStartupFailed",
2103
- ].forEach((eventName) => {
2104
- this.summaryManager?.on(eventName, (...args: any[]) => {
2124
+ ]) {
2125
+ this.summaryManager?.on(eventName, (...args: unknown[]) => {
2105
2126
  this.emit(eventName, ...args);
2106
2127
  });
2107
- });
2128
+ }
2108
2129
 
2109
2130
  this.summaryManager.start();
2110
2131
  }
2111
2132
  }
2112
2133
 
2113
2134
  // logging hardware telemetry
2114
- this.logger.sendTelemetryEvent({
2135
+ this.baseLogger.send({
2136
+ category: "generic",
2115
2137
  eventName: "DeviceSpec",
2116
2138
  ...getDeviceSpec(),
2117
2139
  });
@@ -2124,13 +2146,12 @@ export class ContainerRuntime
2124
2146
  summaryFormatVersion: metadata?.summaryFormatVersion,
2125
2147
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
2126
2148
  gcVersion: metadata?.gcFeature,
2127
- options: JSON.stringify(runtimeOptions),
2149
+ options: JSON.stringify(baseRuntimeOptions),
2128
2150
  idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
2129
- idCompressorMode: this.idCompressorMode,
2151
+ idCompressorMode: this.sessionSchema.idCompressorMode,
2130
2152
  sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
2131
2153
  featureGates: JSON.stringify({
2132
2154
  ...featureGatesForTelemetry,
2133
- disableAttachReorder: this.disableAttachReorder,
2134
2155
  disablePartialFlush,
2135
2156
  closeSummarizerDelayOverride,
2136
2157
  }),
@@ -2139,15 +2160,11 @@ export class ContainerRuntime
2139
2160
  initialSequenceNumber: this.deltaManager.initialSequenceNumber,
2140
2161
  });
2141
2162
 
2142
- ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.logger);
2143
- BindBatchTracker(this, this.logger);
2163
+ ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
2164
+ BindBatchTracker(this, this.baseLogger);
2144
2165
 
2145
2166
  this.entryPoint = new LazyPromise(async () => {
2146
- if (this.isSummarizerClient) {
2147
- assert(
2148
- this._summarizer !== undefined,
2149
- 0x5bf /* Summarizer object is undefined in a summarizer client */,
2150
- );
2167
+ if (this._summarizer !== undefined) {
2151
2168
  return this._summarizer;
2152
2169
  }
2153
2170
  return provideEntryPoint(this);
@@ -2158,8 +2175,9 @@ export class ContainerRuntime
2158
2175
  this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
2159
2176
  }
2160
2177
 
2178
+ // eslint-disable-next-line import/no-deprecated
2161
2179
  public onSchemaChange(schema: IDocumentSchemaCurrent): void {
2162
- this.logger.sendTelemetryEvent({
2180
+ this.mc.logger.sendTelemetryEvent({
2163
2181
  eventName: "SchemaChangeAccept",
2164
2182
  sessionRuntimeSchema: JSON.stringify(schema),
2165
2183
  });
@@ -2216,8 +2234,8 @@ export class ContainerRuntime
2216
2234
  */
2217
2235
  private async initializeBaseState(): Promise<void> {
2218
2236
  if (
2219
- this.idCompressorMode === "on" ||
2220
- (this.idCompressorMode === "delayed" && this.connected)
2237
+ this.sessionSchema.idCompressorMode === "on" ||
2238
+ (this.sessionSchema.idCompressorMode === "delayed" && this.connected)
2221
2239
  ) {
2222
2240
  this._idCompressor = await this.createIdCompressor();
2223
2241
  // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
@@ -2276,7 +2294,7 @@ export class ContainerRuntime
2276
2294
  // be in same loading group. So, once we have fetched the snapshot for that loading group on
2277
2295
  // any request, then cache that as same group could be requested in future too.
2278
2296
  const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(
2279
- sortedLoadingGroupIds.join(),
2297
+ sortedLoadingGroupIds.join(","),
2280
2298
  async () => {
2281
2299
  assert(
2282
2300
  this.storage.getSnapshot !== undefined,
@@ -2291,7 +2309,7 @@ export class ContainerRuntime
2291
2309
  },
2292
2310
  );
2293
2311
 
2294
- this.logger.sendTelemetryEvent({
2312
+ this.mc.logger.sendTelemetryEvent({
2295
2313
  eventName: "GroupIdSnapshotFetched",
2296
2314
  details: JSON.stringify({
2297
2315
  fromCache: loadedFromCache,
@@ -2332,7 +2350,7 @@ export class ContainerRuntime
2332
2350
  // another snapshot from which the summarizer loaded and it is behind, then just give up as
2333
2351
  // the summarizer state is not up to date.
2334
2352
  // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
2335
- if (this.isSummarizerClient) {
2353
+ if (this._summarizer !== undefined) {
2336
2354
  throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
2337
2355
  }
2338
2356
 
@@ -2403,7 +2421,7 @@ export class ContainerRuntime
2403
2421
  return {
2404
2422
  status: 200,
2405
2423
  mimeType: "fluid/object",
2406
- value: this.summarizer,
2424
+ value: this._summarizer,
2407
2425
  };
2408
2426
  }
2409
2427
  return create404Response(request);
@@ -2481,6 +2499,7 @@ export class ContainerRuntime
2481
2499
  // Is document schema explicit control on?
2482
2500
  const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
2483
2501
 
2502
+ // eslint-disable-next-line import/no-deprecated
2484
2503
  const metadata: IContainerRuntimeMetadata = {
2485
2504
  ...this.createContainerMetadata,
2486
2505
  // Increment the summary number for the next summary that will be generated.
@@ -2494,7 +2513,8 @@ export class ContainerRuntime
2494
2513
  // last message's sequence number.
2495
2514
  // See also lastMessageFromMetadata()
2496
2515
  message: explicitSchemaControl
2497
- ? ({ sequenceNumber: -1 } as unknown as ISummaryMetadataMessage)
2516
+ ? // eslint-disable-next-line import/no-deprecated
2517
+ ({ sequenceNumber: -1 } as unknown as ISummaryMetadataMessage)
2498
2518
  : message,
2499
2519
  lastMessage: explicitSchemaControl ? message : undefined,
2500
2520
  documentSchema,
@@ -2639,9 +2659,10 @@ export class ContainerRuntime
2639
2659
  switch (opContents.type) {
2640
2660
  case ContainerMessageType.FluidDataStoreOp:
2641
2661
  case ContainerMessageType.Attach:
2642
- case ContainerMessageType.Alias:
2662
+ case ContainerMessageType.Alias: {
2643
2663
  return this.channelCollection.applyStashedOp(opContents);
2644
- case ContainerMessageType.IdAllocation:
2664
+ }
2665
+ case ContainerMessageType.IdAllocation: {
2645
2666
  // IDs allocation ops in stashed state are ignored because the tip state of the compressor
2646
2667
  // is serialized into the pending state. This is done because generation of new IDs during
2647
2668
  // stashed op application (or, later, resubmit) must generate new IDs and if the compressor
@@ -2652,19 +2673,24 @@ export class ContainerRuntime
2652
2673
  // before applying the rest of the stashed ops. This would accomplish the same thing but with
2653
2674
  // better performance in future incremental stashed state creation.
2654
2675
  assert(
2655
- this.idCompressorMode !== undefined,
2676
+ this.sessionSchema.idCompressorMode !== undefined,
2656
2677
  0x8f1 /* ID compressor should be in use */,
2657
2678
  );
2658
2679
  return;
2659
- case ContainerMessageType.DocumentSchemaChange:
2680
+ }
2681
+ case ContainerMessageType.DocumentSchemaChange: {
2660
2682
  return;
2661
- case ContainerMessageType.BlobAttach:
2683
+ }
2684
+ case ContainerMessageType.BlobAttach: {
2662
2685
  return;
2663
- case ContainerMessageType.Rejoin:
2686
+ }
2687
+ case ContainerMessageType.Rejoin: {
2664
2688
  throw new Error("rejoin not expected here");
2665
- case ContainerMessageType.GC:
2689
+ }
2690
+ case ContainerMessageType.GC: {
2666
2691
  // GC op is only sent in summarizer which should never have stashed ops.
2667
2692
  throw new LoggingError("GC op not expected to be stashed in summarizer");
2693
+ }
2668
2694
  default: {
2669
2695
  const error = getUnknownMessageTypeError(
2670
2696
  opContents.type,
@@ -2679,7 +2705,7 @@ export class ContainerRuntime
2679
2705
  private async loadIdCompressor(): Promise<void | undefined> {
2680
2706
  if (
2681
2707
  this._idCompressor === undefined &&
2682
- this.idCompressorMode !== undefined &&
2708
+ this.sessionSchema.idCompressorMode !== undefined &&
2683
2709
  this._loadIdCompressor === undefined
2684
2710
  ) {
2685
2711
  this._loadIdCompressor = this.createIdCompressor()
@@ -2694,7 +2720,7 @@ export class ContainerRuntime
2694
2720
  this._idCompressor = compressor;
2695
2721
  })
2696
2722
  .catch((error) => {
2697
- this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
2723
+ this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
2698
2724
  throw error;
2699
2725
  });
2700
2726
  }
@@ -2710,7 +2736,7 @@ export class ContainerRuntime
2710
2736
  0x978 /* this.clientId does not match Audience */,
2711
2737
  );
2712
2738
 
2713
- if (connected && this.idCompressorMode === "delayed") {
2739
+ if (connected && this.sessionSchema.idCompressorMode === "delayed") {
2714
2740
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
2715
2741
  this.loadIdCompressor();
2716
2742
  }
@@ -2832,7 +2858,7 @@ export class ContainerRuntime
2832
2858
  // or something different, like a system message.
2833
2859
  const hasModernRuntimeMessageEnvelope = messageCopy.type === MessageType.Operation;
2834
2860
  const savedOp = (messageCopy.metadata as ISavedOpMetadata)?.savedOp;
2835
- const logLegacyCase = getSingleUseLegacyLogCallback(this.logger, messageCopy.type);
2861
+ const logLegacyCase = getSingleUseLegacyLogCallback(this.mc.logger, messageCopy.type);
2836
2862
 
2837
2863
  let runtimeBatch: boolean =
2838
2864
  hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
@@ -2987,11 +3013,11 @@ export class ContainerRuntime
2987
3013
  let error: unknown;
2988
3014
  try {
2989
3015
  if (!runtimeBatch) {
2990
- messagesWithMetadata.forEach(({ message }) => {
3016
+ for (const { message } of messagesWithMetadata) {
2991
3017
  this.ensureNoDataModelChanges(() => {
2992
3018
  this.observeNonRuntimeMessage(message);
2993
3019
  });
2994
- });
3020
+ }
2995
3021
  return;
2996
3022
  }
2997
3023
 
@@ -3076,8 +3102,8 @@ export class ContainerRuntime
3076
3102
  for (const { message } of messagesWithMetadata) {
3077
3103
  this.emit("op", message, true /* runtimeMessage */);
3078
3104
  }
3079
- } catch (e) {
3080
- error = e;
3105
+ } catch (error_) {
3106
+ error = error_;
3081
3107
  throw error;
3082
3108
  } finally {
3083
3109
  if (locationInBatch.batchEnd) {
@@ -3148,38 +3174,46 @@ export class ContainerRuntime
3148
3174
  switch (message.type) {
3149
3175
  case ContainerMessageType.FluidDataStoreOp:
3150
3176
  case ContainerMessageType.Attach:
3151
- case ContainerMessageType.Alias:
3177
+ case ContainerMessageType.Alias: {
3152
3178
  // Remove the metadata from the message before sending it to the channel collection. The metadata
3153
3179
  // is added by the container runtime and is not part of the message that the channel collection and
3154
3180
  // layers below it expect.
3155
3181
  this.channelCollection.processMessages({ envelope: message, messagesContent, local });
3156
3182
  break;
3157
- case ContainerMessageType.BlobAttach:
3183
+ }
3184
+ case ContainerMessageType.BlobAttach: {
3158
3185
  this.blobManager.processBlobAttachMessage(message, local);
3159
3186
  break;
3160
- case ContainerMessageType.IdAllocation:
3187
+ }
3188
+ case ContainerMessageType.IdAllocation: {
3161
3189
  this.processIdCompressorMessages(contents as IdCreationRange[], savedOp);
3162
3190
  break;
3163
- case ContainerMessageType.GC:
3191
+ }
3192
+ case ContainerMessageType.GC: {
3164
3193
  this.garbageCollector.processMessages(
3165
3194
  contents as GarbageCollectionMessage[],
3166
3195
  message.timestamp,
3167
3196
  local,
3168
3197
  );
3169
3198
  break;
3170
- case ContainerMessageType.ChunkedOp:
3199
+ }
3200
+ case ContainerMessageType.ChunkedOp: {
3171
3201
  // From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
3172
3202
  // Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
3173
3203
  assert(false, 0x93d /* should not even get here */);
3174
- case ContainerMessageType.Rejoin:
3204
+ }
3205
+ case ContainerMessageType.Rejoin: {
3175
3206
  break;
3176
- case ContainerMessageType.DocumentSchemaChange:
3207
+ }
3208
+ case ContainerMessageType.DocumentSchemaChange: {
3177
3209
  this.documentsSchemaController.processDocumentSchemaMessages(
3210
+ // eslint-disable-next-line import/no-deprecated
3178
3211
  contents as IDocumentSchemaChangeMessage[],
3179
3212
  local,
3180
3213
  message.sequenceNumber,
3181
3214
  );
3182
3215
  break;
3216
+ }
3183
3217
  default: {
3184
3218
  const error = getUnknownMessageTypeError(
3185
3219
  message.type,
@@ -3206,7 +3240,7 @@ export class ContainerRuntime
3206
3240
  // put it in a pending queue and delay finalization.
3207
3241
  if (this._idCompressor === undefined) {
3208
3242
  assert(
3209
- this.idCompressorMode !== undefined,
3243
+ this.sessionSchema.idCompressorMode !== undefined,
3210
3244
  0x93c /* id compressor should be enabled */,
3211
3245
  );
3212
3246
  this.pendingIdCompressorOps.push(range);
@@ -3246,7 +3280,11 @@ export class ContainerRuntime
3246
3280
  * Updates signal telemetry including emitting telemetry events.
3247
3281
  */
3248
3282
  private processSignalForTelemetry(envelope: ISignalEnvelope): void {
3249
- const { clientBroadcastSignalSequenceNumber } = envelope;
3283
+ const {
3284
+ clientBroadcastSignalSequenceNumber,
3285
+ contents: envelopeContents,
3286
+ address: envelopeAddress,
3287
+ } = envelope;
3250
3288
  if (clientBroadcastSignalSequenceNumber === undefined) {
3251
3289
  return;
3252
3290
  }
@@ -3291,8 +3329,8 @@ export class ContainerRuntime
3291
3329
  };
3292
3330
  // Only log `contents.type` when address is for container to avoid
3293
3331
  // chance that contents type is customer data.
3294
- if (envelope.address === undefined) {
3295
- details.contentsType = envelope.contents.type; // Type of signal that was received out of order.
3332
+ if (envelopeAddress === undefined) {
3333
+ details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
3296
3334
  }
3297
3335
  this.mc.logger.sendTelemetryEvent({
3298
3336
  eventName: "SignalOutOfOrder",
@@ -3388,8 +3426,8 @@ export class ContainerRuntime
3388
3426
  checkpoint.rollback((message: BatchMessage) =>
3389
3427
  this.rollback(message.contents, message.localOpMetadata),
3390
3428
  );
3391
- } catch (err) {
3392
- const error2 = wrapError(err, (message) => {
3429
+ } catch (error_) {
3430
+ const error2 = wrapError(error_, (message) => {
3393
3431
  return DataProcessingError.create(
3394
3432
  `RollbackError: ${message}`,
3395
3433
  "checkpointRollback",
@@ -3549,8 +3587,9 @@ export class ContainerRuntime
3549
3587
  case ContainerMessageType.GC: {
3550
3588
  return false;
3551
3589
  }
3552
- default:
3590
+ default: {
3553
3591
  break;
3592
+ }
3554
3593
  }
3555
3594
  return true;
3556
3595
  }
@@ -3593,7 +3632,7 @@ export class ContainerRuntime
3593
3632
 
3594
3633
  // We should not track the round trip of a new signal in the case we are already tracking one.
3595
3634
  if (
3596
- clientBroadcastSignalSequenceNumber % this.defaultTelemetrySignalSampleCount === 1 &&
3635
+ clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
3597
3636
  this._signalTracking.roundTripSignalSequenceNumber === undefined
3598
3637
  ) {
3599
3638
  this._signalTracking.signalTimestamp = Date.now();
@@ -3687,6 +3726,12 @@ export class ContainerRuntime
3687
3726
 
3688
3727
  public readonly getAbsoluteUrl: (relativeUrl: string) => Promise<string | undefined>;
3689
3728
 
3729
+ /**
3730
+ * Builds the Summary tree including all the channels and the container state.
3731
+ *
3732
+ * @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
3733
+ * so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
3734
+ */
3690
3735
  private async summarizeInternal(
3691
3736
  fullTree: boolean,
3692
3737
  trackState: boolean,
@@ -3834,8 +3879,10 @@ export class ContainerRuntime
3834
3879
  const { dataStoreRoutes, blobManagerRoutes } =
3835
3880
  this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
3836
3881
 
3837
- const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
3838
- return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
3882
+ return [
3883
+ ...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
3884
+ ...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
3885
+ ];
3839
3886
  }
3840
3887
 
3841
3888
  /**
@@ -3864,10 +3911,13 @@ export class ContainerRuntime
3864
3911
  * Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
3865
3912
  * blob manager.
3866
3913
  */
3914
+ // eslint-disable-next-line import/no-deprecated
3867
3915
  public getNodeType(nodePath: string): GCNodeType {
3868
3916
  if (isBlobPath(nodePath)) {
3917
+ // eslint-disable-next-line import/no-deprecated
3869
3918
  return GCNodeType.Blob;
3870
3919
  }
3920
+ // eslint-disable-next-line import/no-deprecated
3871
3921
  return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
3872
3922
  }
3873
3923
 
@@ -3883,13 +3933,19 @@ export class ContainerRuntime
3883
3933
  }
3884
3934
 
3885
3935
  switch (this.getNodeType(nodePath)) {
3886
- case GCNodeType.Blob:
3936
+ // eslint-disable-next-line import/no-deprecated
3937
+ case GCNodeType.Blob: {
3887
3938
  return [blobManagerBasePath];
3939
+ }
3940
+ // eslint-disable-next-line import/no-deprecated
3888
3941
  case GCNodeType.DataStore:
3889
- case GCNodeType.SubDataStore:
3942
+ // eslint-disable-next-line import/no-deprecated
3943
+ case GCNodeType.SubDataStore: {
3890
3944
  return this.channelCollection.getDataStorePackagePath(nodePath);
3891
- default:
3945
+ }
3946
+ default: {
3892
3947
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
3948
+ }
3893
3949
  }
3894
3950
  }
3895
3951
 
@@ -3935,6 +3991,7 @@ export class ContainerRuntime
3935
3991
  fullGC?: boolean;
3936
3992
  },
3937
3993
  telemetryContext?: ITelemetryContext,
3994
+ // eslint-disable-next-line import/no-deprecated
3938
3995
  ): Promise<IGCStats | undefined> {
3939
3996
  return this.garbageCollector.collectGarbage(options, telemetryContext);
3940
3997
  }
@@ -3977,8 +4034,10 @@ export class ContainerRuntime
3977
4034
  * op processing, updating SummarizerNode state tracking, and garbage collection.
3978
4035
  * @param options - options controlling how the summary is generated or submitted
3979
4036
  */
4037
+ // eslint-disable-next-line import/no-deprecated
3980
4038
  public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
3981
4039
  const {
4040
+ cancellationToken,
3982
4041
  fullTree = false,
3983
4042
  finalAttempt = false,
3984
4043
  summaryLogger,
@@ -4098,7 +4157,7 @@ export class ContainerRuntime
4098
4157
  eventName: "LatestSummaryRefSeqNumMismatch",
4099
4158
  details: {
4100
4159
  ...startSummaryResult,
4101
- mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
4160
+ mismatchNumbers: [...startSummaryResult.mismatchNumbers],
4102
4161
  },
4103
4162
  });
4104
4163
 
@@ -4122,7 +4181,7 @@ export class ContainerRuntime
4122
4181
  // summarizer to reconnect in the future.
4123
4182
  // Also checking for cancellation is a must as summary process may be abandoned for other reasons,
4124
4183
  // like loss of connectivity for main (interactive) client.
4125
- if (options.cancellationToken.cancelled) {
4184
+ if (cancellationToken.cancelled) {
4126
4185
  return { continue: false, error: "disconnected" };
4127
4186
  }
4128
4187
  // That said, we rely on submitSystemMessage() that today only works in connected state.
@@ -4263,10 +4322,7 @@ export class ContainerRuntime
4263
4322
 
4264
4323
  let handle: string;
4265
4324
  try {
4266
- handle = await this.storage.uploadSummaryWithContext(
4267
- summarizeResult.summary,
4268
- summaryContext,
4269
- );
4325
+ handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
4270
4326
  } catch (error) {
4271
4327
  return {
4272
4328
  stage: "generate",
@@ -4416,14 +4472,14 @@ export class ContainerRuntime
4416
4472
  }
4417
4473
 
4418
4474
  private updateDocumentDirtyState(dirty: boolean): void {
4419
- if (this.attachState !== AttachState.Attached) {
4420
- assert(dirty, 0x3d2 /* Non-attached container is dirty */);
4421
- } else {
4475
+ if (this.attachState === AttachState.Attached) {
4422
4476
  // Other way is not true = see this.isContainerMessageDirtyable()
4423
4477
  assert(
4424
4478
  !dirty || this.hasPendingMessages(),
4425
4479
  0x3d3 /* if doc is dirty, there has to be pending ops */,
4426
4480
  );
4481
+ } else {
4482
+ assert(dirty, 0x3d2 /* Non-attached container is dirty */);
4427
4483
  }
4428
4484
 
4429
4485
  if (this.dirtyContainer === dirty) {
@@ -4520,7 +4576,7 @@ export class ContainerRuntime
4520
4576
  // on this callback to do actual sending.
4521
4577
  const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
4522
4578
  if (schemaChangeMessage) {
4523
- this.logger.sendTelemetryEvent({
4579
+ this.mc.logger.sendTelemetryEvent({
4524
4580
  eventName: "SchemaChangeProposal",
4525
4581
  refSeq: schemaChangeMessage.refSeq,
4526
4582
  version: schemaChangeMessage.version,
@@ -4574,6 +4630,9 @@ export class ContainerRuntime
4574
4630
  }
4575
4631
 
4576
4632
  this.flushTaskExists = true;
4633
+
4634
+ // TODO: hoist this out of the function scope to save unnecessary allocations
4635
+ // eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
4577
4636
  const flush = (): void => {
4578
4637
  this.flushTaskExists = false;
4579
4638
  try {
@@ -4584,27 +4643,30 @@ export class ContainerRuntime
4584
4643
  };
4585
4644
 
4586
4645
  switch (this.flushMode) {
4587
- case FlushMode.TurnBased:
4646
+ case FlushMode.TurnBased: {
4588
4647
  // When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
4589
4648
  // batch at the end of the turn
4590
4649
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
4591
4650
  Promise.resolve().then(flush);
4592
4651
  break;
4652
+ }
4593
4653
 
4594
4654
  // FlushModeExperimental is experimental and not exposed directly in the runtime APIs
4595
- case FlushModeExperimental.Async as unknown as FlushMode:
4655
+ case FlushModeExperimental.Async as unknown as FlushMode: {
4596
4656
  // When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
4597
4657
  // batch when all micro-tasks are complete.
4598
4658
  // Compared to TurnBased, this flush mode will capture more ops into the same batch.
4599
4659
  setTimeout(flush, 0);
4600
4660
  break;
4661
+ }
4601
4662
 
4602
- default:
4663
+ default: {
4603
4664
  assert(
4604
4665
  this._orderSequentiallyCalls > 0,
4605
4666
  0x587 /* Unreachable unless running under orderSequentially */,
4606
4667
  );
4607
4668
  break;
4669
+ }
4608
4670
  }
4609
4671
  }
4610
4672
 
@@ -4621,10 +4683,7 @@ export class ContainerRuntime
4621
4683
  // System message should not be sent in the middle of the batch.
4622
4684
  assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
4623
4685
 
4624
- // back-compat: ADO #1385: Make this call unconditional in the future
4625
- return this.submitSummaryFn !== undefined
4626
- ? this.submitSummaryFn(contents, referenceSequenceNumber)
4627
- : this.submitFn(MessageType.Summarize, contents, false);
4686
+ return this.submitSummaryFn(contents, referenceSequenceNumber);
4628
4687
  }
4629
4688
 
4630
4689
  /**
@@ -4674,17 +4733,18 @@ export class ContainerRuntime
4674
4733
  opMetadata: Record<string, unknown> | undefined,
4675
4734
  ): void {
4676
4735
  assert(
4677
- !this.isSummarizerClient,
4736
+ this._summarizer === undefined,
4678
4737
  0x8f2 /* Summarizer never reconnects so should never resubmit */,
4679
4738
  );
4680
4739
  switch (message.type) {
4681
4740
  case ContainerMessageType.FluidDataStoreOp:
4682
4741
  case ContainerMessageType.Attach:
4683
- case ContainerMessageType.Alias:
4742
+ case ContainerMessageType.Alias: {
4684
4743
  // For Operations, call resubmitDataStoreOp which will find the right store
4685
4744
  // and trigger resubmission on it.
4686
4745
  this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
4687
4746
  break;
4747
+ }
4688
4748
  case ContainerMessageType.IdAllocation: {
4689
4749
  // Allocation ops are never resubmitted/rebased. This is because they require special handling to
4690
4750
  // avoid being submitted out of order. For example, if the pending state manager contained
@@ -4695,20 +4755,24 @@ export class ContainerRuntime
4695
4755
  // all pending IDs. The resubmitted allocation ops are then ignored here.
4696
4756
  break;
4697
4757
  }
4698
- case ContainerMessageType.BlobAttach:
4758
+ case ContainerMessageType.BlobAttach: {
4699
4759
  this.blobManager.reSubmit(opMetadata);
4700
4760
  break;
4701
- case ContainerMessageType.Rejoin:
4761
+ }
4762
+ case ContainerMessageType.Rejoin: {
4702
4763
  this.submit(message);
4703
4764
  break;
4704
- case ContainerMessageType.GC:
4765
+ }
4766
+ case ContainerMessageType.GC: {
4705
4767
  this.submit(message);
4706
4768
  break;
4707
- case ContainerMessageType.DocumentSchemaChange:
4769
+ }
4770
+ case ContainerMessageType.DocumentSchemaChange: {
4708
4771
  // There is no need to resend this message. Document schema controller will properly resend it again (if needed)
4709
4772
  // on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
4710
4773
  // send any ops, as some other client already changed schema.
4711
4774
  break;
4775
+ }
4712
4776
  default: {
4713
4777
  const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
4714
4778
  this.closeFn(error);
@@ -4721,19 +4785,22 @@ export class ContainerRuntime
4721
4785
  // Need to parse from string for back-compat
4722
4786
  const { type, contents } = this.parseLocalOpContent(content);
4723
4787
  switch (type) {
4724
- case ContainerMessageType.FluidDataStoreOp:
4788
+ case ContainerMessageType.FluidDataStoreOp: {
4725
4789
  // For operations, call rollbackDataStoreOp which will find the right store
4726
4790
  // and trigger rollback on it.
4727
4791
  this.channelCollection.rollback(type, contents, localOpMetadata);
4728
4792
  break;
4729
- default:
4793
+ }
4794
+ default: {
4730
4795
  throw new Error(`Can't rollback ${type}`);
4796
+ }
4731
4797
  }
4732
4798
  }
4733
4799
 
4734
4800
  /**
4735
4801
  * Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
4736
4802
  */
4803
+ // eslint-disable-next-line import/no-deprecated
4737
4804
  public async refreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise<void> {
4738
4805
  const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
4739
4806
  // proposalHandle is always passed from RunningSummarizer.
@@ -4780,6 +4847,9 @@ export class ContainerRuntime
4780
4847
  };
4781
4848
  }
4782
4849
 
4850
+ private readonly readAndParseBlob = async <T>(id: string): Promise<T> =>
4851
+ readAndParse<T>(this.storage, id);
4852
+
4783
4853
  /**
4784
4854
  * Fetches the latest snapshot from storage. If the fetched snapshot is same or newer than the one for which ack
4785
4855
  * was received, close this client. Fetching the snapshot will update the cache for this client so if it's
@@ -4840,6 +4910,7 @@ export class ContainerRuntime
4840
4910
  snapshotTree = snapshot.snapshotTree;
4841
4911
  } else {
4842
4912
  const versions = await this.storage.getVersions(
4913
+ // eslint-disable-next-line unicorn/no-null
4843
4914
  null,
4844
4915
  1,
4845
4916
  scenarioName,
@@ -4855,9 +4926,8 @@ export class ContainerRuntime
4855
4926
  }
4856
4927
 
4857
4928
  props.getSnapshotDuration = trace.trace().duration;
4858
- const readAndParseBlob = async <T>(id: string): Promise<T> =>
4859
- readAndParse<T>(this.storage, id);
4860
- const snapshotRefSeq = await seqFromTree(snapshotTree, readAndParseBlob);
4929
+
4930
+ const snapshotRefSeq = await seqFromTree(snapshotTree, this.readAndParseBlob);
4861
4931
  props.snapshotRefSeq = snapshotRefSeq;
4862
4932
  props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
4863
4933
 
@@ -4937,28 +5007,28 @@ export class ContainerRuntime
4937
5007
  }
4938
5008
 
4939
5009
  public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {
4940
- if (this.isSummarizerClient) {
4941
- return this.summarizer.summarizeOnDemand(options);
4942
- } else if (this.summaryManager !== undefined) {
4943
- return this.summaryManager.summarizeOnDemand(options);
4944
- } else {
5010
+ if (this._summarizer !== undefined) {
5011
+ return this._summarizer.summarizeOnDemand(options);
5012
+ } else if (this.summaryManager === undefined) {
4945
5013
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
4946
5014
  // disableSummaries is turned on. We are throwing instead of returning a failure here,
4947
5015
  // because it is a misuse of the API rather than an expected failure.
4948
5016
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
5017
+ } else {
5018
+ return this.summaryManager.summarizeOnDemand(options);
4949
5019
  }
4950
5020
  }
4951
5021
 
4952
5022
  public enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult {
4953
- if (this.isSummarizerClient) {
4954
- return this.summarizer.enqueueSummarize(options);
4955
- } else if (this.summaryManager !== undefined) {
4956
- return this.summaryManager.enqueueSummarize(options);
4957
- } else {
5023
+ if (this._summarizer !== undefined) {
5024
+ return this._summarizer.enqueueSummarize(options);
5025
+ } else if (this.summaryManager === undefined) {
4958
5026
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
4959
5027
  // generateSummaries is turned off. We are throwing instead of returning a failure here,
4960
5028
  // because it is a misuse of the API rather than an expected failure.
4961
5029
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
5030
+ } else {
5031
+ return this.summaryManager.enqueueSummarize(options);
4962
5032
  }
4963
5033
  }
4964
5034