@fluidframework/container-runtime 0.59.4001 → 1.1.0-75972

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 (157) hide show
  1. package/.eslintrc.js +1 -1
  2. package/dist/blobManager.d.ts +2 -2
  3. package/dist/blobManager.d.ts.map +1 -1
  4. package/dist/blobManager.js +12 -11
  5. package/dist/blobManager.js.map +1 -1
  6. package/dist/connectionTelemetry.d.ts +19 -0
  7. package/dist/connectionTelemetry.d.ts.map +1 -1
  8. package/dist/connectionTelemetry.js +23 -23
  9. package/dist/connectionTelemetry.js.map +1 -1
  10. package/dist/containerRuntime.d.ts +137 -29
  11. package/dist/containerRuntime.d.ts.map +1 -1
  12. package/dist/containerRuntime.js +338 -118
  13. package/dist/containerRuntime.js.map +1 -1
  14. package/dist/dataStore.d.ts.map +1 -1
  15. package/dist/dataStore.js +14 -3
  16. package/dist/dataStore.js.map +1 -1
  17. package/dist/dataStoreContext.d.ts +4 -2
  18. package/dist/dataStoreContext.d.ts.map +1 -1
  19. package/dist/dataStoreContext.js +16 -5
  20. package/dist/dataStoreContext.js.map +1 -1
  21. package/dist/dataStoreRegistry.d.ts +0 -4
  22. package/dist/dataStoreRegistry.d.ts.map +1 -1
  23. package/dist/dataStoreRegistry.js +12 -1
  24. package/dist/dataStoreRegistry.js.map +1 -1
  25. package/dist/dataStores.d.ts +4 -3
  26. package/dist/dataStores.d.ts.map +1 -1
  27. package/dist/dataStores.js +13 -7
  28. package/dist/dataStores.js.map +1 -1
  29. package/dist/garbageCollection.d.ts +23 -27
  30. package/dist/garbageCollection.d.ts.map +1 -1
  31. package/dist/garbageCollection.js +44 -119
  32. package/dist/garbageCollection.js.map +1 -1
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/orderedClientElection.js +0 -4
  38. package/dist/orderedClientElection.js.map +1 -1
  39. package/dist/packageVersion.d.ts +1 -1
  40. package/dist/packageVersion.d.ts.map +1 -1
  41. package/dist/packageVersion.js +1 -1
  42. package/dist/packageVersion.js.map +1 -1
  43. package/dist/pendingStateManager.d.ts +30 -29
  44. package/dist/pendingStateManager.d.ts.map +1 -1
  45. package/dist/pendingStateManager.js +72 -109
  46. package/dist/pendingStateManager.js.map +1 -1
  47. package/dist/runningSummarizer.d.ts +4 -3
  48. package/dist/runningSummarizer.d.ts.map +1 -1
  49. package/dist/runningSummarizer.js +11 -6
  50. package/dist/runningSummarizer.js.map +1 -1
  51. package/dist/serializedSnapshotStorage.d.ts +58 -0
  52. package/dist/serializedSnapshotStorage.d.ts.map +1 -0
  53. package/dist/serializedSnapshotStorage.js +108 -0
  54. package/dist/serializedSnapshotStorage.js.map +1 -0
  55. package/dist/summarizer.d.ts +11 -4
  56. package/dist/summarizer.d.ts.map +1 -1
  57. package/dist/summarizer.js +18 -9
  58. package/dist/summarizer.js.map +1 -1
  59. package/dist/summarizerHeuristics.d.ts +5 -3
  60. package/dist/summarizerHeuristics.d.ts.map +1 -1
  61. package/dist/summarizerHeuristics.js +10 -3
  62. package/dist/summarizerHeuristics.js.map +1 -1
  63. package/dist/summarizerTypes.d.ts +4 -2
  64. package/dist/summarizerTypes.d.ts.map +1 -1
  65. package/dist/summarizerTypes.js.map +1 -1
  66. package/dist/summaryManager.d.ts +3 -3
  67. package/dist/summaryManager.d.ts.map +1 -1
  68. package/dist/summaryManager.js +7 -7
  69. package/dist/summaryManager.js.map +1 -1
  70. package/garbageCollection.md +9 -1
  71. package/lib/blobManager.d.ts +2 -2
  72. package/lib/blobManager.d.ts.map +1 -1
  73. package/lib/blobManager.js +12 -11
  74. package/lib/blobManager.js.map +1 -1
  75. package/lib/connectionTelemetry.d.ts +19 -0
  76. package/lib/connectionTelemetry.d.ts.map +1 -1
  77. package/lib/connectionTelemetry.js +23 -23
  78. package/lib/connectionTelemetry.js.map +1 -1
  79. package/lib/containerRuntime.d.ts +137 -29
  80. package/lib/containerRuntime.d.ts.map +1 -1
  81. package/lib/containerRuntime.js +341 -121
  82. package/lib/containerRuntime.js.map +1 -1
  83. package/lib/dataStore.d.ts.map +1 -1
  84. package/lib/dataStore.js +15 -4
  85. package/lib/dataStore.js.map +1 -1
  86. package/lib/dataStoreContext.d.ts +4 -2
  87. package/lib/dataStoreContext.d.ts.map +1 -1
  88. package/lib/dataStoreContext.js +16 -5
  89. package/lib/dataStoreContext.js.map +1 -1
  90. package/lib/dataStoreRegistry.d.ts +0 -4
  91. package/lib/dataStoreRegistry.d.ts.map +1 -1
  92. package/lib/dataStoreRegistry.js +12 -1
  93. package/lib/dataStoreRegistry.js.map +1 -1
  94. package/lib/dataStores.d.ts +4 -3
  95. package/lib/dataStores.d.ts.map +1 -1
  96. package/lib/dataStores.js +14 -8
  97. package/lib/dataStores.js.map +1 -1
  98. package/lib/garbageCollection.d.ts +23 -27
  99. package/lib/garbageCollection.d.ts.map +1 -1
  100. package/lib/garbageCollection.js +43 -117
  101. package/lib/garbageCollection.js.map +1 -1
  102. package/lib/index.d.ts +2 -2
  103. package/lib/index.d.ts.map +1 -1
  104. package/lib/index.js +1 -1
  105. package/lib/index.js.map +1 -1
  106. package/lib/orderedClientElection.js +0 -4
  107. package/lib/orderedClientElection.js.map +1 -1
  108. package/lib/packageVersion.d.ts +1 -1
  109. package/lib/packageVersion.d.ts.map +1 -1
  110. package/lib/packageVersion.js +1 -1
  111. package/lib/packageVersion.js.map +1 -1
  112. package/lib/pendingStateManager.d.ts +30 -29
  113. package/lib/pendingStateManager.d.ts.map +1 -1
  114. package/lib/pendingStateManager.js +72 -109
  115. package/lib/pendingStateManager.js.map +1 -1
  116. package/lib/runningSummarizer.d.ts +4 -3
  117. package/lib/runningSummarizer.d.ts.map +1 -1
  118. package/lib/runningSummarizer.js +11 -6
  119. package/lib/runningSummarizer.js.map +1 -1
  120. package/lib/serializedSnapshotStorage.d.ts +58 -0
  121. package/lib/serializedSnapshotStorage.d.ts.map +1 -0
  122. package/lib/serializedSnapshotStorage.js +104 -0
  123. package/lib/serializedSnapshotStorage.js.map +1 -0
  124. package/lib/summarizer.d.ts +11 -4
  125. package/lib/summarizer.d.ts.map +1 -1
  126. package/lib/summarizer.js +18 -9
  127. package/lib/summarizer.js.map +1 -1
  128. package/lib/summarizerHeuristics.d.ts +5 -3
  129. package/lib/summarizerHeuristics.d.ts.map +1 -1
  130. package/lib/summarizerHeuristics.js +10 -3
  131. package/lib/summarizerHeuristics.js.map +1 -1
  132. package/lib/summarizerTypes.d.ts +4 -2
  133. package/lib/summarizerTypes.d.ts.map +1 -1
  134. package/lib/summarizerTypes.js.map +1 -1
  135. package/lib/summaryManager.d.ts +3 -3
  136. package/lib/summaryManager.d.ts.map +1 -1
  137. package/lib/summaryManager.js +7 -7
  138. package/lib/summaryManager.js.map +1 -1
  139. package/package.json +19 -32
  140. package/src/blobManager.ts +29 -15
  141. package/src/connectionTelemetry.ts +60 -39
  142. package/src/containerRuntime.ts +502 -156
  143. package/src/dataStore.ts +21 -4
  144. package/src/dataStoreContext.ts +27 -5
  145. package/src/dataStoreRegistry.ts +8 -1
  146. package/src/dataStores.ts +21 -8
  147. package/src/garbageCollection.ts +81 -166
  148. package/src/index.ts +7 -1
  149. package/src/orderedClientElection.ts +1 -1
  150. package/src/packageVersion.ts +1 -1
  151. package/src/pendingStateManager.ts +104 -123
  152. package/src/runningSummarizer.ts +20 -10
  153. package/src/serializedSnapshotStorage.ts +146 -0
  154. package/src/summarizer.ts +20 -16
  155. package/src/summarizerHeuristics.ts +21 -5
  156. package/src/summarizerTypes.ts +4 -2
  157. package/src/summaryManager.ts +5 -6
