@fluidframework/container-runtime 2.0.0-rc.1.0.3 → 2.0.0-rc.2.0.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 (690) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +5 -5
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +54 -0
  4. package/README.md +45 -0
  5. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  6. package/api-extractor-lint.json +1 -1
  7. package/api-extractor.json +1 -1
  8. package/api-report/container-runtime.api.md +68 -30
  9. package/dist/batchTracker.d.ts +1 -2
  10. package/dist/batchTracker.d.ts.map +1 -1
  11. package/dist/batchTracker.js.map +1 -1
  12. package/dist/blobManager.js.map +1 -1
  13. package/dist/channelCollection.d.ts +223 -0
  14. package/dist/channelCollection.d.ts.map +1 -0
  15. package/dist/{dataStores.js → channelCollection.js} +399 -83
  16. package/dist/channelCollection.js.map +1 -0
  17. package/dist/connectionTelemetry.d.ts +11 -1
  18. package/dist/connectionTelemetry.d.ts.map +1 -1
  19. package/dist/connectionTelemetry.js +42 -4
  20. package/dist/connectionTelemetry.js.map +1 -1
  21. package/dist/container-runtime-alpha.d.ts +98 -40
  22. package/dist/container-runtime-beta.d.ts +27 -9
  23. package/dist/container-runtime-public.d.ts +27 -9
  24. package/dist/container-runtime-untrimmed.d.ts +123 -40
  25. package/dist/containerHandleContext.d.ts +1 -1
  26. package/dist/containerHandleContext.d.ts.map +1 -1
  27. package/dist/containerHandleContext.js.map +1 -1
  28. package/dist/containerRuntime.d.ts +79 -55
  29. package/dist/containerRuntime.d.ts.map +1 -1
  30. package/dist/containerRuntime.js +541 -411
  31. package/dist/containerRuntime.js.map +1 -1
  32. package/dist/dataStore.d.ts +2 -3
  33. package/dist/dataStore.d.ts.map +1 -1
  34. package/dist/dataStore.js +12 -11
  35. package/dist/dataStore.js.map +1 -1
  36. package/dist/dataStoreContext.d.ts +71 -30
  37. package/dist/dataStoreContext.d.ts.map +1 -1
  38. package/dist/dataStoreContext.js +182 -141
  39. package/dist/dataStoreContext.js.map +1 -1
  40. package/dist/dataStoreContexts.d.ts +1 -1
  41. package/dist/dataStoreContexts.d.ts.map +1 -1
  42. package/dist/dataStoreContexts.js.map +1 -1
  43. package/dist/deltaManagerSummarizerProxy.d.ts +29 -4
  44. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  45. package/dist/deltaManagerSummarizerProxy.js +91 -5
  46. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  47. package/dist/gc/garbageCollection.d.ts +22 -5
  48. package/dist/gc/garbageCollection.d.ts.map +1 -1
  49. package/dist/gc/garbageCollection.js +134 -75
  50. package/dist/gc/garbageCollection.js.map +1 -1
  51. package/dist/gc/gcConfigs.d.ts +2 -2
  52. package/dist/gc/gcConfigs.d.ts.map +1 -1
  53. package/dist/gc/gcConfigs.js +21 -21
  54. package/dist/gc/gcConfigs.js.map +1 -1
  55. package/dist/gc/gcDefinitions.d.ts +29 -6
  56. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  57. package/dist/gc/gcDefinitions.js +5 -1
  58. package/dist/gc/gcDefinitions.js.map +1 -1
  59. package/dist/gc/gcHelpers.d.ts +2 -2
  60. package/dist/gc/gcHelpers.d.ts.map +1 -1
  61. package/dist/gc/gcHelpers.js.map +1 -1
  62. package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
  63. package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
  64. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  65. package/dist/gc/gcSummaryStateTracker.d.ts +12 -5
  66. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  67. package/dist/gc/gcSummaryStateTracker.js +18 -6
  68. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  69. package/dist/gc/gcTelemetry.d.ts +7 -7
  70. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  71. package/dist/gc/gcTelemetry.js +20 -20
  72. package/dist/gc/gcTelemetry.js.map +1 -1
  73. package/dist/gc/gcUnreferencedStateTracker.d.ts +6 -1
  74. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  75. package/dist/gc/gcUnreferencedStateTracker.js +22 -11
  76. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  77. package/dist/gc/index.d.ts +8 -8
  78. package/dist/gc/index.d.ts.map +1 -1
  79. package/dist/gc/index.js +40 -38
  80. package/dist/gc/index.js.map +1 -1
  81. package/dist/index.d.ts +8 -20
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +28 -40
  84. package/dist/index.js.map +1 -1
  85. package/dist/messageTypes.d.ts +4 -4
  86. package/dist/messageTypes.d.ts.map +1 -1
  87. package/dist/messageTypes.js.map +1 -1
  88. package/dist/opLifecycle/batchManager.d.ts +2 -2
  89. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  90. package/dist/opLifecycle/batchManager.js.map +1 -1
  91. package/dist/opLifecycle/definitions.d.ts +2 -2
  92. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  93. package/dist/opLifecycle/definitions.js.map +1 -1
  94. package/dist/opLifecycle/index.d.ts +8 -8
  95. package/dist/opLifecycle/index.d.ts.map +1 -1
  96. package/dist/opLifecycle/index.js +18 -18
  97. package/dist/opLifecycle/index.js.map +1 -1
  98. package/dist/opLifecycle/opCompressor.d.ts +1 -1
  99. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  100. package/dist/opLifecycle/opCompressor.js +4 -4
  101. package/dist/opLifecycle/opCompressor.js.map +1 -1
  102. package/dist/opLifecycle/opDecompressor.d.ts +1 -1
  103. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  104. package/dist/opLifecycle/opDecompressor.js +3 -3
  105. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  106. package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
  107. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  108. package/dist/opLifecycle/opGroupingManager.js +1 -10
  109. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  110. package/dist/opLifecycle/opSplitter.d.ts +1 -1
  111. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  112. package/dist/opLifecycle/opSplitter.js +5 -5
  113. package/dist/opLifecycle/opSplitter.js.map +1 -1
  114. package/dist/opLifecycle/outbox.d.ts +7 -7
  115. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  116. package/dist/opLifecycle/outbox.js +20 -12
  117. package/dist/opLifecycle/outbox.js.map +1 -1
  118. package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
  119. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  120. package/dist/opLifecycle/remoteMessageProcessor.js +2 -2
  121. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  122. package/dist/package.json +3 -0
  123. package/dist/packageVersion.d.ts +1 -1
  124. package/dist/packageVersion.js +1 -1
  125. package/dist/packageVersion.js.map +1 -1
  126. package/dist/pendingStateManager.d.ts +2 -1
  127. package/dist/pendingStateManager.d.ts.map +1 -1
  128. package/dist/pendingStateManager.js +18 -10
  129. package/dist/pendingStateManager.js.map +1 -1
  130. package/dist/scheduleManager.d.ts +1 -2
  131. package/dist/scheduleManager.d.ts.map +1 -1
  132. package/dist/scheduleManager.js +5 -5
  133. package/dist/scheduleManager.js.map +1 -1
  134. package/dist/summary/index.d.ts +12 -12
  135. package/dist/summary/index.d.ts.map +1 -1
  136. package/dist/summary/index.js +43 -43
  137. package/dist/summary/index.js.map +1 -1
  138. package/dist/summary/orderedClientElection.js +8 -8
  139. package/dist/summary/orderedClientElection.js.map +1 -1
  140. package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
  141. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  142. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  143. package/dist/summary/runningSummarizer.d.ts +11 -10
  144. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  145. package/dist/summary/runningSummarizer.js +114 -81
  146. package/dist/summary/runningSummarizer.js.map +1 -1
  147. package/dist/summary/summarizer.d.ts +4 -4
  148. package/dist/summary/summarizer.d.ts.map +1 -1
  149. package/dist/summary/summarizer.js +6 -6
  150. package/dist/summary/summarizer.js.map +1 -1
  151. package/dist/summary/summarizerClientElection.d.ts +2 -2
  152. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  153. package/dist/summary/summarizerClientElection.js.map +1 -1
  154. package/dist/summary/summarizerHeuristics.d.ts +3 -3
  155. package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
  156. package/dist/summary/summarizerHeuristics.js.map +1 -1
  157. package/dist/summary/summarizerNode/index.d.ts +3 -3
  158. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  159. package/dist/summary/summarizerNode/index.js +4 -4
  160. package/dist/summary/summarizerNode/index.js.map +1 -1
  161. package/dist/summary/summarizerNode/summarizerNode.d.ts +17 -7
  162. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  163. package/dist/summary/summarizerNode/summarizerNode.js +45 -57
  164. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  165. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +10 -19
  166. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  167. package/dist/summary/summarizerNode/summarizerNodeUtils.js +1 -21
  168. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  169. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +5 -6
  170. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  171. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +16 -16
  172. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  173. package/dist/summary/summarizerTypes.d.ts +10 -21
  174. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  175. package/dist/summary/summarizerTypes.js.map +1 -1
  176. package/dist/summary/summaryFormat.d.ts +15 -2
  177. package/dist/summary/summaryFormat.d.ts.map +1 -1
  178. package/dist/summary/summaryFormat.js.map +1 -1
  179. package/dist/summary/summaryGenerator.d.ts +6 -5
  180. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  181. package/dist/summary/summaryGenerator.js +10 -1
  182. package/dist/summary/summaryGenerator.js.map +1 -1
  183. package/dist/summary/summaryManager.d.ts +5 -6
  184. package/dist/summary/summaryManager.d.ts.map +1 -1
  185. package/dist/summary/summaryManager.js +4 -5
  186. package/dist/summary/summaryManager.js.map +1 -1
  187. package/dist/tsdoc-metadata.json +1 -1
  188. package/lib/{batchTracker.d.mts → batchTracker.d.ts} +2 -3
  189. package/lib/batchTracker.d.ts.map +1 -0
  190. package/lib/{batchTracker.mjs → batchTracker.js} +1 -1
  191. package/lib/batchTracker.js.map +1 -0
  192. package/lib/{blobManager.d.mts → blobManager.d.ts} +1 -1
  193. package/lib/blobManager.d.ts.map +1 -0
  194. package/lib/{blobManager.mjs → blobManager.js} +1 -1
  195. package/lib/blobManager.js.map +1 -0
  196. package/lib/channelCollection.d.ts +223 -0
  197. package/lib/channelCollection.d.ts.map +1 -0
  198. package/lib/{dataStores.mjs → channelCollection.js} +384 -71
  199. package/lib/channelCollection.js.map +1 -0
  200. package/lib/{connectionTelemetry.d.mts → connectionTelemetry.d.ts} +12 -2
  201. package/lib/connectionTelemetry.d.ts.map +1 -0
  202. package/lib/{connectionTelemetry.mjs → connectionTelemetry.js} +43 -5
  203. package/lib/connectionTelemetry.js.map +1 -0
  204. package/lib/{container-runtime-alpha.d.mts → container-runtime-alpha.d.ts} +98 -40
  205. package/lib/{container-runtime-public.d.mts → container-runtime-beta.d.ts} +27 -9
  206. package/lib/{container-runtime-beta.d.mts → container-runtime-public.d.ts} +27 -9
  207. package/lib/{container-runtime-untrimmed.d.mts → container-runtime-untrimmed.d.ts} +123 -40
  208. package/lib/{containerHandleContext.d.mts → containerHandleContext.d.ts} +2 -2
  209. package/lib/containerHandleContext.d.ts.map +1 -0
  210. package/lib/{containerHandleContext.mjs → containerHandleContext.js} +1 -1
  211. package/lib/containerHandleContext.js.map +1 -0
  212. package/lib/{containerRuntime.d.mts → containerRuntime.d.ts} +84 -56
  213. package/lib/containerRuntime.d.ts.map +1 -0
  214. package/lib/{containerRuntime.mjs → containerRuntime.js} +460 -332
  215. package/lib/containerRuntime.js.map +1 -0
  216. package/lib/{dataStore.d.mts → dataStore.d.ts} +3 -4
  217. package/lib/dataStore.d.ts.map +1 -0
  218. package/lib/{dataStore.mjs → dataStore.js} +13 -12
  219. package/lib/dataStore.js.map +1 -0
  220. package/lib/{dataStoreContext.d.mts → dataStoreContext.d.ts} +72 -31
  221. package/lib/dataStoreContext.d.ts.map +1 -0
  222. package/lib/{dataStoreContext.mjs → dataStoreContext.js} +174 -133
  223. package/lib/dataStoreContext.js.map +1 -0
  224. package/lib/{dataStoreContexts.d.mts → dataStoreContexts.d.ts} +2 -2
  225. package/lib/dataStoreContexts.d.ts.map +1 -0
  226. package/lib/{dataStoreContexts.mjs → dataStoreContexts.js} +1 -1
  227. package/lib/dataStoreContexts.js.map +1 -0
  228. package/lib/{dataStoreRegistry.d.mts → dataStoreRegistry.d.ts} +1 -1
  229. package/lib/dataStoreRegistry.d.ts.map +1 -0
  230. package/lib/{dataStoreRegistry.mjs → dataStoreRegistry.js} +5 -1
  231. package/lib/dataStoreRegistry.js.map +1 -0
  232. package/{dist/deltaManagerProxyBase.d.ts → lib/deltaManagerSummarizerProxy.d.ts} +16 -7
  233. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
  234. package/lib/deltaManagerSummarizerProxy.js +124 -0
  235. package/lib/deltaManagerSummarizerProxy.js.map +1 -0
  236. package/lib/{deltaScheduler.d.mts → deltaScheduler.d.ts} +1 -1
  237. package/lib/deltaScheduler.d.ts.map +1 -0
  238. package/lib/{deltaScheduler.mjs → deltaScheduler.js} +1 -1
  239. package/lib/deltaScheduler.js.map +1 -0
  240. package/lib/{error.d.mts → error.d.ts} +1 -1
  241. package/lib/error.d.ts.map +1 -0
  242. package/lib/{error.mjs → error.js} +1 -1
  243. package/lib/error.js.map +1 -0
  244. package/lib/gc/{garbageCollection.d.mts → garbageCollection.d.ts} +23 -6
  245. package/lib/gc/garbageCollection.d.ts.map +1 -0
  246. package/lib/gc/{garbageCollection.mjs → garbageCollection.js} +103 -44
  247. package/lib/gc/garbageCollection.js.map +1 -0
  248. package/lib/gc/{gcConfigs.d.mts → gcConfigs.d.ts} +3 -3
  249. package/lib/gc/gcConfigs.d.ts.map +1 -0
  250. package/lib/gc/{gcConfigs.mjs → gcConfigs.js} +3 -3
  251. package/lib/gc/gcConfigs.js.map +1 -0
  252. package/lib/gc/{gcDefinitions.d.mts → gcDefinitions.d.ts} +30 -7
  253. package/lib/gc/gcDefinitions.d.ts.map +1 -0
  254. package/lib/gc/{gcDefinitions.mjs → gcDefinitions.js} +5 -1
  255. package/lib/gc/gcDefinitions.js.map +1 -0
  256. package/lib/gc/{gcHelpers.d.mts → gcHelpers.d.ts} +3 -3
  257. package/lib/gc/{gcHelpers.d.mts.map → gcHelpers.d.ts.map} +1 -1
  258. package/lib/gc/{gcHelpers.mjs → gcHelpers.js} +1 -1
  259. package/lib/gc/gcHelpers.js.map +1 -0
  260. package/lib/gc/{gcReferenceGraphAlgorithm.d.mts → gcReferenceGraphAlgorithm.d.ts} +2 -2
  261. package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
  262. package/lib/gc/{gcReferenceGraphAlgorithm.mjs → gcReferenceGraphAlgorithm.js} +1 -1
  263. package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
  264. package/lib/gc/{gcSummaryDefinitions.d.mts → gcSummaryDefinitions.d.ts} +1 -1
  265. package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
  266. package/lib/gc/{gcSummaryDefinitions.mjs → gcSummaryDefinitions.js} +1 -1
  267. package/lib/gc/gcSummaryDefinitions.js.map +1 -0
  268. package/lib/gc/{gcSummaryStateTracker.d.mts → gcSummaryStateTracker.d.ts} +13 -6
  269. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
  270. package/lib/gc/{gcSummaryStateTracker.mjs → gcSummaryStateTracker.js} +17 -5
  271. package/lib/gc/gcSummaryStateTracker.js.map +1 -0
  272. package/lib/gc/{gcTelemetry.d.mts → gcTelemetry.d.ts} +8 -8
  273. package/lib/gc/gcTelemetry.d.ts.map +1 -0
  274. package/lib/gc/{gcTelemetry.mjs → gcTelemetry.js} +5 -5
  275. package/lib/gc/gcTelemetry.js.map +1 -0
  276. package/lib/gc/{gcUnreferencedStateTracker.d.mts → gcUnreferencedStateTracker.d.ts} +7 -2
  277. package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
  278. package/lib/gc/{gcUnreferencedStateTracker.mjs → gcUnreferencedStateTracker.js} +12 -2
  279. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
  280. package/lib/gc/{index.d.mts → index.d.ts} +9 -9
  281. package/lib/gc/index.d.ts.map +1 -0
  282. package/lib/gc/{index.mjs → index.js} +8 -8
  283. package/lib/gc/index.js.map +1 -0
  284. package/lib/{index.d.mts → index.d.ts} +9 -21
  285. package/lib/index.d.ts.map +1 -0
  286. package/lib/index.js +12 -0
  287. package/lib/index.js.map +1 -0
  288. package/lib/{messageTypes.d.mts → messageTypes.d.ts} +5 -5
  289. package/lib/messageTypes.d.ts.map +1 -0
  290. package/lib/{messageTypes.mjs → messageTypes.js} +1 -1
  291. package/lib/messageTypes.js.map +1 -0
  292. package/lib/{metadata.d.mts → metadata.d.ts} +1 -1
  293. package/lib/metadata.d.ts.map +1 -0
  294. package/lib/{metadata.mjs → metadata.js} +1 -1
  295. package/lib/metadata.js.map +1 -0
  296. package/lib/opLifecycle/{batchManager.d.mts → batchManager.d.ts} +3 -3
  297. package/lib/opLifecycle/batchManager.d.ts.map +1 -0
  298. package/lib/opLifecycle/{batchManager.mjs → batchManager.js} +1 -1
  299. package/lib/opLifecycle/batchManager.js.map +1 -0
  300. package/lib/opLifecycle/{definitions.d.mts → definitions.d.ts} +3 -3
  301. package/lib/opLifecycle/definitions.d.ts.map +1 -0
  302. package/lib/opLifecycle/{definitions.mjs → definitions.js} +1 -1
  303. package/lib/opLifecycle/definitions.js.map +1 -0
  304. package/lib/opLifecycle/index.d.ts +13 -0
  305. package/lib/opLifecycle/index.d.ts.map +1 -0
  306. package/lib/opLifecycle/index.js +12 -0
  307. package/lib/opLifecycle/index.js.map +1 -0
  308. package/lib/opLifecycle/{opCompressor.d.mts → opCompressor.d.ts} +2 -2
  309. package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
  310. package/lib/opLifecycle/{opCompressor.mjs → opCompressor.js} +3 -3
  311. package/lib/opLifecycle/opCompressor.js.map +1 -0
  312. package/lib/opLifecycle/{opDecompressor.d.mts → opDecompressor.d.ts} +2 -2
  313. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
  314. package/lib/opLifecycle/{opDecompressor.mjs → opDecompressor.js} +2 -2
  315. package/lib/opLifecycle/opDecompressor.js.map +1 -0
  316. package/lib/opLifecycle/{opGroupingManager.d.mts → opGroupingManager.d.ts} +2 -2
  317. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
  318. package/lib/opLifecycle/{opGroupingManager.mjs → opGroupingManager.js} +2 -11
  319. package/lib/opLifecycle/opGroupingManager.js.map +1 -0
  320. package/lib/opLifecycle/{opSplitter.d.mts → opSplitter.d.ts} +2 -2
  321. package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
  322. package/lib/opLifecycle/{opSplitter.mjs → opSplitter.js} +3 -3
  323. package/lib/opLifecycle/opSplitter.js.map +1 -0
  324. package/lib/opLifecycle/{outbox.d.mts → outbox.d.ts} +8 -8
  325. package/lib/opLifecycle/outbox.d.ts.map +1 -0
  326. package/lib/opLifecycle/{outbox.mjs → outbox.js} +12 -4
  327. package/lib/opLifecycle/outbox.js.map +1 -0
  328. package/lib/opLifecycle/{remoteMessageProcessor.d.mts → remoteMessageProcessor.d.ts} +5 -5
  329. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
  330. package/lib/opLifecycle/{remoteMessageProcessor.mjs → remoteMessageProcessor.js} +2 -2
  331. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
  332. package/lib/{opProperties.d.mts → opProperties.d.ts} +1 -1
  333. package/lib/opProperties.d.ts.map +1 -0
  334. package/lib/{opProperties.mjs → opProperties.js} +1 -1
  335. package/lib/opProperties.js.map +1 -0
  336. package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
  337. package/lib/packageVersion.d.ts.map +1 -0
  338. package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
  339. package/lib/packageVersion.js.map +1 -0
  340. package/lib/{pendingStateManager.d.mts → pendingStateManager.d.ts} +3 -2
  341. package/lib/pendingStateManager.d.ts.map +1 -0
  342. package/lib/{pendingStateManager.mjs → pendingStateManager.js} +18 -10
  343. package/lib/pendingStateManager.js.map +1 -0
  344. package/lib/{scheduleManager.d.mts → scheduleManager.d.ts} +6 -3
  345. package/lib/scheduleManager.d.ts.map +1 -0
  346. package/lib/{scheduleManager.mjs → scheduleManager.js} +3 -3
  347. package/lib/scheduleManager.js.map +1 -0
  348. package/lib/{storageServiceWithAttachBlobs.d.mts → storageServiceWithAttachBlobs.d.ts} +1 -1
  349. package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
  350. package/lib/{storageServiceWithAttachBlobs.mjs → storageServiceWithAttachBlobs.js} +1 -1
  351. package/lib/storageServiceWithAttachBlobs.js.map +1 -0
  352. package/lib/summary/{index.d.mts → index.d.ts} +13 -13
  353. package/lib/summary/index.d.ts.map +1 -0
  354. package/lib/summary/{index.mjs → index.js} +12 -12
  355. package/lib/summary/index.js.map +1 -0
  356. package/lib/summary/{orderedClientElection.d.mts → orderedClientElection.d.ts} +5 -1
  357. package/lib/summary/orderedClientElection.d.ts.map +1 -0
  358. package/lib/summary/{orderedClientElection.mjs → orderedClientElection.js} +2 -2
  359. package/lib/summary/orderedClientElection.js.map +1 -0
  360. package/lib/summary/{runWhileConnectedCoordinator.d.mts → runWhileConnectedCoordinator.d.ts} +2 -2
  361. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
  362. package/lib/summary/{runWhileConnectedCoordinator.mjs → runWhileConnectedCoordinator.js} +1 -1
  363. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
  364. package/lib/summary/{runningSummarizer.d.mts → runningSummarizer.d.ts} +12 -11
  365. package/lib/summary/runningSummarizer.d.ts.map +1 -0
  366. package/lib/summary/{runningSummarizer.mjs → runningSummarizer.js} +108 -75
  367. package/lib/summary/runningSummarizer.js.map +1 -0
  368. package/lib/summary/{summarizer.d.mts → summarizer.d.ts} +5 -5
  369. package/lib/summary/summarizer.d.ts.map +1 -0
  370. package/lib/summary/{summarizer.mjs → summarizer.js} +4 -4
  371. package/lib/summary/summarizer.js.map +1 -0
  372. package/lib/summary/{summarizerClientElection.d.mts → summarizerClientElection.d.ts} +3 -3
  373. package/lib/summary/summarizerClientElection.d.ts.map +1 -0
  374. package/lib/summary/{summarizerClientElection.mjs → summarizerClientElection.js} +1 -1
  375. package/lib/summary/summarizerClientElection.js.map +1 -0
  376. package/lib/summary/{summarizerHeuristics.d.mts → summarizerHeuristics.d.ts} +4 -4
  377. package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
  378. package/lib/summary/{summarizerHeuristics.mjs → summarizerHeuristics.js} +1 -1
  379. package/lib/summary/summarizerHeuristics.js.map +1 -0
  380. package/lib/summary/summarizerNode/{index.d.mts → index.d.ts} +4 -4
  381. package/lib/summary/summarizerNode/index.d.ts.map +1 -0
  382. package/lib/summary/summarizerNode/index.js +7 -0
  383. package/lib/summary/summarizerNode/index.js.map +1 -0
  384. package/lib/summary/summarizerNode/{summarizerNode.d.mts → summarizerNode.d.ts} +18 -8
  385. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
  386. package/lib/summary/summarizerNode/{summarizerNode.mjs → summarizerNode.js} +41 -53
  387. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
  388. package/lib/summary/summarizerNode/{summarizerNodeUtils.d.mts → summarizerNodeUtils.d.ts} +11 -20
  389. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
  390. package/lib/summary/summarizerNode/{summarizerNodeUtils.mjs → summarizerNodeUtils.js} +1 -20
  391. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
  392. package/lib/summary/summarizerNode/{summarizerNodeWithGc.d.mts → summarizerNodeWithGc.d.ts} +6 -7
  393. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
  394. package/lib/summary/summarizerNode/{summarizerNodeWithGc.mjs → summarizerNodeWithGc.js} +12 -12
  395. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
  396. package/lib/summary/{summarizerTypes.d.mts → summarizerTypes.d.ts} +11 -22
  397. package/lib/summary/summarizerTypes.d.ts.map +1 -0
  398. package/lib/summary/{summarizerTypes.mjs → summarizerTypes.js} +1 -1
  399. package/lib/summary/summarizerTypes.js.map +1 -0
  400. package/lib/summary/{summaryCollection.d.mts → summaryCollection.d.ts} +1 -1
  401. package/lib/summary/summaryCollection.d.ts.map +1 -0
  402. package/lib/summary/{summaryCollection.mjs → summaryCollection.js} +1 -1
  403. package/lib/summary/summaryCollection.js.map +1 -0
  404. package/lib/summary/{summaryFormat.d.mts → summaryFormat.d.ts} +16 -3
  405. package/lib/summary/summaryFormat.d.ts.map +1 -0
  406. package/lib/summary/{summaryFormat.mjs → summaryFormat.js} +1 -1
  407. package/lib/summary/summaryFormat.js.map +1 -0
  408. package/lib/summary/{summaryGenerator.d.mts → summaryGenerator.d.ts} +7 -6
  409. package/lib/summary/summaryGenerator.d.ts.map +1 -0
  410. package/lib/summary/{summaryGenerator.mjs → summaryGenerator.js} +11 -2
  411. package/lib/summary/summaryGenerator.js.map +1 -0
  412. package/lib/summary/{summaryManager.d.mts → summaryManager.d.ts} +6 -7
  413. package/lib/summary/summaryManager.d.ts.map +1 -0
  414. package/lib/summary/{summaryManager.mjs → summaryManager.js} +4 -5
  415. package/lib/summary/summaryManager.js.map +1 -0
  416. package/lib/test/batchTracker.spec.js +88 -0
  417. package/lib/test/batchTracker.spec.js.map +1 -0
  418. package/lib/test/blobManager.spec.js +835 -0
  419. package/lib/test/blobManager.spec.js.map +1 -0
  420. package/lib/test/channelCollection.spec.js +141 -0
  421. package/lib/test/channelCollection.spec.js.map +1 -0
  422. package/lib/test/containerRuntime.spec.js +1748 -0
  423. package/lib/test/containerRuntime.spec.js.map +1 -0
  424. package/lib/test/dataStoreContext.spec.js +801 -0
  425. package/lib/test/dataStoreContext.spec.js.map +1 -0
  426. package/lib/test/dataStoreCreation.spec.js +312 -0
  427. package/lib/test/dataStoreCreation.spec.js.map +1 -0
  428. package/lib/test/dataStoreRegistry.spec.js +26 -0
  429. package/lib/test/dataStoreRegistry.spec.js.map +1 -0
  430. package/lib/test/fuzz/fuzzUtils.js +66 -0
  431. package/lib/test/fuzz/fuzzUtils.js.map +1 -0
  432. package/lib/test/fuzz/summarizer.fuzz.spec.js +31 -0
  433. package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -0
  434. package/lib/test/fuzz/summarizerFuzzMocks.js +162 -0
  435. package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -0
  436. package/lib/test/fuzz/summarizerFuzzSuite.js +106 -0
  437. package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -0
  438. package/lib/test/gc/garbageCollection.spec.js +1465 -0
  439. package/lib/test/gc/garbageCollection.spec.js.map +1 -0
  440. package/lib/test/gc/gcConfigs.spec.js +690 -0
  441. package/lib/test/gc/gcConfigs.spec.js.map +1 -0
  442. package/lib/test/gc/gcHelpers.spec.js +110 -0
  443. package/lib/test/gc/gcHelpers.spec.js.map +1 -0
  444. package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +68 -0
  445. package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +1 -0
  446. package/lib/test/gc/gcStats.spec.js +391 -0
  447. package/lib/test/gc/gcStats.spec.js.map +1 -0
  448. package/lib/test/gc/gcSummaryStateTracker.spec.js +228 -0
  449. package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -0
  450. package/lib/test/gc/gcTelemetry.spec.js +530 -0
  451. package/lib/test/gc/gcTelemetry.spec.js.map +1 -0
  452. package/lib/test/gc/gcUnitTestHelpers.js +29 -0
  453. package/lib/test/gc/gcUnitTestHelpers.js.map +1 -0
  454. package/lib/test/gc/gcUnreferencedStateTracker.spec.js +192 -0
  455. package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -0
  456. package/lib/test/getPendingBlobs.spec.js +193 -0
  457. package/lib/test/getPendingBlobs.spec.js.map +1 -0
  458. package/lib/test/hardwareStats.spec.js +93 -0
  459. package/lib/test/hardwareStats.spec.js.map +1 -0
  460. package/lib/test/index.js +6 -0
  461. package/lib/test/index.js.map +1 -0
  462. package/lib/test/opLifecycle/OpGroupingManager.spec.js +225 -0
  463. package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -0
  464. package/lib/test/opLifecycle/batchManager.spec.js +189 -0
  465. package/lib/test/opLifecycle/batchManager.spec.js.map +1 -0
  466. package/lib/test/opLifecycle/opCompressor.spec.js +74 -0
  467. package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -0
  468. package/lib/test/opLifecycle/opDecompressor.spec.js +218 -0
  469. package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -0
  470. package/lib/test/opLifecycle/opSplitter.spec.js +272 -0
  471. package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -0
  472. package/lib/test/opLifecycle/outbox.spec.js +675 -0
  473. package/lib/test/opLifecycle/outbox.spec.js.map +1 -0
  474. package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +196 -0
  475. package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -0
  476. package/lib/test/pendingStateManager.spec.js +329 -0
  477. package/lib/test/pendingStateManager.spec.js.map +1 -0
  478. package/lib/test/scheduleManager.spec.js +270 -0
  479. package/lib/test/scheduleManager.spec.js.map +1 -0
  480. package/lib/test/summarizerNode.spec.js +326 -0
  481. package/lib/test/summarizerNode.spec.js.map +1 -0
  482. package/lib/test/summarizerNodeWithGc.spec.js +318 -0
  483. package/lib/test/summarizerNodeWithGc.spec.js.map +1 -0
  484. package/lib/test/summary/orderedClientElection.spec.js +535 -0
  485. package/lib/test/summary/orderedClientElection.spec.js.map +1 -0
  486. package/lib/test/summary/runningSummarizer.spec.js +1349 -0
  487. package/lib/test/summary/runningSummarizer.spec.js.map +1 -0
  488. package/lib/test/summary/summarizer.spec.js +29 -0
  489. package/lib/test/summary/summarizer.spec.js.map +1 -0
  490. package/lib/test/summary/summarizerClientElection.spec.js +436 -0
  491. package/lib/test/summary/summarizerClientElection.spec.js.map +1 -0
  492. package/lib/test/summary/summarizerHeuristics.spec.js +289 -0
  493. package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -0
  494. package/lib/test/summary/summaryCollection.spec.js +200 -0
  495. package/lib/test/summary/summaryCollection.spec.js.map +1 -0
  496. package/lib/test/summary/summaryManager.spec.js +430 -0
  497. package/lib/test/summary/summaryManager.spec.js.map +1 -0
  498. package/lib/test/summary/testQuorumClients.js +34 -0
  499. package/lib/test/summary/testQuorumClients.js.map +1 -0
  500. package/lib/test/throttler.spec.js +175 -0
  501. package/lib/test/throttler.spec.js.map +1 -0
  502. package/lib/test/types/validateContainerRuntimePrevious.generated.js +180 -0
  503. package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -0
  504. package/lib/{throttler.d.mts → throttler.d.ts} +1 -1
  505. package/lib/throttler.d.ts.map +1 -0
  506. package/lib/{throttler.mjs → throttler.js} +1 -1
  507. package/lib/throttler.js.map +1 -0
  508. package/package.json +99 -88
  509. package/src/batchTracker.ts +1 -1
  510. package/src/blobManager.ts +1 -1
  511. package/src/{dataStores.ts → channelCollection.ts} +520 -84
  512. package/src/connectionTelemetry.ts +42 -3
  513. package/src/containerHandleContext.ts +1 -1
  514. package/src/containerRuntime.ts +661 -464
  515. package/src/dataStore.ts +13 -15
  516. package/src/dataStoreContext.ts +257 -184
  517. package/src/dataStoreContexts.ts +1 -1
  518. package/src/deltaManagerSummarizerProxy.ts +132 -7
  519. package/src/gc/garbageCollection.ts +121 -46
  520. package/src/gc/gcConfigs.ts +3 -3
  521. package/src/gc/gcDefinitions.ts +30 -7
  522. package/src/gc/gcHelpers.ts +2 -2
  523. package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
  524. package/src/gc/gcSummaryStateTracker.ts +19 -7
  525. package/src/gc/gcTelemetry.ts +10 -9
  526. package/src/gc/gcUnreferencedStateTracker.ts +12 -1
  527. package/src/gc/index.ts +10 -8
  528. package/src/index.ts +16 -27
  529. package/src/messageTypes.ts +4 -4
  530. package/src/opLifecycle/README.md +2 -4
  531. package/src/opLifecycle/batchManager.ts +2 -2
  532. package/src/opLifecycle/definitions.ts +2 -2
  533. package/src/opLifecycle/index.ts +8 -8
  534. package/src/opLifecycle/opCompressor.ts +3 -3
  535. package/src/opLifecycle/opDecompressor.ts +3 -3
  536. package/src/opLifecycle/opGroupingManager.ts +3 -12
  537. package/src/opLifecycle/opSplitter.ts +3 -3
  538. package/src/opLifecycle/outbox.ts +29 -9
  539. package/src/opLifecycle/remoteMessageProcessor.ts +4 -4
  540. package/src/packageVersion.ts +1 -1
  541. package/src/pendingStateManager.ts +19 -13
  542. package/src/scheduleManager.ts +4 -4
  543. package/src/summary/index.ts +13 -12
  544. package/src/summary/orderedClientElection.ts +1 -1
  545. package/src/summary/runWhileConnectedCoordinator.ts +1 -1
  546. package/src/summary/runningSummarizer.ts +141 -93
  547. package/src/summary/summarizer.ts +7 -7
  548. package/src/summary/summarizerClientElection.ts +2 -2
  549. package/src/summary/summarizerHeuristics.ts +3 -3
  550. package/src/summary/summarizerNode/index.ts +6 -3
  551. package/src/summary/summarizerNode/summarizerNode.ts +54 -69
  552. package/src/summary/summarizerNode/summarizerNodeUtils.ts +16 -34
  553. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -17
  554. package/src/summary/summarizerTypes.ts +12 -24
  555. package/src/summary/summaryFormat.ts +16 -2
  556. package/src/summary/summaryGenerator.ts +16 -4
  557. package/src/summary/summaryManager.ts +6 -7
  558. package/tsconfig.cjs.json +7 -0
  559. package/tsconfig.json +2 -5
  560. package/dist/dataStores.d.ts +0 -149
  561. package/dist/dataStores.d.ts.map +0 -1
  562. package/dist/dataStores.js.map +0 -1
  563. package/dist/deltaManagerProxyBase.d.ts.map +0 -1
  564. package/dist/deltaManagerProxyBase.js +0 -77
  565. package/dist/deltaManagerProxyBase.js.map +0 -1
  566. package/lib/batchTracker.d.mts.map +0 -1
  567. package/lib/batchTracker.mjs.map +0 -1
  568. package/lib/blobManager.d.mts.map +0 -1
  569. package/lib/blobManager.mjs.map +0 -1
  570. package/lib/connectionTelemetry.d.mts.map +0 -1
  571. package/lib/connectionTelemetry.mjs.map +0 -1
  572. package/lib/containerHandleContext.d.mts.map +0 -1
  573. package/lib/containerHandleContext.mjs.map +0 -1
  574. package/lib/containerRuntime.d.mts.map +0 -1
  575. package/lib/containerRuntime.mjs.map +0 -1
  576. package/lib/dataStore.d.mts.map +0 -1
  577. package/lib/dataStore.mjs.map +0 -1
  578. package/lib/dataStoreContext.d.mts.map +0 -1
  579. package/lib/dataStoreContext.mjs.map +0 -1
  580. package/lib/dataStoreContexts.d.mts.map +0 -1
  581. package/lib/dataStoreContexts.mjs.map +0 -1
  582. package/lib/dataStoreRegistry.d.mts.map +0 -1
  583. package/lib/dataStoreRegistry.mjs.map +0 -1
  584. package/lib/dataStores.d.mts +0 -149
  585. package/lib/dataStores.d.mts.map +0 -1
  586. package/lib/dataStores.mjs.map +0 -1
  587. package/lib/deltaManagerProxyBase.d.mts +0 -35
  588. package/lib/deltaManagerProxyBase.d.mts.map +0 -1
  589. package/lib/deltaManagerProxyBase.mjs +0 -73
  590. package/lib/deltaManagerProxyBase.mjs.map +0 -1
  591. package/lib/deltaManagerSummarizerProxy.d.mts +0 -19
  592. package/lib/deltaManagerSummarizerProxy.d.mts.map +0 -1
  593. package/lib/deltaManagerSummarizerProxy.mjs +0 -38
  594. package/lib/deltaManagerSummarizerProxy.mjs.map +0 -1
  595. package/lib/deltaScheduler.d.mts.map +0 -1
  596. package/lib/deltaScheduler.mjs.map +0 -1
  597. package/lib/error.d.mts.map +0 -1
  598. package/lib/error.mjs.map +0 -1
  599. package/lib/gc/garbageCollection.d.mts.map +0 -1
  600. package/lib/gc/garbageCollection.mjs.map +0 -1
  601. package/lib/gc/gcConfigs.d.mts.map +0 -1
  602. package/lib/gc/gcConfigs.mjs.map +0 -1
  603. package/lib/gc/gcDefinitions.d.mts.map +0 -1
  604. package/lib/gc/gcDefinitions.mjs.map +0 -1
  605. package/lib/gc/gcHelpers.mjs.map +0 -1
  606. package/lib/gc/gcReferenceGraphAlgorithm.d.mts.map +0 -1
  607. package/lib/gc/gcReferenceGraphAlgorithm.mjs.map +0 -1
  608. package/lib/gc/gcSummaryDefinitions.d.mts.map +0 -1
  609. package/lib/gc/gcSummaryDefinitions.mjs.map +0 -1
  610. package/lib/gc/gcSummaryStateTracker.d.mts.map +0 -1
  611. package/lib/gc/gcSummaryStateTracker.mjs.map +0 -1
  612. package/lib/gc/gcTelemetry.d.mts.map +0 -1
  613. package/lib/gc/gcTelemetry.mjs.map +0 -1
  614. package/lib/gc/gcUnreferencedStateTracker.d.mts.map +0 -1
  615. package/lib/gc/gcUnreferencedStateTracker.mjs.map +0 -1
  616. package/lib/gc/index.d.mts.map +0 -1
  617. package/lib/gc/index.mjs.map +0 -1
  618. package/lib/index.d.mts.map +0 -1
  619. package/lib/index.mjs +0 -24
  620. package/lib/index.mjs.map +0 -1
  621. package/lib/messageTypes.d.mts.map +0 -1
  622. package/lib/messageTypes.mjs.map +0 -1
  623. package/lib/metadata.d.mts.map +0 -1
  624. package/lib/metadata.mjs.map +0 -1
  625. package/lib/opLifecycle/batchManager.d.mts.map +0 -1
  626. package/lib/opLifecycle/batchManager.mjs.map +0 -1
  627. package/lib/opLifecycle/definitions.d.mts.map +0 -1
  628. package/lib/opLifecycle/definitions.mjs.map +0 -1
  629. package/lib/opLifecycle/index.d.mts +0 -13
  630. package/lib/opLifecycle/index.d.mts.map +0 -1
  631. package/lib/opLifecycle/index.mjs +0 -12
  632. package/lib/opLifecycle/index.mjs.map +0 -1
  633. package/lib/opLifecycle/opCompressor.d.mts.map +0 -1
  634. package/lib/opLifecycle/opCompressor.mjs.map +0 -1
  635. package/lib/opLifecycle/opDecompressor.d.mts.map +0 -1
  636. package/lib/opLifecycle/opDecompressor.mjs.map +0 -1
  637. package/lib/opLifecycle/opGroupingManager.d.mts.map +0 -1
  638. package/lib/opLifecycle/opGroupingManager.mjs.map +0 -1
  639. package/lib/opLifecycle/opSplitter.d.mts.map +0 -1
  640. package/lib/opLifecycle/opSplitter.mjs.map +0 -1
  641. package/lib/opLifecycle/outbox.d.mts.map +0 -1
  642. package/lib/opLifecycle/outbox.mjs.map +0 -1
  643. package/lib/opLifecycle/remoteMessageProcessor.d.mts.map +0 -1
  644. package/lib/opLifecycle/remoteMessageProcessor.mjs.map +0 -1
  645. package/lib/opProperties.d.mts.map +0 -1
  646. package/lib/opProperties.mjs.map +0 -1
  647. package/lib/packageVersion.d.mts.map +0 -1
  648. package/lib/packageVersion.mjs.map +0 -1
  649. package/lib/pendingStateManager.d.mts.map +0 -1
  650. package/lib/pendingStateManager.mjs.map +0 -1
  651. package/lib/scheduleManager.d.mts.map +0 -1
  652. package/lib/scheduleManager.mjs.map +0 -1
  653. package/lib/storageServiceWithAttachBlobs.d.mts.map +0 -1
  654. package/lib/storageServiceWithAttachBlobs.mjs.map +0 -1
  655. package/lib/summary/index.d.mts.map +0 -1
  656. package/lib/summary/index.mjs.map +0 -1
  657. package/lib/summary/orderedClientElection.d.mts.map +0 -1
  658. package/lib/summary/orderedClientElection.mjs.map +0 -1
  659. package/lib/summary/runWhileConnectedCoordinator.d.mts.map +0 -1
  660. package/lib/summary/runWhileConnectedCoordinator.mjs.map +0 -1
  661. package/lib/summary/runningSummarizer.d.mts.map +0 -1
  662. package/lib/summary/runningSummarizer.mjs.map +0 -1
  663. package/lib/summary/summarizer.d.mts.map +0 -1
  664. package/lib/summary/summarizer.mjs.map +0 -1
  665. package/lib/summary/summarizerClientElection.d.mts.map +0 -1
  666. package/lib/summary/summarizerClientElection.mjs.map +0 -1
  667. package/lib/summary/summarizerHeuristics.d.mts.map +0 -1
  668. package/lib/summary/summarizerHeuristics.mjs.map +0 -1
  669. package/lib/summary/summarizerNode/index.d.mts.map +0 -1
  670. package/lib/summary/summarizerNode/index.mjs +0 -7
  671. package/lib/summary/summarizerNode/index.mjs.map +0 -1
  672. package/lib/summary/summarizerNode/summarizerNode.d.mts.map +0 -1
  673. package/lib/summary/summarizerNode/summarizerNode.mjs.map +0 -1
  674. package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +0 -1
  675. package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +0 -1
  676. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +0 -1
  677. package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +0 -1
  678. package/lib/summary/summarizerTypes.d.mts.map +0 -1
  679. package/lib/summary/summarizerTypes.mjs.map +0 -1
  680. package/lib/summary/summaryCollection.d.mts.map +0 -1
  681. package/lib/summary/summaryCollection.mjs.map +0 -1
  682. package/lib/summary/summaryFormat.d.mts.map +0 -1
  683. package/lib/summary/summaryFormat.mjs.map +0 -1
  684. package/lib/summary/summaryGenerator.d.mts.map +0 -1
  685. package/lib/summary/summaryGenerator.mjs.map +0 -1
  686. package/lib/summary/summaryManager.d.mts.map +0 -1
  687. package/lib/summary/summaryManager.mjs.map +0 -1
  688. package/lib/throttler.d.mts.map +0 -1
  689. package/lib/throttler.mjs.map +0 -1
  690. package/src/deltaManagerProxyBase.ts +0 -111
