@fluidframework/container-runtime 2.102.0 → 2.110.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 (217) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/container-runtime.test-files.tar +0 -0
  3. package/dist/batchTracker.d.ts +1 -1
  4. package/dist/batchTracker.d.ts.map +1 -1
  5. package/dist/batchTracker.js +1 -1
  6. package/dist/batchTracker.js.map +1 -1
  7. package/dist/blobManager/blobManagerSnapSum.d.ts +2 -2
  8. package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  9. package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
  10. package/dist/connectionTelemetry.js.map +1 -1
  11. package/dist/containerRuntime.d.ts +16 -5
  12. package/dist/containerRuntime.d.ts.map +1 -1
  13. package/dist/containerRuntime.js +112 -9
  14. package/dist/containerRuntime.js.map +1 -1
  15. package/dist/dataStore.d.ts +2 -2
  16. package/dist/dataStore.d.ts.map +1 -1
  17. package/dist/dataStore.js.map +1 -1
  18. package/dist/dataStoreContexts.d.ts.map +1 -1
  19. package/dist/dataStoreContexts.js.map +1 -1
  20. package/dist/deltaScheduler.d.ts +2 -2
  21. package/dist/deltaScheduler.d.ts.map +1 -1
  22. package/dist/deltaScheduler.js.map +1 -1
  23. package/dist/gc/garbageCollection.d.ts +2 -2
  24. package/dist/gc/garbageCollection.d.ts.map +1 -1
  25. package/dist/gc/garbageCollection.js.map +1 -1
  26. package/dist/gc/gcDefinitions.d.ts +3 -3
  27. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  28. package/dist/gc/gcDefinitions.js.map +1 -1
  29. package/dist/gc/gcTelemetry.d.ts +3 -3
  30. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  31. package/dist/gc/gcTelemetry.js.map +1 -1
  32. package/dist/inboundBatchAggregator.d.ts +2 -2
  33. package/dist/inboundBatchAggregator.d.ts.map +1 -1
  34. package/dist/inboundBatchAggregator.js.map +1 -1
  35. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  36. package/dist/opLifecycle/opCompressor.js.map +1 -1
  37. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  38. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  39. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  40. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  41. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  42. package/dist/opLifecycle/opSplitter.js.map +1 -1
  43. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  44. package/dist/opLifecycle/outbox.js.map +1 -1
  45. package/dist/packageVersion.d.ts +1 -1
  46. package/dist/packageVersion.js +1 -1
  47. package/dist/packageVersion.js.map +1 -1
  48. package/dist/pendingStateManager.d.ts +48 -1
  49. package/dist/pendingStateManager.d.ts.map +1 -1
  50. package/dist/pendingStateManager.js +54 -1
  51. package/dist/pendingStateManager.js.map +1 -1
  52. package/dist/runtimeLayerCompatState.d.ts +1 -1
  53. package/dist/signalTelemetryProcessing.d.ts +2 -2
  54. package/dist/signalTelemetryProcessing.d.ts.map +1 -1
  55. package/dist/signalTelemetryProcessing.js.map +1 -1
  56. package/dist/summary/documentSchema.d.ts +2 -2
  57. package/dist/summary/documentSchema.d.ts.map +1 -1
  58. package/dist/summary/documentSchema.js.map +1 -1
  59. package/dist/summary/orderedClientElection.d.ts +2 -2
  60. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  61. package/dist/summary/orderedClientElection.js.map +1 -1
  62. package/dist/summary/summarizerClientElection.d.ts +2 -2
  63. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  64. package/dist/summary/summarizerClientElection.js.map +1 -1
  65. package/dist/summary/summarizerNode/summarizerNode.d.ts +3 -3
  66. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  67. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  68. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -2
  69. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  70. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  71. package/dist/summary/summarizerTypes.d.ts +3 -3
  72. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  73. package/dist/summary/summarizerTypes.js.map +1 -1
  74. package/dist/summary/summaryCollection.d.ts.map +1 -1
  75. package/dist/summary/summaryCollection.js.map +1 -1
  76. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +2 -2
  77. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
  78. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
  79. package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts +2 -2
  80. package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
  81. package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
  82. package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts +2 -2
  83. package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -1
  84. package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
  85. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +2 -2
  86. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
  87. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
  88. package/dist/summary/summaryManager.d.ts.map +1 -1
  89. package/dist/summary/summaryManager.js.map +1 -1
  90. package/lib/batchTracker.d.ts +1 -1
  91. package/lib/batchTracker.d.ts.map +1 -1
  92. package/lib/batchTracker.js +1 -1
  93. package/lib/batchTracker.js.map +1 -1
  94. package/lib/blobManager/blobManagerSnapSum.d.ts +2 -2
  95. package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
  96. package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
  97. package/lib/connectionTelemetry.js.map +1 -1
  98. package/lib/containerRuntime.d.ts +16 -5
  99. package/lib/containerRuntime.d.ts.map +1 -1
  100. package/lib/containerRuntime.js +112 -9
  101. package/lib/containerRuntime.js.map +1 -1
  102. package/lib/dataStore.d.ts +2 -2
  103. package/lib/dataStore.d.ts.map +1 -1
  104. package/lib/dataStore.js.map +1 -1
  105. package/lib/dataStoreContexts.d.ts.map +1 -1
  106. package/lib/dataStoreContexts.js.map +1 -1
  107. package/lib/deltaScheduler.d.ts +2 -2
  108. package/lib/deltaScheduler.d.ts.map +1 -1
  109. package/lib/deltaScheduler.js +1 -1
  110. package/lib/deltaScheduler.js.map +1 -1
  111. package/lib/gc/garbageCollection.d.ts +2 -2
  112. package/lib/gc/garbageCollection.d.ts.map +1 -1
  113. package/lib/gc/garbageCollection.js +1 -1
  114. package/lib/gc/garbageCollection.js.map +1 -1
  115. package/lib/gc/gcDefinitions.d.ts +3 -3
  116. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  117. package/lib/gc/gcDefinitions.js.map +1 -1
  118. package/lib/gc/gcTelemetry.d.ts +3 -3
  119. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  120. package/lib/gc/gcTelemetry.js.map +1 -1
  121. package/lib/inboundBatchAggregator.d.ts +2 -2
  122. package/lib/inboundBatchAggregator.d.ts.map +1 -1
  123. package/lib/inboundBatchAggregator.js.map +1 -1
  124. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  125. package/lib/opLifecycle/opCompressor.js +1 -1
  126. package/lib/opLifecycle/opCompressor.js.map +1 -1
  127. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  128. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  129. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  130. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  131. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  132. package/lib/opLifecycle/opSplitter.js +1 -1
  133. package/lib/opLifecycle/opSplitter.js.map +1 -1
  134. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  135. package/lib/opLifecycle/outbox.js +1 -1
  136. package/lib/opLifecycle/outbox.js.map +1 -1
  137. package/lib/packageVersion.d.ts +1 -1
  138. package/lib/packageVersion.js +1 -1
  139. package/lib/packageVersion.js.map +1 -1
  140. package/lib/pendingStateManager.d.ts +48 -1
  141. package/lib/pendingStateManager.d.ts.map +1 -1
  142. package/lib/pendingStateManager.js +55 -2
  143. package/lib/pendingStateManager.js.map +1 -1
  144. package/lib/runtimeLayerCompatState.d.ts +1 -1
  145. package/lib/signalTelemetryProcessing.d.ts +2 -2
  146. package/lib/signalTelemetryProcessing.d.ts.map +1 -1
  147. package/lib/signalTelemetryProcessing.js.map +1 -1
  148. package/lib/summary/documentSchema.d.ts +2 -2
  149. package/lib/summary/documentSchema.d.ts.map +1 -1
  150. package/lib/summary/documentSchema.js.map +1 -1
  151. package/lib/summary/orderedClientElection.d.ts +2 -2
  152. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  153. package/lib/summary/orderedClientElection.js +1 -1
  154. package/lib/summary/orderedClientElection.js.map +1 -1
  155. package/lib/summary/summarizerClientElection.d.ts +2 -2
  156. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  157. package/lib/summary/summarizerClientElection.js.map +1 -1
  158. package/lib/summary/summarizerNode/summarizerNode.d.ts +3 -3
  159. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  160. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  161. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -2
  162. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  163. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  164. package/lib/summary/summarizerTypes.d.ts +3 -3
  165. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  166. package/lib/summary/summarizerTypes.js.map +1 -1
  167. package/lib/summary/summaryCollection.d.ts.map +1 -1
  168. package/lib/summary/summaryCollection.js.map +1 -1
  169. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +2 -2
  170. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
  171. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js +1 -1
  172. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
  173. package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts +2 -2
  174. package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
  175. package/lib/summary/summaryDelayLoadedModule/summarizer.js +1 -1
  176. package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
  177. package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts +2 -2
  178. package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -1
  179. package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
  180. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +2 -2
  181. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
  182. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
  183. package/lib/summary/summaryManager.d.ts.map +1 -1
  184. package/lib/summary/summaryManager.js +1 -1
  185. package/lib/summary/summaryManager.js.map +1 -1
  186. package/package.json +19 -19
  187. package/src/batchTracker.ts +3 -3
  188. package/src/blobManager/blobManagerSnapSum.ts +2 -2
  189. package/src/connectionTelemetry.ts +5 -5
  190. package/src/containerRuntime.ts +134 -15
  191. package/src/dataStore.ts +3 -3
  192. package/src/dataStoreContexts.ts +2 -2
  193. package/src/deltaScheduler.ts +2 -5
  194. package/src/gc/garbageCollection.ts +6 -6
  195. package/src/gc/gcDefinitions.ts +3 -3
  196. package/src/gc/gcTelemetry.ts +5 -5
  197. package/src/inboundBatchAggregator.ts +2 -2
  198. package/src/opLifecycle/opCompressor.ts +3 -3
  199. package/src/opLifecycle/opDecompressor.ts +2 -2
  200. package/src/opLifecycle/opGroupingManager.ts +2 -2
  201. package/src/opLifecycle/opSplitter.ts +3 -3
  202. package/src/opLifecycle/outbox.ts +4 -4
  203. package/src/packageVersion.ts +1 -1
  204. package/src/pendingStateManager.ts +82 -4
  205. package/src/signalTelemetryProcessing.ts +2 -2
  206. package/src/summary/documentSchema.ts +2 -2
  207. package/src/summary/orderedClientElection.ts +4 -4
  208. package/src/summary/summarizerClientElection.ts +2 -2
  209. package/src/summary/summarizerNode/summarizerNode.ts +3 -3
  210. package/src/summary/summarizerNode/summarizerNodeUtils.ts +2 -2
  211. package/src/summary/summarizerTypes.ts +3 -3
  212. package/src/summary/summaryCollection.ts +2 -2
  213. package/src/summary/summaryDelayLoadedModule/runningSummarizer.ts +4 -6
  214. package/src/summary/summaryDelayLoadedModule/summarizer.ts +4 -4
  215. package/src/summary/summaryDelayLoadedModule/summarizerHeuristics.ts +2 -2
  216. package/src/summary/summaryDelayLoadedModule/summaryGenerator.ts +2 -2
  217. package/src/summary/summaryManager.ts +3 -3