@@ -22,8 +22,9 @@ import {
22
22
  IGarbageCollectionData,
23
23
  IGarbageCollectionState,
24
24
  IGarbageCollectionDetailsBase,
25
- IGarbageCollectionNodeData,
26
25
  ISummarizeResult,
26
+ ITelemetryContext,
27
+ IGarbageCollectionNodeData,
27
28
  } from "@fluidframework/runtime-definitions";
28
29
  import {
29
30
  mergeStats,
@@ -41,7 +42,6 @@ import {
41
42
 
42
43
  import { IGCRuntimeOptions, RuntimeHeaders } from "./containerRuntime";
43
44
  import { getSummaryForDatastores } from "./dataStores";
44
- import { pkgVersion } from "./packageVersion";
45
45
  import {
46
46
  getGCVersion,
47
47
  GCVersion,
@@ -72,12 +72,8 @@ const writeAtRootKey = "Fluid.GarbageCollection.WriteDataAtRoot";
72
72
  export const runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
73
73
  // Feature gate key to disable expiring session after a set period of time, even if expiry value is present
74
74
  export const disableSessionExpiryKey = "Fluid.GarbageCollection.DisableSessionExpiry";
75
- // Feature gate key to log error messages if GC reference validation fails.
76
- export const logUnknownOutboundReferencesKey = "Fluid.GarbageCollection.LogUnknownOutboundReferences";
77
75
  // Feature gate key to write the gc blob as a handle if the data is the same.
78
76
  export const trackGCStateKey = "Fluid.GarbageCollection.TrackGCState";
79
- // Feature gate key to limit which versions can write the gc blob as a handle if the data is the same.
80
- export const trackGCStateMinimumVersionKey = "Fluid.GarbageCollection.TrackGCState.MinVersion";
81
77
 
82
78
  const defaultInactiveTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days
83
79
  export const defaultSessionExpiryDurationMs = 30 * 24 * 60 * 60 * 1000; // 30 days
@@ -162,7 +158,11 @@ export interface IGarbageCollector {
162
158
  options: { logger?: ITelemetryLogger; runGC?: boolean; runSweep?: boolean; fullGC?: boolean; },
163
159
  ): Promise<IGCStats>;
164
160
  /** Summarizes the GC data and returns it as a summary tree. */
165
- summarize(fullTree: boolean, trackState: boolean): ISummarizeResult | undefined;
161
+ summarize(
162
+ fullTree: boolean,
163
+ trackState: boolean,
164
+ telemetryContext?: ITelemetryContext,
165
+ ): ISummarizeResult | undefined;
166
166
  /** Returns the garbage collector specific metadata to be written into the summary. */
167
167
  getMetadata(): IGCMetadata;
168
168
  /** Returns a map of each node id to its base GC details in the base summary. */
@@ -182,6 +182,20 @@ export interface IGarbageCollector {
182
182
  dispose(): void;
183
183
  }
184
184
 
185
+ /** Parameters necessary for creating a GarbageCollector. */
186
+ export interface IGarbageCollectorCreateParams {
187
+ readonly runtime: IGarbageCollectionRuntime;
188
+ readonly gcOptions: IGCRuntimeOptions;
189
+ readonly baseLogger: ITelemetryLogger;
190
+ readonly existing: boolean;
191
+ readonly metadata: IContainerRuntimeMetadata | undefined;
192
+ readonly baseSnapshot: ISnapshotTree | undefined;
193
+ readonly isSummarizerClient: boolean;
194
+ readonly getNodePackagePath: (nodePath: string) => readonly string[] | undefined;
195
+ readonly getLastSummaryTimestampMs: () => number | undefined;
196
+ readonly readAndParseBlob: ReadAndParseBlob;
197
+ }
198
+
185
199
  /**
186
200
  * Helper class that tracks the state of an unreferenced node such as the time it was unreferenced. It also sets
187
201
  * the node's state to inactive if it remains unreferenced for a given amount of time (inactiveTimeoutMs).
@@ -253,30 +267,8 @@ class UnreferencedStateTracker {
253
267
  * NodeId = "dds1" NodeId = "dds2"
254
268
  */
255
269
  export class GarbageCollector implements IGarbageCollector {
256
- public static create(
257
- provider: IGarbageCollectionRuntime,
258
- gcOptions: IGCRuntimeOptions,
259
- getNodePackagePath: (nodePath: string) => readonly string[] | undefined,
260
- getLastSummaryTimestampMs: () => number | undefined,
261
- baseSnapshot: ISnapshotTree | undefined,
262
- readAndParseBlob: ReadAndParseBlob,
263
- baseLogger: ITelemetryLogger,
264
- existing: boolean,
265
- metadata: IContainerRuntimeMetadata | undefined,
266
- isSummarizerClient: boolean,
267
- ): IGarbageCollector {
268
- return new GarbageCollector(
269
- provider,
270
- gcOptions,
271
- getNodePackagePath,
272
- getLastSummaryTimestampMs,
273
- baseSnapshot,
274
- readAndParseBlob,
275
- baseLogger,
276
- existing,
277
- metadata,
278
- isSummarizerClient,
279
- );
270
+ public static create(createParams: IGarbageCollectorCreateParams): IGarbageCollector {
271
+ return new GarbageCollector(createParams);
280
272
  }
281
273
 
282
274
  /**
@@ -327,10 +319,10 @@ export class GarbageCollector implements IGarbageCollector {
327
319
  /**
328
320
  * Tells whether the GC data should be written to the root of the summary tree.
329
321
  */
330
- private _writeDataAtRoot: boolean = false;
322
+ private _writeDataAtRoot: boolean = true;
331
323
  public get writeDataAtRoot(): boolean {
332
324
  return this._writeDataAtRoot;
333
- }
325
+ }
334
326
 
335
327
  /**
336
328
  * Tells whether the initial GC state needs to be reset. This can happen under 2 conditions:
@@ -383,23 +375,29 @@ export class GarbageCollector implements IGarbageCollector {
383
375
  // The number of times GC has successfully completed on this instance of GarbageCollector.
384
376
  private completedRuns = 0;
385
377
 
386
- protected constructor(
387
- private readonly runtime: IGarbageCollectionRuntime,
388
- private readonly gcOptions: IGCRuntimeOptions,
389
- /** For a given node path, returns the node's package path. */
390
- private readonly getNodePackagePath: (nodePath: string) => readonly string[] | undefined,
391
- /** Returns the timestamp of the last summary generated for this container. */
392
- private readonly getLastSummaryTimestampMs: () => number | undefined,
393
- baseSnapshot: ISnapshotTree | undefined,
394
- readAndParseBlob: ReadAndParseBlob,
395
- baseLogger: ITelemetryLogger,
396
- existing: boolean,
397
- metadata: IContainerRuntimeMetadata | undefined,
398
- private readonly isSummarizerClient: boolean = true,
399
- ) {
400
- this.mc = loggerToMonitoringContext(
401
- ChildLogger.create(baseLogger, "GarbageCollector", { all: { completedGCRuns: () => this.completedRuns } }),
402
- );
378
+ private readonly runtime: IGarbageCollectionRuntime;
379
+ private readonly gcOptions: IGCRuntimeOptions;
380
+ private readonly isSummarizerClient: boolean;
381
+
382
+ /** For a given node path, returns the node's package path. */
383
+ private readonly getNodePackagePath: (nodePath: string) => readonly string[] | undefined;
384
+ /** Returns the timestamp of the last summary generated for this container. */
385
+ private readonly getLastSummaryTimestampMs: () => number | undefined;
386
+
387
+ protected constructor(createParams: IGarbageCollectorCreateParams) {
388
+ this.runtime = createParams.runtime;
389
+ this.isSummarizerClient = createParams.isSummarizerClient;
390
+ this.gcOptions = createParams.gcOptions;
391
+ this.getNodePackagePath = createParams.getNodePackagePath;
392
+ this.getLastSummaryTimestampMs = createParams.getLastSummaryTimestampMs;
393
+
394
+ const baseSnapshot = createParams.baseSnapshot;
395
+ const metadata = createParams.metadata;
396
+ const readAndParseBlob = createParams.readAndParseBlob;
397
+
398
+ this.mc = loggerToMonitoringContext(ChildLogger.create(
399
+ createParams.baseLogger, "GarbageCollector", { all: { completedGCRuns: () => this.completedRuns } },
400
+ ));
403
401
 
404
402
  let prevSummaryGCVersion: number | undefined;
405
403
 
@@ -410,7 +408,7 @@ export class GarbageCollector implements IGarbageCollector {
410
408
  * 3. Whether GC session expiry is enabled or not.
411
409
  * For existing containers, we get this information from the metadata blob of its summary.
412
410
  */
413
- if (existing) {
411
+ if (createParams.existing) {
414
412
  prevSummaryGCVersion = getGCVersion(metadata);
415
413
  // Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
416
414
  // other existing documents, GC is enabled.
@@ -420,13 +418,15 @@ export class GarbageCollector implements IGarbageCollector {
420
418
  } else {
421
419
  // Sweep should not be enabled without enabling GC mark phase. We could silently disable sweep in this
422
420
  // scenario but explicitly failing makes it clearer and promotes correct usage.
423
- if (gcOptions.sweepAllowed && !gcOptions.gcAllowed) {
421
+ if (this.gcOptions.sweepAllowed && this.gcOptions.gcAllowed === false) {
424
422
  throw new UsageError("GC sweep phase cannot be enabled without enabling GC mark phase");
425
423
  }
426
424
 
427
- // For new documents, GC has to be explicitly enabled via the flags in GC options.
428
- this.gcEnabled = gcOptions.gcAllowed === true;
429
- this.sweepEnabled = gcOptions.sweepAllowed === true;
425
+ // For new documents, GC is enabled by default. It can be explicitly disabled by setting the gcAllowed
426
+ // flag in GC options to false.
427
+ this.gcEnabled = this.gcOptions.gcAllowed !== false;
428
+ // The sweep phase has to be explicitly enabled by setting the sweepAllowed flag in GC options to true.
429
+ this.sweepEnabled = this.gcOptions.sweepAllowed === true;
430
430
 
431
431
  // Set the Session Expiry only if the flag is enabled or the test option is set.
432
432
  if (this.mc.config.getBoolean(runSessionExpiryKey) && this.gcEnabled) {
@@ -468,13 +468,10 @@ export class GarbageCollector implements IGarbageCollector {
468
468
  // GC must be enabled for the document.
469
469
  this.gcEnabled
470
470
  // GC must not be disabled via GC options.
471
- && !gcOptions.disableGC
471
+ && !this.gcOptions.disableGC
472
472
  );
473
473
 
474
- const minimumVersion = this.mc.config.getString(trackGCStateMinimumVersionKey);
475
- const shouldTrackStateForVersion = meetsMinimumVersionRequirement(pkgVersion, minimumVersion);
476
-
477
- this.trackGCState = this.mc.config.getBoolean(trackGCStateKey) === true && shouldTrackStateForVersion;
474
+ this.trackGCState = this.mc.config.getBoolean(trackGCStateKey) === true;
478
475
 
479
476
  /**
480
477
  * Whether sweep should run or not. The following conditions have to be met to run sweep:
@@ -493,21 +490,17 @@ export class GarbageCollector implements IGarbageCollector {
493
490
  defaultInactiveTimeoutMs;
494
491
 
495
492
  // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
496
- this.testMode = this.mc.config.getBoolean(gcTestModeKey) ?? gcOptions.runGCInTestMode === true;
493
+ this.testMode = this.mc.config.getBoolean(gcTestModeKey) ?? this.gcOptions.runGCInTestMode === true;
497
494
 
498
- /**
499
- * Enable resetting initial state once the following issue is resolved:
500
- * https://github.com/microsoft/FluidFramework/issues/8878.
501
- * Currently, the GC tree is not written at root, so we don't know if the base snapshot contains GC tree or not.
502
- */
503
- // The GC state needs to be reset if the base snapshot contains GC tree and GC is disabled or it doesn't contain
504
- // GC tree and GC is enabled.
505
- // const gcTreePresent = baseSnapshot?.trees[gcTreeKey] !== undefined;
506
- // this.initialStateNeedsReset = gcTreePresent ? !this.shouldRunGC : this.shouldRunGC;
495
+ // GC state is written into root of the summary tree by default. Can be overridden via feature flag for now.
496
+ this._writeDataAtRoot = this.mc.config.getBoolean(writeAtRootKey) ?? true;
507
497
 
508
- // If `writeDataAtRoot` setting is true, write the GC data into the root of the summary tree. We do this so that
509
- // the roll out can be staged. Once its rolled out everywhere, we will start writing at root by default.
510
- this._writeDataAtRoot = this.mc.config.getBoolean(writeAtRootKey) ?? this.gcOptions.writeDataAtRoot === true;
498
+ if (this._writeDataAtRoot) {
499
+ // The GC state needs to be reset if the base snapshot contains GC tree and GC is disabled or it doesn't
500
+ // contain GC tree and GC is enabled.
501
+ const gcTreePresent = baseSnapshot?.trees[gcTreeKey] !== undefined;
502
+ this.initialStateNeedsReset = gcTreePresent !== this.shouldRunGC;
503
+ }
511
504
 
512
505
  // Get the GC state from the GC blob in the base snapshot. Use LazyPromise because we only want to do
513
506
  // this once since it involves fetching blobs from storage which is expensive.
@@ -588,7 +581,7 @@ export class GarbageCollector implements IGarbageCollector {
588
581
  return;
589
582
  }
590
583
 
591
- const gcNodes: { [ id: string ]: string[]; } = {};
584
+ const gcNodes: { [id: string]: string[]; } = {};
592
585
  for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
593
586
  if (nodeData.unreferencedTimestampMs !== undefined) {
594
587
  this.unreferencedNodesState.set(
@@ -613,18 +606,14 @@ export class GarbageCollector implements IGarbageCollector {
613
606
  return new Map();
614
607
  }
615
608
 
616
- const gcNodes: { [ id: string ]: string[]; } = {};
609
+ const gcNodes: { [id: string]: string[]; } = {};
617
610
  for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
618
611
  gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);
619
612
  }
620
613
  // Run GC on the nodes in the base summary to get the routes used in each node in the container.
621
614
  // This is an optimization for space (vs performance) wherein we don't need to store the used routes of
622
615
  // each node in the summary.
623
- const usedRoutes = runGarbageCollection(
624
- gcNodes,
625
- ["/"],
626
- this.mc.logger,
627
- ).referencedNodeIds;
616
+ const usedRoutes = runGarbageCollection(gcNodes, ["/"]).referencedNodeIds;
628
617
 
629
618
  const baseGCDetailsMap = unpackChildNodesGCDetails({ gcData: { gcNodes }, usedRoutes });
630
619
  // Currently, the nodes may write the GC data. So, we need to update it's base GC details with the
@@ -651,7 +640,7 @@ export class GarbageCollector implements IGarbageCollector {
651
640
  testMode: this.testMode,
652
641
  sessionExpiry: this.sessionExpiryTimeoutMs,
653
642
  inactiveTimeout: this.inactiveTimeoutMs,
654
- existing,
643
+ existing: createParams.existing,
655
644
  ...this.gcOptions,
656
645
  });
657
646
  if (this.isSummarizerClient) {
@@ -705,11 +694,7 @@ export class GarbageCollector implements IGarbageCollector {
705
694
 
706
695
  // Get the runtime's GC data and run GC on the reference graph in it.
707
696
  const gcData = await this.runtime.getGCData(fullGC);
708
- const gcResult = runGarbageCollection(
709
- gcData.gcNodes,
710
- ["/"],
711
- logger,
712
- );
697
+ const gcResult = runGarbageCollection(gcData.gcNodes, ["/"]);
713
698
  const gcStats = this.generateStatsAndLogEvents(gcResult, logger);
714
699
 
715
700
  // Update the state since the last GC run. There can be nodes that were referenced between the last and
@@ -737,8 +722,7 @@ export class GarbageCollector implements IGarbageCollector {
737
722
  this.completedRuns++;
738
723
 
739
724
  return gcStats;
740
- },
741
- { end: true, cancel: "error" });
725
+ }, { end: true, cancel: "error" });
742
726
  }
743
727
 
744
728
  /**
@@ -749,6 +733,7 @@ export class GarbageCollector implements IGarbageCollector {
749
733
  public summarize(
750
734
  fullTree: boolean,
751
735
  trackState: boolean,
736
+ telemetryContext?: ITelemetryContext,
752
737
  ): ISummarizeResult | undefined {
753
738
  if (!this.shouldRunGC || this.previousGCDataFromLastRun === undefined) {
754
739
  return;
@@ -822,10 +807,6 @@ export class GarbageCollector implements IGarbageCollector {
822
807
  result: RefreshSummaryResult,
823
808
  readAndParseBlob: ReadAndParseBlob,
824
809
  ): Promise<void> {
825
- // After a summary is successfully submitted and ack'd by this client, the GC state should have been reset in
826
- // the summary and doesn't need to be reset anymore.
827
- this.initialStateNeedsReset = false;
828
-
829
810
  if (!this.shouldRunGC || !result.latestSummaryUpdated) {
830
811
  return;
831
812
  }
@@ -834,6 +815,7 @@ export class GarbageCollector implements IGarbageCollector {
834
815
  // Basically, it was written in the current GC version.
835
816
  if (result.wasSummaryTracked) {
836
817
  this.latestSummaryGCVersion = this.currentGCVersion;
818
+ this.initialStateNeedsReset = false;
837
819
  if (this.trackGCState) {
838
820
  this.latestSerializedSummaryState = this.pendingSerializedSummaryState;
839
821
  this.pendingSerializedSummaryState = undefined;
@@ -1000,10 +982,7 @@ export class GarbageCollector implements IGarbageCollector {
1000
982
  this.newReferencesSinceLastRun,
1001
983
  );
1002
984
 
1003
- // The following log will be enabled once this issue is resolved:
1004
- // https://github.com/microsoft/FluidFramework/issues/8878.
1005
- if (this.mc.config.getBoolean(logUnknownOutboundReferencesKey) === true
1006
- && missingExplicitReferences.length > 0) {
985
+ if (this.writeDataAtRoot && missingExplicitReferences.length > 0) {
1007
986
  missingExplicitReferences.forEach((missingExplicitReference) => {
1008
987
  const event: ITelemetryPerformanceEvent = {
1009
988
  eventName: "gcUnknownOutboundReferences",
@@ -1049,7 +1028,7 @@ export class GarbageCollector implements IGarbageCollector {
1049
1028
  * unreferenced, stop tracking them and remove from unreferenced list.
1050
1029
  * Some of these nodes may be unreferenced now and if so, the current run will add unreferenced state for them.
1051
1030
  */
1052
- const gcResult = runGarbageCollection(gcDataSuperSet.gcNodes, ["/"], logger);
1031
+ const gcResult = runGarbageCollection(gcDataSuperSet.gcNodes, ["/"]);
1053
1032
  for (const nodeId of gcResult.referencedNodeIds) {
1054
1033
  const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
1055
1034
  if (nodeStateTracker !== undefined) {
@@ -1147,11 +1126,10 @@ export class GarbageCollector implements IGarbageCollector {
1147
1126
 
1148
1127
  const updateNodeStats = (nodeId: string, referenced: boolean) => {
1149
1128
  gcStats.nodeCount++;
1150
- /**
1151
- * `this.unreferencedNodesState` has the previous unreferenced state of all nodes. `referenced` flag passed
1152
- * here is current state of the give node. Check if the reference state of the changed.
1153
- */
1154
- const stateUpdated = this.unreferencedNodesState.has(nodeId) ? referenced : !referenced;
1129
+ // If there is no previous GC data, every node's state is generated and is considered as updated.
1130
+ // Otherwise, find out if any node went from referenced to unreferenced or vice-versa.
1131
+ const stateUpdated = this.previousGCDataFromLastRun === undefined ||
1132
+ this.unreferencedNodesState.has(nodeId) === referenced;
1155
1133
  if (stateUpdated) {
1156
1134
  gcStats.updatedNodeCount++;
1157
1135
  }
@@ -1244,7 +1222,7 @@ export class GarbageCollector implements IGarbageCollector {
1244
1222
  if (pkg !== undefined) {
1245
1223
  this.mc.logger.sendErrorEvent({
1246
1224
  ...event,
1247
- pkg: { value: `/${pkg.join("/")}`, tag: TelemetryDataTag.PackageData },
1225
+ pkg: { value: pkg.join("/"), tag: TelemetryDataTag.PackageData },
1248
1226
  });
1249
1227
  } else {
1250
1228
  this.pendingEventsQueue.push(event);
@@ -1313,66 +1291,3 @@ function setLongTimeout(
1313
1291
  }
1314
1292
  setTimerFn(timer);
1315
1293
  }
1316
-
1317
- /**
1318
- * meetsMinimumVersionRequirement is used determining if a feature version should be run. This is similar to feature
1319
- * flags. The advantage of this is that if we ship a bug in version 0.1.1 and fix it in version 0.2.1. We can keep this
1320
- * feature disabled for version 0.1.1 and enabled for 0.2.1. Older versions will run without the feature and new
1321
- * versions will run with the feature.
1322
- * @param currentVersion - the total time the timeout needs to last in ms
1323
- * @param minimumVersion - the function to execute when the timer ends
1324
- */
1325
- function meetsMinimumVersionRequirement(currentVersion: string, minimumVersion: string | undefined) {
1326
- return minimumVersion === undefined || semverCompare(currentVersion, minimumVersion) >= 0;
1327
- }
1328
-
1329
- /**
1330
- * Compare semver versions.
1331
- * @param currentVersion - assumed to be any valid semver version
1332
- * @param minimumVersion - must be [major].[minor].[patch], where major, minor, and patch are all numbers
1333
- * as it complicates the algorithm if we allow comparisons against minimum pre-release versions.
1334
- * @returns
1335
- * 0 if the currentVersion equals the minimumVersion
1336
- * 1 if the currentVersion is greater than the minimumVersion
1337
- * -1 if the minimumVersion is greater than the currentVersion
1338
- */
1339
- export function semverCompare(currentVersion: string, minimumVersion: string): number {
1340
- const minimumValues = minimumVersion.split(".").map((value): number => {
1341
- assert(isNaN(+value) === false, 0x2fa /* Expected real numbers in minimum version! */);
1342
- return Number.parseInt(value, 10);
1343
- });
1344
- assert(minimumValues.length === 3, 0x2fb /* Expected minimumVersion to be [major].[minor].[patch] */);
1345
- const [minMajor, minMinor, minPatch] = minimumValues;
1346
-
1347
- const currentValuesString = currentVersion.split(/\W/);
1348
- assert(currentValuesString.length >= 3, 0x2fc /* Expected version to match semver rules! */);
1349
- const currentValues = currentValuesString.slice(0, 3).map((value) => {
1350
- assert(isNaN(+value) === false, 0x2fd /* Expected real numbers in minimum version! */);
1351
- return Number.parseInt(value, 10);
1352
- });
1353
- const [cMajor, cMinor, cPatch] = currentValues;
1354
-
1355
- if (cMajor > minMajor) {
1356
- return 1;
1357
- } else if (minMajor > cMajor) {
1358
- return -1;
1359
- }
1360
-
1361
- if (cMinor > minMinor) {
1362
- return 1;
1363
- } else if (minMinor > cMinor) {
1364
- return -1;
1365
- }
1366
-
1367
- if (cPatch > minPatch) {
1368
- return 1;
1369
- } else if (minPatch > cPatch) {
1370
- return -1;
1371
- }
1372
-
1373
- if (currentValuesString.length === 3) {
1374
- return 0;
1375
- }
1376
-
1377
- return -1;
1378
- }
package/src/index.ts CHANGED
@@ -9,7 +9,12 @@ export {
9
9
  ContainerRuntimeMessage,
10
10
  IGCRuntimeOptions,
11
11
  ISummaryRuntimeOptions,
12
+ ISummaryBaseConfiguration,
13
+ ISummaryConfigurationHeuristics,
14
+ ISummaryConfigurationDisableSummarizer,
15
+ ISummaryConfigurationDisableHeuristics,
12
16
  IContainerRuntimeOptions,
17
+ IPendingRuntimeState,
13
18
  IRootSummaryTreeWithStats,
14
19
  isRuntimeMessage,
15
20
  RuntimeMessage,
@@ -18,6 +23,8 @@ export {
18
23
  agentSchedulerId,
19
24
  ContainerRuntime,
20
25
  RuntimeHeaders,
26
+ ISummaryConfiguration,
27
+ DefaultSummaryConfiguration,
21
28
  } from "./containerRuntime";
22
29
  export { DeltaScheduler } from "./deltaScheduler";
23
30
  export { FluidDataStoreRegistry } from "./dataStoreRegistry";
@@ -55,7 +62,6 @@ export {
55
62
  ISummarizer,
56
63
  ISummarizerEvents,
57
64
  ISummarizerInternalsProvider,
58
- ISummarizerOptions,
59
65
  ISummarizerRuntime,
60
66
  ISummarizingWarning,
61
67
  ISummaryCancellationToken,
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
-
5
+ /* eslint-disable @rushstack/no-new-null */
6
6
  import { IEvent, IEventProvider, ITelemetryLogger } from "@fluidframework/common-definitions";
7
7
  import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
8
8
  import { IDeltaManager } from "@fluidframework/container-definitions";
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "0.59.4001";
9
+ export const pkgVersion = "1.1.0-75972";