@@ -4,13 +4,13 @@
4
4
  */
5
5
  import {
6
6
  ITelemetryBaseLogger,
7
- ITelemetryGenericEvent,
8
7
  FluidObject,
9
8
  IFluidHandle,
10
9
  IFluidHandleContext,
11
10
  IRequest,
12
11
  IResponse,
13
12
  IProvideFluidHandleContext,
13
+ ISignalEnvelope,
14
14
  } from "@fluidframework/core-interfaces";
15
15
  import {
16
16
  IAudience,
@@ -20,7 +20,6 @@ import {
20
20
  IRuntime,
21
21
  ICriticalContainerError,
22
22
  AttachState,
23
- ILoaderOptions,
24
23
  ILoader,
25
24
  LoaderHeader,
26
25
  IGetPendingLocalStateProps,
@@ -29,7 +28,7 @@ import {
29
28
  IContainerRuntime,
30
29
  IContainerRuntimeEvents,
31
30
  } from "@fluidframework/container-runtime-definitions";
32
- import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
31
+ import { assert, Deferred, delay, LazyPromise, PromiseCache } from "@fluidframework/core-utils";
33
32
  import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
34
33
  import {
35
34
  createChildLogger,
@@ -39,19 +38,22 @@ import {
39
38
  GenericError,
40
39
  raiseConnectedEvent,
41
40
  PerformanceEvent,
42
- // eslint-disable-next-line import/no-deprecated
43
41
  TaggedLoggerAdapter,
44
42
  MonitoringContext,
45
43
  wrapError,
46
44
  ITelemetryLoggerExt,
47
45
  UsageError,
48
46
  LoggingError,
47
+ createSampledLogger,
48
+ IEventSampler,
49
+ type ITelemetryGenericEventExt,
50
+ loggerToMonitoringContext,
49
51
  } from "@fluidframework/telemetry-utils";
50
52
  import {
51
53
  DriverHeader,
52
54
  FetchSource,
53
55
  IDocumentStorageService,
54
- ISummaryContext,
56
+ type ISnapshot,
55
57
  } from "@fluidframework/driver-definitions";
56
58
  import { readAndParse } from "@fluidframework/driver-utils";
57
59
  import {
@@ -73,11 +75,8 @@ import {
73
75
  InboundAttachMessage,
74
76
  IFluidDataStoreContextDetached,
75
77
  IFluidDataStoreRegistry,
76
- IFluidDataStoreChannel,
77
78
  IGarbageCollectionData,
78
- IEnvelope,
79
79
  IInboundSignalMessage,
80
- ISignalEnvelope,
81
80
  NamedFluidDataStoreRegistryEntries,
82
81
  ISummaryTreeWithStats,
83
82
  ISummarizeInternalResult,
@@ -86,18 +85,18 @@ import {
86
85
  channelsTreeName,
87
86
  IDataStore,
88
87
  ITelemetryContext,
88
+ IEnvelope,
89
89
  } from "@fluidframework/runtime-definitions";
90
90
  import type {
91
91
  SerializedIdCompressorWithNoSession,
92
92
  IIdCompressor,
93
93
  IIdCompressorCore,
94
- IdCreationRange,
95
94
  SerializedIdCompressorWithOngoingSession,
95
+ IdCreationRange,
96
96
  } from "@fluidframework/id-compressor";
97
97
  import {
98
98
  addBlobToSummary,
99
99
  addSummarizeResultToSummary,
100
- addTreeToSummary,
101
100
  RequestParser,
102
101
  create404Response,
103
102
  exceptionToResponse,
@@ -109,17 +108,17 @@ import {
109
108
  responseToException,
110
109
  } from "@fluidframework/runtime-utils";
111
110
  import { v4 as uuid } from "uuid";
112
- import { ContainerFluidHandleContext } from "./containerHandleContext";
113
- import { FluidDataStoreRegistry } from "./dataStoreRegistry";
114
- import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry";
111
+ import { ContainerFluidHandleContext } from "./containerHandleContext.js";
112
+ import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
113
+ import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry.js";
115
114
  import {
116
115
  IPendingBatchMessage,
117
116
  IPendingLocalState,
118
117
  PendingStateManager,
119
- } from "./pendingStateManager";
120
- import { pkgVersion } from "./packageVersion";
121
- import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager";
122
- import { DataStores, getSummaryForDatastores } from "./dataStores";
118
+ } from "./pendingStateManager.js";
119
+ import { pkgVersion } from "./packageVersion.js";
120
+ import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager.js";
121
+ import { ChannelCollection, getSummaryForDatastores, wrapContext } from "./channelCollection.js";
123
122
  import {
124
123
  aliasBlobName,
125
124
  blobsTreeName,
@@ -159,8 +158,10 @@ import {
159
158
  ISummarizerEvents,
160
159
  IBaseSummarizeResult,
161
160
  ISummarizer,
162
- } from "./summary";
163
- import { formExponentialFn, Throttler } from "./throttler";
161
+ rootHasIsolatedChannels,
162
+ IdCompressorMode,
163
+ } from "./summary/index.js";
164
+ import { formExponentialFn, Throttler } from "./throttler.js";
164
165
  import {
165
166
  GarbageCollector,
166
167
  GCNodeType,
@@ -168,11 +169,10 @@ import {
168
169
  IGarbageCollector,
169
170
  IGCRuntimeOptions,
170
171
  IGCStats,
171
- trimLeadingAndTrailingSlashes,
172
- } from "./gc";
173
- import { channelToDataStore, IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
174
- import { BindBatchTracker } from "./batchTracker";
175
- import { ScheduleManager } from "./scheduleManager";
172
+ } from "./gc/index.js";
173
+ import { channelToDataStore } from "./dataStore.js";
174
+ import { BindBatchTracker } from "./batchTracker.js";
175
+ import { ScheduleManager } from "./scheduleManager.js";
176
176
  import {
177
177
  BatchMessage,
178
178
  IBatch,
@@ -184,9 +184,9 @@ import {
184
184
  RemoteMessageProcessor,
185
185
  OpGroupingManager,
186
186
  getLongStack,
187
- } from "./opLifecycle";
188
- import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
189
- import { IBatchMetadata, IIdAllocationMetadata } from "./metadata";
187
+ } from "./opLifecycle/index.js";
188
+ import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.js";
189
+ import { IBatchMetadata, IIdAllocationMetadata } from "./metadata.js";
190
190
  import {
191
191
  ContainerMessageType,
192
192
  type InboundSequencedContainerRuntimeMessage,
@@ -196,7 +196,7 @@ import {
196
196
  type OutboundContainerRuntimeMessage,
197
197
  type UnknownContainerRuntimeMessage,
198
198
  ContainerRuntimeGCMessage,
199
- } from "./messageTypes";
199
+ } from "./messageTypes.js";
200
200
 
201
201
  /**
202
202
  * Utility to implement compat behaviors given an unknown message type
@@ -441,7 +441,7 @@ export interface IContainerRuntimeOptions {
441
441
  * Enable the IdCompressor in the runtime.
442
442
  * @experimental Not ready for use.
443
443
  */
444
- readonly enableRuntimeIdCompressor?: boolean;
444
+ readonly enableRuntimeIdCompressor?: IdCompressorMode;
445
445
 
446
446
  /**
447
447
  * If enabled, the runtime will block all attempts to send an op inside the
@@ -466,27 +466,6 @@ export interface IContainerRuntimeOptions {
466
466
  readonly enableGroupedBatching?: boolean;
467
467
  }
468
468
 
469
- /**
470
- * Accepted header keys for requests coming to the runtime.
471
- * @internal
472
- */
473
- export enum RuntimeHeaders {
474
- /** True to wait for a data store to be created and loaded before returning it. */
475
- wait = "wait",
476
- /** True if the request is coming from an IFluidHandle. */
477
- viaHandle = "viaHandle",
478
- }
479
-
480
- /** True if a tombstoned object should be returned without erroring
481
- * @alpha
482
- */
483
- export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
484
- /**
485
- * [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring
486
- * @internal
487
- */
488
- export const AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
489
-
490
469
  /**
491
470
  * Tombstone error responses will have this header set to true
492
471
  * @alpha
@@ -553,6 +532,11 @@ export interface IPendingRuntimeState {
553
532
  * Pending idCompressor state
554
533
  */
555
534
  pendingIdCompressorState?: SerializedIdCompressorWithOngoingSession;
535
+
536
+ /**
537
+ * Time at which session expiry timer started.
538
+ */
539
+ sessionExpiryTimerStarted?: number | undefined;
556
540
  }
557
541
 
558
542
  const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
@@ -767,7 +751,6 @@ export class ContainerRuntime
767
751
  const backCompatContext: IContainerContext | OldContainerContextWithLogger = context;
768
752
  const passLogger =
769
753
  backCompatContext.taggedLogger ??
770
- // eslint-disable-next-line import/no-deprecated
771
754
  new TaggedLoggerAdapter((backCompatContext as OldContainerContextWithLogger).logger);
772
755
  const logger = createChildLogger({
773
756
  logger: passLogger,
@@ -778,6 +761,8 @@ export class ContainerRuntime
778
761
  },
779
762
  });
780
763
 
764
+ const mc = loggerToMonitoringContext(logger);
765
+
781
766
  const {
782
767
  summaryOptions = {},
783
768
  gcOptions = {},
@@ -785,7 +770,7 @@ export class ContainerRuntime
785
770
  flushMode = defaultFlushMode,
786
771
  compressionOptions = defaultCompressionConfig,
787
772
  maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
788
- enableRuntimeIdCompressor = false,
773
+ enableRuntimeIdCompressor = "off",
789
774
  chunkSizeInBytes = defaultChunkSizeInBytes,
790
775
  enableOpReentryCheck = false,
791
776
  enableGroupedBatching = false,
@@ -854,24 +839,72 @@ export class ContainerRuntime
854
839
  }
855
840
  }
856
841
 
857
- const idCompressorEnabled =
858
- metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
859
- let idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
860
- if (idCompressorEnabled) {
842
+ // Enabling the IdCompressor is a one-way operation and we only want to
843
+ // allow new containers to turn it on
844
+ let idCompressorMode: IdCompressorMode;
845
+ if (existing) {
846
+ // This setting has to be sticky for correctness:
847
+ // 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
848
+ // how to process compressor ops
849
+ // 2) if it's ON, then all sessions should load compressor right away
850
+ // 3) Same logic applies for "delayed" mode
851
+ // Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
852
+ // We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
853
+ // this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
854
+ // Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
855
+ idCompressorMode = metadata?.idCompressorMode ?? "off";
856
+ } else {
857
+ // FG overwrite
858
+ const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
859
+ switch (enabled) {
860
+ case true:
861
+ idCompressorMode = "on";
862
+ break;
863
+ case false:
864
+ idCompressorMode = "off";
865
+ break;
866
+ default:
867
+ idCompressorMode = enableRuntimeIdCompressor;
868
+ break;
869
+ }
870
+ }
871
+
872
+ const createIdCompressorFn = async () => {
861
873
  const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import(
862
874
  "@fluidframework/id-compressor"
863
875
  );
864
876
 
877
+ /**
878
+ * Because the IdCompressor emits so much telemetry, this function is used to sample
879
+ * approximately 5% of all clients. Only the given percentage of sessions will emit telemetry.
880
+ */
881
+ const idCompressorEventSampler: IEventSampler = (() => {
882
+ const isIdCompressorTelemetryEnabled = Math.random() < 0.05;
883
+ return {
884
+ sample: () => {
885
+ return isIdCompressorTelemetryEnabled;
886
+ },
887
+ };
888
+ })();
889
+
890
+ const compressorLogger = createSampledLogger(logger, idCompressorEventSampler);
865
891
  const pendingLocalState = context.pendingLocalState as IPendingRuntimeState;
866
892
 
867
893
  if (pendingLocalState?.pendingIdCompressorState !== undefined) {
868
- idCompressor = deserializeIdCompressor(pendingLocalState.pendingIdCompressorState);
894
+ return deserializeIdCompressor(
895
+ pendingLocalState.pendingIdCompressorState,
896
+ compressorLogger,
897
+ );
869
898
  } else if (serializedIdCompressor !== undefined) {
870
- idCompressor = deserializeIdCompressor(serializedIdCompressor, createSessionId());
899
+ return deserializeIdCompressor(
900
+ serializedIdCompressor,
901
+ createSessionId(),
902
+ compressorLogger,
903
+ );
871
904
  } else {
872
- idCompressor = createIdCompressor(logger);
905
+ return createIdCompressor(compressorLogger);
873
906
  }
874
- }
907
+ };
875
908
 
876
909
  const runtime = new containerRuntimeCtor(
877
910
  context,
@@ -897,7 +930,8 @@ export class ContainerRuntime
897
930
  existing,
898
931
  blobManagerSnapshot,
899
932
  context.storage,
900
- idCompressor,
933
+ createIdCompressorFn,
934
+ idCompressorMode,
901
935
  provideEntryPoint,
902
936
  requestHandler,
903
937
  undefined, // summaryConfiguration
@@ -913,7 +947,7 @@ export class ContainerRuntime
913
947
  return runtime;
914
948
  }
915
949
 
916
- public readonly options: ILoaderOptions;
950
+ public readonly options: Record<string | number, any>;
917
951
  private imminentClosure: boolean = false;
918
952
 
919
953
  private readonly _getClientId: () => string | undefined;
@@ -927,6 +961,10 @@ export class ContainerRuntime
927
961
  return this._storage;
928
962
  }
929
963
 
964
+ public get containerRuntime() {
965
+ return this;
966
+ }
967
+
930
968
  private readonly submitFn: (
931
969
  type: MessageType,
932
970
  contents: any,
@@ -964,7 +1002,47 @@ export class ContainerRuntime
964
1002
  return this._getAttachState();
965
1003
  }
966
1004
 
967
- public idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
1005
+ private _idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
1006
+
1007
+ // We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
1008
+ // Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
1009
+ private pendingIdCompressorOps: IdCreationRange[] = [];
1010
+
1011
+ // Id Compressor serializes final state (see getPendingLocalState()). As result, it needs to skip all ops that preceeded that state
1012
+ // (such ops will be marked by Loader layer as savedOp === true)
1013
+ // That said, in "delayed" mode it's possible that Id Compressor was never initialized before getPendingLocalState() is called.
1014
+ // In such case we have to process all ops, including those marked with saveOp === true.
1015
+ private readonly skipSavedCompressorOps: boolean;
1016
+
1017
+ /**
1018
+ * See IContainerRuntimeBase.idCompressor() for details.
1019
+ */
1020
+ public get idCompressor() {
1021
+ // Expose ID Compressor only if it's On from the start.
1022
+ // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
1023
+ // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
1024
+ // to reason over such things as session ID space.
1025
+ if (this.idCompressorMode === "on") {
1026
+ assert(
1027
+ this._idCompressor !== undefined,
1028
+ 0x8ea /* compressor should have been loaded */,
1029
+ );
1030
+ return this._idCompressor;
1031
+ }
1032
+ }
1033
+
1034
+ /**
1035
+ * True if we have ID compressor loading in-flight (async operation). Useful only for
1036
+ * this.idCompressorMode === "delayed" mode
1037
+ */
1038
+ protected compressorLoadInitiated = false;
1039
+
1040
+ /**
1041
+ * See IContainerRuntimeBase.generateDocumentUniqueId() for details.
1042
+ */
1043
+ public generateDocumentUniqueId() {
1044
+ return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
1045
+ }
968
1046
 
969
1047
  public get IFluidHandleContext(): IFluidHandleContext {
970
1048
  return this.handleContext;
@@ -1088,7 +1166,7 @@ export class ContainerRuntime
1088
1166
  private readonly outbox: Outbox;
1089
1167
  private readonly garbageCollector: IGarbageCollector;
1090
1168
 
1091
- private readonly dataStores: DataStores;
1169
+ private readonly channelCollection: ChannelCollection;
1092
1170
  private readonly remoteMessageProcessor: RemoteMessageProcessor;
1093
1171
 
1094
1172
  /** The last message processed at the time of the last summary. */
@@ -1104,11 +1182,6 @@ export class ContainerRuntime
1104
1182
  return this.summaryConfiguration.state === "disabled";
1105
1183
  }
1106
1184
 
1107
- private readonly heuristicsDisabled: boolean;
1108
- private isHeuristicsDisabled(): boolean {
1109
- return this.summaryConfiguration.state === "disableHeuristics";
1110
- }
1111
-
1112
1185
  private readonly maxOpsSinceLastSummary: number;
1113
1186
  private getMaxOpsSinceLastSummary(): number {
1114
1187
  return this.summaryConfiguration.state !== "disabled"
@@ -1151,11 +1224,6 @@ export class ContainerRuntime
1151
1224
  */
1152
1225
  private readonly telemetryDocumentId: string;
1153
1226
 
1154
- /**
1155
- * If true, the runtime has access to an IdCompressor
1156
- */
1157
- private readonly idCompressorEnabled: boolean;
1158
-
1159
1227
  /**
1160
1228
  * Whether this client is the summarizer client itself (type is summarizerClientType)
1161
1229
  */
@@ -1166,11 +1234,19 @@ export class ContainerRuntime
1166
1234
  */
1167
1235
  private readonly loadedFromVersionId: string | undefined;
1168
1236
 
1237
+ /**
1238
+ * It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
1239
+ * Starting with 1 min and based on recorded usage we can tweak it later on.
1240
+ */
1241
+ private readonly snapshotCacheForLoadingGroupIds = new PromiseCache<string, ISnapshot>({
1242
+ expiry: { policy: "absolute", durationMs: 60000 },
1243
+ });
1244
+
1169
1245
  /***/
1170
1246
  protected constructor(
1171
1247
  context: IContainerContext,
1172
1248
  private readonly registry: IFluidDataStoreRegistry,
1173
- metadata: IContainerRuntimeMetadata | undefined,
1249
+ private readonly metadata: IContainerRuntimeMetadata | undefined,
1174
1250
  electedSummarizerData: ISerializedElection | undefined,
1175
1251
  chunks: [string, string[]][],
1176
1252
  dataStoreAliasMap: [string, string][],
@@ -1180,7 +1256,8 @@ export class ContainerRuntime
1180
1256
  existing: boolean,
1181
1257
  blobManagerSnapshot: IBlobManagerLoadInfo,
1182
1258
  private readonly _storage: IDocumentStorageService,
1183
- idCompressor: (IIdCompressor & IIdCompressorCore) | undefined,
1259
+ private readonly createIdCompressor: () => Promise<IIdCompressor & IIdCompressorCore>,
1260
+ private readonly idCompressorMode: IdCompressorMode,
1184
1261
  provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
1185
1262
  private readonly requestHandler?: (
1186
1263
  request: IRequest,
@@ -1224,7 +1301,9 @@ export class ContainerRuntime
1224
1301
  this.submitSummaryFn = submitSummaryFn;
1225
1302
  this.submitSignalFn = submitSignalFn;
1226
1303
 
1227
- this.options = options;
1304
+ // TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
1305
+ // Values are generally expected to be set from the runtime side.
1306
+ this.options = options ?? {};
1228
1307
  this.clientDetails = clientDetails;
1229
1308
  this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
1230
1309
  this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
@@ -1265,20 +1344,12 @@ export class ContainerRuntime
1265
1344
  // summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
1266
1345
  // the count is reset to 0.
1267
1346
  loadSummaryNumber = metadata?.summaryNumber ?? 0;
1268
-
1269
- // Enabling the IdCompressor is a one-way operation and we only want to
1270
- // allow new containers to turn it on
1271
- this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
1272
1347
  } else {
1273
1348
  this.createContainerMetadata = {
1274
1349
  createContainerRuntimeVersion: pkgVersion,
1275
1350
  createContainerTimestamp: Date.now(),
1276
1351
  };
1277
1352
  loadSummaryNumber = 0;
1278
-
1279
- this.idCompressorEnabled =
1280
- this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
1281
- idCompressor !== undefined;
1282
1353
  }
1283
1354
  this.nextSummaryNumber = loadSummaryNumber + 1;
1284
1355
 
@@ -1346,14 +1417,9 @@ export class ContainerRuntime
1346
1417
  disableOpReentryCheck !== true;
1347
1418
 
1348
1419
  this.summariesDisabled = this.isSummariesDisabled();
1349
- this.heuristicsDisabled = this.isHeuristicsDisabled();
1350
1420
  this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
1351
1421
  this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
1352
1422
 
1353
- if (this.idCompressorEnabled) {
1354
- this.idCompressor = idCompressor;
1355
- }
1356
-
1357
1423
  this.maxConsecutiveReconnects =
1358
1424
  this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
1359
1425
  this.defaultMaxConsecutiveReconnects;
@@ -1371,15 +1437,17 @@ export class ContainerRuntime
1371
1437
 
1372
1438
  const pendingRuntimeState = pendingLocalState as IPendingRuntimeState | undefined;
1373
1439
 
1374
- const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
1375
- if (
1376
- maxSnapshotCacheDurationMs !== undefined &&
1377
- maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000
1378
- ) {
1379
- // This is a runtime enforcement of what's already explicit in the policy's type itself,
1380
- // which dictates the value is either undefined or exactly 5 days in ms.
1381
- // As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
1382
- throw new UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
1440
+ if (context.attachState === AttachState.Attached) {
1441
+ const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
1442
+ if (
1443
+ maxSnapshotCacheDurationMs !== undefined &&
1444
+ maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000
1445
+ ) {
1446
+ // This is a runtime enforcement of what's already explicit in the policy's type itself,
1447
+ // which dictates the value is either undefined or exactly 5 days in ms.
1448
+ // As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
1449
+ throw new UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
1450
+ }
1383
1451
  }
1384
1452
 
1385
1453
  this.garbageCollector = GarbageCollector.create({
@@ -1395,6 +1463,7 @@ export class ContainerRuntime
1395
1463
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
1396
1464
  readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
1397
1465
  submitMessage: (message: ContainerRuntimeGCMessage) => this.submit(message),
1466
+ sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
1398
1467
  });
1399
1468
 
1400
1469
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
@@ -1411,9 +1480,6 @@ export class ContainerRuntime
1411
1480
  // Must set to false to prevent sending summary handle which would be pointing to
1412
1481
  // a summary with an older protocol state.
1413
1482
  canReuseHandle: false,
1414
- // Must set to true to throw on any data stores failure that was too severe to be handled.
1415
- // We also are not decoding the base summaries at the root.
1416
- throwOnFailure: true,
1417
1483
  // If GC should not run, let the summarizer node know so that it does not track GC state.
1418
1484
  gcDisabled: !this.garbageCollector.shouldRunGC,
1419
1485
  },
@@ -1427,28 +1493,44 @@ export class ContainerRuntime
1427
1493
  this.summarizerNode.updateBaseSummaryState(baseSnapshot);
1428
1494
  }
1429
1495
 
1430
- this.dataStores = new DataStores(
1496
+ const parentContext = wrapContext(this);
1497
+
1498
+ // Due to a mismatch between different layers in terms of
1499
+ // what is the interface of passing signals, we need the
1500
+ // downstream stores to wrap the signal.
1501
+ parentContext.submitSignal = (type: string, content: any, targetClientId?: string) => {
1502
+ const envelope1 = content as IEnvelope;
1503
+ const envelope2 = this.createNewSignalEnvelope(
1504
+ envelope1.address,
1505
+ type,
1506
+ envelope1.contents,
1507
+ );
1508
+ return this.submitSignalFn(envelope2, targetClientId);
1509
+ };
1510
+
1511
+ this.channelCollection = new ChannelCollection(
1431
1512
  getSummaryForDatastores(baseSnapshot, metadata),
1432
- this,
1433
- (attachMsg) => this.submit({ type: ContainerMessageType.Attach, contents: attachMsg }),
1434
- (id: string, createParam: CreateChildSummarizerNodeParam) =>
1435
- (
1436
- summarizeInternal: SummarizeInternalFn,
1437
- getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
1438
- ) =>
1439
- this.summarizerNode.createChild(
1440
- summarizeInternal,
1441
- id,
1442
- createParam,
1443
- undefined,
1444
- getGCDataFn,
1445
- ),
1446
- (id: string) => this.summarizerNode.deleteChild(id),
1513
+ parentContext,
1447
1514
  this.mc.logger,
1448
- (path: string, timestampMs: number, packagePath?: readonly string[]) =>
1449
- this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath),
1515
+ (
1516
+ path: string,
1517
+ reason: "Loaded" | "Changed",
1518
+ timestampMs?: number,
1519
+ packagePath?: readonly string[],
1520
+ request?: IRequest,
1521
+ headerData?: RuntimeHeaderData,
1522
+ ) =>
1523
+ this.garbageCollector.nodeUpdated(
1524
+ path,
1525
+ reason,
1526
+ timestampMs,
1527
+ packagePath,
1528
+ request,
1529
+ headerData,
1530
+ ),
1450
1531
  (path: string) => this.garbageCollector.isNodeDeleted(path),
1451
1532
  new Map<string, string>(dataStoreAliasMap),
1533
+ async (runtime: ChannelCollection) => provideEntryPoint,
1452
1534
  );
1453
1535
 
1454
1536
  this.blobManager = new BlobManager(
@@ -1490,6 +1572,7 @@ export class ContainerRuntime
1490
1572
  reSubmit: this.reSubmit.bind(this),
1491
1573
  reSubmitBatch: this.reSubmitBatch.bind(this),
1492
1574
  isActiveConnection: () => this.innerDeltaManager.active,
1575
+ isAttached: () => this.attachState !== AttachState.Detached,
1493
1576
  },
1494
1577
  pendingRuntimeState?.pending,
1495
1578
  this.logger,
@@ -1636,7 +1719,6 @@ export class ContainerRuntime
1636
1719
  {
1637
1720
  initialDelayMs: this.initialSummarizerDelayMs,
1638
1721
  },
1639
- this.heuristicsDisabled,
1640
1722
  );
1641
1723
  this.summaryManager.on("summarize", (eventProps) => {
1642
1724
  this.emit("summarize", eventProps);
@@ -1654,26 +1736,27 @@ export class ContainerRuntime
1654
1736
  this.mc.logger.sendTelemetryEvent({
1655
1737
  eventName: "ContainerLoadStats",
1656
1738
  ...this.createContainerMetadata,
1657
- ...this.dataStores.containerLoadStats,
1739
+ ...this.channelCollection.containerLoadStats,
1658
1740
  summaryNumber: loadSummaryNumber,
1659
1741
  summaryFormatVersion: metadata?.summaryFormatVersion,
1660
1742
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
1661
1743
  gcVersion: metadata?.gcFeature,
1662
1744
  options: JSON.stringify(runtimeOptions),
1745
+ idCompressorModeMetadata: metadata?.idCompressorMode,
1746
+ idCompressorMode: this.idCompressorMode,
1663
1747
  featureGates: JSON.stringify({
1664
1748
  disableCompression,
1665
1749
  disableOpReentryCheck,
1666
1750
  disableChunking,
1667
1751
  disableAttachReorder: this.disableAttachReorder,
1668
1752
  disablePartialFlush,
1669
- idCompressorEnabled: this.idCompressorEnabled,
1670
1753
  closeSummarizerDelayOverride,
1671
1754
  }),
1672
1755
  telemetryDocumentId: this.telemetryDocumentId,
1673
1756
  groupedBatchingEnabled: this.groupedBatchingEnabled,
1674
1757
  });
1675
1758
 
1676
- ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
1759
+ ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger);
1677
1760
  BindBatchTracker(this, this.logger);
1678
1761
 
1679
1762
  this.entryPoint = new LazyPromise(async () => {
@@ -1686,12 +1769,47 @@ export class ContainerRuntime
1686
1769
  }
1687
1770
  return provideEntryPoint(this);
1688
1771
  });
1772
+
1773
+ // If we loaded from pending state, then we need to skip any ops that are already accounted in such
1774
+ // saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
1775
+ this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
1776
+ }
1777
+
1778
+ public getCreateChildSummarizerNodeFn(id: string, createParam: CreateChildSummarizerNodeParam) {
1779
+ return (
1780
+ summarizeInternal: SummarizeInternalFn,
1781
+ getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
1782
+ ) =>
1783
+ this.summarizerNode.createChild(
1784
+ summarizeInternal,
1785
+ id,
1786
+ createParam,
1787
+ undefined,
1788
+ getGCDataFn,
1789
+ );
1790
+ }
1791
+
1792
+ public deleteChildSummarizerNode(id: string) {
1793
+ return this.summarizerNode.deleteChild(id);
1794
+ }
1795
+
1796
+ public makeLocallyVisible() {
1797
+ assert(false, 0x8eb /* should not be called */);
1689
1798
  }
1690
1799
 
1691
1800
  /**
1692
1801
  * Initializes the state from the base snapshot this container runtime loaded from.
1693
1802
  */
1694
1803
  private async initializeBaseState(): Promise<void> {
1804
+ if (
1805
+ this.idCompressorMode === "on" ||
1806
+ (this.idCompressorMode === "delayed" && this.connected)
1807
+ ) {
1808
+ // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
1809
+ assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
1810
+ this._idCompressor = await this.createIdCompressor();
1811
+ }
1812
+
1695
1813
  await this.garbageCollector.initializeBaseState();
1696
1814
  }
1697
1815
 
@@ -1716,12 +1834,145 @@ export class ContainerRuntime
1716
1834
  }
