@fluidframework/container-runtime 2.0.0-internal.5.3.2 → 2.0.0-internal.6.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 (290) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dist/batchTracker.d.ts +2 -1
  3. package/dist/batchTracker.d.ts.map +1 -1
  4. package/dist/batchTracker.js +1 -1
  5. package/dist/batchTracker.js.map +1 -1
  6. package/dist/blobManager.d.ts +13 -2
  7. package/dist/blobManager.d.ts.map +1 -1
  8. package/dist/blobManager.js +103 -25
  9. package/dist/blobManager.js.map +1 -1
  10. package/dist/connectionTelemetry.d.ts.map +1 -1
  11. package/dist/connectionTelemetry.js +12 -4
  12. package/dist/connectionTelemetry.js.map +1 -1
  13. package/dist/containerRuntime.d.ts +69 -22
  14. package/dist/containerRuntime.d.ts.map +1 -1
  15. package/dist/containerRuntime.js +344 -238
  16. package/dist/containerRuntime.js.map +1 -1
  17. package/dist/dataStore.js +11 -2
  18. package/dist/dataStore.js.map +1 -1
  19. package/dist/dataStoreContext.d.ts +1 -1
  20. package/dist/dataStoreContext.d.ts.map +1 -1
  21. package/dist/dataStoreContext.js +40 -44
  22. package/dist/dataStoreContext.js.map +1 -1
  23. package/dist/dataStoreContexts.js +1 -1
  24. package/dist/dataStoreContexts.js.map +1 -1
  25. package/dist/dataStores.d.ts +21 -5
  26. package/dist/dataStores.d.ts.map +1 -1
  27. package/dist/dataStores.js +102 -58
  28. package/dist/dataStores.js.map +1 -1
  29. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  30. package/dist/deltaManagerSummarizerProxy.js +2 -0
  31. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  32. package/dist/deltaScheduler.d.ts.map +1 -1
  33. package/dist/deltaScheduler.js +5 -5
  34. package/dist/deltaScheduler.js.map +1 -1
  35. package/dist/gc/garbageCollection.d.ts.map +1 -1
  36. package/dist/gc/garbageCollection.js +29 -25
  37. package/dist/gc/garbageCollection.js.map +1 -1
  38. package/dist/gc/gcConfigs.js +13 -11
  39. package/dist/gc/gcConfigs.js.map +1 -1
  40. package/dist/gc/gcHelpers.d.ts +1 -0
  41. package/dist/gc/gcHelpers.d.ts.map +1 -1
  42. package/dist/gc/gcHelpers.js +5 -6
  43. package/dist/gc/gcHelpers.js.map +1 -1
  44. package/dist/gc/gcSummaryStateTracker.js +4 -6
  45. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  46. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  47. package/dist/gc/gcTelemetry.js +44 -33
  48. package/dist/gc/gcTelemetry.js.map +1 -1
  49. package/dist/id-compressor/idCompressor.d.ts +3 -3
  50. package/dist/id-compressor/idCompressor.d.ts.map +1 -1
  51. package/dist/id-compressor/idCompressor.js +52 -52
  52. package/dist/id-compressor/idCompressor.js.map +1 -1
  53. package/dist/id-compressor/idRange.js +2 -2
  54. package/dist/id-compressor/idRange.js.map +1 -1
  55. package/dist/id-compressor/sessionIdNormalizer.js +11 -16
  56. package/dist/id-compressor/sessionIdNormalizer.js.map +1 -1
  57. package/dist/index.d.ts +1 -1
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/opLifecycle/batchManager.js +10 -6
  61. package/dist/opLifecycle/batchManager.js.map +1 -1
  62. package/dist/opLifecycle/opCompressor.d.ts +2 -2
  63. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  64. package/dist/opLifecycle/opCompressor.js +7 -2
  65. package/dist/opLifecycle/opCompressor.js.map +1 -1
  66. package/dist/opLifecycle/opDecompressor.d.ts +2 -2
  67. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  68. package/dist/opLifecycle/opDecompressor.js +12 -10
  69. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  70. package/dist/opLifecycle/opGroupingManager.js +13 -5
  71. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  72. package/dist/opLifecycle/opSplitter.d.ts +2 -2
  73. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  74. package/dist/opLifecycle/opSplitter.js +11 -7
  75. package/dist/opLifecycle/opSplitter.js.map +1 -1
  76. package/dist/opLifecycle/outbox.d.ts +6 -5
  77. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  78. package/dist/opLifecycle/outbox.js +6 -14
  79. package/dist/opLifecycle/outbox.js.map +1 -1
  80. package/dist/opLifecycle/remoteMessageProcessor.d.ts +6 -1
  81. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  82. package/dist/opLifecycle/remoteMessageProcessor.js +8 -2
  83. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  84. package/dist/opProperties.js +1 -2
  85. package/dist/opProperties.js.map +1 -1
  86. package/dist/packageVersion.d.ts +1 -1
  87. package/dist/packageVersion.js +1 -1
  88. package/dist/packageVersion.js.map +1 -1
  89. package/dist/pendingStateManager.d.ts +6 -3
  90. package/dist/pendingStateManager.d.ts.map +1 -1
  91. package/dist/pendingStateManager.js +41 -32
  92. package/dist/pendingStateManager.js.map +1 -1
  93. package/dist/scheduleManager.d.ts.map +1 -1
  94. package/dist/scheduleManager.js +15 -11
  95. package/dist/scheduleManager.js.map +1 -1
  96. package/dist/summary/orderedClientElection.d.ts +2 -1
  97. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  98. package/dist/summary/orderedClientElection.js +18 -19
  99. package/dist/summary/orderedClientElection.js.map +1 -1
  100. package/dist/summary/runningSummarizer.d.ts +3 -5
  101. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  102. package/dist/summary/runningSummarizer.js +42 -66
  103. package/dist/summary/runningSummarizer.js.map +1 -1
  104. package/dist/summary/summarizer.js +5 -8
  105. package/dist/summary/summarizer.js.map +1 -1
  106. package/dist/summary/summarizerClientElection.js +5 -9
  107. package/dist/summary/summarizerClientElection.js.map +1 -1
  108. package/dist/summary/summarizerHeuristics.js +8 -12
  109. package/dist/summary/summarizerHeuristics.js.map +1 -1
  110. package/dist/summary/summarizerNode/summarizerNode.d.ts +5 -5
  111. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  112. package/dist/summary/summarizerNode/summarizerNode.js +26 -22
  113. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  114. package/dist/summary/summarizerNode/summarizerNodeUtils.js +2 -4
  115. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  116. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
  117. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  118. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +13 -16
  119. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  120. package/dist/summary/summaryCollection.js +3 -5
  121. package/dist/summary/summaryCollection.js.map +1 -1
  122. package/dist/summary/summaryFormat.js +1 -2
  123. package/dist/summary/summaryFormat.js.map +1 -1
  124. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  125. package/dist/summary/summaryGenerator.js +67 -21
  126. package/dist/summary/summaryGenerator.js.map +1 -1
  127. package/dist/summary/summaryManager.d.ts +2 -3
  128. package/dist/summary/summaryManager.d.ts.map +1 -1
  129. package/dist/summary/summaryManager.js +9 -7
  130. package/dist/summary/summaryManager.js.map +1 -1
  131. package/lib/batchTracker.d.ts +2 -1
  132. package/lib/batchTracker.d.ts.map +1 -1
  133. package/lib/batchTracker.js +2 -2
  134. package/lib/batchTracker.js.map +1 -1
  135. package/lib/blobManager.d.ts +13 -2
  136. package/lib/blobManager.d.ts.map +1 -1
  137. package/lib/blobManager.js +103 -25
  138. package/lib/blobManager.js.map +1 -1
  139. package/lib/connectionTelemetry.d.ts.map +1 -1
  140. package/lib/connectionTelemetry.js +13 -5
  141. package/lib/connectionTelemetry.js.map +1 -1
  142. package/lib/containerRuntime.d.ts +69 -22
  143. package/lib/containerRuntime.d.ts.map +1 -1
  144. package/lib/containerRuntime.js +343 -238
  145. package/lib/containerRuntime.js.map +1 -1
  146. package/lib/dataStore.js +11 -2
  147. package/lib/dataStore.js.map +1 -1
  148. package/lib/dataStoreContext.d.ts +1 -1
  149. package/lib/dataStoreContext.d.ts.map +1 -1
  150. package/lib/dataStoreContext.js +42 -46
  151. package/lib/dataStoreContext.js.map +1 -1
  152. package/lib/dataStoreContexts.js +2 -2
  153. package/lib/dataStoreContexts.js.map +1 -1
  154. package/lib/dataStores.d.ts +21 -5
  155. package/lib/dataStores.d.ts.map +1 -1
  156. package/lib/dataStores.js +103 -59
  157. package/lib/dataStores.js.map +1 -1
  158. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
  159. package/lib/deltaManagerSummarizerProxy.js +2 -0
  160. package/lib/deltaManagerSummarizerProxy.js.map +1 -1
  161. package/lib/deltaScheduler.d.ts.map +1 -1
  162. package/lib/deltaScheduler.js +6 -6
  163. package/lib/deltaScheduler.js.map +1 -1
  164. package/lib/gc/garbageCollection.d.ts.map +1 -1
  165. package/lib/gc/garbageCollection.js +30 -26
  166. package/lib/gc/garbageCollection.js.map +1 -1
  167. package/lib/gc/gcConfigs.js +13 -11
  168. package/lib/gc/gcConfigs.js.map +1 -1
  169. package/lib/gc/gcHelpers.d.ts +1 -0
  170. package/lib/gc/gcHelpers.d.ts.map +1 -1
  171. package/lib/gc/gcHelpers.js +5 -6
  172. package/lib/gc/gcHelpers.js.map +1 -1
  173. package/lib/gc/gcSummaryStateTracker.js +4 -6
  174. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  175. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  176. package/lib/gc/gcTelemetry.js +45 -34
  177. package/lib/gc/gcTelemetry.js.map +1 -1
  178. package/lib/id-compressor/idCompressor.d.ts +3 -3
  179. package/lib/id-compressor/idCompressor.d.ts.map +1 -1
  180. package/lib/id-compressor/idCompressor.js +52 -52
  181. package/lib/id-compressor/idCompressor.js.map +1 -1
  182. package/lib/id-compressor/idRange.js +2 -2
  183. package/lib/id-compressor/idRange.js.map +1 -1
  184. package/lib/id-compressor/sessionIdNormalizer.js +11 -16
  185. package/lib/id-compressor/sessionIdNormalizer.js.map +1 -1
  186. package/lib/index.d.ts +1 -1
  187. package/lib/index.d.ts.map +1 -1
  188. package/lib/index.js.map +1 -1
  189. package/lib/opLifecycle/batchManager.js +10 -6
  190. package/lib/opLifecycle/batchManager.js.map +1 -1
  191. package/lib/opLifecycle/opCompressor.d.ts +2 -2
  192. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  193. package/lib/opLifecycle/opCompressor.js +8 -3
  194. package/lib/opLifecycle/opCompressor.js.map +1 -1
  195. package/lib/opLifecycle/opDecompressor.d.ts +2 -2
  196. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  197. package/lib/opLifecycle/opDecompressor.js +13 -11
  198. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  199. package/lib/opLifecycle/opGroupingManager.js +13 -5
  200. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  201. package/lib/opLifecycle/opSplitter.d.ts +2 -2
  202. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  203. package/lib/opLifecycle/opSplitter.js +12 -8
  204. package/lib/opLifecycle/opSplitter.js.map +1 -1
  205. package/lib/opLifecycle/outbox.d.ts +6 -5
  206. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  207. package/lib/opLifecycle/outbox.js +7 -15
  208. package/lib/opLifecycle/outbox.js.map +1 -1
  209. package/lib/opLifecycle/remoteMessageProcessor.d.ts +6 -1
  210. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  211. package/lib/opLifecycle/remoteMessageProcessor.js +8 -2
  212. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  213. package/lib/opProperties.js +1 -2
  214. package/lib/opProperties.js.map +1 -1
  215. package/lib/packageVersion.d.ts +1 -1
  216. package/lib/packageVersion.js +1 -1
  217. package/lib/packageVersion.js.map +1 -1
  218. package/lib/pendingStateManager.d.ts +6 -3
  219. package/lib/pendingStateManager.d.ts.map +1 -1
  220. package/lib/pendingStateManager.js +41 -32
  221. package/lib/pendingStateManager.js.map +1 -1
  222. package/lib/scheduleManager.d.ts.map +1 -1
  223. package/lib/scheduleManager.js +16 -12
  224. package/lib/scheduleManager.js.map +1 -1
  225. package/lib/summary/orderedClientElection.d.ts +2 -1
  226. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  227. package/lib/summary/orderedClientElection.js +19 -20
  228. package/lib/summary/orderedClientElection.js.map +1 -1
  229. package/lib/summary/runningSummarizer.d.ts +3 -5
  230. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  231. package/lib/summary/runningSummarizer.js +43 -67
  232. package/lib/summary/runningSummarizer.js.map +1 -1
  233. package/lib/summary/summarizer.js +6 -9
  234. package/lib/summary/summarizer.js.map +1 -1
  235. package/lib/summary/summarizerClientElection.js +5 -9
  236. package/lib/summary/summarizerClientElection.js.map +1 -1
  237. package/lib/summary/summarizerHeuristics.js +8 -12
  238. package/lib/summary/summarizerHeuristics.js.map +1 -1
  239. package/lib/summary/summarizerNode/summarizerNode.d.ts +5 -5
  240. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  241. package/lib/summary/summarizerNode/summarizerNode.js +27 -23
  242. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  243. package/lib/summary/summarizerNode/summarizerNodeUtils.js +2 -4
  244. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  245. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
  246. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  247. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +14 -17
  248. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  249. package/lib/summary/summaryCollection.js +3 -5
  250. package/lib/summary/summaryCollection.js.map +1 -1
  251. package/lib/summary/summaryFormat.js +1 -2
  252. package/lib/summary/summaryFormat.js.map +1 -1
  253. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  254. package/lib/summary/summaryGenerator.js +68 -22
  255. package/lib/summary/summaryGenerator.js.map +1 -1
  256. package/lib/summary/summaryManager.d.ts +2 -3
  257. package/lib/summary/summaryManager.d.ts.map +1 -1
  258. package/lib/summary/summaryManager.js +10 -8
  259. package/lib/summary/summaryManager.js.map +1 -1
  260. package/package.json +30 -18
  261. package/src/batchTracker.ts +4 -3
  262. package/src/blobManager.ts +113 -15
  263. package/src/connectionTelemetry.ts +7 -3
  264. package/src/containerRuntime.ts +354 -194
  265. package/src/dataStore.ts +10 -1
  266. package/src/dataStoreContext.ts +31 -33
  267. package/src/dataStoreContexts.ts +2 -2
  268. package/src/dataStores.ts +108 -71
  269. package/src/deltaManagerSummarizerProxy.ts +2 -0
  270. package/src/deltaScheduler.ts +6 -10
  271. package/src/gc/garbageCollection.ts +13 -8
  272. package/src/gc/gcHelpers.ts +1 -0
  273. package/src/gc/gcTelemetry.ts +13 -10
  274. package/src/id-compressor/idCompressor.ts +6 -5
  275. package/src/index.ts +0 -1
  276. package/src/opLifecycle/opCompressor.ts +4 -3
  277. package/src/opLifecycle/opDecompressor.ts +4 -3
  278. package/src/opLifecycle/opSplitter.ts +4 -3
  279. package/src/opLifecycle/outbox.ts +13 -25
  280. package/src/opLifecycle/remoteMessageProcessor.ts +8 -2
  281. package/src/packageVersion.ts +1 -1
  282. package/src/pendingStateManager.ts +34 -25
  283. package/src/scheduleManager.ts +2 -2
  284. package/src/summary/orderedClientElection.ts +4 -3
  285. package/src/summary/runningSummarizer.ts +18 -44
  286. package/src/summary/summarizer.ts +2 -2
  287. package/src/summary/summarizerNode/summarizerNode.ts +13 -15
  288. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +8 -7
  289. package/src/summary/summaryGenerator.ts +6 -2
  290. package/src/summary/summaryManager.ts +9 -5
