@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.
- package/dist/blobManager.d.ts +17 -11
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +89 -58
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +5 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +11 -10
- package/dist/containerRuntime.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +4 -5
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +25 -22
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +28 -3
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +15 -2
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +25 -5
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +38 -5
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +5 -7
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +16 -25
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +3 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +2 -0
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/lib/blobManager.d.ts +17 -11
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +89 -58
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +5 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +11 -10
- package/lib/containerRuntime.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +4 -5
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +25 -22
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +28 -3
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +14 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +25 -5
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +36 -4
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +5 -7
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +16 -25
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +2 -0
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/package.json +23 -24
- package/src/blobManager.ts +108 -77
- package/src/containerRuntime.ts +12 -4
- package/src/gc/garbageCollection.ts +4 -8
- package/src/gc/gcConfigs.ts +26 -12
- package/src/gc/gcDefinitions.ts +28 -3
- package/src/gc/gcHelpers.ts +45 -4
- package/src/gc/gcSummaryStateTracker.ts +17 -29
- package/src/gc/index.ts +3 -0
- package/src/packageVersion.ts +1 -1
- package/src/summary/summaryFormat.ts +2 -0
package/src/containerRuntime.ts
CHANGED
|
@@ -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
|
|
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.
|
|
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:
|
|
621
|
+
sweepEnabled: false, // DEPRECATED - to be removed
|
|
626
622
|
sweepTimeoutMs: this.configs.sweepTimeoutMs,
|
|
627
623
|
};
|
|
628
624
|
}
|
package/src/gc/gcConfigs.ts
CHANGED
|
@@ -3,17 +3,20 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { UsageError } from "@fluidframework/
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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 (
|
|
95
|
+
if (tombstoneGeneration !== undefined || sweepGeneration !== undefined) {
|
|
94
96
|
persistedGcFeatureMatrix = {
|
|
95
|
-
tombstoneGeneration
|
|
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
|
|
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
|
|
package/src/gc/gcDefinitions.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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. */
|
package/src/gc/gcHelpers.ts
CHANGED
|
@@ -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 (
|
|
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
|
-
*
|
|
74
|
-
* @param
|
|
75
|
-
* @
|
|
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
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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 {
|
package/src/packageVersion.ts
CHANGED
|
@@ -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 {
|