1717
1835
  this.garbageCollector.dispose();
1718
1836
  this._summarizer?.dispose();
1719
- this.dataStores.dispose();
1837
+ this.channelCollection.dispose();
1720
1838
  this.pendingStateManager.dispose();
1721
1839
  this.emit("dispose");
1722
1840
  this.removeAllListeners();
1723
1841
  }
1724
1842
 
1843
+ /**
1844
+ * Api to fetch the snapshot from the service for a loadingGroupIds.
1845
+ * @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
1846
+ * @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
1847
+ * @returns - snapshotTree and the sequence number of the snapshot.
1848
+ */
1849
+ public async getSnapshotForLoadingGroupId(
1850
+ loadingGroupIds: string[],
1851
+ pathParts: string[],
1852
+ ): Promise<{ snapshotTree: ISnapshotTree; sequenceNumber: number }> {
1853
+ const sortedLoadingGroupIds = loadingGroupIds.sort();
1854
+ assert(
1855
+ this.storage.getSnapshot !== undefined,
1856
+ 0x8ed /* getSnapshot api should be defined if used */,
1857
+ );
1858
+ let loadedFromCache = true;
1859
+ // Lookup up in the cache, if not present then make the network call as multiple datastores could
1860
+ // be in same loading group. So, once we have fetched the snapshot for that loading group on
1861
+ // any request, then cache that as same group could be requested in future too.
1862
+ const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(
1863
+ sortedLoadingGroupIds.join(),
1864
+ async () => {
1865
+ assert(
1866
+ this.storage.getSnapshot !== undefined,
1867
+ 0x8ee /* getSnapshot api should be defined if used */,
1868
+ );
1869
+ loadedFromCache = false;
1870
+ return this.storage.getSnapshot({
1871
+ cacheSnapshot: false,
1872
+ scenarioName: "snapshotForLoadingGroupId",
1873
+ loadingGroupIds: sortedLoadingGroupIds,
1874
+ });
1875
+ },
1876
+ );
1877
+
1878
+ this.logger.sendTelemetryEvent({
1879
+ eventName: "GroupIdSnapshotFetched",
1880
+ details: JSON.stringify({
1881
+ fromCache: loadedFromCache,
1882
+ loadingGroupIds: loadingGroupIds.join(","),
1883
+ }),
1884
+ });
1885
+ // Find the snapshotTree inside the returned snapshot based on the path as given in the request.
1886
+ const hasIsolatedChannels = rootHasIsolatedChannels(this.metadata);
1887
+ const snapshotTreeForPath = this.getSnapshotTreeForPath(
1888
+ snapshot.snapshotTree,
1889
+ pathParts,
1890
+ hasIsolatedChannels,
1891
+ );
1892
+ assert(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
1893
+ const snapshotSeqNumber = snapshot.sequenceNumber;
1894
+ assert(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
1895
+
1896
+ // This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
1897
+ // Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
1898
+ // the file has been overwritten or service lost data.
1899
+ if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
1900
+ throw DataProcessingError.create(
1901
+ "Downloaded snapshot older than snapshot we loaded from",
1902
+ "getSnapshotForLoadingGroupId",
1903
+ undefined,
1904
+ {
1905
+ loadingGroupIds: sortedLoadingGroupIds.join(","),
1906
+ snapshotSeqNumber,
1907
+ initialSequenceNumber: this.deltaManager.initialSequenceNumber,
1908
+ },
1909
+ );
1910
+ }
1911
+
1912
+ // If the snapshot is ahead of the last seq number of the delta manager, then catch up before
1913
+ // returning the snapshot.
1914
+ if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
1915
+ // If this is a summarizer client, which is trying to load a group and it finds that there is
1916
+ // another snapshot from which the summarizer loaded and it is behind, then just give up as
1917
+ // the summarizer state is not up to date.
1918
+ // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
1919
+ if (this.isSummarizerClient) {
1920
+ throw new Error(
1921
+ "Summarizer client behind, loaded newer snapshot with loadingGroupId",
1922
+ );
1923
+ }
1924
+
1925
+ // We want to catchup from sequenceNumber to targetSequenceNumber
1926
+ const props: ITelemetryGenericEventExt = {
1927
+ eventName: "GroupIdSnapshotCatchup",
1928
+ loadingGroupIds: sortedLoadingGroupIds.join(","),
1929
+ targetSequenceNumber: snapshotSeqNumber, // This is so we reuse some columns in telemetry
1930
+ sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
1931
+ };
1932
+
1933
+ const event = PerformanceEvent.start(this.mc.logger, {
1934
+ ...props,
1935
+ });
1936
+ // If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
1937
+ // as long as it's not a summarizer client.
1938
+ if (this.deltaManager.inbound.paused) {
1939
+ props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
1940
+ }
1941
+ const defP = new Deferred<boolean>();
1942
+ this.deltaManager.on("op", (message: ISequencedDocumentMessage) => {
1943
+ if (message.sequenceNumber >= snapshotSeqNumber) {
1944
+ defP.resolve(true);
1945
+ }
1946
+ });
1947
+ await defP.promise;
1948
+ event.end(props);
1949
+ }
1950
+ return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
1951
+ }
1952
+
1953
+ /**
1954
+ * Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
1955
+ * @param snapshotTree - snapshot tree to look into.
1956
+ * @param pathParts - Part of the path, which we want to extract from the snapshot tree.
1957
+ * @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
1958
+ * snapshots will not have trees inside ".channels", so check that.
1959
+ * @returns - requested snapshot tree based on the path parts.
1960
+ */
1961
+ private getSnapshotTreeForPath(
1962
+ snapshotTree: ISnapshotTree,
1963
+ pathParts: string[],
1964
+ hasIsolatedChannels: boolean,
1965
+ ): ISnapshotTree | undefined {
1966
+ let childTree = snapshotTree;
1967
+ for (const part of pathParts) {
1968
+ if (hasIsolatedChannels) {
1969
+ childTree = childTree?.trees[channelsTreeName];
1970
+ }
1971
+ childTree = childTree?.trees[part];
1972
+ }
1973
+ return childTree;
1974
+ }
1975
+
1725
1976
  /**
1726
1977
  * Notifies this object about the request made to the container.
1727
1978
  * @param request - Request made to the handler.
@@ -1778,19 +2029,7 @@ export class ContainerRuntime
1778
2029
  }
1779
2030
  : create404Response(request);
1780
2031
  } else if (requestParser.pathParts.length > 0) {
1781
- // Differentiate between requesting the dataStore directly, or one of its children
1782
- const requestForChild = !requestParser.isLeaf(1);
1783
- const dataStore = await this.getDataStoreFromRequest(id, request, requestForChild);
1784
-
1785
- const subRequest = requestParser.createSubRequest(1);
1786
- // We always expect createSubRequest to include a leading slash, but asserting here to protect against
1787
- // unintentionally modifying the url if that changes.
1788
- assert(
1789
- subRequest.url.startsWith("/"),
1790
- 0x126 /* "Expected createSubRequest url to include a leading slash" */,
1791
- );
1792
- // eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
1793
- return dataStore.request(subRequest);
2032
+ return await this.channelCollection.request(request);
1794
2033
  }
