@fluidframework/container-runtime 2.0.0-internal.5.3.4 → 2.0.0-internal.5.4.2

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 (231) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/batchTracker.d.ts.map +1 -1
  3. package/dist/batchTracker.js +1 -1
  4. package/dist/batchTracker.js.map +1 -1
  5. package/dist/blobManager.d.ts +9 -1
  6. package/dist/blobManager.d.ts.map +1 -1
  7. package/dist/blobManager.js +55 -12
  8. package/dist/blobManager.js.map +1 -1
  9. package/dist/connectionTelemetry.d.ts.map +1 -1
  10. package/dist/connectionTelemetry.js +2 -2
  11. package/dist/connectionTelemetry.js.map +1 -1
  12. package/dist/containerRuntime.d.ts +43 -11
  13. package/dist/containerRuntime.d.ts.map +1 -1
  14. package/dist/containerRuntime.js +189 -137
  15. package/dist/containerRuntime.js.map +1 -1
  16. package/dist/dataStore.js +3 -0
  17. package/dist/dataStore.js.map +1 -1
  18. package/dist/dataStoreContext.d.ts +1 -1
  19. package/dist/dataStoreContext.d.ts.map +1 -1
  20. package/dist/dataStoreContext.js +24 -27
  21. package/dist/dataStoreContext.js.map +1 -1
  22. package/dist/dataStoreContexts.js +1 -1
  23. package/dist/dataStoreContexts.js.map +1 -1
  24. package/dist/dataStores.d.ts +1 -1
  25. package/dist/dataStores.d.ts.map +1 -1
  26. package/dist/dataStores.js +14 -24
  27. package/dist/dataStores.js.map +1 -1
  28. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  29. package/dist/deltaManagerSummarizerProxy.js +2 -0
  30. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  31. package/dist/deltaScheduler.d.ts.map +1 -1
  32. package/dist/deltaScheduler.js +5 -5
  33. package/dist/deltaScheduler.js.map +1 -1
  34. package/dist/gc/garbageCollection.d.ts.map +1 -1
  35. package/dist/gc/garbageCollection.js +12 -5
  36. package/dist/gc/garbageCollection.js.map +1 -1
  37. package/dist/gc/gcHelpers.d.ts +1 -0
  38. package/dist/gc/gcHelpers.d.ts.map +1 -1
  39. package/dist/gc/gcHelpers.js +1 -0
  40. package/dist/gc/gcHelpers.js.map +1 -1
  41. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  42. package/dist/gc/gcTelemetry.js +15 -22
  43. package/dist/gc/gcTelemetry.js.map +1 -1
  44. package/dist/id-compressor/idCompressor.d.ts +3 -3
  45. package/dist/id-compressor/idCompressor.d.ts.map +1 -1
  46. package/dist/id-compressor/idCompressor.js +3 -1
  47. package/dist/id-compressor/idCompressor.js.map +1 -1
  48. package/dist/opLifecycle/opCompressor.d.ts +2 -2
  49. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  50. package/dist/opLifecycle/opCompressor.js +1 -1
  51. package/dist/opLifecycle/opCompressor.js.map +1 -1
  52. package/dist/opLifecycle/opDecompressor.d.ts +2 -2
  53. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  54. package/dist/opLifecycle/opDecompressor.js +1 -1
  55. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  56. package/dist/opLifecycle/opSplitter.d.ts +2 -2
  57. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  58. package/dist/opLifecycle/opSplitter.js +1 -1
  59. package/dist/opLifecycle/opSplitter.js.map +1 -1
  60. package/dist/opLifecycle/outbox.d.ts +6 -5
  61. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  62. package/dist/opLifecycle/outbox.js +5 -12
  63. package/dist/opLifecycle/outbox.js.map +1 -1
  64. package/dist/opLifecycle/remoteMessageProcessor.d.ts +6 -1
  65. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  66. package/dist/opLifecycle/remoteMessageProcessor.js +7 -1
  67. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  68. package/dist/packageVersion.d.ts +1 -1
  69. package/dist/packageVersion.js +1 -1
  70. package/dist/packageVersion.js.map +1 -1
  71. package/dist/pendingStateManager.d.ts +4 -1
  72. package/dist/pendingStateManager.d.ts.map +1 -1
  73. package/dist/pendingStateManager.js +21 -12
  74. package/dist/pendingStateManager.js.map +1 -1
  75. package/dist/scheduleManager.d.ts.map +1 -1
  76. package/dist/scheduleManager.js +1 -1
  77. package/dist/scheduleManager.js.map +1 -1
  78. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  79. package/dist/summary/orderedClientElection.js +1 -1
  80. package/dist/summary/orderedClientElection.js.map +1 -1
  81. package/dist/summary/runningSummarizer.d.ts +3 -5
  82. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  83. package/dist/summary/runningSummarizer.js +10 -28
  84. package/dist/summary/runningSummarizer.js.map +1 -1
  85. package/dist/summary/summarizer.js +1 -1
  86. package/dist/summary/summarizer.js.map +1 -1
  87. package/dist/summary/summarizerNode/summarizerNode.d.ts +5 -5
  88. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  89. package/dist/summary/summarizerNode/summarizerNode.js +7 -10
  90. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  91. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
  92. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  93. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +4 -8
  94. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  95. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  96. package/dist/summary/summaryGenerator.js +5 -1
  97. package/dist/summary/summaryGenerator.js.map +1 -1
  98. package/dist/summary/summaryManager.d.ts +2 -3
  99. package/dist/summary/summaryManager.d.ts.map +1 -1
  100. package/dist/summary/summaryManager.js +6 -2
  101. package/dist/summary/summaryManager.js.map +1 -1
  102. package/lib/batchTracker.d.ts.map +1 -1
  103. package/lib/batchTracker.js +2 -2
  104. package/lib/batchTracker.js.map +1 -1
  105. package/lib/blobManager.d.ts +9 -1
  106. package/lib/blobManager.d.ts.map +1 -1
  107. package/lib/blobManager.js +55 -12
  108. package/lib/blobManager.js.map +1 -1
  109. package/lib/connectionTelemetry.d.ts.map +1 -1
  110. package/lib/connectionTelemetry.js +3 -3
  111. package/lib/connectionTelemetry.js.map +1 -1
  112. package/lib/containerRuntime.d.ts +43 -11
  113. package/lib/containerRuntime.d.ts.map +1 -1
  114. package/lib/containerRuntime.js +188 -137
  115. package/lib/containerRuntime.js.map +1 -1
  116. package/lib/dataStore.js +3 -0
  117. package/lib/dataStore.js.map +1 -1
  118. package/lib/dataStoreContext.d.ts +1 -1
  119. package/lib/dataStoreContext.d.ts.map +1 -1
  120. package/lib/dataStoreContext.js +26 -29
  121. package/lib/dataStoreContext.js.map +1 -1
  122. package/lib/dataStoreContexts.js +2 -2
  123. package/lib/dataStoreContexts.js.map +1 -1
  124. package/lib/dataStores.d.ts +1 -1
  125. package/lib/dataStores.d.ts.map +1 -1
  126. package/lib/dataStores.js +15 -25
  127. package/lib/dataStores.js.map +1 -1
  128. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
  129. package/lib/deltaManagerSummarizerProxy.js +2 -0
  130. package/lib/deltaManagerSummarizerProxy.js.map +1 -1
  131. package/lib/deltaScheduler.d.ts.map +1 -1
  132. package/lib/deltaScheduler.js +6 -6
  133. package/lib/deltaScheduler.js.map +1 -1
  134. package/lib/gc/garbageCollection.d.ts.map +1 -1
  135. package/lib/gc/garbageCollection.js +13 -6
  136. package/lib/gc/garbageCollection.js.map +1 -1
  137. package/lib/gc/gcHelpers.d.ts +1 -0
  138. package/lib/gc/gcHelpers.d.ts.map +1 -1
  139. package/lib/gc/gcHelpers.js +1 -0
  140. package/lib/gc/gcHelpers.js.map +1 -1
  141. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  142. package/lib/gc/gcTelemetry.js +16 -23
  143. package/lib/gc/gcTelemetry.js.map +1 -1
  144. package/lib/id-compressor/idCompressor.d.ts +3 -3
  145. package/lib/id-compressor/idCompressor.d.ts.map +1 -1
  146. package/lib/id-compressor/idCompressor.js +3 -1
  147. package/lib/id-compressor/idCompressor.js.map +1 -1
  148. package/lib/opLifecycle/opCompressor.d.ts +2 -2
  149. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  150. package/lib/opLifecycle/opCompressor.js +2 -2
  151. package/lib/opLifecycle/opCompressor.js.map +1 -1
  152. package/lib/opLifecycle/opDecompressor.d.ts +2 -2
  153. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  154. package/lib/opLifecycle/opDecompressor.js +2 -2
  155. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  156. package/lib/opLifecycle/opSplitter.d.ts +2 -2
  157. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  158. package/lib/opLifecycle/opSplitter.js +2 -2
  159. package/lib/opLifecycle/opSplitter.js.map +1 -1
  160. package/lib/opLifecycle/outbox.d.ts +6 -5
  161. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  162. package/lib/opLifecycle/outbox.js +6 -13
  163. package/lib/opLifecycle/outbox.js.map +1 -1
  164. package/lib/opLifecycle/remoteMessageProcessor.d.ts +6 -1
  165. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  166. package/lib/opLifecycle/remoteMessageProcessor.js +7 -1
  167. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  168. package/lib/packageVersion.d.ts +1 -1
  169. package/lib/packageVersion.js +1 -1
  170. package/lib/packageVersion.js.map +1 -1
  171. package/lib/pendingStateManager.d.ts +4 -1
  172. package/lib/pendingStateManager.d.ts.map +1 -1
  173. package/lib/pendingStateManager.js +21 -12
  174. package/lib/pendingStateManager.js.map +1 -1
  175. package/lib/scheduleManager.d.ts.map +1 -1
  176. package/lib/scheduleManager.js +2 -2
  177. package/lib/scheduleManager.js.map +1 -1
  178. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  179. package/lib/summary/orderedClientElection.js +2 -2
  180. package/lib/summary/orderedClientElection.js.map +1 -1
  181. package/lib/summary/runningSummarizer.d.ts +3 -5
  182. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  183. package/lib/summary/runningSummarizer.js +11 -29
  184. package/lib/summary/runningSummarizer.js.map +1 -1
  185. package/lib/summary/summarizer.js +2 -2
  186. package/lib/summary/summarizer.js.map +1 -1
  187. package/lib/summary/summarizerNode/summarizerNode.d.ts +5 -5
  188. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  189. package/lib/summary/summarizerNode/summarizerNode.js +8 -11
  190. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  191. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
  192. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  193. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +5 -9
  194. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  195. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  196. package/lib/summary/summaryGenerator.js +6 -2
  197. package/lib/summary/summaryGenerator.js.map +1 -1
  198. package/lib/summary/summaryManager.d.ts +2 -3
  199. package/lib/summary/summaryManager.d.ts.map +1 -1
  200. package/lib/summary/summaryManager.js +7 -3
  201. package/lib/summary/summaryManager.js.map +1 -1
  202. package/package.json +16 -16
  203. package/src/batchTracker.ts +2 -2
  204. package/src/blobManager.ts +70 -13
  205. package/src/connectionTelemetry.ts +7 -3
  206. package/src/containerRuntime.ts +287 -150
  207. package/src/dataStore.ts +3 -0
  208. package/src/dataStoreContext.ts +31 -33
  209. package/src/dataStoreContexts.ts +2 -2
  210. package/src/dataStores.ts +15 -18
  211. package/src/deltaManagerSummarizerProxy.ts +2 -0
  212. package/src/deltaScheduler.ts +6 -10
  213. package/src/gc/garbageCollection.ts +13 -8
  214. package/src/gc/gcHelpers.ts +1 -0
  215. package/src/gc/gcTelemetry.ts +12 -8
  216. package/src/id-compressor/idCompressor.ts +6 -5
  217. package/src/opLifecycle/opCompressor.ts +4 -3
  218. package/src/opLifecycle/opDecompressor.ts +4 -3
  219. package/src/opLifecycle/opSplitter.ts +4 -3
  220. package/src/opLifecycle/outbox.ts +13 -25
  221. package/src/opLifecycle/remoteMessageProcessor.ts +8 -2
  222. package/src/packageVersion.ts +1 -1
  223. package/src/pendingStateManager.ts +22 -10
  224. package/src/scheduleManager.ts +2 -2
  225. package/src/summary/orderedClientElection.ts +2 -2
  226. package/src/summary/runningSummarizer.ts +18 -44
  227. package/src/summary/summarizer.ts +2 -2
  228. package/src/summary/summarizerNode/summarizerNode.ts +13 -15
  229. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +8 -7
  230. package/src/summary/summaryGenerator.ts +6 -2
  231. package/src/summary/summaryManager.ts +9 -5
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
13
13
  import { assert, delay, Trace, TypedEventEmitter, unreachableCase, } from "@fluidframework/common-utils";