@@ -18,19 +18,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
18
18
  __setModuleDefault(result, mod);
19
19
  return result;
20
20
  };
21
- var __rest = (this && this.__rest) || function (s, e) {
22
- var t = {};
23
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
24
- t[p] = s[p];
25
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
26
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
27
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
28
- t[p[i]] = s[p[i]];
29
- }
30
- return t;
31
- };
32
21
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.TombstoneResponseHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
22
+ exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.TombstoneResponseHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
34
23
  const container_definitions_1 = require("@fluidframework/container-definitions");
35
24
  const common_utils_1 = require("@fluidframework/common-utils");
36
25
  const core_utils_1 = require("@fluidframework/core-utils");
@@ -137,7 +126,7 @@ const defaultChunkSizeInBytes = 204800;
137
126
  * of the current system, we should close the summarizer and let it recover.
138
127
  * This delay's goal is to prevent tight restart loops
139
128
  */
140
- const defaultCloseSummarizerDelayMs = 10000; // 10 seconds
129
+ const defaultCloseSummarizerDelayMs = 5000; // 5 seconds
141
130
  /**
142
131
  * @deprecated - use ContainerRuntimeMessage instead
143
132
  */
@@ -174,10 +163,25 @@ function getDeviceSpec() {
174
163
  };
175
164
  }
176
165
  }
177
- catch (_a) { }
166
+ catch { }
178
167
  return {};
179
168
  }
180
169
  exports.getDeviceSpec = getDeviceSpec;
170
+ /**
171
+ * Older loader doesn't have a submitBatchFn member, this is the older way of submitting a batch.
172
+ * Rather than exposing the submitFn (now deprecated) and IDeltaManager (dangerous to hand out) to the Outbox,
173
+ * we can provide a partially-applied function to keep those items private to the ContainerRuntime.
174
+ */
175
+ const makeLegacySendBatchFn = (submitFn, deltaManager) => (batch) => {
176
+ for (const message of batch.content) {
177
+ submitFn(protocol_definitions_1.MessageType.Operation,
178
+ // For back-compat (submitFn only works on deserialized content)
179
+ message.contents === undefined ? undefined : JSON.parse(message.contents), true, // batch
180
+ message.metadata);
181
+ }
182
+ deltaManager.flush();
183
+ };
184
+ exports.makeLegacySendBatchFn = makeLegacySendBatchFn;
181
185
  /**
182
186
  * Represents the runtime of the container. Contains helper functions/state of the container.
183
187
  * It will define the store level mappings.
@@ -186,11 +190,13 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
186
190
  /**
187
191
  * @internal
188
192
  */
189
- constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, idCompressor, requestHandler, summaryConfiguration, initializeEntryPoint) {
190
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
191
- if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, exports.DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
193
+ constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, idCompressor, requestHandler, summaryConfiguration = {
194
+ // the defaults
195
+ ...exports.DefaultSummaryConfiguration,
196
+ // the runtime configuration overrides
197
+ ...runtimeOptions.summaryOptions?.summaryConfigOverrides,
198
+ }, initializeEntryPoint) {
192
199
  super();
193
- this.context = context;
194
200
  this.registry = registry;
195
201
  this.runtimeOptions = runtimeOptions;
196
202
  this.containerScope = containerScope;
@@ -220,7 +226,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
220
226
  trackingSignalSequenceNumber: undefined,
221
227
  };
222
228
  this.summarizeOnDemand = (...args) => {
223
- if (this.clientDetails.type === summary_1.summarizerClientType) {
229
+ if (this.isSummarizerClient) {
224
230
  return this.summarizer.summarizeOnDemand(...args);
225
231
  }
226
232
  else if (this.summaryManager !== undefined) {
@@ -234,7 +240,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
234
240
  }
235
241
  };
236
242
  this.enqueueSummarize = (...args) => {
237
- if (this.clientDetails.type === summary_1.summarizerClientType) {
243
+ if (this.isSummarizerClient) {
238
244
  return this.summarizer.enqueueSummarize(...args);
239
245
  }
240
246
  else if (this.summaryManager !== undefined) {
@@ -247,23 +253,56 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
247
253
  throw new container_utils_1.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
248
254
  }
249
255
  };
250
- this.innerDeltaManager = context.deltaManager;
251
- this.deltaManager = new deltaManagerSummarizerProxy_1.DeltaManagerSummarizerProxy(context.deltaManager);
252
- this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(this.logger, "ContainerRuntime"));
256
+ const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
257
+ this.innerDeltaManager = deltaManager;
258
+ this.deltaManager = new deltaManagerSummarizerProxy_1.DeltaManagerSummarizerProxy(this.innerDeltaManager);
259
+ // Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
260
+ // This makes ContainerRuntime the final gatekeeper for outgoing messages.
261
+ this.submitFn = submitFn;
262
+ this.submitBatchFn = submitBatchFn;
263
+ this.submitSummaryFn = submitSummaryFn;
264
+ this.submitSignalFn = submitSignalFn;
265
+ this.options = options;
266
+ this.clientDetails = clientDetails;
267
+ this.isSummarizerClient = this.clientDetails.type === summary_1.summarizerClientType;
268
+ this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
269
+ this._getClientId = () => context.clientId;
270
+ this._getAttachState = () => context.attachState;
271
+ this.getAbsoluteUrl = async (relativeUrl) => {
272
+ if (context.getAbsoluteUrl === undefined) {
273
+ throw new Error("Driver does not implement getAbsoluteUrl");
274
+ }
275
+ if (this.attachState !== container_definitions_1.AttachState.Attached) {
276
+ return undefined;
277
+ }
278
+ return context.getAbsoluteUrl(relativeUrl);
279
+ };
280
+ // TODO: Consider that the Container could just listen to these events itself, or even more appropriately maybe the
281
+ // customer should observe dirty state on the runtime (the owner of dirty state) directly, rather than on the IContainer.
282
+ this.on("dirty", () => context.updateDirtyContainerState(true));
283
+ this.on("saved", () => context.updateDirtyContainerState(false));
284
+ // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
285
+ this.disposeFn = disposeFn ?? closeFn;
286
+ // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
287
+ this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
288
+ this.mc = (0, telemetry_utils_1.createChildMonitoringContext)({
289
+ logger: this.logger,
290
+ namespace: "ContainerRuntime",
291
+ });
253
292
  let loadSummaryNumber;
254
293
  // Get the container creation metadata. For new container, we initialize these. For existing containers,
255
294
  // get the values from the metadata blob.
256
295
  if (existing) {
257
296
  this.createContainerMetadata = {
258
- createContainerRuntimeVersion: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerRuntimeVersion,
259
- createContainerTimestamp: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerTimestamp,
297
+ createContainerRuntimeVersion: metadata?.createContainerRuntimeVersion,
298
+ createContainerTimestamp: metadata?.createContainerTimestamp,
260
299
  };
261
300
  // summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
262
301
  // the count is reset to 0.
263
- loadSummaryNumber = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _b !== void 0 ? _b : 0;
302
+ loadSummaryNumber = metadata?.summaryNumber ?? 0;
264
303
  // Enabling the IdCompressor is a one-way operation and we only want to
265
304
  // allow new containers to turn it on
266
- this.idCompressorEnabled = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.idCompressorEnabled) !== null && _c !== void 0 ? _c : false;
305
+ this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
267
306
  }