1795
2034
 
1796
2035
  return create404Response(request);
@@ -1808,54 +2047,7 @@ export class ContainerRuntime
1808
2047
  private readonly entryPoint: LazyPromise<FluidObject>;
1809
2048
 
1810
2049
  private internalId(maybeAlias: string): string {
1811
- return this.dataStores.aliases.get(maybeAlias) ?? maybeAlias;
1812
- }
1813
-
1814
- private async getDataStoreFromRequest(
1815
- id: string,
1816
- request: IRequest,
1817
- requestForChild: boolean,
1818
- ): Promise<IFluidDataStoreChannel> {
1819
- const headerData: RuntimeHeaderData = {};
1820
- if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
1821
- headerData.wait = request.headers[RuntimeHeaders.wait];
1822
- }
1823
- if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
1824
- headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
1825
- }
1826
- if (typeof request.headers?.[AllowTombstoneRequestHeaderKey] === "boolean") {
1827
- headerData.allowTombstone = request.headers[AllowTombstoneRequestHeaderKey];
1828
- }
1829
- if (typeof request.headers?.[AllowInactiveRequestHeaderKey] === "boolean") {
1830
- headerData.allowInactive = request.headers[AllowInactiveRequestHeaderKey];
1831
- }
1832
-
1833
- // We allow Tombstone requests for sub-DataStore objects
1834
- if (requestForChild) {
1835
- headerData.allowTombstone = true;
1836
- }
1837
-
1838
- await this.dataStores.waitIfPendingAlias(id);
1839
- const internalId = this.internalId(id);
1840
- const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
1841
-
1842
- // Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
1843
- // the same as GC nodes id.
1844
- const urlWithoutQuery = trimLeadingAndTrailingSlashes(request.url.split("?")[0]);
1845
- // Get the initial snapshot details which contain the data store package path.
1846
- const details = await dataStoreContext.getInitialSnapshotDetails();
1847
-
1848
- // Note that this will throw if the data store is inactive or tombstoned and throwing on incorrect usage
1849
- // is configured.
1850
- this.garbageCollector.nodeUpdated(
1851
- `/${urlWithoutQuery}`,
1852
- "Loaded",
1853
- undefined /* timestampMs */,
1854
- details.pkg,
1855
- request,
1856
- headerData,
1857
- );
1858
- return dataStoreContext.realize();
2050
+ return this.channelCollection.internalId(maybeAlias);
1859
2051
  }