14
14
  import { LazyPromise } from "@fluidframework/core-utils";
15
- import { ChildLogger, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, loggerToMonitoringContext, wrapError, } from "@fluidframework/telemetry-utils";
15
+ import { createChildLogger, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, wrapError, createChildMonitoringContext, } from "@fluidframework/telemetry-utils";
16
16
  import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
17
17
  import { readAndParse } from "@fluidframework/driver-utils";
18
18
  import { DataCorruptionError, DataProcessingError, GenericError, UsageError, } from "@fluidframework/container-utils";
@@ -115,7 +115,7 @@ const defaultChunkSizeInBytes = 204800;
115
115
  * of the current system, we should close the summarizer and let it recover.
116
116
  * This delay's goal is to prevent tight restart loops
117
117
  */
118
- const defaultCloseSummarizerDelayMs = 10000; // 10 seconds
118
+ const defaultCloseSummarizerDelayMs = 5000; // 5 seconds
119
119
  /**
120
120
  * @deprecated - use ContainerRuntimeMessage instead
121
121
  */
@@ -154,6 +154,20 @@ export function getDeviceSpec() {
154
154
  catch (_a) { }
155
155
  return {};
156
156
  }
157
+ /**
158
+ * Older loader doesn't have a submitBatchFn member, this is the older way of submitting a batch.
159
+ * Rather than exposing the submitFn (now deprecated) and IDeltaManager (dangerous to hand out) to the Outbox,
160
+ * we can provide a partially-applied function to keep those items private to the ContainerRuntime.
161
+ */
162
+ export const makeLegacySendBatchFn = (submitFn, deltaManager) => (batch) => {
163
+ for (const message of batch.content) {
164
+ submitFn(MessageType.Operation,
165
+ // For back-compat (submitFn only works on deserialized content)
166
+ message.contents === undefined ? undefined : JSON.parse(message.contents), true, // batch
167
+ message.metadata);
168
+ }
169
+ deltaManager.flush();
170
+ };
157
171
  /**
158
172
  * Represents the runtime of the container. Contains helper functions/state of the container.
159
173
  * It will define the store level mappings.
@@ -166,7 +180,6 @@ export class ContainerRuntime extends TypedEventEmitter {
166
180
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
167
181
  if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
168
182
  super();
169
- this.context = context;
170
183
  this.registry = registry;
171
184
  this.runtimeOptions = runtimeOptions;
172
185
  this.containerScope = containerScope;
@@ -196,7 +209,7 @@ export class ContainerRuntime extends TypedEventEmitter {
196
209
  trackingSignalSequenceNumber: undefined,
197
210
  };
198
211
  this.summarizeOnDemand = (...args) => {
199
- if (this.clientDetails.type === summarizerClientType) {
212
+ if (this.isSummarizerClient) {
200
213
  return this.summarizer.summarizeOnDemand(...args);
201
214
  }
202
215
  else if (this.summaryManager !== undefined) {
@@ -210,7 +223,7 @@ export class ContainerRuntime extends TypedEventEmitter {
210
223
  }
211
224
  };
212
225
  this.enqueueSummarize = (...args) => {
213
- if (this.clientDetails.type === summarizerClientType) {
226
+ if (this.isSummarizerClient) {
214
227
  return this.summarizer.enqueueSummarize(...args);
215
228
  }
216
229
  else if (this.summaryManager !== undefined) {
@@ -223,9 +236,48 @@ export class ContainerRuntime extends TypedEventEmitter {
223
236
  throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
224
237
  }
225
238
  };
226
- this.innerDeltaManager = context.deltaManager;
227
- this.deltaManager = new DeltaManagerSummarizerProxy(context.deltaManager);
228
- this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
239
+ const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
240
+ this.innerDeltaManager = deltaManager;
241
+ this.deltaManager = new DeltaManagerSummarizerProxy(this.innerDeltaManager);
242
+ // Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
243
+ // This makes ContainerRuntime the final gatekeeper for outgoing messages.
244
+ this.submitFn = submitFn;
245
+ this.submitBatchFn = submitBatchFn;
246
+ this.submitSummaryFn = submitSummaryFn;
247
+ this.submitSignalFn = submitSignalFn;
248
+ this.options = options;
249
+ this.clientDetails = clientDetails;
250
+ this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
251
+ this.loadedFromVersionId = (_b = context.getLoadedFromVersion()) === null || _b === void 0 ? void 0 : _b.id;
252
+ this._getClientId = () => context.clientId;
253
+ this._getAttachState = () => context.attachState;
254
+ this.getAbsoluteUrl = async (relativeUrl) => {
255
+ if (context.getAbsoluteUrl === undefined) {
256
+ throw new Error("Driver does not implement getAbsoluteUrl");
257
+ }
258
+ if (this.attachState !== AttachState.Attached) {
259
+ return undefined;
260
+ }
261
+ return context.getAbsoluteUrl(relativeUrl);
262
+ };
263
+ // TODO: Consider that the Container could just listen to these events itself, or even more appropriately maybe the
264
+ // customer should observe dirty state on the runtime (the owner of dirty state) directly, rather than on the IContainer.
265
+ this.on("dirty", () => context.updateDirtyContainerState(true));
266
+ this.on("saved", () => context.updateDirtyContainerState(false));
267
+ // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
268
+ this.disposeFn = disposeFn !== null && disposeFn !== void 0 ? disposeFn : closeFn;
269
+ // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
270
+ this.closeFn = this.isSummarizerClient
271
+ ? this.disposeFn
272
+ : (error) => {
273
+ closeFn(error);
274
+ // Also call disposeFn to retain functionality of runtime being disposed on close
275
+ disposeFn === null || disposeFn === void 0 ? void 0 : disposeFn(error);
276
+ };
277
+ this.mc = createChildMonitoringContext({
278
+ logger: this.logger,
279
+ namespace: "ContainerRuntime",
280
+ });
229
281
  let loadSummaryNumber;
230
282
  // Get the container creation metadata. For new container, we initialize these. For existing containers,
231
283
  // get the values from the metadata blob.
@@ -236,10 +288,10 @@ export class ContainerRuntime extends TypedEventEmitter {
236
288
  };
237
289
  // summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
238
290
  // the count is reset to 0.
239
- loadSummaryNumber = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _b !== void 0 ? _b : 0;
291
+ loadSummaryNumber = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _c !== void 0 ? _c : 0;
240
292
  // Enabling the IdCompressor is a one-way operation and we only want to
241
293
  // allow new containers to turn it on
242
- this.idCompressorEnabled = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.idCompressorEnabled) !== null && _c !== void 0 ? _c : false;
294
+ this.idCompressorEnabled = (_d = metadata === null || metadata === void 0 ? void 0 : metadata.idCompressorEnabled) !== null && _d !== void 0 ? _d : false;
243
295
  }
244
296
  else {
245
297
  this.createContainerMetadata = {
@@ -248,12 +300,14 @@ export class ContainerRuntime extends TypedEventEmitter {
248
300
  };
249
301
  loadSummaryNumber = 0;
250
302
  this.idCompressorEnabled =
251
- (_d = this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) !== null && _d !== void 0 ? _d : idCompressor !== undefined;
303
+ (_e = this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) !== null && _e !== void 0 ? _e : idCompressor !== undefined;
252
304
  }
253
305
  this.nextSummaryNumber = loadSummaryNumber + 1;
254
306
  this.messageAtLastSummary = metadata === null || metadata === void 0 ? void 0 : metadata.message;
255
- this._connected = this.context.connected;
256
- this.gcTombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement((_e = metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix) === null || _e === void 0 ? void 0 : _e.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */);
307
+ // Note that we only need to pull the *initial* connected state from the context.
308
+ // Later updates come through calls to setConnectionState.
309
+ this._connected = connected;
310
+ this.gcTombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement((_f = metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix) === null || _f === void 0 ? void 0 : _f.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */);
257
311
  this.mc.logger.sendTelemetryEvent({
258
312
  eventName: "GCFeatureMatrix",
259
313
  metadataValue: JSON.stringify(metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix),
@@ -261,11 +315,11 @@ export class ContainerRuntime extends TypedEventEmitter {
261
315
  gcOptions_gcTombstoneGeneration: this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName],
262
316
  }),
