@fluidframework/container-runtime 0.59.2000-63294 → 0.59.3000-66610
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/.eslintrc.js +0 -1
- package/dist/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.js +8 -8
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.js +8 -8
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.js +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +27 -17
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +149 -174
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +1 -1
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +44 -44
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +2 -2
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +8 -8
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStores.d.ts +4 -2
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +45 -33
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +23 -23
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +81 -50
- package/dist/garbageCollection.js.map +1 -1
- package/dist/opTelemetry.js +1 -1
- package/dist/opTelemetry.js.map +1 -1
- package/dist/orderedClientElection.d.ts.map +1 -1
- package/dist/orderedClientElection.js +2 -2
- package/dist/orderedClientElection.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/pendingStateManager.js +17 -17
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runWhileConnectedCoordinator.js +1 -1
- package/dist/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +7 -6
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +4 -3
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts +1 -1
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +1 -1
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +4 -2
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.js +2 -2
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryFormat.d.ts +37 -11
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +12 -4
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +6 -4
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.js +5 -5
- package/dist/summaryManager.js.map +1 -1
- package/dist/throttler.js +2 -2
- package/dist/throttler.js.map +1 -1
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +27 -17
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +68 -93
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +2 -2
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +2 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStores.d.ts +4 -2
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +22 -10
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +23 -23
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +68 -37
- package/lib/garbageCollection.js.map +1 -1
- package/lib/opTelemetry.js.map +1 -1
- package/lib/orderedClientElection.d.ts.map +1 -1
- package/lib/orderedClientElection.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/pendingStateManager.js.map +1 -1
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +4 -3
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +1 -0
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts +1 -1
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +1 -1
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +4 -2
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryFormat.d.ts +37 -11
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +10 -2
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +2 -0
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.js.map +1 -1
- package/lib/throttler.js.map +1 -1
- package/package.json +26 -20
- package/src/blobManager.ts +3 -3
- package/src/containerRuntime.ts +108 -137
- package/src/dataStoreContext.ts +8 -11
- package/src/dataStoreContexts.ts +5 -5
- package/src/dataStores.ts +30 -13
- package/src/garbageCollection.ts +100 -57
- package/src/orderedClientElection.ts +5 -10
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +2 -2
- package/src/runningSummarizer.ts +8 -9
- package/src/summarizer.ts +2 -2
- package/src/summarizerHeuristics.ts +1 -1
- package/src/summarizerTypes.ts +8 -6
- package/src/summaryFormat.ts +38 -11
- package/src/summaryGenerator.ts +7 -5
- package/src/summaryManager.ts +2 -2
- package/src/throttler.ts +1 -1
|
@@ -29,7 +29,9 @@ const runSweepKey = "Fluid.GarbageCollection.RunSweep";
|
|
|
29
29
|
// Feature gate key to write GC data at the root of the summary tree.
|
|
30
30
|
const writeAtRootKey = "Fluid.GarbageCollection.WriteDataAtRoot";
|
|
31
31
|
// Feature gate key to expire a session after a set period of time.
|
|
32
|
-
const
|
|
32
|
+
const runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
|
|
33
|
+
// Feature gate key to disable expiring session after a set period of time, even if expiry value is present
|
|
34
|
+
const disableSessionExpiryKey = "Fluid.GarbageCollection.DisableSessionExpiry";
|
|
33
35
|
// Feature gate key to log error messages if GC reference validation fails.
|
|
34
36
|
const logUnknownOutboundReferencesKey = "Fluid.GarbageCollection.LogUnknownOutboundReferences";
|
|
35
37
|
const defaultDeleteTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
@@ -38,9 +40,11 @@ exports.defaultSessionExpiryDurationMs = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
|
38
40
|
exports.GCNodeType = {
|
|
39
41
|
// Nodes that are for data stores.
|
|
40
42
|
DataStore: "DataStore",
|
|
43
|
+
// Nodes that are within a data store. For example, DDS nodes.
|
|
44
|
+
SubDataStore: "SubDataStore",
|
|
41
45
|
// Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.
|
|
42
46
|
Blob: "Blob",
|
|
43
|
-
// Nodes that are neither
|
|
47
|
+
// Nodes that are neither of the above. For example, root node.
|
|
44
48
|
Other: "Other",
|
|
45
49
|
};
|
|
46
50
|
/**
|
|
@@ -94,15 +98,15 @@ class UnreferencedStateTracker {
|
|
|
94
98
|
* its state across summaries.
|
|
95
99
|
*
|
|
96
100
|
* Node - represented as nodeId, it's a node on the GC graph
|
|
97
|
-
* Outbound Route - a path from one node to another node, think `nodeA`
|
|
101
|
+
* Outbound Route - a path from one node to another node, think `nodeA` -\> `nodeB`
|
|
98
102
|
* Graph - all nodes with their respective routes
|
|
99
103
|
* GC Graph
|
|
100
104
|
*
|
|
101
105
|
* Node
|
|
102
106
|
* NodeId = "datastore1"
|
|
103
|
-
* /
|
|
107
|
+
* / \\
|
|
104
108
|
* OutboundRoute OutboundRoute
|
|
105
|
-
* /
|
|
109
|
+
* / \\
|
|
106
110
|
* Node Node
|
|
107
111
|
* NodeId = "dds1" NodeId = "dds2"
|
|
108
112
|
*/
|
|
@@ -112,7 +116,7 @@ class GarbageCollector {
|
|
|
112
116
|
getNodePackagePath,
|
|
113
117
|
/** Returns the timestamp of the last summary generated for this container. */
|
|
114
118
|
getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
|
|
115
|
-
var _a, _b, _c, _d, _e;
|
|
119
|
+
var _a, _b, _c, _d, _e, _f;
|
|
116
120
|
this.runtime = runtime;
|
|
117
121
|
this.gcOptions = gcOptions;
|
|
118
122
|
this.getNodePackagePath = getNodePackagePath;
|
|
@@ -144,29 +148,46 @@ class GarbageCollector {
|
|
|
144
148
|
this.loggedUnreferencedEvents = new Set();
|
|
145
149
|
// Queue for unreferenced events that should be logged the next time GC runs.
|
|
146
150
|
this.pendingEventsQueue = [];
|
|
147
|
-
this.mc = telemetry_utils_1.loggerToMonitoringContext(telemetry_utils_1.ChildLogger.create(baseLogger, "GarbageCollector"));
|
|
151
|
+
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(baseLogger, "GarbageCollector"));
|
|
148
152
|
this.deleteTimeoutMs = (_a = this.gcOptions.deleteTimeoutMs) !== null && _a !== void 0 ? _a : defaultDeleteTimeoutMs;
|
|
149
153
|
let prevSummaryGCVersion;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
154
|
+
/**
|
|
155
|
+
* The following GC state is enabled during container creation and cannot be changed throughout its lifetime:
|
|
156
|
+
* 1. Whether running GC mark phase is allowed or not.
|
|
157
|
+
* 2. Whether running GC sweep phase is allowed or not.
|
|
158
|
+
* 3. Whether GC session expiry is enabled or not.
|
|
159
|
+
* For existing containers, we get this information from the metadata blob of its summary.
|
|
160
|
+
*/
|
|
153
161
|
if (existing) {
|
|
154
|
-
prevSummaryGCVersion = summaryFormat_1.getGCVersion(metadata);
|
|
162
|
+
prevSummaryGCVersion = (0, summaryFormat_1.getGCVersion)(metadata);
|
|
155
163
|
// Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
|
|
156
164
|
// other existing documents, GC is enabled.
|
|
157
165
|
this.gcEnabled = prevSummaryGCVersion > 0;
|
|
166
|
+
this.sweepEnabled = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.sweepEnabled) !== null && _b !== void 0 ? _b : false;
|
|
158
167
|
this.sessionExpiryTimeoutMs = metadata === null || metadata === void 0 ? void 0 : metadata.sessionExpiryTimeoutMs;
|
|
159
168
|
}
|
|
160
169
|
else {
|
|
161
|
-
//
|
|
170
|
+
// Sweep should not be enabled without enabling GC mark phase. We could silently disable sweep in this
|
|
171
|
+
// scenario but explicitly failing makes it clearer and promotes correct usage.
|
|
172
|
+
if (gcOptions.sweepAllowed && !gcOptions.gcAllowed) {
|
|
173
|
+
throw new container_utils_1.UsageError("GC sweep phase cannot be enabled without enabling GC mark phase");
|
|
174
|
+
}
|
|
175
|
+
// For new documents, GC has to be explicitly enabled via the flags in GC options.
|
|
162
176
|
this.gcEnabled = gcOptions.gcAllowed === true;
|
|
177
|
+
this.sweepEnabled = gcOptions.sweepAllowed === true;
|
|
163
178
|
// Set the Session Expiry only if the flag is enabled or the test option is set.
|
|
164
|
-
if (this.mc.config.getBoolean(
|
|
179
|
+
if (this.mc.config.getBoolean(runSessionExpiryKey) && this.gcEnabled) {
|
|
165
180
|
this.sessionExpiryTimeoutMs = exports.defaultSessionExpiryDurationMs;
|
|
166
181
|
}
|
|
167
182
|
}
|
|
168
183
|
// If session expiry is enabled, we need to close the container when the timeout expires
|
|
169
|
-
if (this.sessionExpiryTimeoutMs !== undefined
|
|
184
|
+
if (this.sessionExpiryTimeoutMs !== undefined
|
|
185
|
+
&& this.mc.config.getBoolean(disableSessionExpiryKey) !== true) {
|
|
186
|
+
// If Test Override config is set, override Session Expiry timeout
|
|
187
|
+
const overrideSessionExpiryTimeoutMs = this.mc.config.getNumber("Fluid.GarbageCollection.TestOverride.SessionExpiryMs");
|
|
188
|
+
if (overrideSessionExpiryTimeoutMs !== undefined) {
|
|
189
|
+
this.sessionExpiryTimeoutMs = overrideSessionExpiryTimeoutMs;
|
|
190
|
+
}
|
|
170
191
|
const timeoutMs = this.sessionExpiryTimeoutMs;
|
|
171
192
|
setLongTimeout(timeoutMs, () => {
|
|
172
193
|
this.runtime.closeFn(new container_utils_1.ClientSessionExpiredError(`Client session expired.`, timeoutMs));
|
|
@@ -177,19 +198,26 @@ class GarbageCollector {
|
|
|
177
198
|
// For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
|
|
178
199
|
// latest tracked GC version. For new documents, we will be writing the first summary with the current version.
|
|
179
200
|
this.latestSummaryGCVersion = prevSummaryGCVersion !== null && prevSummaryGCVersion !== void 0 ? prevSummaryGCVersion : this.currentGCVersion;
|
|
180
|
-
|
|
181
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Whether GC should run or not. The following conditions have to be met to run sweep:
|
|
203
|
+
* 1. GC should be enabled for this container.
|
|
204
|
+
* 2. GC should not be disabled via disableGC GC option.
|
|
205
|
+
* These conditions can be overridden via runGCKey feature flag.
|
|
206
|
+
*/
|
|
207
|
+
this.shouldRunGC = (_c = this.mc.config.getBoolean(runGCKey)) !== null && _c !== void 0 ? _c : (
|
|
182
208
|
// GC must be enabled for the document.
|
|
183
209
|
this.gcEnabled
|
|
184
210
|
// GC must not be disabled via GC options.
|
|
185
211
|
&& !gcOptions.disableGC);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
212
|
+
/**
|
|
213
|
+
* Whether sweep should run or not. The following conditions have to be met to run sweep:
|
|
214
|
+
* 1. Overall GC or mark phase must be enabled (this.shouldRunGC).
|
|
215
|
+
* 2. Session expiry and sweep should be enabled for this container. Without session expiry we cannot safely
|
|
216
|
+
* delete unreferenced objects. This condition (#2) can be overridden via runSweepKey feature flag.
|
|
217
|
+
*/
|
|
218
|
+
this.shouldRunSweep = this.shouldRunGC && ((_d = this.mc.config.getBoolean(runSweepKey)) !== null && _d !== void 0 ? _d : (this.sessionExpiryTimeoutMs !== undefined && this.sweepEnabled));
|
|
191
219
|
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
192
|
-
this.testMode = (
|
|
220
|
+
this.testMode = (_e = this.mc.config.getBoolean(gcTestModeKey)) !== null && _e !== void 0 ? _e : gcOptions.runGCInTestMode === true;
|
|
193
221
|
/**
|
|
194
222
|
* Enable resetting initial state once the following issue is resolved:
|
|
195
223
|
* https://github.com/microsoft/FluidFramework/issues/8878.
|
|
@@ -201,7 +229,7 @@ class GarbageCollector {
|
|
|
201
229
|
// this.initialStateNeedsReset = gcTreePresent ? !this.shouldRunGC : this.shouldRunGC;
|
|
202
230
|
// If `writeDataAtRoot` setting is true, write the GC data into the root of the summary tree. We do this so that
|
|
203
231
|
// the roll out can be staged. Once its rolled out everywhere, we will start writing at root by default.
|
|
204
|
-
this._writeDataAtRoot = (
|
|
232
|
+
this._writeDataAtRoot = (_f = this.mc.config.getBoolean(writeAtRootKey)) !== null && _f !== void 0 ? _f : this.gcOptions.writeDataAtRoot === true;
|
|
205
233
|
// Get the GC state from the GC blob in the base snapshot. Use LazyPromise because we only want to do
|
|
206
234
|
// this once since it involves fetching blobs from storage which is expensive.
|
|
207
235
|
const baseSummaryStateP = new common_utils_1.LazyPromise(async () => {
|
|
@@ -220,8 +248,8 @@ class GarbageCollector {
|
|
|
220
248
|
// consolidate into IGarbageCollectionState format.
|
|
221
249
|
// Add a node for the root node that is not present in older snapshot format.
|
|
222
250
|
const gcState = { gcNodes: { "/": { outboundRoutes: [] } } };
|
|
223
|
-
const dataStoreSnapshotTree = dataStores_1.getSummaryForDatastores(baseSnapshot, metadata);
|
|
224
|
-
common_utils_1.assert(dataStoreSnapshotTree !== undefined, 0x2a8 /* "Expected data store snapshot tree in base snapshot" */);
|
|
251
|
+
const dataStoreSnapshotTree = (0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata);
|
|
252
|
+
(0, common_utils_1.assert)(dataStoreSnapshotTree !== undefined, 0x2a8 /* "Expected data store snapshot tree in base snapshot" */);
|
|
225
253
|
for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnapshotTree.trees)) {
|
|
226
254
|
const blobId = dsSnapshotTree.blobs[runtime_definitions_1.gcBlobKey];
|
|
227
255
|
if (blobId === undefined) {
|
|
@@ -245,7 +273,7 @@ class GarbageCollector {
|
|
|
245
273
|
const rootId = id === "/" ? dsRootId : `${dsRootId}${id}`;
|
|
246
274
|
gcState.gcNodes[rootId] = { outboundRoutes: Array.from(outboundRoutes) };
|
|
247
275
|
}
|
|
248
|
-
common_utils_1.assert(gcState.gcNodes[dsRootId] !== undefined, 0x2a9 /* `GC nodes for data store ${dsId} not in GC blob` */);
|
|
276
|
+
(0, common_utils_1.assert)(gcState.gcNodes[dsRootId] !== undefined, 0x2a9 /* `GC nodes for data store ${dsId} not in GC blob` */);
|
|
249
277
|
gcState.gcNodes[dsRootId].unreferencedTimestampMs = gcSummaryDetails.unrefTimestamp;
|
|
250
278
|
}
|
|
251
279
|
// If there is only one node (root node just added above), either GC is disabled or we are loading from the
|
|
@@ -286,8 +314,8 @@ class GarbageCollector {
|
|
|
286
314
|
// Run GC on the nodes in the base summary to get the routes used in each node in the container.
|
|
287
315
|
// This is an optimization for space (vs performance) wherein we don't need to store the used routes of
|
|
288
316
|
// each node in the summary.
|
|
289
|
-
const usedRoutes = garbage_collector_1.runGarbageCollection(gcNodes, ["/"], this.mc.logger).referencedNodeIds;
|
|
290
|
-
const baseGCDetailsMap = garbage_collector_1.unpackChildNodesGCDetails({ gcData: { gcNodes }, usedRoutes });
|
|
317
|
+
const usedRoutes = (0, garbage_collector_1.runGarbageCollection)(gcNodes, ["/"], this.mc.logger).referencedNodeIds;
|
|
318
|
+
const baseGCDetailsMap = (0, garbage_collector_1.unpackChildNodesGCDetails)({ gcData: { gcNodes }, usedRoutes });
|
|
291
319
|
// Currently, the nodes may write the GC data. So, we need to update it's base GC details with the
|
|
292
320
|
// unreferenced timestamp. Once we start writing the GC data here, we won't need to do this anymore.
|
|
293
321
|
for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
|
|
@@ -319,14 +347,6 @@ class GarbageCollector {
|
|
|
319
347
|
static create(provider, gcOptions, getNodePackagePath, getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
|
|
320
348
|
return new GarbageCollector(provider, gcOptions, getNodePackagePath, getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata);
|
|
321
349
|
}
|
|
322
|
-
/**
|
|
323
|
-
* This tracks two things:
|
|
324
|
-
* 1. Whether GC is enabled - If this is 0, GC is disabled. If this is greater than 0, GC is enabled.
|
|
325
|
-
* 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.
|
|
326
|
-
*/
|
|
327
|
-
get gcSummaryFeatureVersion() {
|
|
328
|
-
return this.gcEnabled ? this.currentGCVersion : 0;
|
|
329
|
-
}
|
|
330
350
|
/**
|
|
331
351
|
* Tells whether the GC state needs to be reset in the next summary. We need to do this if:
|
|
332
352
|
* 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
|
|
@@ -354,11 +374,11 @@ class GarbageCollector {
|
|
|
354
374
|
await this.runtime.updateStateBeforeGC();
|
|
355
375
|
// Get the runtime's GC data and run GC on the reference graph in it.
|
|
356
376
|
const gcData = await this.runtime.getGCData(fullGC);
|
|
357
|
-
const gcResult = garbage_collector_1.runGarbageCollection(gcData.gcNodes, ["/"], logger);
|
|
358
|
-
const gcStats = this.generateStatsAndLogEvents(gcResult);
|
|
377
|
+
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcData.gcNodes, ["/"], logger);
|
|
378
|
+
const gcStats = this.generateStatsAndLogEvents(gcResult, logger);
|
|
359
379
|
// Update the state since the last GC run. There can be nodes that were referenced between the last and
|
|
360
380
|
// the current run. We need to identify than and update their unreferenced state if needed.
|
|
361
|
-
this.updateStateSinceLastRun(gcData);
|
|
381
|
+
this.updateStateSinceLastRun(gcData, logger);
|
|
362
382
|
// Update the current state of the system based on the GC run.
|
|
363
383
|
const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
|
|
364
384
|
this.updateCurrentState(gcData, gcResult, currentReferenceTimestampMs);
|
|
@@ -396,6 +416,17 @@ class GarbageCollector {
|
|
|
396
416
|
builder.addBlob(`${exports.gcBlobPrefix}_root`, JSON.stringify(gcState));
|
|
397
417
|
return builder.getSummaryTree();
|
|
398
418
|
}
|
|
419
|
+
getMetadata() {
|
|
420
|
+
return {
|
|
421
|
+
/**
|
|
422
|
+
* If GC is enabled, the GC data is written using the current GC version and that is the gcFeature that goes
|
|
423
|
+
* into the metadata blob. If GC is disabled, the gcFeature is 0.
|
|
424
|
+
*/
|
|
425
|
+
gcFeature: this.gcEnabled ? this.currentGCVersion : 0,
|
|
426
|
+
sessionExpiryTimeoutMs: this.sessionExpiryTimeoutMs,
|
|
427
|
+
sweepEnabled: this.sweepEnabled,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
399
430
|
/**
|
|
400
431
|
* Returns a map of node ids to their base GC details generated from the base summary. This is used by the caller
|
|
401
432
|
* to initialize the GC state of the nodes.
|
|
@@ -469,7 +500,7 @@ class GarbageCollector {
|
|
|
469
500
|
const metadataBlobId = snapshot.blobs[summaryFormat_1.metadataBlobName];
|
|
470
501
|
if (metadataBlobId) {
|
|
471
502
|
const metadata = await readAndParseBlob(metadataBlobId);
|
|
472
|
-
this.latestSummaryGCVersion = summaryFormat_1.getGCVersion(metadata);
|
|
503
|
+
this.latestSummaryGCVersion = (0, summaryFormat_1.getGCVersion)(metadata);
|
|
473
504
|
}
|
|
474
505
|
}
|
|
475
506
|
/**
|
|
@@ -482,7 +513,7 @@ class GarbageCollector {
|
|
|
482
513
|
* @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.
|
|
483
514
|
*/
|
|
484
515
|
updateCurrentState(gcData, gcResult, currentReferenceTimestampMs) {
|
|
485
|
-
this.previousGCDataFromLastRun = garbage_collector_1.cloneGCData(gcData);
|
|
516
|
+
this.previousGCDataFromLastRun = (0, garbage_collector_1.cloneGCData)(gcData);
|
|
486
517
|
this.newReferencesSinceLastRun.clear();
|
|
487
518
|
// Iterate through the referenced nodes and stop tracking if they were unreferenced before.
|
|
488
519
|
for (const nodeId of gcResult.referencedNodeIds) {
|
|
@@ -525,7 +556,7 @@ class GarbageCollector {
|
|
|
525
556
|
* This function identifies nodes that were referenced since last run and removes their unreferenced state, if any.
|
|
526
557
|
* If these nodes are currently unreferenced, they will be assigned new unreferenced state by the current run.
|
|
527
558
|
*/
|
|
528
|
-
updateStateSinceLastRun(currentGCData) {
|
|
559
|
+
updateStateSinceLastRun(currentGCData, logger) {
|
|
529
560
|
// If we haven't run GC before there is nothing to do.
|
|
530
561
|
if (this.previousGCDataFromLastRun === undefined) {
|
|
531
562
|
return;
|
|
@@ -542,7 +573,7 @@ class GarbageCollector {
|
|
|
542
573
|
gcNodeId: missingExplicitReference[0],
|
|
543
574
|
gcRoutes: JSON.stringify(missingExplicitReference[1]),
|
|
544
575
|
};
|
|
545
|
-
|
|
576
|
+
logger.sendPerformanceEvent(event);
|
|
546
577
|
});
|
|
547
578
|
}
|
|
548
579
|
// No references were added since the last run so we don't have to update reference states of any unreferenced
|
|
@@ -565,7 +596,7 @@ class GarbageCollector {
|
|
|
565
596
|
* which is tracked by https://github.com/microsoft/FluidFramework/issues/8470.
|
|
566
597
|
* - A new data store may have "root" DDSs already created and we don't detect them today.
|
|
567
598
|
*/
|
|
568
|
-
const gcDataSuperSet = garbage_collector_1.concatGarbageCollectionData(this.previousGCDataFromLastRun, currentGCData);
|
|
599
|
+
const gcDataSuperSet = (0, garbage_collector_1.concatGarbageCollectionData)(this.previousGCDataFromLastRun, currentGCData);
|
|
569
600
|
this.newReferencesSinceLastRun.forEach((outboundRoutes, sourceNodeId) => {
|
|
570
601
|
if (gcDataSuperSet.gcNodes[sourceNodeId] === undefined) {
|
|
571
602
|
gcDataSuperSet.gcNodes[sourceNodeId] = outboundRoutes;
|
|
@@ -579,7 +610,7 @@ class GarbageCollector {
|
|
|
579
610
|
* unreferenced, stop tracking them and remove from unreferenced list.
|
|
580
611
|
* Some of these nodes may be unreferenced now and if so, the current run will add unreferenced state for them.
|
|
581
612
|
*/
|
|
582
|
-
const gcResult = garbage_collector_1.runGarbageCollection(gcDataSuperSet.gcNodes, ["/"],
|
|
613
|
+
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcDataSuperSet.gcNodes, ["/"], logger);
|
|
583
614
|
for (const nodeId of gcResult.referencedNodeIds) {
|
|
584
615
|
const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
|
|
585
616
|
if (nodeStateTracker !== undefined) {
|
|
@@ -604,7 +635,7 @@ class GarbageCollector {
|
|
|
604
635
|
* @returns - a list of missing explicit references
|
|
605
636
|
*/
|
|
606
637
|
findMissingExplicitReferences(currentGCData, previousGCData, explicitReferences) {
|
|
607
|
-
common_utils_1.assert(previousGCData !== undefined, 0x2b7);
|
|
638
|
+
(0, common_utils_1.assert)(previousGCData !== undefined, 0x2b7);
|
|
608
639
|
const currentGraph = Object.entries(currentGCData.gcNodes);
|
|
609
640
|
const missingExplicitReferences = [];
|
|
610
641
|
currentGraph.forEach(([nodeId, currentOutboundRoutes]) => {
|
|
@@ -637,13 +668,13 @@ class GarbageCollector {
|
|
|
637
668
|
* @param gcResult - The result of a GC run.
|
|
638
669
|
* @returns the GC stats of the GC run.
|
|
639
670
|
*/
|
|
640
|
-
generateStatsAndLogEvents(gcResult) {
|
|
671
|
+
generateStatsAndLogEvents(gcResult, logger) {
|
|
641
672
|
// Log pending events for unreferenced nodes after GC has run. We should have the package data available for
|
|
642
673
|
// them now since the GC run should have loaded these nodes.
|
|
643
674
|
let event = this.pendingEventsQueue.shift();
|
|
644
675
|
while (event !== undefined) {
|
|
645
676
|
const pkg = this.getNodePackagePath(event.id);
|
|
646
|
-
|
|
677
|
+
logger.sendErrorEvent(Object.assign(Object.assign({}, event), { pkg: pkg ? { value: `/${pkg.join("/")}`, tag: telemetry_utils_1.TelemetryDataTag.PackageData } : undefined }));
|
|
647
678
|
event = this.pendingEventsQueue.shift();
|
|
648
679
|
}
|
|
649
680
|
const gcStats = {
|
|
@@ -750,9 +781,9 @@ async function getGCStateFromSnapshot(gcSnapshotTree, readAndParseBlob) {
|
|
|
750
781
|
continue;
|
|
751
782
|
}
|
|
752
783
|
const gcState = await readAndParseBlob(blobId);
|
|
753
|
-
common_utils_1.assert(gcState !== undefined, 0x2ad /* "GC blob missing from snapshot" */);
|
|
784
|
+
(0, common_utils_1.assert)(gcState !== undefined, 0x2ad /* "GC blob missing from snapshot" */);
|
|
754
785
|
// Merge the GC state of this blob into the root GC state.
|
|
755
|
-
rootGCState = garbage_collector_1.concatGarbageCollectionStates(rootGCState, gcState);
|
|
786
|
+
rootGCState = (0, garbage_collector_1.concatGarbageCollectionStates)(rootGCState, gcState);
|
|
756
787
|
}
|
|
757
788
|
return rootGCState;
|
|
758
789
|
}
|