1860
2052
 
1861
2053
  /** Adds the container's metadata to the given summary tree. */
@@ -1872,7 +2064,7 @@ export class ContainerRuntime
1872
2064
  extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
1873
2065
  this.messageAtLastSummary,
1874
2066
  telemetryDocumentId: this.telemetryDocumentId,
1875
- idCompressorEnabled: this.idCompressorEnabled ? true : undefined,
2067
+ idCompressorMode: this.idCompressorMode,
1876
2068
  };
1877
2069
  addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
1878
2070
  }
@@ -1885,12 +2077,8 @@ export class ContainerRuntime
1885
2077
  ) {
1886
2078
  this.addMetadataToSummary(summaryTree);
1887
2079
 
1888
- if (this.idCompressorEnabled) {
1889
- assert(
1890
- this.idCompressor !== undefined,
1891
- 0x67a /* IdCompressor should be defined if enabled */,
1892
- );
1893
- const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
2080
+ if (this._idCompressor) {
2081
+ const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
1894
2082
  addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
1895
2083
  }
1896
2084
 
@@ -1899,7 +2087,7 @@ export class ContainerRuntime
1899
2087
  addBlobToSummary(summaryTree, chunksBlobName, content);
1900
2088
  }
1901
2089
 
1902
- const dataStoreAliases = this.dataStores.aliases;
2090
+ const dataStoreAliases = this.channelCollection.aliases;
1903
2091
  if (dataStoreAliases.size > 0) {
1904
2092
  addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
1905
2093
  }
@@ -1915,7 +2103,7 @@ export class ContainerRuntime
1915
2103
  // Some storage (like git) doesn't allow empty tree, so we can omit it.
1916
2104
  // and the blob manager can handle the tree not existing when loading
1917
2105
  if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
1918
- addTreeToSummary(summaryTree, blobsTreeName, blobManagerSummary);
2106
+ addSummarizeResultToSummary(summaryTree, blobsTreeName, blobManagerSummary);
1919
2107
  }