263
317
  });
264
- this.telemetryDocumentId = (_f = metadata === null || metadata === void 0 ? void 0 : metadata.telemetryDocumentId) !== null && _f !== void 0 ? _f : uuid();
318
+ this.telemetryDocumentId = (_g = metadata === null || metadata === void 0 ? void 0 : metadata.telemetryDocumentId) !== null && _g !== void 0 ? _g : uuid();
265
319
  this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
266
320
  const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
267
321
  const opGroupingManager = new OpGroupingManager(this.groupedBatchingEnabled);
268
- const opSplitter = new OpSplitter(chunks, this.context.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
322
+ const opSplitter = new OpSplitter(chunks, this.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
269
323
  this.remoteMessageProcessor = new RemoteMessageProcessor(opSplitter, new OpDecompressor(this.mc.logger), opGroupingManager);
270
324
  this.handleContext = new ContainerFluidHandleContext("", this);
271
325
  if (this.summaryConfiguration.state === "enabled") {
@@ -284,9 +338,9 @@ export class ContainerRuntime extends TypedEventEmitter {
284
338
  this.idCompressor = idCompressor;
285
339
  }
286
340
  this.maxConsecutiveReconnects =
287
- (_g = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _g !== void 0 ? _g : this.defaultMaxConsecutiveReconnects;
341
+ (_h = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _h !== void 0 ? _h : this.defaultMaxConsecutiveReconnects;
288
342
  if (runtimeOptions.flushMode === FlushModeExperimental.Async &&
289
- ((_h = context.supportedFeatures) === null || _h === void 0 ? void 0 : _h.get("referenceSequenceNumbers")) !== true) {
343
+ (supportedFeatures === null || supportedFeatures === void 0 ? void 0 : supportedFeatures.get("referenceSequenceNumbers")) !== true) {
290
344
  // The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
291
345
  this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
292
346
  this._flushMode = FlushMode.TurnBased;
@@ -294,7 +348,7 @@ export class ContainerRuntime extends TypedEventEmitter {
294
348
  else {
295
349
  this._flushMode = runtimeOptions.flushMode;
296
350
  }
297
- const pendingRuntimeState = context.pendingLocalState;
351
+ const pendingRuntimeState = pendingLocalState;
298
352
  const maxSnapshotCacheDurationMs = (_k = (_j = this._storage) === null || _j === void 0 ? void 0 : _j.policies) === null || _k === void 0 ? void 0 : _k.maximumCacheDurationMs;
299
353
  if (maxSnapshotCacheDurationMs !== undefined &&
300
354
  maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
@@ -306,12 +360,12 @@ export class ContainerRuntime extends TypedEventEmitter {
306
360
  this.garbageCollector = GarbageCollector.create({
307
361
  runtime: this,
308
362
  gcOptions: this.runtimeOptions.gcOptions,
309
- baseSnapshot: context.baseSnapshot,
363
+ baseSnapshot,
310
364
  baseLogger: this.mc.logger,
311
365
  existing,
312
366
  metadata,
313
367
  createContainerMetadata: this.createContainerMetadata,
314
- isSummarizerClient: this.context.clientDetails.type === summarizerClientType,
368
+ isSummarizerClient: this.isSummarizerClient,
315
369
  getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
316
370
  getLastSummaryTimestampMs: () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; },
317
371
  readAndParseBlob: async (id) => readAndParse(this.storage, id),
@@ -320,13 +374,13 @@ export class ContainerRuntime extends TypedEventEmitter {
320
374
  activeConnection: () => this.innerDeltaManager.active,
321
375
  });
322
376
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
323
- this.summarizerNode = createRootSummarizerNodeWithGC(ChildLogger.create(this.logger, "SummarizerNode"),
377
+ this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
324
378
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
325
379
  async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
326
380
  // Latest change sequence number, no changes since summary applied yet
327
381
  loadedFromSequenceNumber,
328
382
  // Summary reference sequence number, undefined if no summary yet
329
- context.baseSnapshot ? loadedFromSequenceNumber : undefined, {
383
+ baseSnapshot !== undefined ? loadedFromSequenceNumber : undefined, {
330
384
  // Must set to false to prevent sending summary handle which would be pointing to
331
385
  // a summary with an older protocol state.
332
386
  canReuseHandle: false,
@@ -340,19 +394,19 @@ export class ContainerRuntime extends TypedEventEmitter {
340
394
  async (fullGC) => this.getGCDataInternal(fullGC),
341
395
  // Function to get the GC details from the base snapshot we loaded from.
342
396
  async () => this.garbageCollector.getBaseGCDetails());
343
- if (context.baseSnapshot) {
344
- this.summarizerNode.updateBaseSummaryState(context.baseSnapshot);
397
+ if (baseSnapshot) {
398
+ this.summarizerNode.updateBaseSummaryState(baseSnapshot);
345
399
  }
346
- this.dataStores = new DataStores(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));
400
+ this.dataStores = new DataStores(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));
347
401
  this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
348
402
  if (!this.disposed) {
349
- this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
403
+ this.submit({ type: ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
350
404
  localId,
351
405
  blobId,
352
406
  });
353
407
  }
354
408
  }, (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));
355
- this.scheduleManager = new ScheduleManager(context.deltaManager, this, () => this.clientId, ChildLogger.create(this.logger, "ScheduleManager"));
409
+ this.scheduleManager = new ScheduleManager(this.innerDeltaManager, this, () => this.clientId, createChildLogger({ logger: this.logger, namespace: "ScheduleManager" }));
356
410
  this.pendingStateManager = new PendingStateManager({
357
411
  applyStashedOp: this.applyStashedOp.bind(this),
358
412
  clientId: () => this.clientId,
@@ -360,7 +414,8 @@ export class ContainerRuntime extends TypedEventEmitter {
360
414
  connected: () => this.connected,
361
415
  reSubmit: this.reSubmit.bind(this),
362
416
  reSubmitBatch: this.reSubmitBatch.bind(this),
363
- }, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending);
417
+ isActiveConnection: () => this.innerDeltaManager.active,
418
+ }, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending, this.logger);
364
419
  const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
365
420
  const compressionOptions = disableCompression === true
366
421
  ? {
@@ -369,10 +424,12 @@ export class ContainerRuntime extends TypedEventEmitter {
369
424
  }
370
425
  : runtimeOptions.compressionOptions;
371
426
  const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
427
+ const legacySendBatchFn = makeLegacySendBatchFn(this.submitFn, this.innerDeltaManager);
372
428
  this.outbox = new Outbox({
373
429
  shouldSend: () => this.canSendOps(),
374
430
  pendingStateManager: this.pendingStateManager,
375
- containerContext: this.context,
431
+ submitBatchFn: this.submitBatchFn,
432
+ legacySendBatchFn,
376
433
  compressor: new OpCompressor(this.mc.logger),
377
434
  splitter: opSplitter,
378
435
  config: {
@@ -391,9 +448,12 @@ export class ContainerRuntime extends TypedEventEmitter {
391
448
  opReentrancy: () => this.ensureNoDataModelChangesCalls > 0,
392
449
  closeContainer: this.closeFn,
393
450
  });
394
- this.context.quorum.on("removeMember", (clientId) => {
451
+ this._quorum = quorum;
452
+ this._quorum.on("removeMember", (clientId) => {
395
453
  this.remoteMessageProcessor.clearPartialMessagesFor(clientId);
396
454
  });
455
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
456
+ this._audience = audience;
397
457
  this.summaryStateUpdateMethod = this.mc.config.getString("Fluid.ContainerRuntime.Test.SummaryStateUpdateMethodV2");
398
458
  const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
399
459
  this.closeSummarizerDelayMs = closeSummarizerDelayOverride !== null && closeSummarizerDelayOverride !== void 0 ? closeSummarizerDelayOverride : defaultCloseSummarizerDelayMs;
@@ -401,34 +461,39 @@ export class ContainerRuntime extends TypedEventEmitter {
401
461
  (_l = this.mc.config.getBoolean("Fluid.ContainerRuntime.Test.ValidateSummaryBeforeUpload")) !== null && _l !== void 0 ? _l : false;
402
462
  this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
403
463
  this.dirtyContainer =
404
- this.context.attachState !== AttachState.Attached ||
464
+ this.attachState !== AttachState.Attached ||
405
465
  this.pendingStateManager.hasPendingMessages();
406
- this.context.updateDirtyContainerState(this.dirtyContainer);
466
+ context.updateDirtyContainerState(this.dirtyContainer);
407
467
  if (this.summariesDisabled) {
408
468
  this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
409
469
  }
410
470
  else {
411
- const orderedClientLogger = ChildLogger.create(this.logger, "OrderedClientElection");
412
- const orderedClientCollection = new OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
413
- const orderedClientElectionForSummarizer = new OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, SummarizerClientElection.isClientEligible);
471
+ const orderedClientLogger = createChildLogger({
472
+ logger: this.logger,
473
+ namespace: "OrderedClientElection",
474
+ });
475
+ const orderedClientCollection = new OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
476
+ const orderedClientElectionForSummarizer = new OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.innerDeltaManager.lastSequenceNumber, SummarizerClientElection.isClientEligible);
414
477
  this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
415
- if (this.context.clientDetails.type === summarizerClientType) {
478
+ if (this.isSummarizerClient) {
416
479
  this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => RunWhileConnectedCoordinator.create(runtime,
417
480
  // Summarization runs in summarizer client and needs access to the real (non-proxy) active
418
481
  // information. The proxy delta manager would always return false for summarizer client.
419
482
  () => this.innerDeltaManager.active));
420
483
  }
421
- else if (SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)) {
484
+ else if (SummarizerClientElection.clientDetailsPermitElection(this.clientDetails)) {
422
485
  // Only create a SummaryManager and SummarizerClientElection
423
486
  // if summaries are enabled and we are not the summarizer client.
424
487
  const defaultAction = () => {
425
488
  if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
426
- this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
489
+ this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
427
490
  // unregister default to no log on every op after falling behind
428
491
  // and register summary ack handler to re-register this handler
429
492
  // after successful summary
430
493
  this.summaryCollection.once(MessageType.SummaryAck, () => {
431
- this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:CaughtUp" });
494
+ this.mc.logger.sendTelemetryEvent({
495
+ eventName: "SummaryStatus:CaughtUp",
496
+ });
432
497
  // we've caught up, so re-register the default action to monitor for
433
498
  // falling behind, and unregister ourself
434
499
  this.summaryCollection.on("default", defaultAction);
@@ -439,7 +504,7 @@ export class ContainerRuntime extends TypedEventEmitter {
439
504
  this.summaryCollection.on("default", defaultAction);
440
505
  // Create the SummaryManager and mark the initial state
441
506
  this.summaryManager = new SummaryManager(this.summarizerClientElection, this, // IConnectedState
442
- this.summaryCollection, this.logger, this.formRequestSummarizerFn(this.context.loader), new Throttler(60 * 1000, // 60 sec delay window
507
+ this.summaryCollection, this.logger, this.formRequestSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
443
508
  30 * 1000, // 30 sec max delay
444
509
  // throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
445
510
  formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
@@ -470,7 +535,7 @@ export class ContainerRuntime extends TypedEventEmitter {
470
535
  });
471
536
  // logging hardware telemetry
472
537
  logger.sendTelemetryEvent(Object.assign({ eventName: "DeviceSpec" }, getDeviceSpec()));
473
- 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({
538
+ this.mc.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({
474
539
  disableCompression,
475
540
  disableOpReentryCheck,
476
541
  disableChunking,
@@ -480,10 +545,10 @@ export class ContainerRuntime extends TypedEventEmitter {
480
545
  summaryStateUpdateMethod: this.summaryStateUpdateMethod,
481
546
  closeSummarizerDelayOverride,
482
547
  }), telemetryDocumentId: this.telemetryDocumentId, groupedBatchingEnabled: this.groupedBatchingEnabled }));
483
- ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
548
+ ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
484
549
  BindBatchTracker(this, this.logger);
485
550
  this.entryPoint = new LazyPromise(async () => {
486
- if (this.context.clientDetails.type === summarizerClientType) {
551
+ if (this.isSummarizerClient) {
487
552
  assert(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
488
553
  return this._summarizer;
489
554
  }
@@ -541,9 +606,12 @@ export class ContainerRuntime extends TypedEventEmitter {
541
606
  // back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
542
607
  const backCompatContext = context;
543
608
  const passLogger = (_a = backCompatContext.taggedLogger) !== null && _a !== void 0 ? _a : new TaggedLoggerAdapter(backCompatContext.logger);
544
- const logger = ChildLogger.create(passLogger, undefined, {
545
- all: {
546
- runtimeVersion: pkgVersion,
609
+ const logger = createChildLogger({
610
+ logger: passLogger,
611
+ properties: {
612
+ all: {
613
+ runtimeVersion: pkgVersion,
614
+ },
547
615
  },
548
616
  });
549
617
  const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = false, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
@@ -624,38 +692,15 @@ export class ContainerRuntime extends TypedEventEmitter {
624
692
  await runtime.initializeBaseState();
625
693
  return runtime;
626
694
  }
627
- get options() {
628
- return this.context.options;
629
- }
630
695
  get clientId() {
631
- return this.context.clientId;
632
- }
633
- get clientDetails() {
634
- return this.context.clientDetails;
696
+ return this._getClientId();
635
697
  }
636
698
  get storage() {
637
699
  return this._storage;
638
700
  }
701
+ /** @deprecated - The functionality is no longer exposed publicly */
639
702
  get reSubmitFn() {
640
- // eslint-disable-next-line @typescript-eslint/unbound-method
641
- return this.reSubmitCore;
642
- }
643
- get disposeFn() {
644
- var _a;
645
- // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
646
- return (_a = this.context.disposeFn) !== null && _a !== void 0 ? _a : this.context.closeFn;
647
- }
648
- get closeFn() {
649
- if (this._summarizer !== undefined) {
650
- // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
651
- return this.disposeFn;
652
- }
653
- // Also call disposeFn to retain functionality of runtime being disposed on close
654
- return (error) => {
655
- var _a, _b;
656
- this.context.closeFn(error);
657
- (_b = (_a = this.context).disposeFn) === null || _b === void 0 ? void 0 : _b.call(_a, error);
658
- };
703
+ return (type, contents, localOpMetadata, opMetadata) => this.reSubmitCore({ type, contents }, localOpMetadata, opMetadata);
659
704
  }
660
705
  get flushMode() {
661
706
  return this._flushMode;
@@ -667,7 +712,7 @@ export class ContainerRuntime extends TypedEventEmitter {
667
712
  return this.registry;
668
713
  }
669
714
  get attachState() {
670
- return this.context.attachState;
715
+ return this._getAttachState();
671
716
  }
672
717
  get IFluidHandleContext() {
673
718
  return this.handleContext;
@@ -737,7 +782,7 @@ export class ContainerRuntime extends TypedEventEmitter {
737
782
  return;
738
783
  }
739
784
  this._disposed = true;
740
- this.logger.sendTelemetryEvent({
785
+ this.mc.logger.sendTelemetryEvent({
741
786
  eventName: "ContainerRuntimeDisposed",
742
787
  isDirty: this.isDirty,
743
788
  lastSequenceNumber: this.deltaManager.lastSequenceNumber,
@@ -972,9 +1017,9 @@ export class ContainerRuntime extends TypedEventEmitter {
972
1017
  */
973
1018
  parseOpContent(serializedContent) {
974
1019
  assert(serializedContent !== undefined, 0x6d5 /* content must be defined */);
975
- const parsed = JSON.parse(serializedContent);
976
- assert(parsed.type !== undefined, 0x6d6 /* incorrect op content format */);
977
- return { type: parsed.type, contents: parsed.contents };
1020
+ const { type, contents } = JSON.parse(serializedContent);
1021
+ assert(type !== undefined, 0x6d6 /* incorrect op content format */);
1022
+ return { type, contents };
978
1023
  }
979
1024
  async applyStashedOp(op) {
980
1025
  // Need to parse from string for back-compat
@@ -1033,6 +1078,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1033
1078
  // There might be no change of state due to Container calling this API after loading runtime.
1034
1079
  const changeOfState = this._connected !== connected;
1035
1080
  const reconnection = changeOfState && !connected;
1081
+ // We need to flush the ops currently collected by Outbox to preserve original order.
1082
+ // This flush NEEDS to happen before we set the ContainerRuntime to "connected".
1083
+ // We want these ops to get to the PendingStateManager without sending to service and have them return to the Outbox upon calling "replayPendingStates".
1084
+ if (changeOfState && connected) {
1085
+ this.flush();
1086
+ }
1036
1087
  this._connected = connected;
1037
1088
  if (!connected) {
1038
1089
  this._perfSignalData.signalsLost = 0;
@@ -1076,6 +1127,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1076
1127
  this.processCore(message, local, runtimeMessage);
1077
1128
  }
1078
1129
  }
1130
+ /**
1131
+ * Direct the message to the correct subsystem for processing, and implement other side effects
1132
+ * @param message - The unpacked message. Likely a ContainerRuntimeMessage, but could also be a system op
1133
+ * @param local - Did this client send the op?
1134
+ * @param runtimeMessage - Does this appear like a current ContainerRuntimeMessage? If true, certain validation will occur.
1135
+ */
1079
1136
  processCore(message, local, runtimeMessage) {
1080
1137
  var _a;
1081
1138
  // Surround the actual processing of the operation with messages to the schedule manager indicating
@@ -1129,9 +1186,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1129
1186
  throw error;
1130
1187
  }
1131
1188
  }
1132
- if (runtimeMessage || this.groupedBatchingEnabled) {
1133
- this.emit("op", message, runtimeMessage);
1134
- }
1189
+ this.emit("op", message, runtimeMessage);
1135
1190
  this.scheduleManager.afterOpProcessing(undefined, message);
1136
1191
  if (local) {
1137
1192
  // If we have processed a local op, this means that the container is
@@ -1154,7 +1209,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1154
1209
  */
1155
1210
  sendSignalTelemetryEvent(clientSignalSequenceNumber) {
1156
1211
  const duration = Date.now() - this._perfSignalData.signalTimestamp;
1157
- this.logger.sendPerformanceEvent({
1212
+ this.mc.logger.sendPerformanceEvent({
1158
1213
  eventName: "SignalLatency",
1159
1214
  duration,
1160
1215
  signalsLost: this._perfSignalData.signalsLost,
@@ -1177,7 +1232,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1177
1232
  this._perfSignalData.trackingSignalSequenceNumber) {
1178
1233
  this._perfSignalData.signalsLost++;
1179
1234
  this._perfSignalData.trackingSignalSequenceNumber = undefined;
1180
- this.logger.sendErrorEvent({
1235
+ this.mc.logger.sendErrorEvent({
1181
1236
  eventName: "SignalLost",
1182
1237
  type: envelope.contents.type,
1183
1238
  signalsLost: this._perfSignalData.signalsLost,
@@ -1298,11 +1353,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1298
1353
  return this.flushMode !== FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
1299
1354
  }
1300
1355
  getQuorum() {
1301
- return this.context.quorum;
1356
+ return this._quorum;
1302
1357
  }
1303
1358
  getAudience() {
1304
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1305
- return this.context.audience;
1359
+ return this._audience;
1306
1360
  }
1307
1361
  /**
1308
1362
  * Returns true of container is dirty, i.e. there are some pending local changes that
@@ -1311,7 +1365,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1311
1365
  get isDirty() {
1312
1366
  return this.dirtyContainer;
1313
1367
  }
1314
- isContainerMessageDirtyable(type, contents) {
1368
+ isContainerMessageDirtyable({ type, contents }) {
1315
1369
  // For legacy purposes, exclude the old built-in AgentScheduler from dirty consideration as a special-case.
1316
1370
  // Ultimately we should have no special-cases from the ContainerRuntime's perspective.
1317
1371
  if (type === ContainerMessageType.Attach) {
@@ -1351,11 +1405,11 @@ export class ContainerRuntime extends TypedEventEmitter {
1351
1405
  submitSignal(type, content) {
1352
1406
  this.verifyNotClosed();
1353
1407
  const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
1354
- return this.context.submitSignalFn(envelope);
1408
+ return this.submitSignalFn(envelope);
1355
1409
  }
1356
1410
  submitDataStoreSignal(address, type, content) {
1357
1411
  const envelope = this.createNewSignalEnvelope(address, type, content);
1358
- return this.context.submitSignalFn(envelope);
1412
+ return this.submitSignalFn(envelope);
1359
1413
  }
1360
1414
  setAttachState(attachState) {
1361
1415
  if (attachState === AttachState.Attaching) {
@@ -1388,15 +1442,6 @@ export class ContainerRuntime extends TypedEventEmitter {
1388
1442
  this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
1389
1443
  return summarizeResult.summary;
1390
1444
  }
1391
- async getAbsoluteUrl(relativeUrl) {
1392
- if (this.context.getAbsoluteUrl === undefined) {
1393
- throw new Error("Driver does not implement getAbsoluteUrl");
1394
- }
1395
- if (this.attachState !== AttachState.Attached) {
1396
- return undefined;
1397
- }
1398
- return this.context.getAbsoluteUrl(relativeUrl);
1399
- }
1400
1445
  async summarizeInternal(fullTree, trackState, telemetryContext) {
1401
1446
  const summarizeResult = await this.dataStores.summarize(fullTree, trackState, telemetryContext);
1402
1447
  // Wrap data store summaries in .channels subtree.
@@ -1430,7 +1475,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1430
1475
  return { stats, summary, gcStats };
1431
1476
  }
1432
1477
  finally {
1433
- this.logger.sendTelemetryEvent({
1478
+ this.mc.logger.sendTelemetryEvent({
1434
1479
  eventName: "SummarizeTelemetry",
1435
1480
  details: telemetryContext.serialize(),
1436
1481
  });
@@ -1597,18 +1642,25 @@ export class ContainerRuntime extends TypedEventEmitter {
1597
1642
  * @param options - options controlling how the summary is generated or submitted
1598
1643
  */
1599
1644
  async submitSummary(options) {
1600
- var _a, _b, _c;
1645
+ var _a, _b;
1601
1646
  const { fullTree = false, refreshLatestAck, summaryLogger } = options;
1602
1647
  // The summary number for this summary. This will be updated during the summary process, so get it now and
1603
1648
  // use it for all events logged during this summary.
1604
1649
  const summaryNumber = this.nextSummaryNumber;
1605
- const summaryNumberLogger = ChildLogger.create(summaryLogger, undefined, {
1606
- all: { summaryNumber },
1650
+ const summaryNumberLogger = createChildLogger({
1651
+ logger: summaryLogger,
1652
+ properties: {
1653
+ all: { summaryNumber },
1654
+ },
1607
1655
  });
1608
1656
  assert(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
1609
1657
  let latestSnapshotVersionId;
1610
1658
  if (refreshLatestAck) {
1611
- const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer(ChildLogger.create(summaryNumberLogger, undefined, { all: { safeSummary: true } }));
1659
+ const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer(createChildLogger({
1660
+ logger: summaryNumberLogger,
1661
+ namespace: undefined,
1662
+ properties: { all: { safeSummary: true } },
1663
+ }));
1612
1664
  const latestSnapshotRefSeq = latestSnapshotInfo.latestSnapshotRefSeq;
1613
1665
  latestSnapshotVersionId = latestSnapshotInfo.latestSnapshotVersionId;
1614
1666
  // We might need to catch up to the latest summary's reference sequence number before pausing.
@@ -1742,7 +1794,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1742
1794
  else if (lastAck === undefined) {
1743
1795
  summaryContext = {
1744
1796
  proposalHandle: undefined,
1745
- ackHandle: (_a = this.context.getLoadedFromVersion()) === null || _a === void 0 ? void 0 : _a.id,
1797
+ ackHandle: this.loadedFromVersionId,
1746
1798
  referenceSequenceNumber: summaryRefSeqNum,
1747
1799
  };
1748
1800
  }
@@ -1794,7 +1846,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1794
1846
  // Cleanup wip summary in case of failure
1795
1847
  this.summarizerNode.clearSummary();
1796
1848
  // ! This needs to happen before we resume inbound queues to ensure heuristics are tracked correctly
1797
- (_c = (_b = this._summarizer) === null || _b === void 0 ? void 0 : _b.recordSummaryAttempt) === null || _c === void 0 ? void 0 : _c.call(_b, summaryRefSeqNum);
1849
+ (_b = (_a = this._summarizer) === null || _a === void 0 ? void 0 : _a.recordSummaryAttempt) === null || _b === void 0 ? void 0 : _b.call(_a, summaryRefSeqNum);
1798
1850
  // Restart the delta manager
1799
1851
  this.deltaManager.inbound.resume();
1800
1852
  if (shouldPauseInboundSignal) {
@@ -1819,7 +1871,6 @@ export class ContainerRuntime extends TypedEventEmitter {
1819
1871
  this.dirtyContainer = dirty;
1820
1872
  if (this.emitDirtyDocumentEvent) {
1821
1873
  this.emit(dirty ? "dirty" : "saved");
1822
- this.context.updateDirtyContainerState(dirty);
1823
1874
  }
1824
1875
  }
1825
1876
  submitDataStoreOp(id, contents, localOpMetadata = undefined) {
@@ -1827,18 +1878,18 @@ export class ContainerRuntime extends TypedEventEmitter {
1827
1878
  address: id,
1828
1879
  contents,
1829
1880
  };
1830
- this.submit(ContainerMessageType.FluidDataStoreOp, envelope, localOpMetadata);
1881
+ this.submit({ type: ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
1831
1882
  }
1832
1883
  submitDataStoreAliasOp(contents, localOpMetadata) {
1833
1884
  const aliasMessage = contents;
1834
1885
  if (!isDataStoreAliasMessage(aliasMessage)) {
1835
1886
  throw new UsageError("malformedDataStoreAliasMessage");
1836
1887
  }
1837
- this.submit(ContainerMessageType.Alias, contents, localOpMetadata);
1888
+ this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
1838
1889
  }
1839
- async uploadBlob(blob) {
1890
+ async uploadBlob(blob, signal) {
1840
1891
  this.verifyNotClosed();
1841
- return this.blobManager.createBlob(blob);
1892
+ return this.blobManager.createBlob(blob, signal);
1842
1893
  }
1843
1894
  maybeSubmitIdAllocationOp(type) {
1844
1895
  var _a, _b;
@@ -1869,20 +1920,21 @@ export class ContainerRuntime extends TypedEventEmitter {
1869
1920
  }
1870
1921
  }
1871
1922
  }
1872
- submit(type, contents, localOpMetadata = undefined, metadata = undefined) {
1923
+ submit(containerRuntimeMessage, localOpMetadata = undefined, metadata = undefined) {
1873
1924
  this.verifyNotClosed();
1874
1925
  this.verifyCanSubmitOps();
1875
1926
  // There should be no ops in detached container state!
1876
1927
  assert(this.attachState !== AttachState.Detached, 0x132 /* "sending ops in detached container" */);
1877
- const serializedContent = JSON.stringify({ type, contents });
1928
+ const serializedContent = JSON.stringify(containerRuntimeMessage);
1878
1929
  // Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
1879
1930
  // container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
1880
1931
  if (this.innerDeltaManager.readOnlyInfo.readonly) {
1881
- this.logger.sendTelemetryEvent({
1932
+ this.mc.logger.sendTelemetryEvent({
1882
1933
  eventName: "SubmitOpInReadonly",
1883
1934
  connected: this.connected,
1884
1935
  });
1885
1936
  }
1937
+ const type = containerRuntimeMessage.type;
1886
1938
  const message = {
1887
1939
  contents: serializedContent,
1888
1940
  type,
@@ -1939,7 +1991,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1939
1991
  this.closeFn(error);
1940
1992
  throw error;
1941
1993
  }
1942
- if (this.isContainerMessageDirtyable(type, contents)) {
1994
+ if (this.isContainerMessageDirtyable(containerRuntimeMessage)) {
1943
1995
  this.updateDocumentDirtyState(true);
1944
1996
  }
1945
1997
  }
@@ -1982,9 +2034,9 @@ export class ContainerRuntime extends TypedEventEmitter {
1982
2034
  // System message should not be sent in the middle of the batch.
1983
2035
  assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
1984
2036
  // back-compat: ADO #1385: Make this call unconditional in the future
1985
- return this.context.submitSummaryFn !== undefined
1986
- ? this.context.submitSummaryFn(contents, referenceSequenceNumber)
1987
- : this.context.submitFn(MessageType.Summarize, contents, false);
2037
+ return this.submitSummaryFn !== undefined
2038
+ ? this.submitSummaryFn(contents, referenceSequenceNumber)
2039
+ : this.submitFn(MessageType.Summarize, contents, false);
1988
2040
  }
1989
2041
  /**
1990
2042
  * Throw an error if the runtime is closed. Methods that are expected to potentially
@@ -2031,32 +2083,33 @@ export class ContainerRuntime extends TypedEventEmitter {
2031
2083
  }
2032
2084
  reSubmit(message) {
2033
2085
  // Need to parse from string for back-compat
2034
- const { contents, type } = this.parseOpContent(message.content);
2035
- this.reSubmitCore(type, contents, message.localOpMetadata, message.opMetadata);
2086
+ const containerRuntimeMessage = this.parseOpContent(message.content);
2087
+ this.reSubmitCore(containerRuntimeMessage, message.localOpMetadata, message.opMetadata);
2036
2088
  }
2037
2089
  /**
2038
2090
  * Finds the right store and asks it to resubmit the message. This typically happens when we
2039
2091
  * reconnect and there are pending messages.
2040
- * @param content - The content of the original message.
2092
+ * @param message - The original ContainerRuntimeMessage.
2041
2093
  * @param localOpMetadata - The local metadata associated with the original message.
2042
2094
  */
2043
- reSubmitCore(type, content, localOpMetadata, opMetadata) {
2044
- switch (type) {
2095
+ reSubmitCore(message, localOpMetadata, opMetadata) {
2096
+ const contents = message.contents;
2097
+ switch (message.type) {
2045
2098
  case ContainerMessageType.FluidDataStoreOp:
2046
2099
  // For Operations, call resubmitDataStoreOp which will find the right store
2047
2100
  // and trigger resubmission on it.
2048
- this.dataStores.resubmitDataStoreOp(content, localOpMetadata);
2101
+ this.dataStores.resubmitDataStoreOp(contents, localOpMetadata);
2049
2102
  break;
2050
2103
  case ContainerMessageType.Attach:
2051
2104
  case ContainerMessageType.Alias:
2052
- this.submit(type, content, localOpMetadata);
2105
+ this.submit(message, localOpMetadata);
2053
2106
  break;
2054
2107
  case ContainerMessageType.IdAllocation:
2055
2108
  // Remove the stashedState from the op if it's a stashed op
2056
- if (content.stashedState !== undefined) {
2057
- delete content.stashedState;
2109
+ if (contents.stashedState !== undefined) {
2110
+ delete contents.stashedState;
2058
2111
  }
2059
- this.submit(type, content, localOpMetadata);
2112
+ this.submit(message, localOpMetadata);
2060
2113
  break;
2061
2114
  case ContainerMessageType.ChunkedOp:
2062
2115
  throw new Error(`chunkedOp not expected here`);
@@ -2064,10 +2117,10 @@ export class ContainerRuntime extends TypedEventEmitter {
2064
2117
  this.blobManager.reSubmit(opMetadata);
2065
2118
  break;
2066
2119
  case ContainerMessageType.Rejoin:
2067
- this.submit(type, content);
2120
+ this.submit(message);
2068
2121
  break;
2069
2122
  default:
2070
- unreachableCase(type, `Unknown ContainerMessageType: ${type}`);
2123
+ unreachableCase(message.type, `Unknown ContainerMessageType [type: ${message.type}]`);
2071
2124
  }
2072
2125
  }
2073
2126
  rollback(content, localOpMetadata) {
@@ -2114,7 +2167,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2114
2167
  * change that started fetching latest snapshot always.
2115
2168
  */
2116
2169
  if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
2117
- fetchResult = await this.fetchSnapshotFromStorage(summaryLogger, {
2170
+ fetchResult = await this.fetchSnapshotFromStorageAndClose(summaryLogger, {
2118
2171
  eventName: "RefreshLatestSummaryAckFetchBackCompat",
2119
2172
  ackHandle,
2120
2173
  targetSequenceNumber: summaryRefSeq,
@@ -2172,9 +2225,9 @@ export class ContainerRuntime extends TypedEventEmitter {
2172
2225
  return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
2173
2226
  }
2174
2227
  async fetchLatestSnapshotFromStorage(logger, event, readAndParseBlob) {
2175
- return this.fetchSnapshotFromStorage(logger, event, readAndParseBlob, null /* latest */);
2228
+ return this.fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, null /* latest */);
2176
2229
  }
2177
- async fetchSnapshotFromStorage(logger, event, readAndParseBlob, versionId) {
2230
+ async fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, versionId) {
2178
2231
  var _a;
2179
2232
  const snapshotResults = await PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
2180
2233
  const stats = {};
@@ -2198,14 +2251,12 @@ export class ContainerRuntime extends TypedEventEmitter {
2198
2251
  // We choose to close the summarizer after the snapshot cache is updated to avoid
2199
2252
  // situations which the main client (which is likely to be re-elected as the leader again)
2200
2253
  // loads the summarizer from cache.
2201
- if (this.summaryStateUpdateMethod === "restart") {
2202
- const error = new GenericError("Restarting summarizer instead of refreshing");
2203
- 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);
2204
- // Delay 10 seconds before restarting summarizer to prevent the summarizer from restarting too frequently.
2254
+ if (this.summaryStateUpdateMethod !== "refreshFromSnapshot") {
2255
+ 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 }), new GenericError("Restarting summarizer instead of refreshing"));
2256
+ // Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
2205
2257
  await delay(this.closeSummarizerDelayMs);
2206
2258
  (_a = this._summarizer) === null || _a === void 0 ? void 0 : _a.stop("latestSummaryStateStale");
2207
- this.closeFn();
2208
- throw error;
2259
+ this.disposeFn();
2209
2260
  }
2210
2261
  return snapshotResults;
2211
2262
  }