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