@fluidframework/container-runtime 2.0.0-internal.3.3.1 → 2.0.0-internal.3.4.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 (83) hide show
  1. package/dist/blobManager.d.ts +17 -11
  2. package/dist/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager.js +89 -58
  4. package/dist/blobManager.js.map +1 -1
  5. package/dist/containerRuntime.d.ts +5 -0
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +11 -10
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/gc/garbageCollection.d.ts.map +1 -1
  10. package/dist/gc/garbageCollection.js +4 -5
  11. package/dist/gc/garbageCollection.js.map +1 -1
  12. package/dist/gc/gcConfigs.d.ts.map +1 -1
  13. package/dist/gc/gcConfigs.js +25 -22
  14. package/dist/gc/gcConfigs.js.map +1 -1
  15. package/dist/gc/gcDefinitions.d.ts +28 -3
  16. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  17. package/dist/gc/gcDefinitions.js +15 -2
  18. package/dist/gc/gcDefinitions.js.map +1 -1
  19. package/dist/gc/gcHelpers.d.ts +25 -5
  20. package/dist/gc/gcHelpers.d.ts.map +1 -1
  21. package/dist/gc/gcHelpers.js +38 -5
  22. package/dist/gc/gcHelpers.js.map +1 -1
  23. package/dist/gc/gcSummaryStateTracker.d.ts +5 -7
  24. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  25. package/dist/gc/gcSummaryStateTracker.js +16 -25
  26. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  27. package/dist/gc/index.d.ts +2 -2
  28. package/dist/gc/index.d.ts.map +1 -1
  29. package/dist/gc/index.js +3 -1
  30. package/dist/gc/index.js.map +1 -1
  31. package/dist/packageVersion.d.ts +1 -1
  32. package/dist/packageVersion.js +1 -1
  33. package/dist/packageVersion.js.map +1 -1
  34. package/dist/summary/summaryFormat.d.ts +2 -0
  35. package/dist/summary/summaryFormat.d.ts.map +1 -1
  36. package/dist/summary/summaryFormat.js.map +1 -1
  37. package/lib/blobManager.d.ts +17 -11
  38. package/lib/blobManager.d.ts.map +1 -1
  39. package/lib/blobManager.js +89 -58
  40. package/lib/blobManager.js.map +1 -1
  41. package/lib/containerRuntime.d.ts +5 -0
  42. package/lib/containerRuntime.d.ts.map +1 -1
  43. package/lib/containerRuntime.js +11 -10
  44. package/lib/containerRuntime.js.map +1 -1
  45. package/lib/gc/garbageCollection.d.ts.map +1 -1
  46. package/lib/gc/garbageCollection.js +4 -5
  47. package/lib/gc/garbageCollection.js.map +1 -1
  48. package/lib/gc/gcConfigs.d.ts.map +1 -1
  49. package/lib/gc/gcConfigs.js +25 -22
  50. package/lib/gc/gcConfigs.js.map +1 -1
  51. package/lib/gc/gcDefinitions.d.ts +28 -3
  52. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  53. package/lib/gc/gcDefinitions.js +14 -1
  54. package/lib/gc/gcDefinitions.js.map +1 -1
  55. package/lib/gc/gcHelpers.d.ts +25 -5
  56. package/lib/gc/gcHelpers.d.ts.map +1 -1
  57. package/lib/gc/gcHelpers.js +36 -4
  58. package/lib/gc/gcHelpers.js.map +1 -1
  59. package/lib/gc/gcSummaryStateTracker.d.ts +5 -7
  60. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  61. package/lib/gc/gcSummaryStateTracker.js +16 -25
  62. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  63. package/lib/gc/index.d.ts +2 -2
  64. package/lib/gc/index.d.ts.map +1 -1
  65. package/lib/gc/index.js +2 -2
  66. package/lib/gc/index.js.map +1 -1
  67. package/lib/packageVersion.d.ts +1 -1
  68. package/lib/packageVersion.js +1 -1
  69. package/lib/packageVersion.js.map +1 -1
  70. package/lib/summary/summaryFormat.d.ts +2 -0
  71. package/lib/summary/summaryFormat.d.ts.map +1 -1
  72. package/lib/summary/summaryFormat.js.map +1 -1
  73. package/package.json +23 -24
  74. package/src/blobManager.ts +108 -77
  75. package/src/containerRuntime.ts +12 -4
  76. package/src/gc/garbageCollection.ts +4 -8
  77. package/src/gc/gcConfigs.ts +26 -12
  78. package/src/gc/gcDefinitions.ts +28 -3
  79. package/src/gc/gcHelpers.ts +45 -4
  80. package/src/gc/gcSummaryStateTracker.ts +17 -29
  81. package/src/gc/index.ts +3 -0
  82. package/src/packageVersion.ts +1 -1
  83. package/src/summary/summaryFormat.ts +2 -0