@@ -19,13 +19,13 @@ import {
19
19
  responseToException,
20
20
  } from "@fluidframework/runtime-utils/internal";
21
21
  import {
22
- type ITelemetryLoggerExt,
22
+ createChildLogger,
23
+ createChildMonitoringContext,
23
24
  DataProcessingError,
24
25
  type MonitoringContext,
25
26
  PerformanceEvent,
26
- createChildLogger,
27
- createChildMonitoringContext,
28
27
  tagCodeArtifacts,
28
+ type TelemetryLoggerExt,
29
29
  } from "@fluidframework/telemetry-utils/internal";
30
30
 
31
31
  import { blobManagerBasePath } from "../blobManager/index.js";
@@ -498,7 +498,7 @@ export class GarbageCollector implements IGarbageCollector {
498
498
  /**
499
499
  * Logger to use for logging GC events
500
500
  */
501
- logger?: ITelemetryLoggerExt;
501
+ logger?: TelemetryLoggerExt;
502
502
  /**
503
503
  * True to run GC sweep phase after the mark phase
504
504
  */
@@ -605,7 +605,7 @@ export class GarbageCollector implements IGarbageCollector {
605
605
  private async runGC(
606
606
  fullGC: boolean,
607
607
  currentReferenceTimestampMs: number,
608
- logger: ITelemetryLoggerExt,
608
+ logger: TelemetryLoggerExt,
609
609
  ): Promise<IGCStats> {
610
610
  // 1. Generate / analyze the runtime's reference graph.
611
611
  // Get the reference graph (gcData) and run GC algorithm to get referenced / unreferenced nodes.
@@ -796,7 +796,7 @@ export class GarbageCollector implements IGarbageCollector {
796
796
  private findAllNodesReferencedBetweenGCs(
797
797
  currentGCData: IGarbageCollectionData,
798
798
  previousGCData: IGarbageCollectionData | undefined,
799
- logger: ITelemetryLoggerExt,
799
+ logger: TelemetryLoggerExt,
800
800
  ): string[] | undefined {
801
801
  // If we haven't run GC before there is nothing to do.
802
802
  // No previousGCData, means nothing is unreferenced, and there are no reference state trackers to clear
@@ -14,8 +14,8 @@ import type {
14
14
  } from "@fluidframework/runtime-definitions/internal";
15
15
  import type { ReadAndParseBlob } from "@fluidframework/runtime-utils/internal";
16
16
  import type {
17
- ITelemetryLoggerExt,
18
17
  ITelemetryPropertiesExt,
18
+ TelemetryLoggerExt,
19
19
  } from "@fluidframework/telemetry-utils/internal";
20
20
 
21
21
  import type { RuntimeHeaderData } from "../containerRuntime.js";
@@ -396,7 +396,7 @@ export interface IGarbageCollector {
396
396
  */
397
397
  collectGarbage(
398
398
  options: {
399
- logger?: ITelemetryLoggerExt;
399
+ logger?: TelemetryLoggerExt;
400
400
  runSweep?: boolean;
401
401
  fullGC?: boolean;
402
402
  },
@@ -505,7 +505,7 @@ export interface IGarbageCollectorCreateParams {
505
505
  readonly closeFn: (error: ICriticalContainerError) => void;
506
506
 
507
507
  readonly gcOptions: IGCRuntimeOptions;
508
- readonly baseLogger: ITelemetryLoggerExt;
508
+ readonly baseLogger: TelemetryLoggerExt;
509
509
  readonly existing: boolean;
510
510
 
511
511
  readonly metadata: IContainerRuntimeMetadata | undefined;
@@ -6,11 +6,11 @@
6
6
  import type { Tagged } from "@fluidframework/core-interfaces";
7
7
  import type { IGarbageCollectionData } from "@fluidframework/runtime-definitions/internal";
8
8
  import {
9
- type ITelemetryLoggerExt,
10
- type MonitoringContext,
11
9
  generateStack,
12
- tagCodeArtifacts,
13
10
  type ITelemetryPropertiesExt,
11
+ type MonitoringContext,
12
+ tagCodeArtifacts,
13
+ type TelemetryLoggerExt,
14
14
  } from "@fluidframework/telemetry-utils/internal";
15
15
 
16
16
  import type { RuntimeHeaderData } from "../containerRuntime.js";
@@ -350,7 +350,7 @@ export class GCTelemetryTracker {
350
350
  currentGCData: IGarbageCollectionData,
351
351
  previousGCData: IGarbageCollectionData,
352
352
  explicitReferences: Map<string, string[]>,
353
- logger: ITelemetryLoggerExt,
353
+ logger: TelemetryLoggerExt,
354
354
  ): void {
355
355
  for (const [nodeId, currentOutboundRoutes] of Object.entries(currentGCData.gcNodes)) {
356
356
  const previousRoutes = previousGCData.gcNodes[nodeId] ?? [];
@@ -395,7 +395,7 @@ export class GCTelemetryTracker {
395
395
  * Log events that are pending in pendingEventsQueue. This is called after GC runs in the summarizer client
396
396
  * so that the state of an unreferenced node is updated.
397
397
  */
398
- public async logPendingEvents(logger: ITelemetryLoggerExt): Promise<void> {
398
+ public async logPendingEvents(logger: TelemetryLoggerExt): Promise<void> {
399
399
  // Events sent come only from the summarizer client. In between summaries, events are pushed to a queue and at
400
400
  // summary time they are then logged.
401
401
  // Events generated:
@@ -9,10 +9,10 @@ import { assert } from "@fluidframework/core-utils/internal";
9
9
  import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
10
10
  import { isRuntimeMessage } from "@fluidframework/driver-utils/internal";
11
11
  import {
12
- type ITelemetryLoggerExt,
13
12
  DataCorruptionError,
14
13
  DataProcessingError,
15
14
  extractSafePropertiesFromMessage,
15
+ type TelemetryLoggerExt,
16
16
  } from "@fluidframework/telemetry-utils/internal";
17
17
 
18
18
  import type { IBatchMetadata } from "./metadata.js";
@@ -38,7 +38,7 @@ export class InboundBatchAggregator {
38
38
  constructor(
39
39
  private readonly deltaManager: IDeltaManagerFull,
40
40
  private readonly getClientId: () => string | undefined,
41
- private readonly logger: ITelemetryLoggerExt,
41
+ private readonly logger: TelemetryLoggerExt,
42
42
  ) {
43
43
  // Listen for updates and peek at the inbound
44
44
  this.deltaManager.inbound.on("push", this.trackPending);
@@ -7,9 +7,9 @@ import { IsoBuffer } from "@fluid-internal/client-utils";
7
7
  import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
8
8
  import { assert } from "@fluidframework/core-utils/internal";
9
9
  import {
10
- DataProcessingError,
11
10
  createChildLogger,
12
- type ITelemetryLoggerExt,
11
+ DataProcessingError,
12
+ type TelemetryLoggerExt,
13
13
  } from "@fluidframework/telemetry-utils/internal";
14
14
  import { compress } from "lz4js";
15
15
 
@@ -25,7 +25,7 @@ import { estimateSocketSize } from "./outbox.js";
25
25
  * Use opGroupingManager to group a batch into a singleton batch suitable for compression.
26
26
  */
27
27
  export class OpCompressor {
28
- private readonly logger: ITelemetryLoggerExt;
28
+ private readonly logger: TelemetryLoggerExt;
29
29
 
30
30
  constructor(logger: ITelemetryBaseLogger) {
31
31
  this.logger = createChildLogger({ logger, namespace: "OpCompressor" });
@@ -9,7 +9,7 @@ import { assert } from "@fluidframework/core-utils/internal";
9
9
  import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
10
10
  import {
11
11
  createChildLogger,
12
- type ITelemetryLoggerExt,
12
+ type TelemetryLoggerExt,
13
13
  } from "@fluidframework/telemetry-utils/internal";
14
14
  import { decompress } from "lz4js";
15
15
 
@@ -40,7 +40,7 @@ export class OpDecompressor {
40
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
41
  private rootMessageContents: any | undefined;
42
42
  private processedCount = 0;
43
- private readonly logger: ITelemetryLoggerExt;
43
+ private readonly logger: TelemetryLoggerExt;
44
44
 
45
45
  constructor(logger: ITelemetryBaseLogger) {
46
46
  this.logger = createChildLogger({ logger, namespace: "OpDecompressor" });
@@ -8,7 +8,7 @@ import { assert } from "@fluidframework/core-utils/internal";
8
8
  import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
9
9
  import {
10
10
  createChildLogger,
11
- type ITelemetryLoggerExt,
11
+ type TelemetryLoggerExt,
12
12
  } from "@fluidframework/telemetry-utils/internal";
13
13
 
14
14
  import type {
@@ -65,7 +65,7 @@ export interface EmptyGroupedBatch {
65
65
 
66
66
  export class OpGroupingManager {
67
67
  static readonly groupedBatchOp = "groupedBatch";
68
- private readonly logger: ITelemetryLoggerExt;
68
+ private readonly logger: TelemetryLoggerExt;
69
69
 
70
70
  constructor(
71
71
  private readonly config: OpGroupingManagerConfig,
@@ -8,10 +8,10 @@ import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
8
8
  import { assert } from "@fluidframework/core-utils/internal";
9
9
  import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
10
10
  import {
11
- DataCorruptionError,
12
11
  createChildLogger,
12
+ DataCorruptionError,
13
13
  extractSafePropertiesFromMessage,
14
- type ITelemetryLoggerExt,
14
+ type TelemetryLoggerExt,
15
15
  } from "@fluidframework/telemetry-utils/internal";
16
16
 
17
17
  import {
@@ -45,7 +45,7 @@ function isChunkedContents(contents: unknown): contents is IChunkedContents {
45
45
  export class OpSplitter {
46
46
  // Local copy of incomplete received chunks.
47
47
  private readonly chunkMap: Map<string, string[]>;
48
- private readonly logger: ITelemetryLoggerExt;
48
+ private readonly logger: TelemetryLoggerExt;
49
49
 
50
50
  constructor(
51
51
  chunks: [string, string[]][],
@@ -10,11 +10,11 @@ import type {
10
10
  } from "@fluidframework/core-interfaces";
11
11
  import { assert, Lazy } from "@fluidframework/core-utils/internal";
12
12
  import {
13
- DataProcessingError,
14
- UsageError,
15
13
  createChildLogger,
14
+ DataProcessingError,
16
15
  type IFluidErrorBase,
17
- type ITelemetryLoggerExt,
16
+ type TelemetryLoggerExt,
17
+ UsageError,
18
18
  } from "@fluidframework/telemetry-utils/internal";
19
19
 
20
20
  import type { ICompressionRuntimeOptions } from "../compressionDefinitions.js";
@@ -194,7 +194,7 @@ export const estimateSocketSize = (batch: OutboundBatch): number => {
194
194
  * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping).
195
195
  */
196
196
  export class Outbox {
197
- private readonly logger: ITelemetryLoggerExt;
197
+ private readonly logger: TelemetryLoggerExt;
198
198
  private readonly mainBatch: BatchManager;
199
199
  private readonly blobAttachBatch: BatchManager;
200
200
  private batchRebasesToReport = 5;
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.102.0";
9
+ export const pkgVersion = "2.110.0";
@@ -6,11 +6,11 @@
6
6
  import type { IDisposable, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
7
  import { assert, Lazy } from "@fluidframework/core-utils/internal";
8
8
  import {
9
- type ITelemetryLoggerExt,
9
+ createChildLogger,
10
10
  DataProcessingError,
11
- LoggingError,
12
11
  extractSafePropertiesFromMessage,
13
- createChildLogger,
12
+ LoggingError,
13
+ type TelemetryLoggerExt,
14
14
  } from "@fluidframework/telemetry-utils/internal";
15
15
  import Deque from "double-ended-queue";
16
16
  import { v4 as uuid } from "uuid";
@@ -142,6 +142,25 @@ export interface IRuntimeStateHandler {
142
142
  isAttached: () => boolean;
143
143
  }
144
144
 
145
+ /**
146
+ * Optional hooks invoked at the close of the stashed-op apply lifecycle.
147
+ *
148
+ * `onAfterStashedOpsApplied` fires synchronously the first time
149
+ * `initialMessages` drains during `applyStashedOpsAt`, immediately after
150
+ * `isApplyingStashedOps` flips to `false`. Fires at most once per PSM
151
+ * lifetime. If an apply throws, control never reaches the close site and
152
+ * the hook is not invoked — load is fatal in that case.
153
+ *
154
+ * No corresponding open hook is exposed. The apply window is opened eagerly
155
+ * in the PSM constructor, but at that point `ContainerRuntime` has not yet
156
+ * wired up the downstream observers (`channelCollection` is undefined), so a
157
+ * fanout fired from the constructor would be a no-op. Consumers that care
158
+ * about the open transition can read `isApplyingStashedOps` directly.
159
+ */
160
+ export interface PendingStateManagerHooks {
161
+ onAfterStashedOpsApplied?: () => void;
162
+ }
163
+
145
164
  function isEmptyBatchPendingMessage(message: IPendingMessageFromStash): boolean {
146
165
  const content = JSON.parse(message.content) as Partial<EmptyGroupedBatch>;
147
166
  return content.type === "groupedBatch" && content.contents?.length === 0;
@@ -366,17 +385,62 @@ export class PendingStateManager implements IDisposable {
366
385
  };
367
386
  }
368
387
 
369
- private readonly logger: ITelemetryLoggerExt;
388
+ private readonly logger: TelemetryLoggerExt;
389
+
390
+ /**
391
+ * One-way lifecycle of the stashed-op apply window: `ended` → `applying` → `ended`.
392
+ *
393
+ * Default is `ended` — no stashed state means there's nothing to apply, so the window is
394
+ * closed before it ever opens. `ended` → `applying` happens in the constructor when
395
+ * stashed state is present (i.e. `initialMessages` is non-empty at construction). The
396
+ * open is eager so the runtime is readonly from the moment any DDS could possibly
397
+ * observe it. `applying` → `ended` happens the first time {@link applyStashedOpsAt}
398
+ * drains `initialMessages`. After that, local edits are safe — they queue FIFO behind
399
+ * any remaining `pendingMessages`, preserving server-side ordering.
400
+ *
401
+ * The window never reopens. After the close, subsequent `applyStashedOpsAt` calls (e.g.
402
+ * from late `notifyOpReplay`s) early-return at the empty guard.
403
+ *
404
+ * `pendingMessages` state is intentionally NOT part of the close condition. Those
405
+ * entries are drained transparently by {@link replayPendingStates} on connect via
406
+ * resubmit (each pop is matched by a fresh push), so the queue size is conserved across
407
+ * resubmit and DDSes can't distinguish a resubmit-ack from a normal ack. Holding the
408
+ * window open through resubmit would force resubmits to run while the runtime is
409
+ * readonly, which is the inverse of what we want ("never resubmit during apply stashed
410
+ * ops").
411
+ *
412
+ * An apply error leaves the lifecycle at `applying` because the queue isn't drained.
413
+ * That's fine: an error here is fatal for the load, the container is unusable, and
414
+ * there's no state to restore.
415
+ */
416
+ private _applyLifecycle: "applying" | "ended" = "ended";
417
+ public get isApplyingStashedOps(): boolean {
418
+ return this._applyLifecycle === "applying";
419
+ }
420
+
421
+ private readonly hooks: PendingStateManagerHooks;
370
422
 
371
423
  constructor(
372
424
  private readonly stateHandler: IRuntimeStateHandler,
373
425
  stashedLocalState: IPendingLocalState | undefined,
374
426
  logger: ITelemetryBaseLogger,
427
+ hooks: PendingStateManagerHooks = {},
375
428
  ) {
376
429
  this.logger = createChildLogger({ logger });
430
+ this.hooks = hooks;
377
431
  if (stashedLocalState?.pendingStates) {
378
432
  this.initialMessages.push(...stashedLocalState.pendingStates);
379
433
  }
434
+ // Open the apply window eagerly if there is any stashed work. The
435
+ // runtime is readonly while `isApplyingStashedOps` is true (see
436
+ // `ContainerRuntime.isReadOnly`); compliant DDSes consult `readOnly`
437
+ // at realize time and skip submits. No fanout fires here — downstream
438
+ // observers (`channelCollection`) are not yet constructed at this
439
+ // point in the runtime constructor, and the first real readonly read
440
+ // happens after the constructor returns.
441
+ if (!this.initialMessages.isEmpty()) {
442
+ this._applyLifecycle = "applying";
443
+ }
380
444
  }
381
445
 
382
446
  public get disposed(): boolean {
@@ -451,6 +515,10 @@ export class PendingStateManager implements IDisposable {
451
515
  * @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.
452
516
  */
453
517
  public async applyStashedOpsAt(seqNum?: number): Promise<void> {
518
+ if (this.initialMessages.isEmpty()) {
519
+ return;
520
+ }
521
+
454
522
  // apply stashed ops at sequence number
455
523
  while (!this.initialMessages.isEmpty()) {
456
524
  if (seqNum !== undefined) {
@@ -497,6 +565,16 @@ export class PendingStateManager implements IDisposable {
497
565
  throw DataProcessingError.wrapIfUnrecognized(error, "applyStashedOp", nextMessage);
498
566
  }
499
567
  }
568
+
569
+ // The apply window was opened eagerly in the constructor when there
570
+ // was any stashed work. We close it on full successful drain only.
571
+ // If an apply throws above, control never reaches here and the
572
+ // lifecycle stays at "applying" — the load is fatal so there's no
573
+ // recoverable state.
574
+ if (this._applyLifecycle === "applying" && this.initialMessages.isEmpty()) {
575
+ this._applyLifecycle = "ended";
576
+ this.hooks.onAfterStashedOpsApplied?.();
577
+ }
500
578
  }
501
579
 
502
580
  /**
@@ -5,8 +5,8 @@
5
5
 
6
6
  import type { ISignalEnvelope } from "@fluidframework/core-interfaces/internal";
7
7
  import type {
8
- ITelemetryLoggerExt,
9
8
  TelemetryEventPropertyTypeExt,
9
+ TelemetryLoggerExt,
10
10
  } from "@fluidframework/telemetry-utils/internal";
11
11
 
12
12
  const defaultTelemetrySignalSampleCount = 100;
@@ -101,7 +101,7 @@ export class SignalTelemetryManager {
101
101
  */
102
102
  public trackReceivedSignal(
103
103
  envelope: ISignalEnvelope,
104
- logger: ITelemetryLoggerExt,
104
+ logger: TelemetryLoggerExt,
105
105
  consecutiveReconnects: number,
106
106
  ): void {
107
107
  const {
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { assert } from "@fluidframework/core-utils/internal";
7
7
  import type { SemanticVersion } from "@fluidframework/runtime-utils/internal";
8
- import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
8
+ import type { TelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
9
9
  import { DataProcessingError } from "@fluidframework/telemetry-utils/internal";
10
10
  import { gt, lt, parse } from "semver-ts";
11
11
 
@@ -633,7 +633,7 @@ export class DocumentsSchemaController {
633
633
  features: IDocumentSchemaFeatures,
634
634
  private readonly onSchemaChange: (schema: IDocumentSchemaCurrent) => void,
635
635
  info: IDocumentSchemaInfo,
636
- logger: ITelemetryLoggerExt,
636
+ logger: TelemetryLoggerExt,
637
637
  private readonly disableSchemaUpgrade: boolean,
638
638
  ) {
639
639
  // For simplicity, let's only support new schema features for explicit schema control mode
@@ -19,9 +19,9 @@ import type {
19
19
  ISequencedClient,
20
20
  } from "@fluidframework/driver-definitions";
21
21
  import {
22
- type ITelemetryLoggerExt,
23
- UsageError,
24
22
  createChildLogger,
23
+ type TelemetryLoggerExt,
24
+ UsageError,
25
25
  } from "@fluidframework/telemetry-utils/internal";
26
26
 
27
27
  import { summarizerClientType } from "./summarizerTypes.js";
@@ -135,7 +135,7 @@ export class OrderedClientCollection
135
135
  * Pointer to end of linked list, for optimized client adds.
136
136
  */
137
137
  private _youngestClient: LinkNode = this.rootNode;
138
- private readonly logger: ITelemetryLoggerExt;
138
+ private readonly logger: TelemetryLoggerExt;
139
139
 
140
140
  public get count(): number {
141
141
  return this.clientMap.size;
@@ -413,7 +413,7 @@ export class OrderedClientElection
413
413
  }
414
414
 
415
415
  constructor(
416
- private readonly logger: ITelemetryLoggerExt,
416
+ private readonly logger: TelemetryLoggerExt,
417
417
  private readonly orderedClientCollection: IOrderedClientCollection,
418
418
  /**
419
419
  * Serialized state from summary or current sequence number at time of load if new.
@@ -7,7 +7,7 @@ import { TypedEventEmitter } from "@fluid-internal/client-utils";
7
7
  import type { IEvent, IEventProvider } from "@fluidframework/core-interfaces";
8
8
  import type { IClientDetails } from "@fluidframework/driver-definitions";
9
9
  import { MessageType } from "@fluidframework/driver-definitions/internal";
10
- import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
10
+ import type { TelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
11
11
 
12
12
  import type {
13
13
  IOrderedClientElection,
@@ -58,7 +58,7 @@ export class SummarizerClientElection
58
58
  }
59
59
 
60
60
  constructor(
61
- private readonly logger: ITelemetryLoggerExt,
61
+ private readonly logger: TelemetryLoggerExt,
62
62
  private readonly summaryCollection: IEventProvider<ISummaryCollectionOpEvents>,
63
63
  public readonly clientElection: IOrderedClientElection,
64
64
  private readonly maxOpsSinceLastSummary: number,
@@ -31,7 +31,7 @@ import {
31
31
  } from "@fluidframework/telemetry-utils/internal";
32
32
  import type {
33
33
  ITelemetryErrorEventExt,
34
- ITelemetryLoggerExt,
34
+ TelemetryLoggerExt,
35
35
  } from "@fluidframework/telemetry-utils/internal";
36
36
 
37
37
  import type {
@@ -90,7 +90,7 @@ export class SummarizerNode implements IRootSummarizerNode {
90
90
  private wipSummarizeCalled: boolean = false;
91
91
  private wipSkipRecursion = false;
92
92
 
93
- protected readonly logger: ITelemetryLoggerExt;
93
+ protected readonly logger: TelemetryLoggerExt;
94
94
 
95
95
  /**
96
96
  * Do not call constructor directly.
@@ -664,7 +664,7 @@ export class SummarizerNode implements IRootSummarizerNode {
664
664
  * @param config - Configure behavior of summarizer node
665
665
  */
666
666
  export const createRootSummarizerNode = (
667
- logger: ITelemetryLoggerExt,
667
+ logger: TelemetryLoggerExt,
668
668
  summarizeInternalFn: SummarizeInternalFn,
669
669
  changeSequenceNumber: number,
670
670
  referenceSequenceNumber: number | undefined,
@@ -6,8 +6,8 @@
6
6
  import type { SummaryObject } from "@fluidframework/driver-definitions";
7
7
  import type { ISnapshotTree } from "@fluidframework/driver-definitions/internal";
8
8
  import type {
9
- ITelemetryLoggerExt,
10
9
  TelemetryDataTag,
10
+ TelemetryLoggerExt,
11
11
  } from "@fluidframework/telemetry-utils/internal";
12
12
 
13
13
  export interface IRefreshSummaryResult {
@@ -67,7 +67,7 @@ export type ValidateSummaryResult =
67
67
  export interface ISummarizerNodeRootContract {
68
68
  startSummary(
69
69
  referenceSequenceNumber: number,
70
- summaryLogger: ITelemetryLoggerExt,
70
+ summaryLogger: TelemetryLoggerExt,
71
71
  latestSummaryRefSeqNum: number,
72
72
  ): IStartSummaryResult;
73
73
  validateSummary(): ValidateSummaryResult;
@@ -24,8 +24,8 @@ import type {
24
24
  import type { ISummaryStats } from "@fluidframework/runtime-definitions/internal";
25
25
  import type { TelemetryContext } from "@fluidframework/runtime-utils/internal";
26
26
  import type {
27
- ITelemetryLoggerExt,
28
27
  ITelemetryLoggerPropertyBag,
28
+ TelemetryLoggerExt,
29
29
  } from "@fluidframework/telemetry-utils/internal";
30
30
 
31
31
  import type { SummarizeReason } from "./summarizerUtils.js";
@@ -79,7 +79,7 @@ export interface IRefreshSummaryAckOptions {
79
79
  /**
80
80
  * Telemetry logger to which telemetry events will be forwarded.
81
81
  */
82
- readonly summaryLogger: ITelemetryLoggerExt;
82
+ readonly summaryLogger: TelemetryLoggerExt;
83
83
  }
84
84
 
85
85
  /**
@@ -157,7 +157,7 @@ export interface ISubmitSummaryOptions extends ISummarizeOptions {
157
157
  /**
158
158
  * Logger to use for correlated summary events
159
159
  */
160
- readonly summaryLogger: ITelemetryLoggerExt;
160
+ readonly summaryLogger: TelemetryLoggerExt;
161
161
  /**
162
162
  * Tells when summary process should be cancelled
163
163
  */
@@ -21,7 +21,7 @@ import {
21
21
  } from "@fluidframework/driver-definitions/internal";
22
22
  import {
23
23
  createChildLogger,
24
- type ITelemetryLoggerExt,
24
+ type TelemetryLoggerExt,
25
25
  } from "@fluidframework/telemetry-utils/internal";
26
26
 
27
27
  /**
@@ -281,7 +281,7 @@ export class SummaryCollection extends TypedEventEmitter<ISummaryCollectionOpEve
281
281
  this.deltaManager.off("op", listener);
282
282
  }
283
283
 
284
- private readonly logger: ITelemetryLoggerExt;
284
+ private readonly logger: TelemetryLoggerExt;
285
285
  public constructor(
286
286
  private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
287
287
  logger: ITelemetryBaseLogger,
@@ -18,12 +18,12 @@ import {
18
18
  type ISequencedDocumentMessage,
19
19
  } from "@fluidframework/driver-definitions/internal";
20
20
  import {
21
- type MonitoringContext,
22
- UsageError,
23
21
  createChildLogger,
24
22
  createChildMonitoringContext,
25
23
  isFluidError,
26
- type ITelemetryLoggerExt,
24
+ type MonitoringContext,
25
+ type TelemetryLoggerExt,
26
+ UsageError,
27
27
  } from "@fluidframework/telemetry-utils/internal";
28
28
 
29
29
  import { opSize } from "../../opProperties.js";
@@ -432,9 +432,7 @@ export class RunningSummarizer
432
432
  * but only if they're logging about that same summary.
433
433
  * @param summaryOpRefSeq - RefSeq number of the summary op, to ensure the log correlation will be correct
434
434
  */
435
- public tryGetCorrelatedLogger = (
436
- summaryOpRefSeq: number,
437
- ): ITelemetryLoggerExt | undefined =>
435
+ public tryGetCorrelatedLogger = (summaryOpRefSeq: number): TelemetryLoggerExt | undefined =>
438
436
  this.heuristicData.lastAttempt.refSequenceNumber === summaryOpRefSeq
439
437
  ? this.mc.logger
440
438
  : undefined;
@@ -11,11 +11,11 @@ import type {
11
11
  import type { IFluidHandleContext } from "@fluidframework/core-interfaces/internal";
12
12
  import { assert, Deferred } from "@fluidframework/core-utils/internal";
13
13
  import {
14
+ createChildLogger,
14
15
  type IFluidErrorBase,
15
- type ITelemetryLoggerExt,
16
16
  LoggingError,
17
+ type TelemetryLoggerExt,
17
18
  UsageError,
18
- createChildLogger,
19
19
  wrapErrorAndLog,
20
20
  } from "@fluidframework/telemetry-utils/internal";
21
21
 
@@ -67,7 +67,7 @@ export class SummarizingWarning
67
67
  static wrap(
68
68
  error: unknown,
69
69
  logged: boolean = false,
70
- logger: ITelemetryLoggerExt,
70
+ logger: TelemetryLoggerExt,
71
71
  ): SummarizingWarning {
72
72
  const newErrorFn = (errMsg: string): SummarizingWarning =>
73
73
  new SummarizingWarning(errMsg, logged);
@@ -91,7 +91,7 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
91
91
  return this;
92
92
  }
93
93
 
94
- private readonly logger: ITelemetryLoggerExt;
94
+ private readonly logger: TelemetryLoggerExt;
95
95
  private runningSummarizer?: RunningSummarizer;
96
96
  private _disposed: boolean = false;
97
97
  private starting: boolean = false;
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { Timer } from "@fluidframework/core-utils/internal";
7
- import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
7
+ import type { TelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
8
8
 
9
9
  import type {
10
10
  ISummaryConfigurationHeuristics,
@@ -108,7 +108,7 @@ export class SummarizeHeuristicRunner implements ISummarizeHeuristicRunner {
108
108
  private readonly heuristicData: ISummarizeHeuristicData,
109
109
  private readonly configuration: ISummaryConfigurationHeuristics,
110
110
  trySummarize: (reason: SummarizeReason) => void,
111
- private readonly logger: ITelemetryLoggerExt,
111
+ private readonly logger: TelemetryLoggerExt,
112
112
  private readonly summarizeStrategies: ISummaryHeuristicStrategy[] = getDefaultSummaryHeuristicStrategies(),
113
113
  ) {
114
114
  this.idleTimer = new Timer(this.idleTime, () => this.runSummarize("idle"));
@@ -11,8 +11,8 @@ import { getRetryDelaySecondsFromError } from "@fluidframework/driver-utils/inte
11
11
  import { TelemetryContext } from "@fluidframework/runtime-utils/internal";
12
12
  import {
13
13
  isFluidError,
14
- type ITelemetryLoggerExt,
15
14
  PerformanceEvent,
15
+ type TelemetryLoggerExt,
16
16
  wrapError,
17
17
  } from "@fluidframework/telemetry-utils/internal";
18
18
 
@@ -57,7 +57,7 @@ export class SummaryGenerator extends TypedEventEmitter<ISummarizerEvents> {
57
57
  options: IRefreshSummaryAckOptions,
58
58
  ) => Promise<void>,
59
59
  private readonly summaryWatcher: Pick<IClientSummaryWatcher, "watchSummary">,
60
- private readonly logger: ITelemetryLoggerExt,
60
+ private readonly logger: TelemetryLoggerExt,
61
61
  ) {
62
62
  super();
63
63
  this.summarizeTimer = new Timer(maxSummarizeTimeoutTime, () =>