268
307
  else {
269
308
  this.createContainerMetadata = {
@@ -272,24 +311,27 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
272
311
  };
273
312
  loadSummaryNumber = 0;
274
313
  this.idCompressorEnabled =
275
- (_d = this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) !== null && _d !== void 0 ? _d : idCompressor !== undefined;
314
+ this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
315
+ idCompressor !== undefined;
276
316
  }
277
317
  this.nextSummaryNumber = loadSummaryNumber + 1;
278
- this.messageAtLastSummary = metadata === null || metadata === void 0 ? void 0 : metadata.message;
279
- this._connected = this.context.connected;
280
- this.gcTombstoneEnforcementAllowed = (0, gc_1.shouldAllowGcTombstoneEnforcement)((_e = metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix) === null || _e === void 0 ? void 0 : _e.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gc_1.gcTombstoneGenerationOptionName] /* current */);
318
+ this.messageAtLastSummary = metadata?.message;
319
+ // Note that we only need to pull the *initial* connected state from the context.
320
+ // Later updates come through calls to setConnectionState.
321
+ this._connected = connected;
322
+ this.gcTombstoneEnforcementAllowed = (0, gc_1.shouldAllowGcTombstoneEnforcement)(metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gc_1.gcTombstoneGenerationOptionName] /* current */);
281
323
  this.mc.logger.sendTelemetryEvent({
282
324
  eventName: "GCFeatureMatrix",
283
- metadataValue: JSON.stringify(metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix),
325
+ metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
284
326
  inputs: JSON.stringify({
285
327
  gcOptions_gcTombstoneGeneration: this.runtimeOptions.gcOptions[gc_1.gcTombstoneGenerationOptionName],
286
328
  }),
287
329
  });
288
- this.telemetryDocumentId = (_f = metadata === null || metadata === void 0 ? void 0 : metadata.telemetryDocumentId) !== null && _f !== void 0 ? _f : (0, uuid_1.v4)();
330
+ this.telemetryDocumentId = metadata?.telemetryDocumentId ?? (0, uuid_1.v4)();
289
331
  this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
290
332
  const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
291
333
  const opGroupingManager = new opLifecycle_1.OpGroupingManager(this.groupedBatchingEnabled);