@@ -1001,6 +1001,12 @@ export class ContainerRuntime
1001
1001
  */
1002
1002
  public readonly gcTombstoneEnforcementAllowed: boolean;
1003
1003
 
1004
+ /**
1005
+ * GUID to identify a document in telemetry
1006
+ * ! Note: should not be used for anything other than telemetry and is not considered a stable GUID
1007
+ */
1008
+ private readonly telemetryDocumentId: string;
1009
+
1004
1010
  /**
1005
1011
  * @internal
1006
1012
  */
@@ -1074,6 +1080,8 @@ export class ContainerRuntime
1074
1080
  }),
1075
1081
  });
1076
1082
 
1083
+ this.telemetryDocumentId = metadata?.telemetryDocumentId ?? uuid();
1084
+
1077
1085
  this.disableAttachReorder = this.mc.config.getBoolean(
1078
1086
  "Fluid.ContainerRuntime.disableAttachOpReorder",
1079
1087
  );
@@ -1226,8 +1234,6 @@ export class ContainerRuntime
1226
1234
  }
1227
1235
  },
1228
1236
  (blobPath: string) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"),
1229
- (fromPath: string, toPath: string) =>
1230
- this.garbageCollector.addedOutboundReference(fromPath, toPath),
1231
1237
  (blobPath: string) => this.garbageCollector.isNodeDeleted(blobPath),
1232
1238
  this,
1233
1239
  pendingRuntimeState?.pendingAttachmentBlobs,
@@ -1428,6 +1434,7 @@ export class ContainerRuntime
1428
1434
  disableAttachReorder: this.disableAttachReorder,
1429
1435
  disablePartialFlush,
1430
1436
  }),
1437
+ telemetryDocumentId: this.telemetryDocumentId,
1431
1438
  });
1432
1439
 
1433
1440
  ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
@@ -1608,6 +1615,7 @@ export class ContainerRuntime
1608
1615
  message:
1609
1616
  extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
1610
1617
  this.messageAtLastSummary,
1618
+ telemetryDocumentId: this.telemetryDocumentId,
1611
1619
  };
1612
1620
  addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
1613
1621
  }
@@ -2544,7 +2552,7 @@ export class ContainerRuntime
2544
2552
  * @param options - options controlling how the summary is generated or submitted
2545
2553
  */
2546
2554
  public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
2547
- const { fullTree, refreshLatestAck, summaryLogger } = options;
2555
+ const { fullTree = false, refreshLatestAck, summaryLogger } = options;
2548
2556
  // The summary number for this summary. This will be updated during the summary process, so get it now and
2549
2557
  // use it for all events logged during this summary.
2550
2558
  const summaryNumber = this.nextSummaryNumber;
@@ -2639,7 +2647,7 @@ export class ContainerRuntime
2639
2647
  const forcedFullTree = this.garbageCollector.summaryStateNeedsReset;