1920
2108
 
1921
2109
  const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
@@ -2015,16 +2203,12 @@ export class ContainerRuntime
2015
2203
  const opContents = this.parseLocalOpContent(serializedOpContent);
2016
2204
  switch (opContents.type) {
2017
2205
  case ContainerMessageType.FluidDataStoreOp:
2018
- return this.dataStores.applyStashedOp(opContents.contents);
2019
2206
  case ContainerMessageType.Attach:
2020
- return this.dataStores.applyStashedAttachOp(opContents.contents);
2207
+ case ContainerMessageType.Alias:
2208
+ return this.channelCollection.applyStashedOp(opContents);
2021
2209
  case ContainerMessageType.IdAllocation:
2022
- assert(
2023
- this.idCompressor !== undefined,
2024
- 0x67b /* IdCompressor should be defined if enabled */,
2025
- );
2210
+ assert(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
2026
2211
  return;
2027
- case ContainerMessageType.Alias:
2028
2212
  case ContainerMessageType.BlobAttach:
2029
2213
  return;
2030
2214
  case ContainerMessageType.ChunkedOp:
@@ -2054,11 +2238,27 @@ export class ContainerRuntime
2054
2238
  this.closeFn(error);
2055
2239
  throw error;
2056
2240
  }
2241
+ // Note: Even if its compat behavior allows it, we don't know how to apply this stashed op.
2242
+ // All we can do is ignore it (similar to on process).
2057
2243
  }
2058
2244
  }
2059
2245
  }
2060
2246
 