292
- const opSplitter = new opLifecycle_1.OpSplitter(chunks, this.context.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
334
+ const opSplitter = new opLifecycle_1.OpSplitter(chunks, this.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
293
335
  this.remoteMessageProcessor = new opLifecycle_1.RemoteMessageProcessor(opSplitter, new opLifecycle_1.OpDecompressor(this.mc.logger), opGroupingManager);
294
336
  this.handleContext = new containerHandleContext_1.ContainerFluidHandleContext("", this);
295
337
  if (this.summaryConfiguration.state === "enabled") {
@@ -308,9 +350,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
308
350
  this.idCompressor = idCompressor;
309
351
  }
310
352
  this.maxConsecutiveReconnects =
311
- (_g = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _g !== void 0 ? _g : this.defaultMaxConsecutiveReconnects;
353
+ this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
354
+ this.defaultMaxConsecutiveReconnects;
312
355
  if (runtimeOptions.flushMode === runtime_definitions_1.FlushModeExperimental.Async &&
313
- ((_h = context.supportedFeatures) === null || _h === void 0 ? void 0 : _h.get("referenceSequenceNumbers")) !== true) {
356
+ supportedFeatures?.get("referenceSequenceNumbers") !== true) {
314
357
  // The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
315
358
  this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
316
359
  this._flushMode = runtime_definitions_1.FlushMode.TurnBased;
@@ -318,8 +361,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
318
361
  else {
319
362
  this._flushMode = runtimeOptions.flushMode;
320
363
  }
321
- const pendingRuntimeState = context.pendingLocalState;
322
- const maxSnapshotCacheDurationMs = (_k = (_j = this._storage) === null || _j === void 0 ? void 0 : _j.policies) === null || _k === void 0 ? void 0 : _k.maximumCacheDurationMs;
364
+ const pendingRuntimeState = pendingLocalState;
365
+ const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
323
366
  if (maxSnapshotCacheDurationMs !== undefined &&
324
367
  maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
325
368
  // This is a runtime enforcement of what's already explicit in the policy's type itself,
@@ -330,27 +373,27 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
330
373
  this.garbageCollector = gc_1.GarbageCollector.create({
331
374
  runtime: this,
332
375
  gcOptions: this.runtimeOptions.gcOptions,
333
- baseSnapshot: context.baseSnapshot,
376
+ baseSnapshot,
334
377
  baseLogger: this.mc.logger,
335
378
  existing,
336
379
  metadata,
337
380
  createContainerMetadata: this.createContainerMetadata,
338
- isSummarizerClient: this.context.clientDetails.type === summary_1.summarizerClientType,
381
+ isSummarizerClient: this.isSummarizerClient,
339
382
  getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
340
- getLastSummaryTimestampMs: () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; },
383
+ getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
341
384
  readAndParseBlob: async (id) => (0, driver_utils_1.readAndParse)(this.storage, id),
342
385
  // GC runs in summarizer client and needs access to the real (non-proxy) active information. The proxy
343
386
  // delta manager would always return false for summarizer client.
344
387
  activeConnection: () => this.innerDeltaManager.active,
345
388
  });
346
389
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
347
- this.summarizerNode = (0, summary_1.createRootSummarizerNodeWithGC)(telemetry_utils_1.ChildLogger.create(this.logger, "SummarizerNode"),
390
+ this.summarizerNode = (0, summary_1.createRootSummarizerNodeWithGC)((0, telemetry_utils_1.createChildLogger)({ logger: this.logger, namespace: "SummarizerNode" }),
348
391
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
349
392
  async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
350
393
  // Latest change sequence number, no changes since summary applied yet
351
394
  loadedFromSequenceNumber,
352
395
  // Summary reference sequence number, undefined if no summary yet
353
- context.baseSnapshot ? loadedFromSequenceNumber : undefined, {
396
+ baseSnapshot !== undefined ? loadedFromSequenceNumber : undefined, {
354
397
  // Must set to false to prevent sending summary handle which would be pointing to
355
398
  // a summary with an older protocol state.
356
399
  canReuseHandle: false,
@@ -364,19 +407,19 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
364
407
  async (fullGC) => this.getGCDataInternal(fullGC),
365
408
  // Function to get the GC details from the base snapshot we loaded from.
366
409
  async () => this.garbageCollector.getBaseGCDetails());
367
- if (context.baseSnapshot) {
368
- this.summarizerNode.updateBaseSummaryState(context.baseSnapshot);
410
+ if (baseSnapshot) {
411
+ this.summarizerNode.updateBaseSummaryState(baseSnapshot);
369
412
  }
370
- this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
413
+ this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata), this, (attachMsg) => this.submit({ type: ContainerMessageType.Attach, contents: attachMsg }), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
371
414
  this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
372
415
  if (!this.disposed) {
373
- this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
416
+ this.submit({ type: ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
374
417
  localId,
375
418
  blobId,
376
419
  });
377
420
  }
378
- }, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs, (error) => this.closeFn(error));
379
- this.scheduleManager = new scheduleManager_1.ScheduleManager(context.deltaManager, this, () => this.clientId, telemetry_utils_1.ChildLogger.create(this.logger, "ScheduleManager"));
421
+ }, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState?.pendingAttachmentBlobs, (error) => this.closeFn(error));
422
+ this.scheduleManager = new scheduleManager_1.ScheduleManager(this.innerDeltaManager, this, () => this.clientId, (0, telemetry_utils_1.createChildLogger)({ logger: this.logger, namespace: "ScheduleManager" }));
380
423
  this.pendingStateManager = new pendingStateManager_1.PendingStateManager({
381
424
  applyStashedOp: this.applyStashedOp.bind(this),
382
425
  clientId: () => this.clientId,
@@ -384,7 +427,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
384
427
  connected: () => this.connected,
385
428
  reSubmit: this.reSubmit.bind(this),
386
429
  reSubmitBatch: this.reSubmitBatch.bind(this),
387
- }, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending);
430
+ isActiveConnection: () => this.innerDeltaManager.active,
431
+ }, pendingRuntimeState?.pending, this.logger);
388
432
  const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
389
433
  const compressionOptions = disableCompression === true
390
434
  ? {
@@ -393,10 +437,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
393
437
  }
394
438
  : runtimeOptions.compressionOptions;
395
439
  const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
440
+ const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(this.submitFn, this.innerDeltaManager);
396
441
  this.outbox = new opLifecycle_1.Outbox({
397
442
  shouldSend: () => this.canSendOps(),
398
443
  pendingStateManager: this.pendingStateManager,
399
- containerContext: this.context,
444
+ submitBatchFn: this.submitBatchFn,
445
+ legacySendBatchFn,
400
446
  compressor: new opLifecycle_1.OpCompressor(this.mc.logger),
401
447
  splitter: opSplitter,
402
448
  config: {
@@ -415,44 +461,53 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
415
461
  opReentrancy: () => this.ensureNoDataModelChangesCalls > 0,
416
462
  closeContainer: this.closeFn,
417
463
  });
418
- this.context.quorum.on("removeMember", (clientId) => {
464
+ this._quorum = quorum;
465
+ this._quorum.on("removeMember", (clientId) => {
419
466
  this.remoteMessageProcessor.clearPartialMessagesFor(clientId);
420
467
  });
468
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
469
+ this._audience = audience;
421
470
  this.summaryStateUpdateMethod = this.mc.config.getString("Fluid.ContainerRuntime.Test.SummaryStateUpdateMethodV2");
422
471
  const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
423
- this.closeSummarizerDelayMs = closeSummarizerDelayOverride !== null && closeSummarizerDelayOverride !== void 0 ? closeSummarizerDelayOverride : defaultCloseSummarizerDelayMs;
472
+ this.closeSummarizerDelayMs = closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
424
473
  this.validateSummaryBeforeUpload =
425
- (_l = this.mc.config.getBoolean("Fluid.ContainerRuntime.Test.ValidateSummaryBeforeUpload")) !== null && _l !== void 0 ? _l : false;
474
+ this.mc.config.getBoolean("Fluid.ContainerRuntime.Test.ValidateSummaryBeforeUpload") ??
475
+ false;
426
476
  this.summaryCollection = new summary_1.SummaryCollection(this.deltaManager, this.logger);
427
477
  this.dirtyContainer =
428
- this.context.attachState !== container_definitions_1.AttachState.Attached ||
478
+ this.attachState !== container_definitions_1.AttachState.Attached ||
429
479
  this.pendingStateManager.hasPendingMessages();
430
- this.context.updateDirtyContainerState(this.dirtyContainer);
480
+ context.updateDirtyContainerState(this.dirtyContainer);
431
481
  if (this.summariesDisabled) {
432
482
  this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
433
483
  }
434
484
  else {
435
- const orderedClientLogger = telemetry_utils_1.ChildLogger.create(this.logger, "OrderedClientElection");
436
- const orderedClientCollection = new summary_1.OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
437
- const orderedClientElectionForSummarizer = new summary_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, summary_1.SummarizerClientElection.isClientEligible);
485
+ const orderedClientLogger = (0, telemetry_utils_1.createChildLogger)({
486
+ logger: this.logger,
487
+ namespace: "OrderedClientElection",
488
+ });
489
+ const orderedClientCollection = new summary_1.OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
490
+ const orderedClientElectionForSummarizer = new summary_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, summary_1.SummarizerClientElection.isClientEligible);
438
491
  this.summarizerClientElection = new summary_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
439
- if (this.context.clientDetails.type === summary_1.summarizerClientType) {
492
+ if (this.isSummarizerClient) {
440
493
  this._summarizer = new summary_1.Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => summary_1.RunWhileConnectedCoordinator.create(runtime,
441
494
  // Summarization runs in summarizer client and needs access to the real (non-proxy) active
442
495
  // information. The proxy delta manager would always return false for summarizer client.
443
496
  () => this.innerDeltaManager.active));
444
497
  }
445
- else if (summary_1.SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)) {
498
+ else if (summary_1.SummarizerClientElection.clientDetailsPermitElection(this.clientDetails)) {
446
499
  // Only create a SummaryManager and SummarizerClientElection
447
500
  // if summaries are enabled and we are not the summarizer client.
448
501
  const defaultAction = () => {
449
502
  if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
450
- this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
503
+ this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
451
504
  // unregister default to no log on every op after falling behind
452
505
  // and register summary ack handler to re-register this handler
453
506
  // after successful summary
454
507
  this.summaryCollection.once(protocol_definitions_1.MessageType.SummaryAck, () => {
455
- this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:CaughtUp" });
508
+ this.mc.logger.sendTelemetryEvent({
509
+ eventName: "SummaryStatus:CaughtUp",
510
+ });
456
511
  // we've caught up, so re-register the default action to monitor for
457
512
  // falling behind, and unregister ourself
458
513
  this.summaryCollection.on("default", defaultAction);
@@ -463,7 +518,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
463
518
  this.summaryCollection.on("default", defaultAction);
464
519
  // Create the SummaryManager and mark the initial state
465
520
  this.summaryManager = new summary_1.SummaryManager(this.summarizerClientElection, this, // IConnectedState
466
- this.summaryCollection, this.logger, this.formRequestSummarizerFn(this.context.loader), new throttler_1.Throttler(60 * 1000, // 60 sec delay window
521
+ this.summaryCollection, this.logger, this.formRequestSummarizerFn(loader), new throttler_1.Throttler(60 * 1000, // 60 sec delay window
467
522
  30 * 1000, // 30 sec max delay
468
523
  // throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
469
524
  (0, throttler_1.formExponentialFn)({ coefficient: 20, initialDelay: 0 })), {
@@ -493,8 +548,20 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
493
548
  this.replayPendingStates();
494
549
  });
495
550
  // logging hardware telemetry
496
- logger.sendTelemetryEvent(Object.assign({ eventName: "DeviceSpec" }, getDeviceSpec()));
497
- this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, summaryFormatVersion: metadata === null || metadata === void 0 ? void 0 : metadata.summaryFormatVersion, disableIsolatedChannels: metadata === null || metadata === void 0 ? void 0 : metadata.disableIsolatedChannels, gcVersion: metadata === null || metadata === void 0 ? void 0 : metadata.gcFeature, options: JSON.stringify(runtimeOptions), featureGates: JSON.stringify({
551
+ logger.sendTelemetryEvent({
552
+ eventName: "DeviceSpec",
553
+ ...getDeviceSpec(),
554
+ });
555
+ this.mc.logger.sendTelemetryEvent({
556
+ eventName: "ContainerLoadStats",
557
+ ...this.createContainerMetadata,
558
+ ...this.dataStores.containerLoadStats,
559
+ summaryNumber: loadSummaryNumber,
560
+ summaryFormatVersion: metadata?.summaryFormatVersion,
561
+ disableIsolatedChannels: metadata?.disableIsolatedChannels,
562
+ gcVersion: metadata?.gcFeature,
563
+ options: JSON.stringify(runtimeOptions),
564
+ featureGates: JSON.stringify({
498
565
  disableCompression,
499
566
  disableOpReentryCheck,
500
567
  disableChunking,
@@ -503,17 +570,23 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
503
570
  idCompressorEnabled: this.idCompressorEnabled,
504
571
  summaryStateUpdateMethod: this.summaryStateUpdateMethod,
505
572
  closeSummarizerDelayOverride,
506
- }), telemetryDocumentId: this.telemetryDocumentId, groupedBatchingEnabled: this.groupedBatchingEnabled }));
507
- (0, connectionTelemetry_1.ReportOpPerfTelemetry)(this.context.clientId, this.deltaManager, this.logger);
573
+ }),
574
+ telemetryDocumentId: this.telemetryDocumentId,
575
+ groupedBatchingEnabled: this.groupedBatchingEnabled,
576
+ });
577
+ (0, connectionTelemetry_1.ReportOpPerfTelemetry)(this.clientId, this.deltaManager, this.logger);
508
578
  (0, batchTracker_1.BindBatchTracker)(this, this.logger);
509
579
  this.entryPoint = new core_utils_1.LazyPromise(async () => {
510
- if (this.context.clientDetails.type === summary_1.summarizerClientType) {
580
+ if (this.isSummarizerClient) {
511
581
  (0, common_utils_1.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
512
582
  return this._summarizer;
513
583
  }
514
- return initializeEntryPoint === null || initializeEntryPoint === void 0 ? void 0 : initializeEntryPoint(this);
584
+ return initializeEntryPoint?.(this);
515
585
  });
516
586
  }
587
+ /**
588
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
589
+ */
517
590
  get IFluidRouter() {
518
591
  return this;
519
592
  }
@@ -559,22 +632,24 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
559
632
  * This object should provide all the functionality that the Container is expected to provide to the loader layer.
560
633
  */
561
634
  static async loadRuntime(params) {
562
- var _a, _b, _c, _d, _e, _f;
563
635
  const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, initializeEntryPoint, } = params;
564
636
  // If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
565
637
  // back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
566
638
  const backCompatContext = context;
567
- const passLogger = (_a = backCompatContext.taggedLogger) !== null && _a !== void 0 ? _a : new telemetry_utils_1.TaggedLoggerAdapter(backCompatContext.logger);
568
- const logger = telemetry_utils_1.ChildLogger.create(passLogger, undefined, {
569
- all: {
570
- runtimeVersion: packageVersion_1.pkgVersion,
639
+ const passLogger = backCompatContext.taggedLogger ??
640
+ new telemetry_utils_1.TaggedLoggerAdapter(backCompatContext.logger);
641
+ const logger = (0, telemetry_utils_1.createChildLogger)({
642
+ logger: passLogger,
643
+ properties: {
644
+ all: {
645
+ runtimeVersion: packageVersion_1.pkgVersion,
646
+ },
571
647
  },
572
648
  });
573
649
  const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = false, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
574
650
  const registry = new dataStoreRegistry_1.FluidDataStoreRegistry(registryEntries);
575
651
  const tryFetchBlob = async (blobName) => {
576
- var _a;
577
- const blobId = (_a = context.baseSnapshot) === null || _a === void 0 ? void 0 : _a.blobs[blobName];
652
+ const blobId = context.baseSnapshot?.blobs[blobName];
578
653
  if (context.baseSnapshot && blobId) {
579
654
  // IContainerContext storage api return type still has undefined in 0.39 package version.
580
655
  // So once we release 0.40 container-defn package we can remove this check.
@@ -589,16 +664,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
589
664
  tryFetchBlob(summary_1.aliasBlobName),
590
665
  tryFetchBlob(summary_1.idCompressorBlobName),
591
666
  ]);
592
- const loadExisting = existing === true || context.existing === true;
593
667
  // read snapshot blobs needed for BlobManager to load
594
- const blobManagerSnapshot = await blobManager_1.BlobManager.load((_b = context.baseSnapshot) === null || _b === void 0 ? void 0 : _b.trees[summary_1.blobsTreeName], async (id) => {
668
+ const blobManagerSnapshot = await blobManager_1.BlobManager.load(context.baseSnapshot?.trees[summary_1.blobsTreeName], async (id) => {
595
669
  // IContainerContext storage api return type still has undefined in 0.39 package version.
596
670
  // So once we release 0.40 container-defn package we can remove this check.
597
671
  (0, common_utils_1.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
598
672
  return (0, driver_utils_1.readAndParse)(context.storage, id);
599
673
  });
600
674
  // Verify summary runtime sequence number matches protocol sequence number.
601
- const runtimeSequenceNumber = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.message) === null || _c === void 0 ? void 0 : _c.sequenceNumber;
675
+ const runtimeSequenceNumber = metadata?.message?.sequenceNumber;
602
676
  // When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
603
677
  if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
604
678
  const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
@@ -613,13 +687,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
613
687
  logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
614
688
  }
615
689
  else {
616
- // Call both close and dispose as closeFn implementation will no longer dispose runtime in future
617
690
  context.closeFn(error);
618
- (_d = context.disposeFn) === null || _d === void 0 ? void 0 : _d.call(context, error);
619
691
  }
620
692
  }
621
693
  }
622
- const idCompressorEnabled = (_f = (_e = metadata === null || metadata === void 0 ? void 0 : metadata.idCompressorEnabled) !== null && _e !== void 0 ? _e : runtimeOptions.enableRuntimeIdCompressor) !== null && _f !== void 0 ? _f : false;
694
+ const idCompressorEnabled = metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
623
695
  let idCompressor;
624
696
  if (idCompressorEnabled) {
625
697
  const { IdCompressor, createSessionId } = await Promise.resolve().then(() => __importStar(require("./id-compressor")));
@@ -628,7 +700,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
628
700
  ? IdCompressor.deserialize(serializedIdCompressor, createSessionId())
629
701
  : new IdCompressor(createSessionId(), logger);
630
702
  }
631
- const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks !== null && chunks !== void 0 ? chunks : [], aliases !== null && aliases !== void 0 ? aliases : [], {
703
+ const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
632
704
  summaryOptions,
633
705
  gcOptions,
634
706
  loadSequenceNumberVerification,
@@ -639,7 +711,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
639
711
  enableRuntimeIdCompressor,
640
712
  enableOpReentryCheck,
641
713
  enableGroupedBatching,
642
- }, containerScope, logger, loadExisting, blobManagerSnapshot, context.storage, idCompressor, requestHandler, undefined, // summaryConfiguration
714
+ }, containerScope, logger, existing, blobManagerSnapshot, context.storage, idCompressor, requestHandler, undefined, // summaryConfiguration
643
715
  initializeEntryPoint);
644
716
  // It's possible to have ops with a reference sequence number of 0. Op sequence numbers start
645
717
  // at 1, so we won't see a replayed saved op with a sequence number of 0.
@@ -648,38 +720,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
648
720
  await runtime.initializeBaseState();
649
721
  return runtime;
650
722
  }
651
- get options() {
652
- return this.context.options;
653
- }
654
723
  get clientId() {
655
- return this.context.clientId;
656
- }
657
- get clientDetails() {
658
- return this.context.clientDetails;
724
+ return this._getClientId();
659
725
  }
660
726
  get storage() {
661
727
  return this._storage;
662
728
  }
729
+ /** @deprecated - The functionality is no longer exposed publicly */
663
730
  get reSubmitFn() {
664
- // eslint-disable-next-line @typescript-eslint/unbound-method
665
- return this.reSubmitCore;
666
- }
667
- get disposeFn() {
668
- var _a;
669
- // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
670
- return (_a = this.context.disposeFn) !== null && _a !== void 0 ? _a : this.context.closeFn;
671
- }
672
- get closeFn() {
673
- if (this._summarizer !== undefined) {
674
- // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
675
- return this.disposeFn;
676
- }
677
- // Also call disposeFn to retain functionality of runtime being disposed on close
678
- return (error) => {
679
- var _a, _b;
680
- this.context.closeFn(error);
681
- (_b = (_a = this.context).disposeFn) === null || _b === void 0 ? void 0 : _b.call(_a, error);
682
- };
731
+ return (type, contents, localOpMetadata, opMetadata) => this.reSubmitCore({ type, contents }, localOpMetadata, opMetadata);
683
732
  }
684
733
  get flushMode() {
685
734
  return this._flushMode;
@@ -691,7 +740,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
691
740
  return this.registry;
692
741
  }
693
742
  get attachState() {
694
- return this.context.attachState;
743
+ return this._getAttachState();
695
744
  }
696
745
  get IFluidHandleContext() {
697
746
  return this.handleContext;
@@ -718,8 +767,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
718
767
  }
719
768
  /** clientId of parent (non-summarizing) container that owns summarizer container */
720
769
  get summarizerClientId() {
721
- var _a;
722
- return (_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.electedClientId;
770
+ return this.summarizerClientElection?.electedClientId;
723
771
  }
724
772
  get disposed() {
725
773
  return this._disposed;
@@ -756,12 +804,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
756
804
  await this.garbageCollector.initializeBaseState();
757
805
  }
758
806
  dispose(error) {
759
- var _a;
760
807
  if (this._disposed) {
761
808
  return;
762
809
  }
763
810
  this._disposed = true;
764
- this.logger.sendTelemetryEvent({
811
+ this.mc.logger.sendTelemetryEvent({
765
812
  eventName: "ContainerRuntimeDisposed",
766
813
  isDirty: this.isDirty,
767
814
  lastSequenceNumber: this.deltaManager.lastSequenceNumber,
@@ -771,7 +818,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
771
818
  this.summaryManager.dispose();
772
819
  }
773
820
  this.garbageCollector.dispose();
774
- (_a = this._summarizer) === null || _a === void 0 ? void 0 : _a.dispose();
821
+ this._summarizer?.dispose();
775
822
  this.dataStores.dispose();
776
823
  this.pendingStateManager.dispose();
777
824
  this.emit("dispose");
@@ -780,6 +827,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
780
827
  /**
781
828
  * Notifies this object about the request made to the container.
782
829
  * @param request - Request made to the handler.
830
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
783
831
  */
784
832
  async request(request) {
785
833
  try {
@@ -846,19 +894,17 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
846
894
  return this.entryPoint;
847
895
  }
848
896
  internalId(maybeAlias) {
849
- var _a;
850
- return (_a = this.dataStores.aliases.get(maybeAlias)) !== null && _a !== void 0 ? _a : maybeAlias;
897
+ return this.dataStores.aliases.get(maybeAlias) ?? maybeAlias;
851
898
  }
852
899
  async getDataStoreFromRequest(id, request) {
853
- var _a, _b, _c;
854
900
  const headerData = {};
855
- if (typeof ((_a = request.headers) === null || _a === void 0 ? void 0 : _a[RuntimeHeaders.wait]) === "boolean") {
901
+ if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
856
902
  headerData.wait = request.headers[RuntimeHeaders.wait];
857
903
  }
858
- if (typeof ((_b = request.headers) === null || _b === void 0 ? void 0 : _b[RuntimeHeaders.viaHandle]) === "boolean") {
904
+ if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
859
905
  headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
860
906
  }
861
- if (typeof ((_c = request.headers) === null || _c === void 0 ? void 0 : _c[exports.AllowTombstoneRequestHeaderKey]) === "boolean") {
907
+ if (typeof request.headers?.[exports.AllowTombstoneRequestHeaderKey] === "boolean") {
862
908
  headerData.allowTombstone = request.headers[exports.AllowTombstoneRequestHeaderKey];
863
909
  }
864
910
  await this.dataStores.waitIfPendingAlias(id);
@@ -868,22 +914,27 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
868
914
  // Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
869
915
  // the same as GC nodes id.
870
916
  const urlWithoutQuery = (0, gc_1.trimLeadingAndTrailingSlashes)(request.url.split("?")[0]);
871
- this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, dataStoreContext.packagePath, request === null || request === void 0 ? void 0 : request.headers);
917
+ this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, dataStoreContext.packagePath, request?.headers);
872
918
  return dataStoreChannel;
873
919
  }
874
920
  /** Adds the container's metadata to the given summary tree. */
875
921
  addMetadataToSummary(summaryTree) {
876
- var _a;
877
- const metadata = Object.assign(Object.assign(Object.assign(Object.assign({}, this.createContainerMetadata), {
922
+ const metadata = {
923
+ ...this.createContainerMetadata,
878
924
  // Increment the summary number for the next summary that will be generated.
879
- summaryNumber: this.nextSummaryNumber++, summaryFormatVersion: 1 }), this.garbageCollector.getMetadata()), {
925
+ summaryNumber: this.nextSummaryNumber++,
926
+ summaryFormatVersion: 1,
927
+ ...this.garbageCollector.getMetadata(),
880
928
  // The last message processed at the time of summary. If there are no new messages, use the message from the
881
929
  // last summary.
882
- message: (_a = (0, summary_1.extractSummaryMetadataMessage)(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.messageAtLastSummary, telemetryDocumentId: this.telemetryDocumentId, idCompressorEnabled: this.idCompressorEnabled ? true : undefined });
930
+ message: (0, summary_1.extractSummaryMetadataMessage)(this.deltaManager.lastMessage) ??
931
+ this.messageAtLastSummary,
932
+ telemetryDocumentId: this.telemetryDocumentId,
933
+ idCompressorEnabled: this.idCompressorEnabled ? true : undefined,
934
+ };
883
935
  (0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.metadataBlobName, JSON.stringify(metadata));
884
936
  }
885
937
  addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
886
- var _a;
887
938
  this.addMetadataToSummary(summaryTree);
888
939
  if (this.idCompressorEnabled) {
889
940
  (0, common_utils_1.assert)(this.idCompressor !== undefined, 0x67a /* IdCompressor should be defined if enabled */);
@@ -899,7 +950,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
899
950
  (0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.aliasBlobName, JSON.stringify([...dataStoreAliases]));
900
951
  }
901
952
  if (this.summarizerClientElection) {
902
- const electedSummarizerContent = JSON.stringify((_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.serialize());
953
+ const electedSummarizerContent = JSON.stringify(this.summarizerClientElection?.serialize());
903
954
  (0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.electedSummarizerBlobName, electedSummarizerContent);
904
955
  }
905
956
  const blobManagerSummary = this.blobManager.summarize();
@@ -946,7 +997,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
946
997
  // in their own batches before the originating batch is sent.
947
998
  // Therefore, receiving them while attempting to send the originating batch
948
999
  // does not mean that the container is making any progress.
949
- if ((message === null || message === void 0 ? void 0 : message.type) !== ContainerMessageType.ChunkedOp) {
1000
+ if (message?.type !== ContainerMessageType.ChunkedOp) {
950
1001
  this.consecutiveReconnects = 0;
951
1002
  }
952
1003
  }
@@ -996,9 +1047,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
996
1047
  */
997
1048
  parseOpContent(serializedContent) {
998
1049
  (0, common_utils_1.assert)(serializedContent !== undefined, 0x6d5 /* content must be defined */);
999
- const parsed = JSON.parse(serializedContent);
1000
- (0, common_utils_1.assert)(parsed.type !== undefined, 0x6d6 /* incorrect op content format */);
1001
- return { type: parsed.type, contents: parsed.contents };
1050
+ const { type, contents } = JSON.parse(serializedContent);
1051
+ (0, common_utils_1.assert)(type !== undefined, 0x6d6 /* incorrect op content format */);
1052
+ return { type, contents };
1002
1053
  }
1003
1054
  async applyStashedOp(op) {
1004
1055
  // Need to parse from string for back-compat
@@ -1057,6 +1108,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1057
1108
  // There might be no change of state due to Container calling this API after loading runtime.
1058
1109
  const changeOfState = this._connected !== connected;
1059
1110
  const reconnection = changeOfState && !connected;
1111
+ // We need to flush the ops currently collected by Outbox to preserve original order.
1112
+ // This flush NEEDS to happen before we set the ContainerRuntime to "connected".
1113
+ // We want these ops to get to the PendingStateManager without sending to service and have them return to the Outbox upon calling "replayPendingStates".
1114
+ if (changeOfState && connected) {
1115
+ this.flush();
1116
+ }
1060
1117
  this._connected = connected;
1061
1118
  if (!connected) {
1062
1119
  this._perfSignalData.signalsLost = 0;
@@ -1095,13 +1152,18 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1095
1152
  // or something different, like a system message.
1096
1153
  const runtimeMessage = messageArg.type === protocol_definitions_1.MessageType.Operation;
1097
1154
  // Do shallow copy of message, as the processing flow will modify it.
1098
- const messageCopy = Object.assign({}, messageArg);
1155
+ const messageCopy = { ...messageArg };
1099
1156
  for (const message of this.remoteMessageProcessor.process(messageCopy)) {
1100
1157
  this.processCore(message, local, runtimeMessage);
1101
1158
  }
1102
1159
  }
1160
+ /**
1161
+ * Direct the message to the correct subsystem for processing, and implement other side effects
1162
+ * @param message - The unpacked message. Likely a ContainerRuntimeMessage, but could also be a system op
1163
+ * @param local - Did this client send the op?
1164
+ * @param runtimeMessage - Does this appear like a current ContainerRuntimeMessage? If true, certain validation will occur.
1165
+ */
1103
1166
  processCore(message, local, runtimeMessage) {
1104
- var _a;
1105
1167
  // Surround the actual processing of the operation with messages to the schedule manager indicating
1106
1168
  // the beginning and end. This allows it to emit appropriate events and/or pause the processing of new
1107
1169
  // messages once a batch has been fully processed.
@@ -1146,16 +1208,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1146
1208
  local,
1147
1209
  type: message.type,
1148
1210
  contentType: typeof message.contents,
1149
- batch: (_a = message.metadata) === null || _a === void 0 ? void 0 : _a.batch,
1211
+ batch: message.metadata?.batch,
1150
1212
  compression: message.compression,
1151
1213
  });
1152
1214
  this.closeFn(error);
1153
1215
  throw error;
1154
1216
  }
1155
1217
  }
1156
- if (runtimeMessage || this.groupedBatchingEnabled) {
1157
- this.emit("op", message, runtimeMessage);
1158
- }
1218
+ this.emit("op", message, runtimeMessage);
1159
1219
  this.scheduleManager.afterOpProcessing(undefined, message);
1160
1220
  if (local) {
1161
1221
  // If we have processed a local op, this means that the container is
@@ -1178,7 +1238,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1178
1238
  */
1179
1239
  sendSignalTelemetryEvent(clientSignalSequenceNumber) {
1180
1240
  const duration = Date.now() - this._perfSignalData.signalTimestamp;
1181
- this.logger.sendPerformanceEvent({
1241
+ this.mc.logger.sendPerformanceEvent({
1182
1242
  eventName: "SignalLatency",
1183
1243
  duration,
1184
1244
  signalsLost: this._perfSignalData.signalsLost,
@@ -1201,7 +1261,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1201
1261
  this._perfSignalData.trackingSignalSequenceNumber) {
1202
1262
  this._perfSignalData.signalsLost++;
1203
1263
  this._perfSignalData.trackingSignalSequenceNumber = undefined;
1204
- this.logger.sendErrorEvent({
1264
+ this.mc.logger.sendErrorEvent({
1205
1265
  eventName: "SignalLost",
1206
1266
  type: envelope.contents.type,
1207
1267
  signalsLost: this._perfSignalData.signalsLost,
@@ -1225,6 +1285,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1225
1285
  }
1226
1286
  this.dataStores.processSignal(envelope.address, transformed, local);
1227
1287
  }
1288
+ /**
1289
+ * Returns the runtime of the data store.
1290
+ * @param id - Id supplied during creating the data store.
1291
+ * @param wait - True if you want to wait for it.
1292
+ * @deprecated - Use getAliasedDataStoreEntryPoint instead to get an aliased data store's entry point.
1293
+ */
1228
1294
  async getRootDataStore(id, wait = true) {
1229
1295
  return this.getRootDataStoreChannel(id, wait);
1230
1296
  }
@@ -1286,9 +1352,25 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1286
1352
  }
1287
1353
  return result;
1288
1354
  }
1289
- async createDataStore(pkg) {
1290
- const internalId = (0, uuid_1.v4)();
1291
- return (0, dataStore_1.channelToDataStore)(await this._createDataStore(pkg, internalId), internalId, this, this.dataStores, this.mc.logger);
1355
+ /**
1356
+ * Returns the aliased data store's entryPoint, given the alias.
1357
+ * @param alias - The alias for the data store.
1358
+ * @returns - The data store's entry point (IFluidHandle) if it exists and is aliased. Returns undefined if no
1359
+ * data store has been assigned the given alias.
1360
+ */
1361
+ async getAliasedDataStoreEntryPoint(alias) {
1362
+ await this.dataStores.waitIfPendingAlias(alias);
1363
+ const internalId = this.internalId(alias);
1364
+ const context = await this.dataStores.getDataStoreIfAvailable(internalId, { wait: false });
1365
+ // If the data store is not available or not an alias, return undefined.
1366
+ if (context === undefined || !(await context.isRoot())) {
1367
+ return undefined;
1368
+ }
1369
+ const channel = await context.realize();
1370
+ if (channel.entryPoint === undefined) {
1371
+ throw new container_utils_1.UsageError("entryPoint must be defined on data store runtime for using getAliasedDataStoreEntryPoint");
1372
+ }
1373
+ return channel.entryPoint;
1292
1374
  }
1293
1375
  createDetachedRootDataStore(pkg, rootDataStoreId) {
1294
1376
  if (rootDataStoreId.includes("/")) {
@@ -1299,16 +1381,20 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1299
1381
  createDetachedDataStore(pkg) {
1300
1382
  return this.dataStores.createDetachedDataStoreCore(pkg, false);
1301
1383
  }
1302
- async _createDataStoreWithProps(pkg, props, id = (0, uuid_1.v4)()) {
1303
- const fluidDataStore = await this.dataStores
1304
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
1305
- .realize();
1306
- return (0, dataStore_1.channelToDataStore)(fluidDataStore, id, this, this.dataStores, this.mc.logger);
1384
+ async createDataStore(pkg) {
1385
+ const id = (0, uuid_1.v4)();
1386
+ return (0, dataStore_1.channelToDataStore)(await this.dataStores
1387
+ ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id)
1388
+ .realize(), id, this, this.dataStores, this.mc.logger);
1307
1389
  }
1308
- async _createDataStore(pkg, id = (0, uuid_1.v4)(), props) {
1309
- return this.dataStores
1390
+ /**
1391
+ * @deprecated 0.16 Issue #1537, #3631
1392
+ * @internal
1393
+ */
1394
+ async _createDataStoreWithProps(pkg, props, id = (0, uuid_1.v4)()) {
1395
+ return (0, dataStore_1.channelToDataStore)(await this.dataStores
1310
1396
  ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
1311
- .realize();
1397
+ .realize(), id, this, this.dataStores, this.mc.logger);
1312
1398
  }
1313
1399
  canSendOps() {
1314
1400
  // Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
@@ -1322,11 +1408,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1322
1408
  return this.flushMode !== runtime_definitions_1.FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
1323
1409
  }
1324
1410
  getQuorum() {
1325
- return this.context.quorum;
1411
+ return this._quorum;
1326
1412
  }
1327
1413
  getAudience() {
1328
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1329
- return this.context.audience;
1414
+ return this._audience;
1330
1415
  }
1331
1416
  /**
1332
1417
  * Returns true of container is dirty, i.e. there are some pending local changes that
@@ -1335,7 +1420,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1335
1420
  get isDirty() {
1336
1421
  return this.dirtyContainer;
1337
1422
  }
1338
- isContainerMessageDirtyable(type, contents) {
1423
+ isContainerMessageDirtyable({ type, contents }) {
1339
1424
  // For legacy purposes, exclude the old built-in AgentScheduler from dirty consideration as a special-case.
1340
1425
  // Ultimately we should have no special-cases from the ContainerRuntime's perspective.
1341
1426
  if (type === ContainerMessageType.Attach) {
@@ -1375,11 +1460,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1375
1460
  submitSignal(type, content) {
1376
1461
  this.verifyNotClosed();
1377
1462
  const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
1378
- return this.context.submitSignalFn(envelope);
1463
+ return this.submitSignalFn(envelope);
1379
1464
  }
1380
1465
  submitDataStoreSignal(address, type, content) {
1381
1466
  const envelope = this.createNewSignalEnvelope(address, type, content);
1382
- return this.context.submitSignalFn(envelope);
1467
+ return this.submitSignalFn(envelope);
1383
1468
  }
1384
1469
  setAttachState(attachState) {
1385
1470
  if (attachState === container_definitions_1.AttachState.Attaching) {
@@ -1412,22 +1497,17 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1412
1497
  this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
1413
1498
  return summarizeResult.summary;
1414
1499
  }
1415
- async getAbsoluteUrl(relativeUrl) {
1416
- if (this.context.getAbsoluteUrl === undefined) {
1417
- throw new Error("Driver does not implement getAbsoluteUrl");
1418
- }
1419
- if (this.attachState !== container_definitions_1.AttachState.Attached) {
1420
- return undefined;
1421
- }
1422
- return this.context.getAbsoluteUrl(relativeUrl);
1423
- }
1424
1500
  async summarizeInternal(fullTree, trackState, telemetryContext) {
1425
1501
  const summarizeResult = await this.dataStores.summarize(fullTree, trackState, telemetryContext);
1426
1502
  // Wrap data store summaries in .channels subtree.
1427
1503
  (0, summary_1.wrapSummaryInChannelsTree)(summarizeResult);
1428
1504
  const pathPartsForChildren = [runtime_definitions_1.channelsTreeName];
1429
1505
  this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
1430
- return Object.assign(Object.assign({}, summarizeResult), { id: "", pathPartsForChildren });
1506
+ return {
1507
+ ...summarizeResult,
1508
+ id: "",
1509
+ pathPartsForChildren,
1510
+ };
1431
1511
  }
1432
1512
  /**
1433
1513
  * Returns a summary of the runtime at the current sequence number.
@@ -1445,16 +1525,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1445
1525
  runSweep,
1446
1526
  });
1447
1527
  try {
1448
- let gcStats;
1449
1528
  if (runGC) {
1450
- gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC }, telemetryContext);
1529
+ await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC }, telemetryContext);
1451
1530
  }
1452
1531
  const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
1453
1532
  (0, common_utils_1.assert)(summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
1454
- return { stats, summary, gcStats };
1533
+ return { stats, summary };
1455
1534
  }
1456
1535
  finally {
1457
- this.logger.sendTelemetryEvent({
1536
+ this.mc.logger.sendTelemetryEvent({
1458
1537
  eventName: "SummarizeTelemetry",
1459
1538
  details: telemetryContext.serialize(),
1460
1539
  });
@@ -1536,21 +1615,19 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1536
1615
  * Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
1537
1616
  */
1538
1617
  getCurrentReferenceTimestampMs() {
1539
- var _a, _b, _c;
1540
1618
  // Use the timestamp of the last message seen by this client as that is server generated. If no messages have
1541
1619
  // been processed, use the timestamp of the message from the last summary.
1542
- return (_b = (_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : (_c = this.messageAtLastSummary) === null || _c === void 0 ? void 0 : _c.timestamp;
1620
+ return this.deltaManager.lastMessage?.timestamp ?? this.messageAtLastSummary?.timestamp;
1543
1621
  }
1544
1622
  /**
1545
1623
  * Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
1546
1624
  * blob manager.
1547
1625
  */
1548
1626
  getNodeType(nodePath) {
1549
- var _a;
1550
1627
  if (this.isBlobPath(nodePath)) {
1551
1628
  return gc_1.GCNodeType.Blob;
1552
1629
  }
1553
- return (_a = this.dataStores.getGCNodeType(nodePath)) !== null && _a !== void 0 ? _a : gc_1.GCNodeType.Other;
1630
+ return this.dataStores.getGCNodeType(nodePath) ?? gc_1.GCNodeType.Other;
1554
1631
  }
1555
1632
  /**
1556
1633
  * Called by GC to retrieve the package path of the node with the given path. The node should belong to a
@@ -1621,18 +1698,24 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1621
1698
  * @param options - options controlling how the summary is generated or submitted
1622
1699
  */
1623
1700
  async submitSummary(options) {
1624
- var _a, _b, _c;
1625
1701
  const { fullTree = false, refreshLatestAck, summaryLogger } = options;
1626
1702
  // The summary number for this summary. This will be updated during the summary process, so get it now and
1627
1703
  // use it for all events logged during this summary.
1628
1704
  const summaryNumber = this.nextSummaryNumber;
1629
- const summaryNumberLogger = telemetry_utils_1.ChildLogger.create(summaryLogger, undefined, {
1630
- all: { summaryNumber },
1705
+ const summaryNumberLogger = (0, telemetry_utils_1.createChildLogger)({
1706
+ logger: summaryLogger,
1707
+ properties: {
1708
+ all: { summaryNumber },
1709
+ },
1631
1710
  });
1632
1711
  (0, common_utils_1.assert)(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
1633
1712
  let latestSnapshotVersionId;
1634
1713
  if (refreshLatestAck) {
1635
- const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer(telemetry_utils_1.ChildLogger.create(summaryNumberLogger, undefined, { all: { safeSummary: true } }));
1714
+ const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer((0, telemetry_utils_1.createChildLogger)({
1715
+ logger: summaryNumberLogger,
1716
+ namespace: undefined,
1717
+ properties: { all: { safeSummary: true } },
1718
+ }));
1636
1719
  const latestSnapshotRefSeq = latestSnapshotInfo.latestSnapshotRefSeq;
1637
1720
  latestSnapshotVersionId = latestSnapshotInfo.latestSnapshotVersionId;
1638
1721
  // We might need to catch up to the latest summary's reference sequence number before pausing.
@@ -1652,7 +1735,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1652
1735
  this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
1653
1736
  // Helper function to check whether we should still continue between each async step.
1654
1737
  const checkContinue = () => {
1655
- var _a;
1656
1738
  // Do not check for loss of connectivity directly! Instead leave it up to
1657
1739
  // RunWhileConnectedCoordinator to control policy in a single place.
1658
1740
  // This will allow easier change of design if we chose to. For example, we may chose to allow
@@ -1675,7 +1757,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1675
1757
  error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
1676
1758
  };
1677
1759
  }
1678
- (0, common_utils_1.assert)(summaryRefSeqNum === ((_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.sequenceNumber), 0x395 /* it's one and the same thing */);
1760
+ (0, common_utils_1.assert)(summaryRefSeqNum === this.deltaManager.lastMessage?.sequenceNumber, 0x395 /* it's one and the same thing */);
1679
1761
  if (lastAck !== this.summaryCollection.latestAck) {
1680
1762
  return {
1681
1763
  continue: false,
@@ -1726,7 +1808,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1726
1808
  const gcSummaryTreeStats = summaryTree.tree[runtime_definitions_1.gcTreeKey]
1727
1809
  ? (0, runtime_utils_1.calculateStats)(summaryTree.tree[runtime_definitions_1.gcTreeKey])
1728
1810
  : undefined;
1729
- const summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount, gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary, gcBlobNodeCount: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.blobNodeCount, gcTotalBlobsSize: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.totalBlobSize, summaryNumber }, partialStats);
1811
+ const summaryStats = {
1812
+ dataStoreCount: this.dataStores.size,
1813
+ summarizedDataStoreCount: this.dataStores.size - handleCount,
1814
+ gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
1815
+ gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
1816
+ gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
1817
+ summaryNumber,
1818
+ ...partialStats,
1819
+ };
1730
1820
  const generateSummaryData = {
1731
1821
  referenceSequenceNumber: summaryRefSeqNum,
1732
1822
  minimumSequenceNumber,
@@ -1740,14 +1830,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1740
1830
  if (this.validateSummaryBeforeUpload) {
1741
1831
  const validateResult = this.summarizerNode.validateSummary();
1742
1832
  if (!validateResult.success) {
1743
- const { success } = validateResult, loggingProps = __rest(validateResult, ["success"]);
1744
- const error = new summary_1.RetriableSummaryError(validateResult.reason, validateResult.retryAfterSeconds, Object.assign({}, loggingProps));
1745
- return Object.assign(Object.assign({ stage: "base" }, generateSummaryData), { error });
1833
+ const { success, ...loggingProps } = validateResult;
1834
+ const error = new summary_1.RetriableSummaryError(validateResult.reason, validateResult.retryAfterSeconds, { ...loggingProps });
1835
+ return { stage: "base", ...generateSummaryData, error };
1746
1836
  }
1747
1837
  }
1748
1838
  continueResult = checkContinue();
1749
1839
  if (!continueResult.continue) {
1750
- return Object.assign(Object.assign({ stage: "generate" }, generateSummaryData), { error: continueResult.error });
1840
+ return { stage: "generate", ...generateSummaryData, error: continueResult.error };
1751
1841
  }
1752
1842
  // It may happen that the lastAck it not correct due to missing summaryAck in case of single commit
1753
1843
  // summary. So if the previous summarizer closes just after submitting the summary and before
@@ -1755,7 +1845,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1755
1845
  // latestSnapshotVersionId from storage and it does not match with the lastAck ackHandle, then use
1756
1846
  // the one fetched from storage as parent as that is the latest.
1757
1847
  let summaryContext;
1758
- if ((lastAck === null || lastAck === void 0 ? void 0 : lastAck.summaryAck.contents.handle) !== latestSnapshotVersionId &&
1848
+ if (lastAck?.summaryAck.contents.handle !== latestSnapshotVersionId &&
1759
1849
  latestSnapshotVersionId !== undefined) {
1760
1850
  summaryContext = {
1761
1851
  proposalHandle: undefined,
@@ -1766,7 +1856,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1766
1856
  else if (lastAck === undefined) {
1767
1857
  summaryContext = {
1768
1858
  proposalHandle: undefined,
1769
- ackHandle: (_a = this.context.getLoadedFromVersion()) === null || _a === void 0 ? void 0 : _a.id,
1859
+ ackHandle: this.loadedFromVersionId,
1770
1860
  referenceSequenceNumber: summaryRefSeqNum,
1771
1861
  };
1772
1862
  }
@@ -1782,7 +1872,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1782
1872
  handle = await this.storage.uploadSummaryWithContext(summarizeResult.summary, summaryContext);
1783
1873
  }
1784
1874
  catch (error) {
1785
- return Object.assign(Object.assign({ stage: "generate" }, generateSummaryData), { error });
1875
+ return { stage: "generate", ...generateSummaryData, error };
1786
1876
  }
1787
1877
  const parent = summaryContext.ackHandle;
1788
1878
  const summaryMessage = {
@@ -1792,25 +1882,34 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1792
1882
  message,
1793
1883
  parents: parent ? [parent] : [],
1794
1884
  };
1795
- const uploadData = Object.assign(Object.assign({}, generateSummaryData), { handle, uploadDuration: trace.trace().duration });
1885
+ const uploadData = {
1886
+ ...generateSummaryData,
1887
+ handle,
1888
+ uploadDuration: trace.trace().duration,
1889
+ };
1796
1890
  continueResult = checkContinue();
1797
1891
  if (!continueResult.continue) {
1798
- return Object.assign(Object.assign({ stage: "upload" }, uploadData), { error: continueResult.error });
1892
+ return { stage: "upload", ...uploadData, error: continueResult.error };
1799
1893
  }
1800
1894
  let clientSequenceNumber;
1801
1895
  try {
1802
1896
  clientSequenceNumber = this.submitSummaryMessage(summaryMessage, summaryRefSeqNum);
1803
1897
  }
1804
1898
  catch (error) {
1805
- return Object.assign(Object.assign({ stage: "upload" }, uploadData), { error });
1899
+ return { stage: "upload", ...uploadData, error };
1806
1900
  }
1807
- const submitData = Object.assign(Object.assign({ stage: "submit" }, uploadData), { clientSequenceNumber, submitOpDuration: trace.trace().duration });
1901
+ const submitData = {
1902
+ stage: "submit",
1903
+ ...uploadData,
1904
+ clientSequenceNumber,
1905
+ submitOpDuration: trace.trace().duration,
1906
+ };
1808
1907
  try {
1809
1908
  // If validateSummaryBeforeUpload is false, the summary should be validated in this step.
1810
1909
  this.summarizerNode.completeSummary(handle, !this.validateSummaryBeforeUpload /* validate */);
1811
1910
  }
1812
1911
  catch (error) {
1813
- return Object.assign(Object.assign({ stage: "upload" }, uploadData), { error });
1912
+ return { stage: "upload", ...uploadData, error };
1814
1913
  }
1815
1914
  return submitData;
1816
1915
  }
@@ -1818,7 +1917,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1818
1917
  // Cleanup wip summary in case of failure
1819
1918
  this.summarizerNode.clearSummary();
1820
1919
  // ! This needs to happen before we resume inbound queues to ensure heuristics are tracked correctly
1821
- (_c = (_b = this._summarizer) === null || _b === void 0 ? void 0 : _b.recordSummaryAttempt) === null || _c === void 0 ? void 0 : _c.call(_b, summaryRefSeqNum);
1920
+ this._summarizer?.recordSummaryAttempt?.(summaryRefSeqNum);
1822
1921
  // Restart the delta manager
1823
1922
  this.deltaManager.inbound.resume();
1824
1923
  if (shouldPauseInboundSignal) {
@@ -1843,7 +1942,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1843
1942
  this.dirtyContainer = dirty;
1844
1943
  if (this.emitDirtyDocumentEvent) {
1845
1944
  this.emit(dirty ? "dirty" : "saved");
1846
- this.context.updateDirtyContainerState(dirty);
1847
1945
  }
1848
1946
  }
1849
1947
  submitDataStoreOp(id, contents, localOpMetadata = undefined) {
@@ -1851,21 +1949,20 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1851
1949
  address: id,
1852
1950
  contents,
1853
1951
  };
1854
- this.submit(ContainerMessageType.FluidDataStoreOp, envelope, localOpMetadata);
1952
+ this.submit({ type: ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
1855
1953
  }
1856
1954
  submitDataStoreAliasOp(contents, localOpMetadata) {
1857
1955
  const aliasMessage = contents;
1858
1956
  if (!(0, dataStore_1.isDataStoreAliasMessage)(aliasMessage)) {
1859
1957
  throw new container_utils_1.UsageError("malformedDataStoreAliasMessage");
1860
1958
  }
1861
- this.submit(ContainerMessageType.Alias, contents, localOpMetadata);
1959
+ this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
1862
1960
  }
1863
- async uploadBlob(blob) {
1961
+ async uploadBlob(blob, signal) {
1864
1962
  this.verifyNotClosed();
1865
- return this.blobManager.createBlob(blob);
1963
+ return this.blobManager.createBlob(blob, signal);
1866
1964
  }
1867
1965
  maybeSubmitIdAllocationOp(type) {
1868
- var _a, _b;
1869
1966
  if (type !== ContainerMessageType.IdAllocation) {
1870
1967
  let idAllocationBatchMessage;
1871
1968
  let idRange;
@@ -1873,7 +1970,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1873
1970
  (0, common_utils_1.assert)(this.idCompressor !== undefined, 0x67d /* IdCompressor should be defined if enabled */);
1874
1971
  idRange = this.idCompressor.takeNextCreationRange();
1875
1972
  // Don't include the idRange if there weren't any Ids allocated
1876
- idRange = ((_a = idRange === null || idRange === void 0 ? void 0 : idRange.ids) === null || _a === void 0 ? void 0 : _a.first) !== undefined ? idRange : undefined;
1973
+ idRange = idRange?.ids?.first !== undefined ? idRange : undefined;
1877
1974
  }
1878
1975
  if (idRange !== undefined) {
1879
1976
  const idAllocationMessage = {
@@ -1884,7 +1981,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1884
1981
  contents: JSON.stringify(idAllocationMessage),
1885
1982
  referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
1886
1983
  metadata: undefined,
1887
- localOpMetadata: (_b = this.idCompressor) === null || _b === void 0 ? void 0 : _b.serialize(true),
1984
+ localOpMetadata: this.idCompressor?.serialize(true),
1888
1985
  type: ContainerMessageType.IdAllocation,
1889
1986
  };
1890
1987
  }
@@ -1893,20 +1990,21 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1893
1990
  }
1894
1991
  }
1895
1992
  }
1896
- submit(type, contents, localOpMetadata = undefined, metadata = undefined) {
1993
+ submit(containerRuntimeMessage, localOpMetadata = undefined, metadata = undefined) {
1897
1994
  this.verifyNotClosed();
1898
1995
  this.verifyCanSubmitOps();
1899
1996
  // There should be no ops in detached container state!
1900
1997
  (0, common_utils_1.assert)(this.attachState !== container_definitions_1.AttachState.Detached, 0x132 /* "sending ops in detached container" */);
1901
- const serializedContent = JSON.stringify({ type, contents });
1998
+ const serializedContent = JSON.stringify(containerRuntimeMessage);
1902
1999
  // Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
1903
2000
  // container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
1904
2001
  if (this.innerDeltaManager.readOnlyInfo.readonly) {
1905
- this.logger.sendTelemetryEvent({
2002
+ this.mc.logger.sendTelemetryEvent({
1906
2003
  eventName: "SubmitOpInReadonly",
1907
2004
  connected: this.connected,
1908
2005
  });
1909
2006
  }
2007
+ const type = containerRuntimeMessage.type;
1910
2008
  const message = {
1911
2009
  contents: serializedContent,
1912
2010
  type,
@@ -1963,7 +2061,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1963
2061
  this.closeFn(error);
1964
2062
  throw error;
1965
2063
  }
1966
- if (this.isContainerMessageDirtyable(type, contents)) {
2064
+ if (this.isContainerMessageDirtyable(containerRuntimeMessage)) {
1967
2065
  this.updateDocumentDirtyState(true);
1968
2066
  }
1969
2067
  }
@@ -2006,9 +2104,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
2006
2104
  // System message should not be sent in the middle of the batch.
2007
2105
  (0, common_utils_1.assert)(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
2008
2106
  // back-compat: ADO #1385: Make this call unconditional in the future
2009
- return this.context.submitSummaryFn !== undefined
2010
- ? this.context.submitSummaryFn(contents, referenceSequenceNumber)
2011
- : this.context.submitFn(protocol_definitions_1.MessageType.Summarize, contents, false);
2107
+ return this.submitSummaryFn !== undefined
2108
+ ? this.submitSummaryFn(contents, referenceSequenceNumber)
2109
+ : this.submitFn(protocol_definitions_1.MessageType.Summarize, contents, false);
2012
2110
  }
2013
2111
  /**
2014
2112
  * Throw an error if the runtime is closed. Methods that are expected to potentially
@@ -2055,32 +2153,33 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
2055
2153
  }
2056
2154
  reSubmit(message) {
2057
2155
  // Need to parse from string for back-compat
2058
- const { contents, type } = this.parseOpContent(message.content);
2059
- this.reSubmitCore(type, contents, message.localOpMetadata, message.opMetadata);
2156
+ const containerRuntimeMessage = this.parseOpContent(message.content);
2157
+ this.reSubmitCore(containerRuntimeMessage, message.localOpMetadata, message.opMetadata);
2060
2158
  }
2061
2159
  /**
2062
2160
  * Finds the right store and asks it to resubmit the message. This typically happens when we
2063
2161
  * reconnect and there are pending messages.
2064
- * @param content - The content of the original message.
2162
+ * @param message - The original ContainerRuntimeMessage.
2065
2163
  * @param localOpMetadata - The local metadata associated with the original message.
2066
2164
  */
2067
- reSubmitCore(type, content, localOpMetadata, opMetadata) {
2068
- switch (type) {
2165
+ reSubmitCore(message, localOpMetadata, opMetadata) {
2166
+ const contents = message.contents;
2167
+ switch (message.type) {
2069
2168
  case ContainerMessageType.FluidDataStoreOp:
2070
2169
  // For Operations, call resubmitDataStoreOp which will find the right store
2071
2170
  // and trigger resubmission on it.
2072
- this.dataStores.resubmitDataStoreOp(content, localOpMetadata);
2171
+ this.dataStores.resubmitDataStoreOp(contents, localOpMetadata);
2073
2172
  break;
2074
2173
  case ContainerMessageType.Attach:
2075
2174
  case ContainerMessageType.Alias:
2076
- this.submit(type, content, localOpMetadata);
2175
+ this.submit(message, localOpMetadata);
2077
2176
  break;
2078
2177
  case ContainerMessageType.IdAllocation:
2079
2178
  // Remove the stashedState from the op if it's a stashed op
2080
- if (content.stashedState !== undefined) {
2081
- delete content.stashedState;
2179
+ if (contents.stashedState !== undefined) {
2180
+ delete contents.stashedState;
2082
2181
  }
2083
- this.submit(type, content, localOpMetadata);
2182
+ this.submit(message, localOpMetadata);
2084
2183
  break;
2085
2184
  case ContainerMessageType.ChunkedOp:
2086
2185
  throw new Error(`chunkedOp not expected here`);
@@ -2088,10 +2187,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
2088
2187
  this.blobManager.reSubmit(opMetadata);
2089
2188
  break;
2090
2189
  case ContainerMessageType.Rejoin:
2091
- this.submit(type, content);
2190
+ this.submit(message);
2092
2191
  break;
2093
2192
  default:
2094
- (0, common_utils_1.unreachableCase)(type, `Unknown ContainerMessageType: ${type}`);
2193
+ (0, common_utils_1.unreachableCase)(message.type, `Unknown ContainerMessageType [type: ${message.type}]`);
2095
2194
  }
2096
2195
  }
2097
2196
  rollback(content, localOpMetadata) {
@@ -2138,7 +2237,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
2138
2237
  * change that started fetching latest snapshot always.
2139
2238
  */
2140
2239
  if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
2141
- fetchResult = await this.fetchSnapshotFromStorage(summaryLogger, {
2240
+ fetchResult = await this.fetchSnapshotFromStorageAndClose(summaryLogger, {
2142
2241
  eventName: "RefreshLatestSummaryAckFetchBackCompat",
2143
2242
  ackHandle,
2144
2243
  targetSequenceNumber: summaryRefSeq,
@@ -2160,7 +2259,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
2160
2259
  summaryRefSeq,
2161
2260
  fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
2162
2261
  });
2163
- this.closeFn(error);
2262
+ this.disposeFn(error);
2164
2263
  throw error;
2165
2264
  }
2166
2265
  // In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
@@ -2196,10 +2295,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
2196
2295
  return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
2197
2296
  }
2198
2297
  async fetchLatestSnapshotFromStorage(logger, event, readAndParseBlob) {
2199
- return this.fetchSnapshotFromStorage(logger, event, readAndParseBlob, null /* latest */);
2298
+ return this.fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, null /* latest */);
2200
2299
  }
2201
- async fetchSnapshotFromStorage(logger, event, readAndParseBlob, versionId) {
2202
- var _a;
2300
+ async fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, versionId) {
2203
2301
  const snapshotResults = await telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
2204
2302
  const stats = {};
2205
2303
  const trace = common_utils_1.Trace.start();
@@ -2222,29 +2320,37 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
2222
2320
  // We choose to close the summarizer after the snapshot cache is updated to avoid
2223
2321
  // situations which the main client (which is likely to be re-elected as the leader again)
2224
2322
  // loads the summarizer from cache.
2225
- if (this.summaryStateUpdateMethod === "restart") {
2226
- const error = new container_utils_1.GenericError("Restarting summarizer instead of refreshing");
2227
- this.mc.logger.sendTelemetryEvent(Object.assign(Object.assign({}, event), { eventName: "ClosingSummarizerOnSummaryStale", codePath: event.eventName, message: "Stopping fetch from storage", versionId: versionId != null ? versionId : undefined, closeSummarizerDelayMs: this.closeSummarizerDelayMs }), error);
2228
- // Delay 10 seconds before restarting summarizer to prevent the summarizer from restarting too frequently.
2323
+ if (this.summaryStateUpdateMethod !== "refreshFromSnapshot") {
2324
+ this.mc.logger.sendTelemetryEvent({
2325
+ ...event,
2326
+ eventName: "ClosingSummarizerOnSummaryStale",
2327
+ codePath: event.eventName,
2328
+ message: "Stopping fetch from storage",
2329
+ versionId: versionId != null ? versionId : undefined,
2330
+ closeSummarizerDelayMs: this.closeSummarizerDelayMs,
2331
+ }, new container_utils_1.GenericError("Restarting summarizer instead of refreshing"));
2332
+ // Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
2229
2333
  await (0, common_utils_1.delay)(this.closeSummarizerDelayMs);
2230
- (_a = this._summarizer) === null || _a === void 0 ? void 0 : _a.stop("latestSummaryStateStale");
2231
- this.closeFn();
2232
- throw error;
2334
+ this._summarizer?.stop("latestSummaryStateStale");
2335
+ this.disposeFn();
2233
2336
  }
2234
2337
  return snapshotResults;
2235
2338
  }
2236
2339
  notifyAttaching() { } // do nothing (deprecated method)
2237
- getPendingLocalState() {
2340
+ async getPendingLocalState(props) {
2341
+ this.verifyNotClosed();
2342
+ const waitBlobsToAttach = props?.notifyImminentClosure;
2238
2343
  if (this._orderSequentiallyCalls !== 0) {
2239
2344
  throw new container_utils_1.UsageError("can't get state during orderSequentially");
2240
2345
  }
2346
+ const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(waitBlobsToAttach);
2241
2347
  // Flush pending batch.
2242
2348
  // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
2243
2349
  // to close current batch.
2244
2350
  this.flush();
2245
2351
  return {
2246
2352
  pending: this.pendingStateManager.getLocalState(),
2247
- pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
2353
+ pendingAttachmentBlobs,
2248
2354
  };
2249
2355
  }
2250
2356
  /**