2640
2648
  try {
2641
2649
  summarizeResult = await this.summarize({
2642
- fullTree: fullTree ?? forcedFullTree,
2650
+ fullTree: fullTree || forcedFullTree,
2643
2651
  trackState: true,
2644
2652
  summaryLogger: summaryNumberLogger,
2645
2653
  runGC: this.garbageCollector.shouldRunGC,
@@ -153,7 +153,7 @@ export class GarbageCollector implements IGarbageCollector {
153
153
  private readonly activeConnection: () => boolean;
154
154
 
155
155
  public get summaryStateNeedsReset(): boolean {
156
- return this.summaryStateTracker.doesSummaryStateNeedReset();
156
+ return this.summaryStateTracker.doesSummaryStateNeedReset;
157
157
  }
158
158
 
159
159
  /** Handler to respond to when a SweepReady object is used */
@@ -201,11 +201,8 @@ export class GarbageCollector implements IGarbageCollector {
201
201
  }
202
202
 
203
203
  this.summaryStateTracker = new GCSummaryStateTracker(
204
- this.shouldRunGC,
205
- this.configs.tombstoneMode,
206
- this.mc,
204
+ this.configs,
207
205
  baseSnapshot?.trees[gcTreeKey] !== undefined /* wasGCRunInBaseSnapshot */,
208
- this.configs.gcVersionInBaseSnapshot,
209
206
  );
210
207
 
211
208
  // Get the GC data from the base snapshot. Use LazyPromise because we only want to do this once since it
@@ -469,8 +466,7 @@ export class GarbageCollector implements IGarbageCollector {
469
466
  ): Promise<IGCStats | undefined> {
470
467
  const fullGC =
471
468
  options.fullGC ??
472
- (this.configs.runFullGC === true ||
473
- this.summaryStateTracker.doesSummaryStateNeedReset());
469
+ (this.configs.runFullGC === true || this.summaryStateTracker.doesSummaryStateNeedReset);
474
470
  const logger = options.logger
475
471
  ? ChildLogger.create(options.logger, undefined, {
476
472
  all: { completedGCRuns: () => this.completedRuns },
@@ -622,7 +618,7 @@ export class GarbageCollector implements IGarbageCollector {
622
618
  gcFeature: this.configs.gcEnabled ? this.summaryStateTracker.currentGCVersion : 0,
623
619
  gcFeatureMatrix: this.configs.persistedGcFeatureMatrix,
624
620
  sessionExpiryTimeoutMs: this.configs.sessionExpiryTimeoutMs,
625
- sweepEnabled: this.configs.sweepEnabled,
621
+ sweepEnabled: false, // DEPRECATED - to be removed
626
622
  sweepTimeoutMs: this.configs.sweepTimeoutMs,
627
623
  };
628
624
  }
@@ -3,17 +3,20 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { UsageError } from "@fluidframework/driver-utils";
6
+ import { UsageError } from "@fluidframework/container-utils";
7
7
  import { MonitoringContext } from "@fluidframework/telemetry-utils";
8
8
  import { IContainerRuntimeMetadata } from "../summary";
9
9
  import {
10
+ currentGCVersion,
10
11
  defaultInactiveTimeoutMs,
11
12
  defaultSessionExpiryDurationMs,
12
13
  disableTombstoneKey,
13
14
  GCFeatureMatrix,
15
+ gcSweepGenerationOptionName,
14
16
  gcTestModeKey,
15
17
  gcTombstoneGenerationOptionName,
16
18
  GCVersion,
19
+ gcVersionUpgradeToV2Key,
17
20
  IGarbageCollectorConfigs,
18
21
  IGCRuntimeOptions,
19
22
  maxSnapshotCacheExpiryMs,
@@ -21,8 +24,9 @@ import {
21
24
  runGCKey,
22
25
  runSessionExpiryKey,
23
26
  runSweepKey,
27
+ stableGCVersion,
24
28
  } from "./gcDefinitions";
25
- import { getGCVersion } from "./gcHelpers";
29
+ import { getGCVersion, shouldAllowGcSweep } from "./gcHelpers";
26
30
 
27
31
  /**
28
32
  * Generates configurations for the Garbage Collector that it uses to determine what to run and how.
@@ -42,7 +46,6 @@ export function generateGCConfigs(
42
46
  },
43
47
  ): IGarbageCollectorConfigs {
44
48
  let gcEnabled: boolean;
45
- let sweepEnabled: boolean;
46
49
  let sessionExpiryTimeoutMs: number | undefined;
47
50
  let sweepTimeoutMs: number | undefined;
48
51
  let persistedGcFeatureMatrix: GCFeatureMatrix | undefined;
@@ -60,15 +63,16 @@ export function generateGCConfigs(
60
63
  // Existing documents which did not have createParams.metadata blob or had GC disabled have version as 0. For all
61
64
  // other existing documents, GC is enabled.
62
65
  gcEnabled = gcVersionInBaseSnapshot > 0;
63
- sweepEnabled = createParams.metadata?.sweepEnabled ?? false;
64
66
  sessionExpiryTimeoutMs = createParams.metadata?.sessionExpiryTimeoutMs;
65
67
  sweepTimeoutMs =
66
68
  createParams.metadata?.sweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs); // Backfill old documents that didn't persist this
67
69
  persistedGcFeatureMatrix = createParams.metadata?.gcFeatureMatrix;
68
70
  } else {
69
- // Sweep should not be enabled without enabling GC mark phase. We could silently disable sweep in this
70
- // scenario but explicitly failing makes it clearer and promotes correct usage.
71
- if (createParams.gcOptions.sweepAllowed && createParams.gcOptions.gcAllowed === false) {
71
+ const tombstoneGeneration = createParams.gcOptions[gcTombstoneGenerationOptionName];
72
+ const sweepGeneration = createParams.gcOptions[gcSweepGenerationOptionName];
73
+
74
+ // Sweep should not be enabled (via sweepGeneration value) without enabling GC mark phase.
75
+ if (sweepGeneration !== undefined && createParams.gcOptions.gcAllowed === false) {
72
76
  throw new UsageError("GC sweep phase cannot be enabled without enabling GC mark phase");
73
77
  }
74
78
 
@@ -80,8 +84,6 @@ export function generateGCConfigs(
80
84
  // For new documents, GC is enabled by default. It can be explicitly disabled by setting the gcAllowed
81
85
  // flag in GC options to false.
82
86
  gcEnabled = createParams.gcOptions.gcAllowed !== false;
83
- // The sweep phase has to be explicitly enabled by setting the sweepAllowed flag in GC options to true.
84
- sweepEnabled = createParams.gcOptions.sweepAllowed === true;
85
87
 
86
88
  // Set the Session Expiry if GC is enabled and session expiry flag isn't explicitly set to false.
87
89
  if (gcEnabled && mc.config.getBoolean(runSessionExpiryKey) !== false) {
@@ -90,13 +92,20 @@ export function generateGCConfigs(
90
92
  }
91
93
  sweepTimeoutMs = testOverrideSweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs);
92
94
 
93
- if (createParams.gcOptions[gcTombstoneGenerationOptionName] !== undefined) {
95
+ if (tombstoneGeneration !== undefined || sweepGeneration !== undefined) {
94
96
  persistedGcFeatureMatrix = {
95
- tombstoneGeneration: createParams.gcOptions[gcTombstoneGenerationOptionName],
97
+ tombstoneGeneration,
98
+ sweepGeneration,
96
99
  };
97
100
  }
98
101
  }
99
102
 
103
+ // Is sweepEnabled for this document?
104
+ const sweepEnabled = shouldAllowGcSweep(
105
+ persistedGcFeatureMatrix ?? {} /* persistedGenerations */,
106
+ createParams.gcOptions[gcSweepGenerationOptionName] /* currentGeneration */,
107
+ );
108
+
100
109
  /**
101
110
  * Whether GC should run or not. The following conditions have to be met to run sweep:
102
111
  *
@@ -120,7 +129,7 @@ export function generateGCConfigs(
120
129
  * 2. Sweep timeout should be available. Without this, we wouldn't know when an object should be deleted.
121
130
  * 3. The driver must implement the policy limiting the age of snapshots used for loading. Otherwise
122
131
  * the Sweep Timeout calculation is not valid. We use the persisted value to ensure consistency over time.
123
- * 4. Sweep should be enabled for this container (this.sweepEnabled). This can be overridden via runSweep
132
+ * 4. Sweep should be enabled for this container. This can be overridden via runSweep
124
133
  * feature flag.
125
134
  */
126
135
  const shouldRunSweep =
@@ -147,6 +156,10 @@ export function generateGCConfigs(
147
156
  const tombstoneMode = !shouldRunSweep && mc.config.getBoolean(disableTombstoneKey) !== true;
148
157
  const runFullGC = createParams.gcOptions.runFullGC;
149
158
 
159
+ // If version upgrade is not enabled, fall back to the stable GC version.
160
+ const gcVersionInEffect =
161
+ mc.config.getBoolean(gcVersionUpgradeToV2Key) === true ? currentGCVersion : stableGCVersion;
162
+
150
163
  return {
151
164
  gcEnabled,
152
165
  sweepEnabled,
@@ -160,6 +173,7 @@ export function generateGCConfigs(
160
173
  inactiveTimeoutMs,
161
174
  persistedGcFeatureMatrix,
162
175
  gcVersionInBaseSnapshot,
176
+ gcVersionInEffect,
163
177
  };
164
178
  }
165
179
 
@@ -23,8 +23,21 @@ export const stableGCVersion: GCVersion = 1;
23
23
  /** The current version of garbage collection. */
24
24
  export const currentGCVersion: GCVersion = 2;
25
25
 
26
- /** This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value */
26
+ /**
27
+ * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value
28
+ *
29
+ * If unset, GC Tombstone phase will operate as otherwise configured
30
+ * Otherwise, only enforce GC Tombstone if the passed in value matches the persisted value
31
+ */
27
32
  export const gcTombstoneGenerationOptionName = "gcTombstoneGeneration";
33
+ /**
34
+ * This GC Option (on ContainerRuntime Options) allows an app to disable GC Sweep on old documents by incrementing this value.
35
+ *
36
+ * If unset altogether, Sweep will be disabled.
37
+ * If 0 is passed in, Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.
38
+ * If any other number is passed in, Sweep will be enabled only for documents with the same value persisted.
39
+ */
40
+ export const gcSweepGenerationOptionName = "gcSweepGeneration";
28
41
 
29
42
  // Feature gate key to turn GC on / off.
30
43
  export const runGCKey = "Fluid.GarbageCollection.RunGC";
@@ -68,10 +81,16 @@ export const defaultSessionExpiryDurationMs = 30 * oneDayMs; // 30 days
68
81
  export interface GCFeatureMatrix {
69
82
  /**
70
83
  * The Tombstone Generation value in effect when this file was created.
71
- * Gives a way for an app to disqualify old files from GC Tombstone enforcement
72
- * Provided via Container Runtime Options
84
+ * Gives a way for an app to disqualify old files from GC Tombstone enforcement.
85
+ * Provided via Container Runtime Options.
73
86
  */
74
87
  tombstoneGeneration?: number;
88
+ /**
89
+ * The Sweep Generation value in effect when this file was created.
90
+ * Gives a way for an app to disqualify old files from GC Sweep.
91
+ * Provided via Container Runtime Options.
92
+ */
93
+ sweepGeneration?: number;
75
94
  }
76
95
 
77
96
  export interface IGCMetadata {
@@ -97,6 +116,8 @@ export interface IGCMetadata {
97
116
  */
98
117
  readonly gcFeatureMatrix?: GCFeatureMatrix;
99
118
  /**
119
+ * @deprecated - @see GCFeatureMatrix.sweepGeneration
120
+ *
100
121
  * Tells whether the GC sweep phase is enabled for this container.
101
122
  * - True means sweep phase is enabled.
102
123
  * - False means sweep phase is disabled. If GC is disabled as per gcFeature, sweep is also disabled.
@@ -255,6 +276,8 @@ export interface IGCRuntimeOptions {
255
276
  gcAllowed?: boolean;
256
277
 
257
278
  /**
279
+ * @deprecated - @see gcSweepGenerationOptionName and @see GCFeatureMatrix.sweepGeneration
280
+ *
258
281
  * Flag that if true, enables GC's sweep phase for a new container.
259
282
  *
260
283
  * This will allow GC to eventually delete unreferenced objects from the container.
@@ -336,6 +359,8 @@ export interface IGarbageCollectorConfigs {
336
359
  readonly persistedGcFeatureMatrix: GCFeatureMatrix | undefined;
337
360
  /** The version of GC in the base snapshot. */
338
361
  readonly gcVersionInBaseSnapshot: GCVersion | undefined;
362
+ /** The current version of GC data in the running code */
363
+ readonly gcVersionInEffect: GCVersion;
339
364
  }
340
365
 
341
366
  /** The state of node that is unreferenced. */
@@ -23,6 +23,7 @@ import {
23
23
  } from "../summary";
24
24
  import {
25
25
  disableTombstoneKey,
26
+ GCFeatureMatrix,
26
27
  GCVersion,
27
28
  IGCMetadata,
28
29
  runSweepKey,
@@ -65,14 +66,19 @@ export function sendGCUnexpectedUsageEvent(
65
66
  }
66
67
 
67
68
  /**
69
+ * Indicates whether Tombstone Enforcement is allowed for this document based on the current/persisted
70
+ * TombstoneGeneration values
71
+ *
68
72
  * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants
69
- * such that enforcing GC (Fail on Tombstone load/usage, GC Sweep) would cause legitimate data loss,
73
+ * such that enforcing GC Tombstone (Failing on Tombstone load/usage) would cause legitimate data loss,
70
74
  * the container author may increment the generation value for Tombstone such that containers created
71
75
  * with a different value will not be subjected to GC enforcement.
76
+ *
72
77
  * If no generation is provided at runtime, this defaults to return true to maintain expected default behavior
73
- * @param persistedGeneration - The persisted feature support value
74
- * @param currentGeneration - The current app-provided feature support value
75
- * @returns true if GC Enforcement (Fail on Tombstone load/usage) should be allowed
78
+ *
79
+ * @param persistedGeneration - The persisted tombstoneGeneration value
80
+ * @param currentGeneration - The current app-provided tombstoneGeneration value
81
+ * @returns true if GC Tombstone enforcement (Fail on Tombstone load/usage) should be allowed for this document
76
82
  */
77
83
  export function shouldAllowGcTombstoneEnforcement(
78
84
  persistedGeneration: number | undefined,
@@ -85,6 +91,41 @@ export function shouldAllowGcTombstoneEnforcement(
85
91
  return persistedGeneration === currentGeneration;
86
92
  }
87
93
 
94
+ /**
95
+ * Indicates whether Sweep is allowed for this document based on the GC Feature Matrix and current SweepGeneration
96
+ *
97
+ * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants
98
+ * such that enforcing GC Sweep would cause legitimate data loss, the container author may increment the generation value for Sweep
99
+ * such that containers created with a different value will not be subjected to GC Sweep.
100
+ *
101
+ * If no generation is provided, Sweep will be disabled.
102
+ * Passing 0 is a special case: Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.
103
+ *
104
+ * @param persistedGenerations - The persisted sweep/tombstone generations from the GC Feature Matrix
105
+ * @param currentGeneration - The current app-provided sweepGeneration value
106
+ * @returns true if GC Sweep should be allowed for this document
107
+ */
108
+ export function shouldAllowGcSweep(
109
+ persistedGenerations: Pick<GCFeatureMatrix, "sweepGeneration" | "tombstoneGeneration">,
110
+ currentGeneration: number | undefined,
111
+ ): boolean {
112
+ // If no Generation value is provided for this session, default to false
113
+ if (currentGeneration === undefined) {
114
+ return false;
115
+ }
116
+
117
+ // 0 is a special case: It matches both SweepGeneration and TombstoneGeneration
118
+ // This is an optimistic measure to maximize coverage of GC Sweep if no bumps to TombstoneGeneration are needed before enabling Sweep.
119
+ if (currentGeneration === 0) {
120
+ return (
121
+ persistedGenerations.sweepGeneration === 0 ||
122
+ persistedGenerations.tombstoneGeneration === 0
123
+ );
124
+ }
125
+
126
+ return persistedGenerations.sweepGeneration === currentGeneration;
127
+ }
128
+
88
129
  /**
89
130
  * Sorts the given GC state as per the id of the GC nodes. It also sorts the outbound routes array of each node.
90
131
  */
@@ -21,15 +21,10 @@ import {
21
21
  RefreshSummaryResult,
22
22
  SummaryTreeBuilder,
23
23
  } from "@fluidframework/runtime-utils";
24
- import { MonitoringContext } from "@fluidframework/telemetry-utils";
25
24
  import { IContainerRuntimeMetadata, metadataBlobName } from "../summary";
26
- import {
27
- currentGCVersion,
28
- GCVersion,
29
- gcVersionUpgradeToV2Key,
30
- stableGCVersion,
31
- } from "./gcDefinitions";
25
+ import { GCVersion } from "./gcDefinitions";
32
26
  import { generateSortedGCState, getGCVersion } from "./gcHelpers";
27
+ import { IGarbageCollectorConfigs } from ".";
33
28
 
34
29
  /**
35
30
  * The GC data that is tracked for a summary.
@@ -48,7 +43,7 @@ interface IGCSummaryTrackingData {
48
43
  */
49
44
  export class GCSummaryStateTracker {
50
45
  // The current version of GC running.
51
- public readonly currentGCVersion: GCVersion;
46
+ public readonly currentGCVersion: GCVersion = this.configs.gcVersionInEffect;
52
47
  // This is the version of GC data in the latest summary being tracked.
53
48
  private latestSummaryGCVersion: GCVersion;
54
49
 
@@ -62,24 +57,17 @@ export class GCSummaryStateTracker {
62
57
 
63
58
  constructor(
64
59
  // Tells whether GC should run or not.
65
- private readonly shouldRunGC: boolean,
66
- // Tells whether tombstone mode is enabled or not.
67
- private readonly tombstoneMode: boolean,
68
- private readonly mc: MonitoringContext,
60
+ private readonly configs: Pick<
61
+ IGarbageCollectorConfigs,
62
+ "shouldRunGC" | "tombstoneMode" | "gcVersionInBaseSnapshot" | "gcVersionInEffect"
63
+ >,
69
64
  // Tells whether GC was run in the base snapshot this container loaded from.
70
65
  wasGCRunInBaseSnapshot: boolean,
71
- // The GC version in the base snapshot this container loaded from.
72
- gcVersionInBaseSnapshot: GCVersion | undefined,
73
66
  ) {
74
67
  this.wasGCRunInLatestSummary = wasGCRunInBaseSnapshot;
75
- // If version upgrade is not enabled, fall back to the stable GC version.
76
- this.currentGCVersion =
77
- this.mc.config.getBoolean(gcVersionUpgradeToV2Key) === true
78
- ? currentGCVersion
79
- : stableGCVersion;
80
68
  // For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
81
69
  // latest tracked GC version. For new documents, we will be writing the first summary with the current version.
82
- this.latestSummaryGCVersion = gcVersionInBaseSnapshot ?? this.currentGCVersion;
70
+ this.latestSummaryGCVersion = this.configs.gcVersionInBaseSnapshot ?? this.currentGCVersion;
83
71
  }
84
72
 
85
73
  /**
@@ -96,8 +84,8 @@ export class GCSummaryStateTracker {
96
84
  * Note that the state will be reset only once for the first summary generated after this returns true. After that,
97
85
  * this will return false.
98
86
  */
99
- public doesGCStateNeedReset(): boolean {
100
- return this.wasGCRunInLatestSummary !== this.shouldRunGC;
87
+ public get doesGCStateNeedReset(): boolean {
88
+ return this.wasGCRunInLatestSummary !== this.configs.shouldRunGC;
101
89
  }
102
90
 
103
91
  /**
@@ -115,10 +103,10 @@ export class GCSummaryStateTracker {
115
103
  *
116
104
  * 4.2. This client's latest summary was updated from a snapshot that has a different GC version.
117
105
  */
118
- public doesSummaryStateNeedReset(): boolean {
106
+ public get doesSummaryStateNeedReset(): boolean {
119
107
  return (
120
- this.doesGCStateNeedReset() ||
121
- (this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion)
108
+ this.doesGCStateNeedReset ||
109
+ (this.configs.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion)
122
110
  );
123
111
  }
124
112
 
@@ -135,7 +123,7 @@ export class GCSummaryStateTracker {
135
123
  deletedNodes: Set<string>,
136
124
  tombstones: string[],
137
125
  ): ISummarizeResult | undefined {
138
- if (!this.shouldRunGC) {
126
+ if (!this.configs.shouldRunGC) {
139
127
  return;
140
128
  }
141
129
 
@@ -145,7 +133,7 @@ export class GCSummaryStateTracker {
145
133
  const serializedDeletedNodes =
146
134
  deletedNodes.size > 0 ? JSON.stringify(Array.from(deletedNodes).sort()) : undefined;
147
135
  // If running in tombstone mode, serialize and write tombstones, if any.
148
- const serializedTombstones = this.tombstoneMode
136
+ const serializedTombstones = this.configs.tombstoneMode
149
137
  ? tombstones.length > 0
150
138
  ? JSON.stringify(tombstones.sort())
151
139
  : undefined
@@ -276,10 +264,10 @@ export class GCSummaryStateTracker {
276
264
  // Note that this has to be updated if GC did not run too. Otherwise, `gcStateNeedsReset` will always return
277
265
  // true in scenarios where GC is disabled but enabled in the snapshot we loaded from.
278
266
  if (result.latestSummaryUpdated && result.wasSummaryTracked) {
279
- this.wasGCRunInLatestSummary = this.shouldRunGC;
267
+ this.wasGCRunInLatestSummary = this.configs.shouldRunGC;
280
268
  }
281
269
 
282
- if (!result.latestSummaryUpdated || !this.shouldRunGC) {
270
+ if (!result.latestSummaryUpdated || !this.configs.shouldRunGC) {
283
271
  return undefined;
284
272
  }
285
273
 
package/src/gc/index.ts CHANGED
@@ -12,6 +12,8 @@ export {
12
12
  GCNodeType,
13
13
  gcTestModeKey,
14
14
  gcTombstoneGenerationOptionName,
15
+ gcSweepGenerationOptionName,
16
+ GCFeatureMatrix,
15
17
  GCVersion,
16
18
  gcVersionUpgradeToV2Key,
17
19
  IGarbageCollectionRuntime, // Deprecated
@@ -36,6 +38,7 @@ export {
36
38
  getSnapshotDataFromOldSnapshotFormat,
37
39
  sendGCUnexpectedUsageEvent,
38
40
  shouldAllowGcTombstoneEnforcement,
41
+ shouldAllowGcSweep,
39
42
  } from "./gcHelpers";
40
43
  export { GCSummaryStateTracker } from "./gcSummaryStateTracker";
41
44
  export {
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.0.0-internal.3.3.1";
9
+ export const pkgVersion = "2.0.0-internal.3.4.0";
@@ -89,6 +89,8 @@ export interface IContainerRuntimeMetadata extends ICreateContainerMetadata, IGC
89
89
  readonly disableIsolatedChannels?: true;
90
90
  /** The summary number for a container's summary. Incremented on summaries throughout its lifetime. */
91
91
  readonly summaryNumber?: number;
92
+ /** GUID to identify a document in telemetry */
93
+ readonly telemetryDocumentId?: string;
92
94
  }
93
95
 
94
96
  export interface ICreateContainerMetadata {