2061
2247
  public setConnectionState(connected: boolean, clientId?: string) {
2248
+ if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
2249
+ this.compressorLoadInitiated = true;
2250
+ this.createIdCompressor()
2251
+ .then((compressor) => {
2252
+ this._idCompressor = compressor;
2253
+ for (const range of this.pendingIdCompressorOps) {
2254
+ this._idCompressor.finalizeCreationRange(range);
2255
+ }
2256
+ this.pendingIdCompressorOps = [];
2257
+ })
2258
+ .catch((error) => {
2259
+ this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
2260
+ });
2261
+ }
2062
2262
  if (connected === false && this.delayConnectClientId !== undefined) {
2063
2263
  this.delayConnectClientId = undefined;
2064
2264
  this.mc.logger.sendTelemetryEvent({
@@ -2151,7 +2351,7 @@ export class ContainerRuntime
2151
2351
  this.replayPendingStates();
2152
2352
  }
2153
2353
 
2154
- this.dataStores.setConnectionState(connected, clientId);
2354
+ this.channelCollection.setConnectionState(connected, clientId);
2155
2355
  this.garbageCollector.setConnectionState(connected, clientId);
2156
2356
 
2157
2357
  raiseConnectedEvent(this.mc.logger, this, connected, clientId);
@@ -2254,17 +2454,9 @@ export class ContainerRuntime
2254
2454
  const { local } = messageWithContext;
2255
2455
  switch (messageWithContext.message.type) {
2256
2456
  case ContainerMessageType.Attach:
2257
- this.dataStores.processAttachMessage(messageWithContext.message, local);
2258
- break;
2259
2457
  case ContainerMessageType.Alias:
2260
- this.dataStores.processAliasMessage(
2261
- messageWithContext.message,
2262
- localOpMetadata,
2263
- local,
2264
- );
2265
- break;
2266
2458
  case ContainerMessageType.FluidDataStoreOp:
2267
- this.dataStores.processFluidDataStoreOp(
2459
+ this.channelCollection.process(
2268
2460
  messageWithContext.message,
2269
2461
  local,
2270
2462
  localOpMetadata,
@@ -2275,17 +2467,23 @@ export class ContainerRuntime
2275
2467
  this.blobManager.processBlobAttachOp(messageWithContext.message, local);
2276
2468
  break;
2277
2469
  case ContainerMessageType.IdAllocation:
2278
- assert(
2279
- this.idCompressor !== undefined,
2280
- 0x67c /* IdCompressor should be defined if enabled */,
2281
- );
2282
-
2283
2470
  // Don't re-finalize the range if we're processing a "savedOp" in
2284
2471
  // stashed ops flow. The compressor is stashed with these ops already processed.
2472
+ // That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
2473
+ // thus we need to process all the ops.
2285
2474
  if (
2286
- (messageWithContext.message.metadata as IIdAllocationMetadata)?.savedOp !== true
2475
+ !(
2476
+ this.skipSavedCompressorOps &&
2477
+ (messageWithContext.message.metadata as IIdAllocationMetadata)?.savedOp ===
2478
+ true
2479
+ )
2287
2480
  ) {
2288
- this.idCompressor.finalizeCreationRange(messageWithContext.message.contents);
2481
+ const range = messageWithContext.message.contents;
2482
+ if (this._idCompressor === undefined) {
2483
+ this.pendingIdCompressorOps.push(range);
2484
+ } else {
2485
+ this._idCompressor.finalizeCreationRange(range);
2486
+ }
2289
2487
  }
2290
2488
  break;
2291
2489
  case ContainerMessageType.GC:
@@ -2391,7 +2589,16 @@ export class ContainerRuntime
2391
2589
  return;
2392
2590
  }
2393
2591
 
2394
- this.dataStores.processSignal(envelope.address, transformed, local);
2592
+ // Due to a mismatch between different layers in terms of
2593
+ // what is the interface of passing signals, we need to adjust
2594
+ // the signal envelope before sending it to the datastores to be processed
2595
+ const envelope2: IEnvelope = {
2596
+ address: envelope.address,
2597
+ contents: transformed.content,
2598
+ };
2599
+ transformed.content = envelope2;
2600
+
2601
+ this.channelCollection.processSignal(transformed, local);
2395
2602
  }
2396
2603
 
2397
2604
  /**
@@ -2478,9 +2685,17 @@ export class ContainerRuntime
2478
2685
  public async getAliasedDataStoreEntryPoint(
2479
2686
  alias: string,
2480
2687
  ): Promise<IFluidHandle<FluidObject> | undefined> {
2481
- await this.dataStores.waitIfPendingAlias(alias);
2688
+ // Back-comapatibility:
2689
+ // There are old files that were created without using data store aliasing feature, but
2690
+ // used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
2691
+ // and internalID provided by user. The expectation is that such files behave as new files, where
2692
+ // same data store instances created using aliasing feature.
2693
+ // Please also see note on name collisions in DataStores.createDataStoreId()
2694
+ await this.channelCollection.waitIfPendingAlias(alias);
2482
2695
  const internalId = this.internalId(alias);
2483
- const context = await this.dataStores.getDataStoreIfAvailable(internalId, { wait: false });
2696
+ const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
2697
+ wait: false,
2698
+ });
2484
2699
  // If the data store is not available or not an alias, return undefined.
2485
2700
  if (context === undefined || !(await context.isRoot())) {
2486
2701
  return undefined;
@@ -2501,29 +2716,26 @@ export class ContainerRuntime
2501
2716
  return channel.entryPoint;
2502
2717
  }
2503
2718
 
2504
- public createDetachedRootDataStore(
2719
+ public createDetachedDataStore(
2505
2720
  pkg: Readonly<string[]>,
2506
- rootDataStoreId: string,
2721
+ loadingGroupId?: string,
2507
2722
  ): IFluidDataStoreContextDetached {
2508
- if (rootDataStoreId.includes("/")) {
2509
- throw new UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
2510
- }
2511
- return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
2512
- }
2513
-
2514
- public createDetachedDataStore(pkg: Readonly<string[]>): IFluidDataStoreContextDetached {
2515
- return this.dataStores.createDetachedDataStoreCore(pkg, false);
2723
+ return this.channelCollection.createDetachedDataStoreCore(pkg, loadingGroupId);
2516
2724
  }
2517
2725
 
2518
- public async createDataStore(pkg: string | string[]): Promise<IDataStore> {
2519
- const id = uuid();
2726
+ public async createDataStore(
2727
+ pkg: Readonly<string | string[]>,
2728
+ loadingGroupId?: string,
2729
+ ): Promise<IDataStore> {
2730
+ const context = this.channelCollection._createFluidDataStoreContext(
2731
+ Array.isArray(pkg) ? pkg : [pkg],
2732
+ undefined, // props
2733
+ loadingGroupId,
2734
+ );
2520
2735
  return channelToDataStore(
2521
- await this.dataStores
2522
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id)
2523
- .realize(),
2524
- id,
2525
- this,
2526
- this.dataStores,
2736
+ await context.realize(),
2737
+ context.id,
2738
+ this.channelCollection,
2527
2739
  this.mc.logger,
2528
2740
  );
2529
2741
  }
@@ -2532,17 +2744,17 @@ export class ContainerRuntime
2532
2744
  * @deprecated 0.16 Issue #1537, #3631
2533
2745
  */
2534
2746
  public async _createDataStoreWithProps(
2535
- pkg: string | string[],
2747
+ pkg: Readonly<string | string[]>,
2536
2748
  props?: any,
2537
- id = uuid(),
2538
2749
  ): Promise<IDataStore> {
2750
+ const context = this.channelCollection._createFluidDataStoreContext(
2751
+ Array.isArray(pkg) ? pkg : [pkg],
2752
+ props,
2753
+ );
2539
2754
  return channelToDataStore(
2540
- await this.dataStores
2541
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
2542
- .realize(),
2543
- id,
2544
- this,
2545
- this.dataStores,
2755
+ await context.realize(),
2756
+ context.id,
2757
+ this.channelCollection,
2546
2758
  this.mc.logger,
2547
2759
  );
2548
2760
  }
@@ -2643,22 +2855,6 @@ export class ContainerRuntime
2643
2855
  return this.submitSignalFn(envelope, targetClientId);
2644
2856
  }
2645
2857
 
2646
- /**
2647
- * Submits the signal to be sent to other clients.
2648
- * @param type - Type of the signal.
2649
- * @param content - Content of the signal.
2650
- * @param targetClientId - When specified, the signal is only sent to the provided client id.
2651
- */
2652
- public submitDataStoreSignal(
2653
- address: string,
2654
- type: string,
2655
- content: any,
2656
- targetClientId?: string,
2657
- ) {
2658
- const envelope = this.createNewSignalEnvelope(address, type, content);
2659
- return this.submitSignalFn(envelope, targetClientId);
2660
- }
2661
-
2662
2858
  public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {
2663
2859
  if (attachState === AttachState.Attaching) {
2664
2860
  assert(
@@ -2676,7 +2872,7 @@ export class ContainerRuntime
2676
2872
  if (attachState === AttachState.Attached && !this.hasPendingMessages()) {
2677
2873
  this.updateDocumentDirtyState(false);
2678
2874
  }
2679
- this.dataStores.setAttachState(attachState);
2875
+ this.channelCollection.setAttachState(attachState);
2680
2876
  }
2681
2877
 
2682
2878
  /**
@@ -2696,12 +2892,12 @@ export class ContainerRuntime
2696
2892
  }
2697
2893
 
2698
2894
  // We can finalize any allocated IDs since we're the only client
2699
- const idRange = this.idCompressor?.takeNextCreationRange();
2895
+ const idRange = this._idCompressor?.takeNextCreationRange();
2700
2896
  if (idRange !== undefined) {
2701
- this.idCompressor?.finalizeCreationRange(idRange);
2897
+ this._idCompressor?.finalizeCreationRange(idRange);
2702
2898
  }
2703
2899
 
2704
- const summarizeResult = this.dataStores.createSummary(telemetryContext);
2900
+ const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
2705
2901
  // Wrap data store summaries in .channels subtree.
2706
2902
  wrapSummaryInChannelsTree(summarizeResult);
2707
2903
 
@@ -2721,7 +2917,7 @@ export class ContainerRuntime
2721
2917
  trackState: boolean,
2722
2918
  telemetryContext?: ITelemetryContext,
2723
2919
  ): Promise<ISummarizeInternalResult> {
2724
- const summarizeResult = await this.dataStores.summarize(
2920
+ const summarizeResult = await this.channelCollection.summarize(
2725
2921
  fullTree,
2726
2922
  trackState,
2727
2923
  telemetryContext,
@@ -2812,11 +3008,11 @@ export class ContainerRuntime
2812
3008
  * @see IGarbageCollectionRuntime.updateStateBeforeGC
2813
3009
  */
2814
3010
  public async updateStateBeforeGC() {
2815
- return this.dataStores.updateStateBeforeGC();
3011
+ return this.channelCollection.updateStateBeforeGC();
2816
3012
  }
2817
3013
 
2818
3014
  private async getGCDataInternal(fullGC?: boolean): Promise<IGarbageCollectionData> {
2819
- return this.dataStores.getGCData(fullGC);
3015
+ return this.channelCollection.getGCData(fullGC);
2820
3016
  }
2821
3017
 
2822
3018
  /**
@@ -2846,7 +3042,7 @@ export class ContainerRuntime
2846
3042
  this.summarizerNode.updateUsedRoutes([""]);
2847
3043
 
2848
3044
  const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(usedRoutes);
2849
- this.dataStores.updateUsedRoutes(dataStoreRoutes);
3045
+ this.channelCollection.updateUsedRoutes(dataStoreRoutes);
2850
3046
  }
2851
3047
 
2852
3048
  /**
@@ -2857,7 +3053,7 @@ export class ContainerRuntime
2857
3053
  const { blobManagerRoutes, dataStoreRoutes } =
2858
3054
  this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
2859
3055
  this.blobManager.updateUnusedRoutes(blobManagerRoutes);
2860
- this.dataStores.updateUnusedRoutes(dataStoreRoutes);
3056
+ this.channelCollection.updateUnusedRoutes(dataStoreRoutes);
2861
3057
  }
2862
3058
 
2863
3059
  /**
@@ -2876,7 +3072,7 @@ export class ContainerRuntime
2876
3072
  const { dataStoreRoutes, blobManagerRoutes } =
2877
3073
  this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
2878
3074
 
2879
- const deletedRoutes = this.dataStores.deleteSweepReadyNodes(dataStoreRoutes);
3075
+ const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
2880
3076
  return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
2881
3077
  }
2882
3078
 
@@ -2892,7 +3088,7 @@ export class ContainerRuntime
2892
3088
  const { blobManagerRoutes, dataStoreRoutes } =
2893
3089
  this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
2894
3090
  this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
2895
- this.dataStores.updateTombstonedRoutes(dataStoreRoutes);
3091
+ this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
2896
3092
  }
2897
3093
 
2898
3094
  /**
@@ -2912,7 +3108,7 @@ export class ContainerRuntime
2912
3108
  if (this.isBlobPath(nodePath)) {
2913
3109
  return GCNodeType.Blob;
2914
3110
  }
2915
- return this.dataStores.getGCNodeType(nodePath) ?? GCNodeType.Other;
3111
+ return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
2916
3112
  }
2917
3113
 
2918
3114
  /**
@@ -2920,12 +3116,18 @@ export class ContainerRuntime
2920
3116
  * data store or an attachment blob.
2921
3117
  */
2922
3118
  public async getGCNodePackagePath(nodePath: string): Promise<readonly string[] | undefined> {
3119
+ // GC uses "/" when adding "root" references, e.g. for Aliasing or as part of Tombstone Auto-Recovery.
3120
+ // These have no package path so return a special value.
3121
+ if (nodePath === "/") {
3122
+ return ["_gcRoot"];
3123
+ }
3124
+
2923
3125
  switch (this.getNodeType(nodePath)) {
2924
3126
  case GCNodeType.Blob:
2925
3127
  return [BlobManager.basePath];
2926
3128
  case GCNodeType.DataStore:
2927
3129
  case GCNodeType.SubDataStore:
2928
- return this.dataStores.getDataStorePackagePath(nodePath);
3130
+ return this.channelCollection.getDataStorePackagePath(nodePath);
2929
3131
  default:
2930
3132
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
2931
3133
  }
@@ -2985,7 +3187,10 @@ export class ContainerRuntime
2985
3187
  * @param srcHandle - The handle of the node that added the reference.
2986
3188
  * @param outboundHandle - The handle of the outbound node that is referenced.
2987
3189
  */
2988
- public addedGCOutboundReference(srcHandle: IFluidHandle, outboundHandle: IFluidHandle) {
3190
+ public addedGCOutboundReference(
3191
+ srcHandle: { absolutePath: string },
3192
+ outboundHandle: { absolutePath: string },
3193
+ ) {
2989
3194
  this.garbageCollector.addedOutboundReference(
2990
3195
  srcHandle.absolutePath,
2991
3196
  outboundHandle.absolutePath,
@@ -3001,7 +3206,13 @@ export class ContainerRuntime
3001
3206
  * @param options - options controlling how the summary is generated or submitted
3002
3207
  */
3003
3208
  public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
3004
- const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger } = options;
3209
+ const {
3210
+ fullTree = false,
3211
+ finalAttempt = false,
3212
+ refreshLatestAck,
3213
+ summaryLogger,
3214
+ latestSummaryRefSeqNum,
3215
+ } = options;
3005
3216
  // The summary number for this summary. This will be updated during the summary process, so get it now and
3006
3217
  // use it for all events logged during this summary.
3007
3218
  const summaryNumber = this.nextSummaryNumber;
@@ -3015,7 +3226,6 @@ export class ContainerRuntime
3015
3226
  assert(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
3016
3227
 
3017
3228
  // We close the summarizer and download a new snapshot and reload the container
3018
- let latestSnapshotVersionId: string | undefined;
3019
3229
  if (refreshLatestAck === true) {
3020
3230
  return this.prefetchLatestSummaryThenClose(
3021
3231
  createChildLogger({
@@ -3073,6 +3283,10 @@ export class ContainerRuntime
3073
3283
  this.mc.config.getBoolean(
3074
3284
  "Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause",
3075
3285
  ) !== true;
3286
+ const shouldValidatePreSummaryState =
3287
+ this.mc.config.getBoolean(
3288
+ "Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState",
3289
+ ) === true;
3076
3290
 
3077
3291
  let summaryRefSeqNum: number | undefined;
3078
3292
 
@@ -3087,7 +3301,33 @@ export class ContainerRuntime
3087
3301
  const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
3088
3302
  const lastAck = this.summaryCollection.latestAck;
3089
3303
 
3090
- this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
3304
+ const startSummaryResult = this.summarizerNode.startSummary(
3305
+ summaryRefSeqNum,
3306
+ summaryNumberLogger,
3307
+ latestSummaryRefSeqNum,
3308
+ );
3309
+
3310
+ if (
3311
+ startSummaryResult.invalidNodes > 0 ||
3312
+ startSummaryResult.mismatchNumbers.size > 0
3313
+ ) {
3314
+ summaryLogger.sendErrorEvent({
3315
+ eventName: "LatestSummaryRefSeqNumMismatch",
3316
+ details: {
3317
+ ...startSummaryResult,
3318
+ mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
3319
+ },
3320
+ });
3321
+
3322
+ if (shouldValidatePreSummaryState && !finalAttempt) {
3323
+ return {
3324
+ stage: "base",
3325
+ referenceSequenceNumber: summaryRefSeqNum,
3326
+ minimumSequenceNumber,
3327
+ error: `Summarizer node state inconsistent with summarizer state.`,
3328
+ };
3329
+ }
3330
+ }
3091
3331
 
3092
3332
  // Helper function to check whether we should still continue between each async step.
3093
3333
  const checkContinue = (): { continue: true } | { continue: false; error: string } => {
@@ -3209,8 +3449,8 @@ export class ContainerRuntime
3209
3449
  : undefined;
3210
3450
 
3211
3451
  const summaryStats: IGeneratedSummaryStats = {
3212
- dataStoreCount: this.dataStores.size,
3213
- summarizedDataStoreCount: this.dataStores.size - handleCount,
3452
+ dataStoreCount: this.channelCollection.size,
3453
+ summarizedDataStoreCount: this.channelCollection.size - handleCount,
3214
3454
  gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
3215
3455
  gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
3216
3456
  gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
@@ -3231,34 +3471,18 @@ export class ContainerRuntime
3231
3471
  return { stage: "generate", ...generateSummaryData, error: continueResult.error };
3232
3472
  }
3233
3473
 
3234
- // It may happen that the lastAck it not correct due to missing summaryAck in case of single commit
3235
- // summary. So if the previous summarizer closes just after submitting the summary and before
3236
- // submitting the summaryOp then we can't rely on summaryAck. So in case we have
3237
- // latestSnapshotVersionId from storage and it does not match with the lastAck ackHandle, then use
3238
- // the one fetched from storage as parent as that is the latest.
3239
- let summaryContext: ISummaryContext;
3240
- if (
3241
- lastAck?.summaryAck.contents.handle !== latestSnapshotVersionId &&
3242
- latestSnapshotVersionId !== undefined
3243
- ) {
3244
- summaryContext = {
3245
- proposalHandle: undefined,
3246
- ackHandle: latestSnapshotVersionId,
3247
- referenceSequenceNumber: summaryRefSeqNum,
3248
- };
3249
- } else if (lastAck === undefined) {
3250
- summaryContext = {
3251
- proposalHandle: undefined,
3252
- ackHandle: this.loadedFromVersionId,
3253
- referenceSequenceNumber: summaryRefSeqNum,
3254
- };
3255
- } else {
3256
- summaryContext = {
3257
- proposalHandle: lastAck.summaryOp.contents.handle,
3258
- ackHandle: lastAck.summaryAck.contents.handle,
3259
- referenceSequenceNumber: summaryRefSeqNum,
3260
- };
3261
- }
3474
+ const summaryContext =
3475
+ lastAck === undefined
3476
+ ? {
3477
+ proposalHandle: undefined,
3478
+ ackHandle: this.loadedFromVersionId,
3479
+ referenceSequenceNumber: summaryRefSeqNum,
3480
+ }
3481
+ : {
3482
+ proposalHandle: lastAck.summaryOp.contents.handle,
3483
+ ackHandle: lastAck.summaryAck.contents.handle,
3484
+ referenceSequenceNumber: summaryRefSeqNum,
3485
+ };
3262
3486
 
3263
3487
  let handle: string;
3264
3488
  try {
@@ -3423,28 +3647,15 @@ export class ContainerRuntime
3423
3647
  }
3424
3648
  }
3425
3649
 
3426
- public submitDataStoreOp(
3427
- id: string,
3650
+ public submitMessage(
3651
+ type:
3652
+ | ContainerMessageType.FluidDataStoreOp
3653
+ | ContainerMessageType.Alias
3654
+ | ContainerMessageType.Attach,
3428
3655
  contents: any,
3429
3656
  localOpMetadata: unknown = undefined,
3430
3657
  ): void {
3431
- const envelope: IEnvelope = {
3432
- address: id,
3433
- contents,
3434
- };
3435
- this.submit(
3436
- { type: ContainerMessageType.FluidDataStoreOp, contents: envelope },
3437
- localOpMetadata,
3438
- );
3439
- }
3440
-
3441
- public submitDataStoreAliasOp(contents: any, localOpMetadata: unknown): void {
3442
- const aliasMessage = contents as IDataStoreAliasMessage;
3443
- if (!isDataStoreAliasMessage(aliasMessage)) {
3444
- throw new UsageError("malformedDataStoreAliasMessage");
3445
- }
3446
-
3447
- this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
3658
+ this.submit({ type, contents }, localOpMetadata);
3448
3659
  }
3449
3660
 
3450
3661
  public async uploadBlob(
@@ -3455,35 +3666,22 @@ export class ContainerRuntime
3455
3666
  return this.blobManager.createBlob(blob, signal);
3456
3667
  }
3457
3668
 
3458
- private maybeSubmitIdAllocationOp(type: ContainerMessageType) {
3459
- if (type !== ContainerMessageType.IdAllocation) {
3460
- let idAllocationBatchMessage: BatchMessage | undefined;
3461
- let idRange: IdCreationRange | undefined;
3462
- if (this.idCompressorEnabled) {
3463
- assert(
3464
- this.idCompressor !== undefined,
3465
- 0x67d /* IdCompressor should be defined if enabled */,
3466
- );
3467
- idRange = this.idCompressor.takeNextCreationRange();
3468
- // Don't include the idRange if there weren't any Ids allocated
3469
- idRange = idRange?.ids !== undefined ? idRange : undefined;
3470
- }
3471
-
3472
- if (idRange !== undefined) {
3669
+ private submitIdAllocationOpIfNeeded(): void {
3670
+ if (this._idCompressor) {
3671
+ const idRange = this._idCompressor.takeNextCreationRange();
3672
+ // Don't include the idRange if there weren't any Ids allocated
3673
+ if (idRange?.ids !== undefined) {
3473
3674
  const idAllocationMessage: ContainerRuntimeIdAllocationMessage = {
3474
3675
  type: ContainerMessageType.IdAllocation,
3475
3676
  contents: idRange,
3476
3677
  };
3477
- idAllocationBatchMessage = {
3678
+ const idAllocationBatchMessage: BatchMessage = {
3478
3679
  contents: JSON.stringify(idAllocationMessage),
3479
3680
  referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
3480
3681
  metadata: undefined,
3481
3682
  localOpMetadata: undefined,
3482
3683
  type: ContainerMessageType.IdAllocation,
3483
3684
  };
3484
- }
3485
-
3486
- if (idAllocationBatchMessage !== undefined) {
3487
3685
  this.outbox.submitIdAllocation(idAllocationBatchMessage);
3488
3686
  }
3489
3687
  }
@@ -3524,43 +3722,47 @@ export class ContainerRuntime
3524
3722
  };
3525
3723
 
3526
3724
  try {
3527
- // Submit an IdAllocation op if any Ids have been generated since
3528
- // the last op was submitted. Don't submit another if it's an IdAllocation
3529
- // op as that means we're in resubmission flow and we don't want to send
3530
- // IdRanges out of order.
3531
- this.maybeSubmitIdAllocationOp(type);
3532
-
3533
- // If this is attach message for new data store, and we are in a batch, send this op out of order
3534
- // Is it safe:
3535
- // Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
3536
- // They become visible only when aliased, or handle to some sub-element of newly created datastore
3537
- // is stored in some DDS, i.e. only after some other op.
3538
- // Why:
3539
- // Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
3540
- // stores are created, causing issues like relay service throttling (too many ops) and catastrophic
3541
- // failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
3542
- // these issues.
3543
- // Cons:
3544
- // 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
3545
- // This change creates new possibility of a lot of newly created data stores never being referenced
3546
- // because client died before it had a change to submit the rest of the ops. This will create more
3547
- // garbage that needs to be collected leveraging GC (Garbage Collection) feature.
3548
- // 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
3549
- // today as rollback can't undo creation of data store. To some extent not sending them is a bigger
3550
- // issue than sending.
3551
- // Please note that this does not change file format, so it can be disabled in the future if this
3552
- // optimization no longer makes sense (for example, batch compression may make it less appealing).
3553
- if (
3554
- this.currentlyBatching() &&
3555
- type === ContainerMessageType.Attach &&
3556
- this.disableAttachReorder !== true
3557
- ) {
3558
- this.outbox.submitAttach(message);
3559
- } else if (type === ContainerMessageType.BlobAttach) {
3560
- // BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
3561
- this.outbox.submitBlobAttach(message);
3725
+ // If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
3726
+ // op into the correct batch to avoid ranges being finalized out of order.
3727
+ // Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
3728
+ // any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
3729
+ if (type === ContainerMessageType.IdAllocation) {
3730
+ this.outbox.submitIdAllocation(message);
3562
3731
  } else {
3563
- this.outbox.submit(message);
3732
+ this.submitIdAllocationOpIfNeeded();
3733
+
3734
+ // If this is attach message for new data store, and we are in a batch, send this op out of order
3735
+ // Is it safe:
3736
+ // Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
3737
+ // They become visible only when aliased, or handle to some sub-element of newly created datastore
3738
+ // is stored in some DDS, i.e. only after some other op.
3739
+ // Why:
3740
+ // Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
3741
+ // stores are created, causing issues like relay service throttling (too many ops) and catastrophic
3742
+ // failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
3743
+ // these issues.
3744
+ // Cons:
3745
+ // 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
3746
+ // This change creates new possibility of a lot of newly created data stores never being referenced
3747
+ // because client died before it had a change to submit the rest of the ops. This will create more
3748
+ // garbage that needs to be collected leveraging GC (Garbage Collection) feature.
3749
+ // 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
3750
+ // today as rollback can't undo creation of data store. To some extent not sending them is a bigger
3751
+ // issue than sending.
3752
+ // Please note that this does not change file format, so it can be disabled in the future if this
3753
+ // optimization no longer makes sense (for example, batch compression may make it less appealing).
3754
+ if (
3755
+ this.currentlyBatching() &&
3756
+ type === ContainerMessageType.Attach &&
3757
+ this.disableAttachReorder !== true
3758
+ ) {
3759
+ this.outbox.submitAttach(message);
3760
+ } else if (type === ContainerMessageType.BlobAttach) {
3761
+ // BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
3762
+ this.outbox.submitBlobAttach(message);
3763
+ } else {
3764
+ this.outbox.submit(message);
3765
+ }
3564
3766
  }
3565
3767
 
3566
3768
  if (!this.currentlyBatching()) {
@@ -3702,14 +3904,18 @@ export class ContainerRuntime
3702
3904
  localOpMetadata: unknown,
3703
3905
  opMetadata: Record<string, unknown> | undefined,
3704
3906
  ) {
3907
+ assert(
3908
+ !this.isSummarizerClient,
3909
+ 0x8f2 /* Summarizer never reconnects so should never resubmit */,
3910
+ );
3705
3911
  switch (message.type) {
3706
3912
  case ContainerMessageType.FluidDataStoreOp:
3913
+ case ContainerMessageType.Attach:
3914
+ case ContainerMessageType.Alias:
3707
3915
  // For Operations, call resubmitDataStoreOp which will find the right store
3708
3916
  // and trigger resubmission on it.
3709
- this.dataStores.resubmitDataStoreOp(message.contents, localOpMetadata);
3917
+ this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
3710
3918
  break;
3711
- case ContainerMessageType.Attach:
3712
- case ContainerMessageType.Alias:
3713
3919
  case ContainerMessageType.IdAllocation: {
3714
3920
  this.submit(message, localOpMetadata);
3715
3921
  break;
@@ -3723,13 +3929,14 @@ export class ContainerRuntime
3723
3929
  this.submit(message);
3724
3930
  break;
3725
3931
  case ContainerMessageType.GC:
3726
- // GC op is only sent in summarizer which should never reconnect.
3727
- throw new LoggingError("GC op not expected to be resubmitted in summarizer");
3932
+ this.submit(message);
3933
+ break;
3728
3934
  default: {
3729
3935
  // This case should be very rare - it would imply an op was stashed from a
3730
- // future version of runtime code and now is being applied on an older version
3936
+ // future version of runtime code and now is being applied on an older version.
3731
3937
  const compatBehavior = message.compatDetails?.behavior;
3732
3938
  if (compatBehaviorAllowsMessageType(message.type, compatBehavior)) {
3939
+ // We do not ultimately resubmit it, to be consistent with this version of the code.
3733
3940
  this.logger.sendTelemetryEvent({
3734
3941
  eventName: "resubmitUnrecognizedMessageTypeAllowed",
3735
3942
  messageDetails: { type: message.type, compatBehavior },
@@ -3760,7 +3967,7 @@ export class ContainerRuntime
3760
3967
  case ContainerMessageType.FluidDataStoreOp:
3761
3968
  // For operations, call rollbackDataStoreOp which will find the right store
3762
3969
  // and trigger rollback on it.
3763
- this.dataStores.rollbackDataStoreOp(contents, localOpMetadata);
3970
+ this.channelCollection.rollback(type, contents, localOpMetadata);
3764
3971
  break;
3765
3972
  default:
3766
3973
  // Don't check message.compatDetails because this is for rolling back a local op so the type will be known
@@ -3786,7 +3993,7 @@ export class ContainerRuntime
3786
3993
  * and then close as the current main client is likely to be re-elected as the parent summarizer again.
3787
3994
  */
3788
3995
  if (!result.isSummaryTracked && result.isSummaryNewer) {
3789
- const fetchResult = await this.fetchLatestSnapshotFromStorage(
3996
+ await this.fetchLatestSnapshotFromStorage(
3790
3997
  summaryLogger,
3791
3998
  {
3792
3999
  eventName: "RefreshLatestSummaryAckFetch",
@@ -3796,32 +4003,7 @@ export class ContainerRuntime
3796
4003
  readAndParseBlob,
3797
4004
  );
3798
4005
 
3799
- /**
3800
- * If the fetched snapshot is older than the one for which the ack was received, close the container.
3801
- * This should never happen because an ack should be sent after the latest summary is updated in the server.
3802
- * However, there are couple of scenarios where it's possible:
3803
- * 1. A file was modified externally resulting in modifying the snapshot's sequence number. This can lead to
3804
- * the document being unusable and we should not proceed.
3805
- * 2. The server DB failed after the ack was sent which may delete the corresponding snapshot. Ideally, in
3806
- * such cases, the file will be rolled back along with the ack and we will eventually reach a consistent
3807
- * state.
3808
- */
3809
- if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
3810
- const error = DataProcessingError.create(
3811
- "Fetched snapshot is older than the received ack",
3812
- "RefreshLatestSummaryAck",
3813
- undefined /* sequencedMessage */,
3814
- {
3815
- ackHandle,
3816
- summaryRefSeq,
3817
- fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
3818
- },
3819
- );
3820
- this.disposeFn(error);
3821
- throw error;
3822
- }
3823
-
3824
- await this.closeStaleSummarizer("RefreshLatestSummaryAckFetch");
4006
+ await this.closeStaleSummarizer();
3825
4007
  return;
3826
4008
  }
3827
4009
 
@@ -3850,7 +4032,7 @@ export class ContainerRuntime
3850
4032
  readAndParseBlob,
3851
4033
  );
3852
4034
 
3853
- await this.closeStaleSummarizer("RefreshLatestSummaryFromServerFetch");
4035
+ await this.closeStaleSummarizer();
3854
4036
 
3855
4037
  return {
3856
4038
  stage: "base",
@@ -3860,7 +4042,7 @@ export class ContainerRuntime
3860
4042
  };
3861
4043
  }
3862
4044
 
3863
- private async closeStaleSummarizer(codePath: string): Promise<void> {
4045
+ private async closeStaleSummarizer(): Promise<void> {
3864
4046
  // Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
3865
4047
  await delay(this.closeSummarizerDelayMs);
3866
4048
  this._summarizer?.stop("latestSummaryStateStale");
@@ -3874,7 +4056,7 @@ export class ContainerRuntime
3874
4056
  */
3875
4057
  private async fetchLatestSnapshotFromStorage(
3876
4058
  logger: ITelemetryLoggerExt,
3877
- event: ITelemetryGenericEvent,
4059
+ event: ITelemetryGenericEventExt,
3878
4060
  readAndParseBlob: ReadAndParseBlob,
3879
4061
  ): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
3880
4062
  return PerformanceEvent.timedExecAsync(
@@ -3925,50 +4107,65 @@ export class ContainerRuntime
3925
4107
  );
3926
4108
  }
3927
4109
 
3928
- public async getPendingLocalState(props?: IGetPendingLocalStateProps): Promise<unknown> {
3929
- return PerformanceEvent.timedExecAsync(
3930
- this.mc.logger,
3931
- {
3932
- eventName: "getPendingLocalState",
3933
- notifyImminentClosure: props?.notifyImminentClosure,
3934
- },
3935
- async (event) => {
3936
- this.verifyNotClosed();
3937
- // in case imminentClosure is set to true by future code, we don't
3938
- // try to change its value
3939
- if (!this.imminentClosure) {
3940
- this.imminentClosure = props?.notifyImminentClosure ?? this.imminentClosure;
3941
- }
3942
- const stopBlobAttachingSignal = props?.stopBlobAttachingSignal;
3943
- if (this._orderSequentiallyCalls !== 0) {
3944
- throw new UsageError("can't get state during orderSequentially");
3945
- }
3946
- // Flush pending batch.
3947
- // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
3948
- // to close current batch.
3949
- this.flush();
3950
- const pendingAttachmentBlobs = this.imminentClosure
3951
- ? await this.blobManager.attachAndGetPendingBlobs(stopBlobAttachingSignal)
3952
- : undefined;
3953
- const pending = this.pendingStateManager.getLocalState();
3954
- if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
3955
- return; // no pending state to save
3956
- }
4110
+ public getPendingLocalState(props?: IGetPendingLocalStateProps): unknown {
4111
+ this.verifyNotClosed();
4112
+
4113
+ if (this._orderSequentiallyCalls !== 0) {
4114
+ throw new UsageError("can't get state during orderSequentially");
4115
+ }
4116
+ this.imminentClosure ||= props?.notifyImminentClosure ?? false;
4117
+
4118
+ const getSyncState = (
4119
+ pendingAttachmentBlobs?: IPendingBlobs,
4120
+ ): IPendingRuntimeState | undefined => {
4121
+ const pending = this.pendingStateManager.getLocalState();
4122
+ if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
4123
+ return; // no pending state to save
4124
+ }
3957
4125
 
3958
- const pendingIdCompressorState = this.idCompressor?.serialize(true);
4126
+ const pendingIdCompressorState = this._idCompressor?.serialize(true);
3959
4127
 
3960
- const pendingState: IPendingRuntimeState = {
3961
- pending,
3962
- pendingAttachmentBlobs,
3963
- pendingIdCompressorState,
3964
- };
3965
- event.end({
3966
- attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
3967
- pendingOpsSize: pending?.pendingStates.length,
3968
- });
3969
- return pendingState;
3970
- },
3971
- );
4128
+ return {
4129
+ pending,
4130
+ pendingIdCompressorState,
4131
+ pendingAttachmentBlobs,
4132
+ sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
4133
+ };
4134
+ };
4135
+ const perfEvent = {
4136
+ eventName: "getPendingLocalState",
4137
+ notifyImminentClosure: props?.notifyImminentClosure,
4138
+ };
4139
+ const logAndReturnPendingState = (
4140
+ event: PerformanceEvent,
4141
+ pendingState?: IPendingRuntimeState,
4142
+ ) => {
4143
+ event.end({
4144
+ attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
4145
+ pendingOpsSize: pendingState?.pending?.pendingStates.length,
4146
+ });
4147
+ return pendingState;
4148
+ };
4149
+
4150
+ // Flush pending batch.
4151
+ // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
4152
+ // to close current batch.
4153
+ this.flush();
4154
+
4155
+ return props?.notifyImminentClosure === true
4156
+ ? PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) =>
4157
+ logAndReturnPendingState(
4158
+ event,
4159
+ getSyncState(
4160
+ await this.blobManager.attachAndGetPendingBlobs(
4161
+ props?.stopBlobAttachingSignal,
4162
+ ),
4163
+ ),
4164
+ ),
4165
+ )
4166
+ : PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) =>
4167
+ logAndReturnPendingState(event, getSyncState()),
4168
+ );
3972
4169
  }
3973
4170
 
3974
4171
  public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {