@fluidframework/container-runtime 1.2.0-77818 → 1.2.0-78837
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/garbageCollection.d.ts +25 -10
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +182 -88
- package/dist/garbageCollection.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/summaryFormat.d.ts +6 -3
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +6 -3
- package/dist/summaryFormat.js.map +1 -1
- package/lib/garbageCollection.d.ts +25 -10
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +181 -87
- package/lib/garbageCollection.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/summaryFormat.d.ts +6 -3
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +6 -3
- package/lib/summaryFormat.js.map +1 -1
- package/package.json +14 -14
- package/src/garbageCollection.ts +228 -120
- package/src/packageVersion.ts +1 -1
- package/src/summaryFormat.ts +6 -3
|
@@ -15,6 +15,7 @@ export declare const gcBlobPrefix = "__gc";
|
|
|
15
15
|
export declare const runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
|
|
16
16
|
export declare const disableSessionExpiryKey = "Fluid.GarbageCollection.DisableSessionExpiry";
|
|
17
17
|
export declare const trackGCStateKey = "Fluid.GarbageCollection.TrackGCState";
|
|
18
|
+
export declare const oneDayMs: number;
|
|
18
19
|
export declare const defaultSessionExpiryDurationMs: number;
|
|
19
20
|
/** The statistics of the system state after a garbage collection run. */
|
|
20
21
|
export interface IGCStats {
|
|
@@ -74,7 +75,6 @@ export interface IGarbageCollector {
|
|
|
74
75
|
/** Run garbage collection and update the reference / used state of the system. */
|
|
75
76
|
collectGarbage(options: {
|
|
76
77
|
logger?: ITelemetryLogger;
|
|
77
|
-
runGC?: boolean;
|
|
78
78
|
runSweep?: boolean;
|
|
79
79
|
fullGC?: boolean;
|
|
80
80
|
}): Promise<IGCStats>;
|
|
@@ -104,7 +104,18 @@ export interface IGarbageCollectorCreateParams {
|
|
|
104
104
|
readonly getNodePackagePath: (nodePath: string) => Promise<readonly string[] | undefined>;
|
|
105
105
|
readonly getLastSummaryTimestampMs: () => number | undefined;
|
|
106
106
|
readonly readAndParseBlob: ReadAndParseBlob;
|
|
107
|
+
readonly snapshotCacheExpiryMs?: number;
|
|
107
108
|
}
|
|
109
|
+
/** The state of node that is unreferenced. */
|
|
110
|
+
declare const UnreferencedState: {
|
|
111
|
+
/** The node is active, i.e., it can become referenced again. */
|
|
112
|
+
Active: string;
|
|
113
|
+
/** The node is inactive, i.e., it should not become referenced. */
|
|
114
|
+
Inactive: string;
|
|
115
|
+
/** The node is ready to be deleted by the sweep phase. */
|
|
116
|
+
SweepReady: string;
|
|
117
|
+
};
|
|
118
|
+
export declare type UnreferencedState = typeof UnreferencedState[keyof typeof UnreferencedState];
|
|
108
119
|
/**
|
|
109
120
|
* The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains
|
|
110
121
|
* its state across summaries.
|
|
@@ -124,10 +135,6 @@ export interface IGarbageCollectorCreateParams {
|
|
|
124
135
|
*/
|
|
125
136
|
export declare class GarbageCollector implements IGarbageCollector {
|
|
126
137
|
static create(createParams: IGarbageCollectorCreateParams): IGarbageCollector;
|
|
127
|
-
/**
|
|
128
|
-
* The time in ms to expire a session for a client for gc.
|
|
129
|
-
*/
|
|
130
|
-
private readonly sessionExpiryTimeoutMs;
|
|
131
138
|
/**
|
|
132
139
|
* Tells whether the GC state needs to be reset in the next summary. We need to do this if:
|
|
133
140
|
* 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
|
|
@@ -190,7 +197,6 @@ export declare class GarbageCollector implements IGarbageCollector {
|
|
|
190
197
|
private readonly newReferencesSinceLastRun;
|
|
191
198
|
private readonly initializeBaseStateP;
|
|
192
199
|
private readonly baseGCDetailsP;
|
|
193
|
-
private readonly inactiveTimeoutMs;
|
|
194
200
|
private readonly unreferencedNodesState;
|
|
195
201
|
private sessionExpiryTimer?;
|
|
196
202
|
private readonly loggedUnreferencedEvents;
|
|
@@ -199,6 +205,12 @@ export declare class GarbageCollector implements IGarbageCollector {
|
|
|
199
205
|
private readonly runtime;
|
|
200
206
|
private readonly gcOptions;
|
|
201
207
|
private readonly isSummarizerClient;
|
|
208
|
+
/** The time in ms to expire a session for a client for gc. */
|
|
209
|
+
private readonly sessionExpiryTimeoutMs;
|
|
210
|
+
/** The time after which an unreferenced node is inactive. */
|
|
211
|
+
private readonly inactiveTimeoutMs;
|
|
212
|
+
/** The time after which an unreferenced node is ready to be swept. */
|
|
213
|
+
private readonly sweepTimeoutMs;
|
|
202
214
|
/** For a given node path, returns the node's package path. */
|
|
203
215
|
private readonly getNodePackagePath;
|
|
204
216
|
/** Returns the timestamp of the last summary generated for this container. */
|
|
@@ -293,12 +305,15 @@ export declare class GarbageCollector implements IGarbageCollector {
|
|
|
293
305
|
*/
|
|
294
306
|
private generateStats;
|
|
295
307
|
/**
|
|
296
|
-
*
|
|
308
|
+
* For nodes that are ready to sweep, log an event for now. Until we start running sweep which deletes objects,
|
|
309
|
+
* this will give us a view into how much deleted content a container has.
|
|
297
310
|
*/
|
|
298
|
-
private
|
|
311
|
+
private logSweepEvents;
|
|
299
312
|
/**
|
|
300
|
-
*
|
|
313
|
+
* Called when an inactive node is used after. Queue up an event that will be logged next time GC runs.
|
|
301
314
|
*/
|
|
302
|
-
private
|
|
315
|
+
private inactiveNodeUsed;
|
|
316
|
+
private logUnreferencedEvents;
|
|
303
317
|
}
|
|
318
|
+
export {};
|
|
304
319
|
//# sourceMappingURL=garbageCollection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAA8B,MAAM,oCAAoC,CAAC;AAElG,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAEhF,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AASjE,OAAO,EAAE,aAAa,EAAe,MAAM,sCAAsC,CAAC;AAClF,OAAO,EAEH,sBAAsB,EAEtB,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EAEpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEH,gBAAgB,EAChB,oBAAoB,EAEvB,MAAM,+BAA+B,CAAC;AASvC,OAAO,EAAE,iBAAiB,EAAkB,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EAGH,yBAAyB,EAIzB,WAAW,EACd,MAAM,iBAAiB,CAAC;AAMzB,eAAO,MAAM,SAAS,OAAO,CAAC;AAE9B,eAAO,MAAM,YAAY,SAAS,CAAC;AAWnC,eAAO,MAAM,mBAAmB,6CAA6C,CAAC;AAE9E,eAAO,MAAM,uBAAuB,iDAAiD,CAAC;AAEtF,eAAO,MAAM,eAAe,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,19 @@
|
|
|
3
3
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
7
|
+
var t = {};
|
|
8
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
9
|
+
t[p] = s[p];
|
|
10
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
11
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
12
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
13
|
+
t[p[i]] = s[p[i]];
|
|
14
|
+
}
|
|
15
|
+
return t;
|
|
16
|
+
};
|
|
6
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.GarbageCollector = exports.GCNodeType = exports.defaultSessionExpiryDurationMs = exports.trackGCStateKey = exports.disableSessionExpiryKey = exports.runSessionExpiryKey = exports.gcBlobPrefix = exports.gcTreeKey = void 0;
|
|
18
|
+
exports.GarbageCollector = exports.GCNodeType = exports.defaultSessionExpiryDurationMs = exports.oneDayMs = exports.trackGCStateKey = exports.disableSessionExpiryKey = exports.runSessionExpiryKey = exports.gcBlobPrefix = exports.gcTreeKey = void 0;
|
|
8
19
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
9
20
|
const container_utils_1 = require("@fluidframework/container-utils");
|
|
10
21
|
const garbage_collector_1 = require("@fluidframework/garbage-collector");
|
|
@@ -23,10 +34,10 @@ exports.gcTreeKey = "gc";
|
|
|
23
34
|
exports.gcBlobPrefix = "__gc";
|
|
24
35
|
// Feature gate key to turn GC on / off.
|
|
25
36
|
const runGCKey = "Fluid.GarbageCollection.RunGC";
|
|
26
|
-
// Feature gate key to turn GC test mode on / off.
|
|
27
|
-
const gcTestModeKey = "Fluid.GarbageCollection.GCTestMode";
|
|
28
37
|
// Feature gate key to turn GC sweep on / off.
|
|
29
38
|
const runSweepKey = "Fluid.GarbageCollection.RunSweep";
|
|
39
|
+
// Feature gate key to turn GC test mode on / off.
|
|
40
|
+
const gcTestModeKey = "Fluid.GarbageCollection.GCTestMode";
|
|
30
41
|
// Feature gate key to write GC data at the root of the summary tree.
|
|
31
42
|
const writeAtRootKey = "Fluid.GarbageCollection.WriteDataAtRoot";
|
|
32
43
|
// Feature gate key to expire a session after a set period of time.
|
|
@@ -35,8 +46,12 @@ exports.runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
|
|
|
35
46
|
exports.disableSessionExpiryKey = "Fluid.GarbageCollection.DisableSessionExpiry";
|
|
36
47
|
// Feature gate key to write the gc blob as a handle if the data is the same.
|
|
37
48
|
exports.trackGCStateKey = "Fluid.GarbageCollection.TrackGCState";
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
// Feature gate key to turn GC sweep log off.
|
|
50
|
+
const disableSweepLogKey = "Fluid.GarbageCollection.DisableSweepLog";
|
|
51
|
+
// One day in milliseconds.
|
|
52
|
+
exports.oneDayMs = 1 * 24 * 60 * 60 * 1000;
|
|
53
|
+
const defaultInactiveTimeoutMs = 7 * exports.oneDayMs; // 7 days
|
|
54
|
+
exports.defaultSessionExpiryDurationMs = 30 * exports.oneDayMs; // 30 days
|
|
40
55
|
/** The types of GC nodes in the GC reference graph. */
|
|
41
56
|
exports.GCNodeType = {
|
|
42
57
|
// Nodes that are for data stores.
|
|
@@ -48,50 +63,84 @@ exports.GCNodeType = {
|
|
|
48
63
|
// Nodes that are neither of the above. For example, root node.
|
|
49
64
|
Other: "Other",
|
|
50
65
|
};
|
|
66
|
+
/** The state of node that is unreferenced. */
|
|
67
|
+
const UnreferencedState = {
|
|
68
|
+
/** The node is active, i.e., it can become referenced again. */
|
|
69
|
+
Active: "Active",
|
|
70
|
+
/** The node is inactive, i.e., it should not become referenced. */
|
|
71
|
+
Inactive: "Inactive",
|
|
72
|
+
/** The node is ready to be deleted by the sweep phase. */
|
|
73
|
+
SweepReady: "SweepReady",
|
|
74
|
+
};
|
|
51
75
|
/**
|
|
52
|
-
* Helper class that tracks the state of an unreferenced node such as the time it was unreferenced
|
|
53
|
-
*
|
|
76
|
+
* Helper class that tracks the state of an unreferenced node such as the time it was unreferenced and if it can
|
|
77
|
+
* be deleted by the sweep phase.
|
|
54
78
|
*/
|
|
55
79
|
class UnreferencedStateTracker {
|
|
56
|
-
constructor(unreferencedTimestampMs,
|
|
80
|
+
constructor(unreferencedTimestampMs,
|
|
81
|
+
/** The time after which node transitions to Inactive state. */
|
|
82
|
+
inactiveTimeoutMs,
|
|
83
|
+
/** The time after which node transitions to SweepReady state; undefined if session expiry is disabled. */
|
|
84
|
+
sweepTimeoutMs,
|
|
85
|
+
/** The current reference timestamp; undefined if no ops have ever been processed which can happen in tests. */
|
|
86
|
+
currentReferenceTimestampMs) {
|
|
57
87
|
this.unreferencedTimestampMs = unreferencedTimestampMs;
|
|
58
88
|
this.inactiveTimeoutMs = inactiveTimeoutMs;
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
//
|
|
89
|
+
this.sweepTimeoutMs = sweepTimeoutMs;
|
|
90
|
+
this._state = UnreferencedState.Active;
|
|
91
|
+
// If there is no current reference timestamp, don't track the node's unreferenced state. This will happen
|
|
92
|
+
// later when updateTracking is called with a reference timestamp.
|
|
62
93
|
if (currentReferenceTimestampMs !== undefined) {
|
|
63
94
|
this.updateTracking(currentReferenceTimestampMs);
|
|
64
95
|
}
|
|
65
96
|
}
|
|
66
|
-
get
|
|
67
|
-
return this.
|
|
97
|
+
get state() {
|
|
98
|
+
return this._state;
|
|
68
99
|
}
|
|
69
|
-
|
|
70
|
-
* Updates the tracking state based on the provided timestamp.
|
|
71
|
-
*/
|
|
100
|
+
/* Updates the unreferenced state based on the provided timestamp. */
|
|
72
101
|
updateTracking(currentReferenceTimestampMs) {
|
|
73
|
-
var _a;
|
|
74
102
|
const unreferencedDurationMs = currentReferenceTimestampMs - this.unreferencedTimestampMs;
|
|
75
|
-
// If the
|
|
76
|
-
if (unreferencedDurationMs
|
|
77
|
-
this.
|
|
78
|
-
|
|
103
|
+
// If the node has been unreferenced for sweep timeout amount of time, update the state to SweepReady.
|
|
104
|
+
if (this.sweepTimeoutMs !== undefined && unreferencedDurationMs >= this.sweepTimeoutMs) {
|
|
105
|
+
this._state = UnreferencedState.SweepReady;
|
|
106
|
+
this.clearTimers();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// If the node has been unreferenced for inactive timeoutMs amount of time, update the state to inactive.
|
|
110
|
+
// Also, start a timer for the sweep timeout.
|
|
111
|
+
if (unreferencedDurationMs >= this.inactiveTimeoutMs) {
|
|
112
|
+
this._state = UnreferencedState.Inactive;
|
|
113
|
+
this.clearTimers();
|
|
114
|
+
if (this.sweepTimeoutMs !== undefined) {
|
|
115
|
+
setLongTimeout(this.sweepTimeoutMs - unreferencedDurationMs, () => { this._state = UnreferencedState.SweepReady; }, (timer) => { this.sweepTimer = timer; });
|
|
116
|
+
}
|
|
79
117
|
return;
|
|
80
118
|
}
|
|
81
|
-
// The node
|
|
119
|
+
// The node is still active. Start the inactive timer for the remaining duration.
|
|
82
120
|
const remainingDurationMs = this.inactiveTimeoutMs - unreferencedDurationMs;
|
|
83
|
-
if (this.
|
|
84
|
-
|
|
121
|
+
if (this.inactiveTimer === undefined) {
|
|
122
|
+
const inactiveTimeoutHandler = () => {
|
|
123
|
+
this._state = UnreferencedState.Inactive;
|
|
124
|
+
// After the node becomes inactive, start the sweep timer after which the node will be ready for sweep.
|
|
125
|
+
if (this.sweepTimeoutMs !== undefined) {
|
|
126
|
+
setLongTimeout(this.sweepTimeoutMs - this.inactiveTimeoutMs, () => { this._state = UnreferencedState.SweepReady; }, (timer) => { this.sweepTimer = timer; });
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
this.inactiveTimer = new common_utils_1.Timer(remainingDurationMs, () => inactiveTimeoutHandler());
|
|
85
130
|
}
|
|
86
|
-
this.
|
|
131
|
+
this.inactiveTimer.restart(remainingDurationMs);
|
|
87
132
|
}
|
|
88
|
-
|
|
89
|
-
* Stop tracking this node. Reset the unreferenced timer, if any, and reset inactive state.
|
|
90
|
-
*/
|
|
91
|
-
stopTracking() {
|
|
133
|
+
clearTimers() {
|
|
92
134
|
var _a;
|
|
93
|
-
(_a = this.
|
|
94
|
-
this.
|
|
135
|
+
(_a = this.inactiveTimer) === null || _a === void 0 ? void 0 : _a.clear();
|
|
136
|
+
if (this.sweepTimer !== undefined) {
|
|
137
|
+
clearTimeout(this.sweepTimer);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** Stop tracking this node. Reset the unreferenced timers and state, if any. */
|
|
141
|
+
stopTracking() {
|
|
142
|
+
this.clearTimers();
|
|
143
|
+
this._state = UnreferencedState.Active;
|
|
95
144
|
}
|
|
96
145
|
}
|
|
97
146
|
/**
|
|
@@ -184,20 +233,21 @@ class GarbageCollector {
|
|
|
184
233
|
this.sessionExpiryTimeoutMs = exports.defaultSessionExpiryDurationMs;
|
|
185
234
|
}
|
|
186
235
|
}
|
|
187
|
-
// If session expiry is enabled, we need to close the container when the timeout expires
|
|
188
|
-
if (this.sessionExpiryTimeoutMs !== undefined
|
|
189
|
-
|
|
190
|
-
// If Test Override config is set, override Session Expiry timeout
|
|
236
|
+
// If session expiry is enabled, we need to close the container when the session expiry timeout expires.
|
|
237
|
+
if (this.sessionExpiryTimeoutMs !== undefined && this.mc.config.getBoolean(exports.disableSessionExpiryKey) !== true) {
|
|
238
|
+
// If Test Override config is set, override Session Expiry timeout.
|
|
191
239
|
const overrideSessionExpiryTimeoutMs = this.mc.config.getNumber("Fluid.GarbageCollection.TestOverride.SessionExpiryMs");
|
|
192
|
-
|
|
193
|
-
|
|
240
|
+
const timeoutMs = overrideSessionExpiryTimeoutMs !== null && overrideSessionExpiryTimeoutMs !== void 0 ? overrideSessionExpiryTimeoutMs : this.sessionExpiryTimeoutMs;
|
|
241
|
+
setLongTimeout(timeoutMs, () => { this.runtime.closeFn(new container_utils_1.ClientSessionExpiredError(`Client session expired.`, timeoutMs)); }, (timer) => { this.sessionExpiryTimer = timer; });
|
|
242
|
+
/**
|
|
243
|
+
* Sweep timeout is the time after which unreferenced content can be swept.
|
|
244
|
+
* Sweep timeout = session expiry timeout + snapshot cache expiry timeout + one day buffer. The buffer is
|
|
245
|
+
* added to account for any clock skew. We use server timestamps throughout so the skew should be minimal
|
|
246
|
+
* but make it one day to be safe.
|
|
247
|
+
*/
|
|
248
|
+
if (createParams.snapshotCacheExpiryMs !== undefined) {
|
|
249
|
+
this.sweepTimeoutMs = this.sessionExpiryTimeoutMs + createParams.snapshotCacheExpiryMs + exports.oneDayMs;
|
|
194
250
|
}
|
|
195
|
-
const timeoutMs = this.sessionExpiryTimeoutMs;
|
|
196
|
-
setLongTimeout(timeoutMs, () => {
|
|
197
|
-
this.runtime.closeFn(new container_utils_1.ClientSessionExpiredError(`Client session expired.`, timeoutMs));
|
|
198
|
-
}, (timer) => {
|
|
199
|
-
this.sessionExpiryTimer = timer;
|
|
200
|
-
});
|
|
201
251
|
}
|
|
202
252
|
// For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
|
|
203
253
|
// latest tracked GC version. For new documents, we will be writing the first summary with the current version.
|
|
@@ -213,17 +263,23 @@ class GarbageCollector {
|
|
|
213
263
|
this.gcEnabled
|
|
214
264
|
// GC must not be disabled via GC options.
|
|
215
265
|
&& !this.gcOptions.disableGC);
|
|
216
|
-
this.trackGCState = this.mc.config.getBoolean(exports.trackGCStateKey) === true;
|
|
217
266
|
/**
|
|
218
267
|
* Whether sweep should run or not. The following conditions have to be met to run sweep:
|
|
219
268
|
* 1. Overall GC or mark phase must be enabled (this.shouldRunGC).
|
|
220
|
-
* 2.
|
|
221
|
-
*
|
|
269
|
+
* 2. Sweep timeout should be available. Without this, we wouldn't know when an object should be deleted.
|
|
270
|
+
* 3. Sweep should be enabled for this container (this.sweepEnabled). This can be overridden via runSweep
|
|
271
|
+
* feature flag.
|
|
222
272
|
*/
|
|
223
|
-
this.shouldRunSweep = this.shouldRunGC
|
|
273
|
+
this.shouldRunSweep = this.shouldRunGC
|
|
274
|
+
&& this.sweepTimeoutMs !== undefined
|
|
275
|
+
&& ((_c = this.mc.config.getBoolean(runSweepKey)) !== null && _c !== void 0 ? _c : this.sweepEnabled);
|
|
276
|
+
this.trackGCState = this.mc.config.getBoolean(exports.trackGCStateKey) === true;
|
|
224
277
|
// Override inactive timeout if test config or gc options to override it is set.
|
|
225
|
-
this.inactiveTimeoutMs =
|
|
226
|
-
|
|
278
|
+
this.inactiveTimeoutMs = (_e = (_d = this.mc.config.getNumber("Fluid.GarbageCollection.TestOverride.InactiveTimeoutMs")) !== null && _d !== void 0 ? _d : this.gcOptions.inactiveTimeoutMs) !== null && _e !== void 0 ? _e : defaultInactiveTimeoutMs;
|
|
279
|
+
// Inactive timeout must be greater than sweep timeout since a node goes from active -> inactive -> sweep ready.
|
|
280
|
+
if (this.sweepTimeoutMs !== undefined && this.inactiveTimeoutMs > this.sweepTimeoutMs) {
|
|
281
|
+
throw new container_utils_1.UsageError("inactive timeout should not be greated than the sweep timeout");
|
|
282
|
+
}
|
|
227
283
|
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
228
284
|
this.testMode = (_f = this.mc.config.getBoolean(gcTestModeKey)) !== null && _f !== void 0 ? _f : this.gcOptions.runGCInTestMode === true;
|
|
229
285
|
// GC state is written into root of the summary tree by default. Can be overridden via feature flag for now.
|
|
@@ -302,7 +358,7 @@ class GarbageCollector {
|
|
|
302
358
|
const gcNodes = {};
|
|
303
359
|
for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
|
|
304
360
|
if (nodeData.unreferencedTimestampMs !== undefined) {
|
|
305
|
-
this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(nodeData.unreferencedTimestampMs, this.inactiveTimeoutMs, currentReferenceTimestampMs));
|
|
361
|
+
this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(nodeData.unreferencedTimestampMs, this.inactiveTimeoutMs, this.sweepTimeoutMs, currentReferenceTimestampMs));
|
|
306
362
|
}
|
|
307
363
|
gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);
|
|
308
364
|
}
|
|
@@ -338,7 +394,7 @@ class GarbageCollector {
|
|
|
338
394
|
});
|
|
339
395
|
// Log all the GC options and the state determined by the garbage collector. This is interesting only for the
|
|
340
396
|
// summarizer client since it is the only one that runs GC. It also helps keep the telemetry less noisy.
|
|
341
|
-
const gcConfigProps = JSON.stringify(Object.assign({ gcEnabled: this.gcEnabled, sweepEnabled: this.sweepEnabled, runGC: this.shouldRunGC, runSweep: this.shouldRunSweep, writeAtRoot: this._writeDataAtRoot, testMode: this.testMode, sessionExpiry: this.sessionExpiryTimeoutMs, inactiveTimeout: this.inactiveTimeoutMs, existing: createParams.existing }, this.gcOptions));
|
|
397
|
+
const gcConfigProps = JSON.stringify(Object.assign({ gcEnabled: this.gcEnabled, sweepEnabled: this.sweepEnabled, runGC: this.shouldRunGC, runSweep: this.shouldRunSweep, writeAtRoot: this._writeDataAtRoot, testMode: this.testMode, sessionExpiry: this.sessionExpiryTimeoutMs, inactiveTimeout: this.inactiveTimeoutMs, existing: createParams.existing, trackGCState: this.trackGCState }, this.gcOptions));
|
|
342
398
|
if (this.isSummarizerClient) {
|
|
343
399
|
this.mc.logger.sendTelemetryEvent({
|
|
344
400
|
eventName: "GarbageCollectorLoaded",
|
|
@@ -409,6 +465,9 @@ class GarbageCollector {
|
|
|
409
465
|
const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
|
|
410
466
|
this.updateCurrentState(gcData, gcResult, currentReferenceTimestampMs);
|
|
411
467
|
this.runtime.updateUsedRoutes(gcResult.referencedNodeIds, currentReferenceTimestampMs);
|
|
468
|
+
// Log events for objects that are ready to be deleted by sweep. When we have sweep enabled, we will
|
|
469
|
+
// delete these objects here instead.
|
|
470
|
+
this.logSweepEvents(logger, currentReferenceTimestampMs);
|
|
412
471
|
// If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios
|
|
413
472
|
// involving access to deleted data.
|
|
414
473
|
if (this.testMode) {
|
|
@@ -417,7 +476,7 @@ class GarbageCollector {
|
|
|
417
476
|
// Log pending unreferenced events such as a node being used after inactive. This is done after GC runs and
|
|
418
477
|
// updates its state so that we don't send false positives based on intermediate state. For example, we may get
|
|
419
478
|
// reference to an unreferenced node from another unreferenced node which means the node wasn't revived.
|
|
420
|
-
await this.
|
|
479
|
+
await this.logUnreferencedEvents(logger);
|
|
421
480
|
return gcStats;
|
|
422
481
|
}
|
|
423
482
|
/**
|
|
@@ -531,9 +590,9 @@ class GarbageCollector {
|
|
|
531
590
|
if (!this.shouldRunGC) {
|
|
532
591
|
return;
|
|
533
592
|
}
|
|
534
|
-
const
|
|
535
|
-
if (
|
|
536
|
-
this.inactiveNodeUsed(reason, nodePath,
|
|
593
|
+
const nodeStateTracker = this.unreferencedNodesState.get(nodePath);
|
|
594
|
+
if (nodeStateTracker && nodeStateTracker.state !== UnreferencedState.Active) {
|
|
595
|
+
this.inactiveNodeUsed(reason, nodePath, nodeStateTracker, undefined /* fromNodeId */, packagePath, timestampMs, requestHeaders);
|
|
537
596
|
}
|
|
538
597
|
}
|
|
539
598
|
/**
|
|
@@ -551,9 +610,9 @@ class GarbageCollector {
|
|
|
551
610
|
const outboundRoutes = (_a = this.newReferencesSinceLastRun.get(fromNodePath)) !== null && _a !== void 0 ? _a : [];
|
|
552
611
|
outboundRoutes.push(toNodePath);
|
|
553
612
|
this.newReferencesSinceLastRun.set(fromNodePath, outboundRoutes);
|
|
554
|
-
const
|
|
555
|
-
if (
|
|
556
|
-
this.inactiveNodeUsed("Revived", toNodePath,
|
|
613
|
+
const nodeStateTracker = this.unreferencedNodesState.get(toNodePath);
|
|
614
|
+
if (nodeStateTracker && nodeStateTracker.state !== UnreferencedState.Active) {
|
|
615
|
+
this.inactiveNodeUsed("Revived", toNodePath, nodeStateTracker, fromNodePath);
|
|
557
616
|
}
|
|
558
617
|
}
|
|
559
618
|
dispose() {
|
|
@@ -600,7 +659,7 @@ class GarbageCollector {
|
|
|
600
659
|
for (const nodeId of gcResult.deletedNodeIds) {
|
|
601
660
|
const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
|
|
602
661
|
if (nodeStateTracker === undefined) {
|
|
603
|
-
this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(currentReferenceTimestampMs, this.inactiveTimeoutMs, currentReferenceTimestampMs));
|
|
662
|
+
this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(currentReferenceTimestampMs, this.inactiveTimeoutMs, this.sweepTimeoutMs, currentReferenceTimestampMs));
|
|
604
663
|
}
|
|
605
664
|
else {
|
|
606
665
|
nodeStateTracker.updateTracking(currentReferenceTimestampMs);
|
|
@@ -774,12 +833,48 @@ class GarbageCollector {
|
|
|
774
833
|
return gcStats;
|
|
775
834
|
}
|
|
776
835
|
/**
|
|
777
|
-
*
|
|
836
|
+
* For nodes that are ready to sweep, log an event for now. Until we start running sweep which deletes objects,
|
|
837
|
+
* this will give us a view into how much deleted content a container has.
|
|
838
|
+
*/
|
|
839
|
+
logSweepEvents(logger, currentReferenceTimestampMs) {
|
|
840
|
+
if (this.mc.config.getBoolean(disableSweepLogKey) === true
|
|
841
|
+
|| currentReferenceTimestampMs === undefined
|
|
842
|
+
|| this.sweepTimeoutMs === undefined) {
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
this.unreferencedNodesState.forEach((nodeStateTracker, nodeId) => {
|
|
846
|
+
if (nodeStateTracker.state !== UnreferencedState.SweepReady) {
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
const nodeType = this.runtime.getNodeType(nodeId);
|
|
850
|
+
if (nodeType !== exports.GCNodeType.DataStore && nodeType !== exports.GCNodeType.Blob) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
// Log deleted event for each node only once to reduce noise in telemetry.
|
|
854
|
+
const uniqueEventId = `Deleted-${nodeId}`;
|
|
855
|
+
if (this.loggedUnreferencedEvents.has(uniqueEventId)) {
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
this.loggedUnreferencedEvents.add(uniqueEventId);
|
|
859
|
+
logger.sendTelemetryEvent({
|
|
860
|
+
eventName: "GCObjectDeleted",
|
|
861
|
+
id: nodeId,
|
|
862
|
+
type: nodeType,
|
|
863
|
+
age: currentReferenceTimestampMs - nodeStateTracker.unreferencedTimestampMs,
|
|
864
|
+
timeout: this.sweepTimeoutMs,
|
|
865
|
+
completedGCRuns: this.completedRuns,
|
|
866
|
+
lastSummaryTime: this.getLastSummaryTimestampMs(),
|
|
867
|
+
});
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Called when an inactive node is used after. Queue up an event that will be logged next time GC runs.
|
|
778
872
|
*/
|
|
779
|
-
inactiveNodeUsed(usageType, nodeId,
|
|
873
|
+
inactiveNodeUsed(usageType, nodeId, nodeStateTracker, fromNodeId, packagePath, currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs(), requestHeaders) {
|
|
780
874
|
// If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip
|
|
781
875
|
// logging as nothing interesting would have happened worth logging.
|
|
782
|
-
|
|
876
|
+
// If the node is active, skip logging.
|
|
877
|
+
if (currentReferenceTimestampMs === undefined || nodeStateTracker.state === UnreferencedState.Active) {
|
|
783
878
|
return;
|
|
784
879
|
}
|
|
785
880
|
// For non-summarizer clients, only log "Loaded" type events since these objects may not be loaded in the
|
|
@@ -793,18 +888,20 @@ class GarbageCollector {
|
|
|
793
888
|
if (nodeType !== exports.GCNodeType.DataStore && nodeType !== exports.GCNodeType.Blob) {
|
|
794
889
|
return;
|
|
795
890
|
}
|
|
796
|
-
|
|
797
|
-
const uniqueEventId = `${nodeId}-${usageType}`;
|
|
891
|
+
const state = nodeStateTracker.state;
|
|
892
|
+
const uniqueEventId = `${state}-${nodeId}-${usageType}`;
|
|
798
893
|
if (this.loggedUnreferencedEvents.has(uniqueEventId)) {
|
|
799
894
|
return;
|
|
800
895
|
}
|
|
801
896
|
this.loggedUnreferencedEvents.add(uniqueEventId);
|
|
802
|
-
const
|
|
803
|
-
usageType,
|
|
897
|
+
const propsToLog = {
|
|
804
898
|
id: nodeId,
|
|
805
899
|
type: nodeType,
|
|
806
|
-
|
|
807
|
-
|
|
900
|
+
unrefTime: nodeStateTracker.unreferencedTimestampMs,
|
|
901
|
+
age: currentReferenceTimestampMs - nodeStateTracker.unreferencedTimestampMs,
|
|
902
|
+
timeout: nodeStateTracker.state === UnreferencedState.Inactive
|
|
903
|
+
? this.inactiveTimeoutMs
|
|
904
|
+
: this.sweepTimeoutMs,
|
|
808
905
|
completedGCRuns: this.completedRuns,
|
|
809
906
|
lastSummaryTime: this.getLastSummaryTimestampMs(),
|
|
810
907
|
externalRequest: requestHeaders === null || requestHeaders === void 0 ? void 0 : requestHeaders[containerRuntime_1.RuntimeHeaders.externalRequest],
|
|
@@ -815,31 +912,28 @@ class GarbageCollector {
|
|
|
815
912
|
// For non-summarizer client, log the event now since GC won't run on it. This may result in false positives
|
|
816
913
|
// but it's a good signal nonetheless and we can consume it with a grain of salt.
|
|
817
914
|
if (this.isSummarizerClient) {
|
|
818
|
-
this.pendingEventsQueue.push(
|
|
915
|
+
this.pendingEventsQueue.push(Object.assign(Object.assign({}, propsToLog), { usageType, state }));
|
|
819
916
|
}
|
|
820
917
|
else {
|
|
821
|
-
this.mc.logger.sendErrorEvent(Object.assign(Object.assign({},
|
|
918
|
+
this.mc.logger.sendErrorEvent(Object.assign(Object.assign({}, propsToLog), { eventName: `${state}Object_${usageType}`, pkg: packagePath ? { value: packagePath.join("/"), tag: telemetry_utils_1.TelemetryDataTag.CodeArtifact } : undefined }));
|
|
822
919
|
}
|
|
823
920
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
921
|
+
async logUnreferencedEvents(logger) {
|
|
922
|
+
for (const eventProps of this.pendingEventsQueue) {
|
|
923
|
+
const { usageType, state } = eventProps, propsToLog = __rest(eventProps, ["usageType", "state"]);
|
|
924
|
+
/**
|
|
925
|
+
* Revived event is logged only if the node is active. If the node is not active, the reference to it was
|
|
926
|
+
* from another unreferenced node and this scenario is not interesting to log.
|
|
927
|
+
* Loaded and Changed events are logged only if the node is not active. If the node is active, it was
|
|
928
|
+
* revived and a Revived event will be logged for it.
|
|
929
|
+
*/
|
|
930
|
+
const nodeStateTracker = this.unreferencedNodesState.get(eventProps.id);
|
|
931
|
+
const active = nodeStateTracker === undefined || nodeStateTracker.state === UnreferencedState.Active;
|
|
932
|
+
if ((usageType === "Revived") === active) {
|
|
933
|
+
const pkg = await this.getNodePackagePath(eventProps.id);
|
|
934
|
+
const fromPkg = eventProps.fromId ? await this.getNodePackagePath(eventProps.fromId) : undefined;
|
|
935
|
+
logger.sendErrorEvent(Object.assign(Object.assign({}, propsToLog), { eventName: `${state}Object_${usageType}`, pkg: pkg ? { value: pkg.join("/"), tag: telemetry_utils_1.TelemetryDataTag.CodeArtifact } : undefined, fromPkg: fromPkg ? { value: fromPkg.join("/"), tag: telemetry_utils_1.TelemetryDataTag.CodeArtifact } : undefined }));
|
|
839
936
|
}
|
|
840
|
-
const pkg = await this.getNodePackagePath(event.id);
|
|
841
|
-
const fromPkg = event.fromId ? await this.getNodePackagePath(event.fromId) : undefined;
|
|
842
|
-
logger.sendErrorEvent(Object.assign(Object.assign({}, event), { eventName: `inactiveObject_${event.usageType}`, pkg: pkg ? { value: pkg.join("/"), tag: telemetry_utils_1.TelemetryDataTag.PackageData } : undefined, fromPkg: fromPkg ? { value: fromPkg.join("/"), tag: telemetry_utils_1.TelemetryDataTag.PackageData } : undefined }));
|
|
843
937
|
}
|
|
844
938
|
this.pendingEventsQueue = [];
|
|
845
939
|
}
|