@fluidframework/container-runtime 0.51.0-43124 → 0.51.3
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/containerRuntime.d.ts +31 -31
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +61 -144
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.js +1 -1
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +3 -5
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +3 -4
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +116 -0
- package/dist/garbageCollection.d.ts.map +1 -0
- package/dist/garbageCollection.js +148 -0
- package/dist/garbageCollection.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.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 +0 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +0 -36
- package/dist/pendingStateManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +31 -31
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +62 -145
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.js +1 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +3 -5
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +3 -4
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +116 -0
- package/lib/garbageCollection.d.ts.map +1 -0
- package/lib/garbageCollection.js +144 -0
- package/lib/garbageCollection.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.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 +0 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +0 -36
- package/lib/pendingStateManager.js.map +1 -1
- package/package.json +11 -11
- package/src/containerRuntime.ts +89 -188
- package/src/dataStoreContext.ts +1 -1
- package/src/dataStores.ts +5 -5
- package/src/garbageCollection.ts +269 -0
- package/src/index.ts +1 -0
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +0 -43
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
6
|
+
import { IGarbageCollectionData } from "@fluidframework/runtime-definitions";
|
|
7
|
+
import { ReadAndParseBlob, RefreshSummaryResult } from "@fluidframework/runtime-utils";
|
|
8
|
+
import { IGCRuntimeOptions } from "./containerRuntime";
|
|
9
|
+
import { IContainerRuntimeMetadata } from "./summaryFormat";
|
|
10
|
+
/** The used state statistics of a node. */
|
|
11
|
+
export interface IUsedStateStats {
|
|
12
|
+
totalNodeCount: number;
|
|
13
|
+
unusedNodeCount: number;
|
|
14
|
+
}
|
|
15
|
+
/** The statistics of the system state after a garbage collection run. */
|
|
16
|
+
export interface IGCStats {
|
|
17
|
+
totalNodes: number;
|
|
18
|
+
deletedNodes: number;
|
|
19
|
+
totalDataStores: number;
|
|
20
|
+
deletedDataStores: number;
|
|
21
|
+
}
|
|
22
|
+
/** Defines the APIs for the runtime object to be passed to the garbage collector. */
|
|
23
|
+
export interface IGarbageCollectionRuntime {
|
|
24
|
+
/** Returns the garbage collection data of the runtime. */
|
|
25
|
+
getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;
|
|
26
|
+
/** After GC has run, called to notify the runtime of routes that are used in it. */
|
|
27
|
+
updateUsedRoutes(usedRoutes: string[]): IUsedStateStats;
|
|
28
|
+
}
|
|
29
|
+
/** Defines the contract for the garbage collector. */
|
|
30
|
+
export interface IGarbageCollector {
|
|
31
|
+
/** Tells whether GC should run or not. */
|
|
32
|
+
readonly shouldRunGC: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* This tracks two things:
|
|
35
|
+
* 1. Whether GC is enabled - If this is 0, GC is disabled. If this is > 0, GC is enabled.
|
|
36
|
+
* 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.
|
|
37
|
+
*/
|
|
38
|
+
readonly gcSummaryFeatureVersion: number;
|
|
39
|
+
/** Tells whether the GC version has changed compared to the version in the latest summary. */
|
|
40
|
+
readonly hasGCVersionChanged: boolean;
|
|
41
|
+
/** Run garbage collection and update the reference / used state of the system. */
|
|
42
|
+
collectGarbage(options: {
|
|
43
|
+
logger?: ITelemetryLogger;
|
|
44
|
+
runGC?: boolean;
|
|
45
|
+
runSweep?: boolean;
|
|
46
|
+
fullGC?: boolean;
|
|
47
|
+
}): Promise<IGCStats>;
|
|
48
|
+
/** Called when the latest summary of the system has been refreshed. */
|
|
49
|
+
latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains
|
|
53
|
+
* its state across summaries.
|
|
54
|
+
*/
|
|
55
|
+
export declare class GarbageCollector implements IGarbageCollector {
|
|
56
|
+
private readonly provider;
|
|
57
|
+
private readonly gcOptions;
|
|
58
|
+
/**
|
|
59
|
+
* After GC has run, called to delete objects in the runtime whose routes are unused. This is not part of the
|
|
60
|
+
* provider because its specific to this garbage collector implementation and is not part of the contract.
|
|
61
|
+
*/
|
|
62
|
+
private readonly deleteUnusedRoutes;
|
|
63
|
+
static create(provider: IGarbageCollectionRuntime, gcOptions: IGCRuntimeOptions, deleteUnusedRoutes: (unusedRoutes: string[]) => void, baseLogger: ITelemetryLogger, existing: boolean, metadata?: IContainerRuntimeMetadata): IGarbageCollector;
|
|
64
|
+
/**
|
|
65
|
+
* Tells whether GC should be run based on the GC options and local storage flags.
|
|
66
|
+
*/
|
|
67
|
+
readonly shouldRunGC: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* This tracks two things:
|
|
70
|
+
* 1. Whether GC is enabled - If this is 0, GC is disabled. If this is > 0, GC is enabled.
|
|
71
|
+
* 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.
|
|
72
|
+
*/
|
|
73
|
+
get gcSummaryFeatureVersion(): number;
|
|
74
|
+
/**
|
|
75
|
+
* Tells whether the GC version has changed compared to the version in the latest summary.
|
|
76
|
+
*/
|
|
77
|
+
get hasGCVersionChanged(): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Tracks if GC is enabled for this document. This is specified during document creation and doesn't change
|
|
80
|
+
* throughout its lifetime.
|
|
81
|
+
*/
|
|
82
|
+
private readonly gcEnabled;
|
|
83
|
+
private readonly shouldRunSweep;
|
|
84
|
+
private readonly testMode;
|
|
85
|
+
private readonly logger;
|
|
86
|
+
private readonly currentGCVersion;
|
|
87
|
+
private latestSummaryGCVersion;
|
|
88
|
+
protected constructor(provider: IGarbageCollectionRuntime, gcOptions: IGCRuntimeOptions,
|
|
89
|
+
/**
|
|
90
|
+
* After GC has run, called to delete objects in the runtime whose routes are unused. This is not part of the
|
|
91
|
+
* provider because its specific to this garbage collector implementation and is not part of the contract.
|
|
92
|
+
*/
|
|
93
|
+
deleteUnusedRoutes: (unusedRoutes: string[]) => void, baseLogger: ITelemetryLogger, existing: boolean, metadata?: IContainerRuntimeMetadata);
|
|
94
|
+
/**
|
|
95
|
+
* Runs garbage collection and udpates the reference / used state of the nodes in the container.
|
|
96
|
+
* @returns the number of data stores that have been marked as unreferenced.
|
|
97
|
+
*/
|
|
98
|
+
collectGarbage(options: {
|
|
99
|
+
/** Logger to use for logging GC events */
|
|
100
|
+
logger?: ITelemetryLogger;
|
|
101
|
+
/** True to run GC sweep phase after the mark phase */
|
|
102
|
+
runSweep?: boolean;
|
|
103
|
+
/** True to generate full GC data */
|
|
104
|
+
fullGC?: boolean;
|
|
105
|
+
}): Promise<IGCStats>;
|
|
106
|
+
/**
|
|
107
|
+
* Called when the latest summary of the system has been refreshed. This will be used to update the state of the
|
|
108
|
+
* latest summary tracked.
|
|
109
|
+
*/
|
|
110
|
+
latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Update the latest summary GC version from the metadata blob in the given snapshot.
|
|
113
|
+
*/
|
|
114
|
+
private updateSummaryGCVersionFromSnapshot;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=garbageCollection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.GarbageCollector = void 0;
|
|
8
|
+
const garbage_collector_1 = require("@fluidframework/garbage-collector");
|
|
9
|
+
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
10
|
+
const localStorageFeatureGates_1 = require("./localStorageFeatureGates");
|
|
11
|
+
const summaryFormat_1 = require("./summaryFormat");
|
|
12
|
+
/** This is the current version of garbage collection. */
|
|
13
|
+
const GCVersion = 1;
|
|
14
|
+
// Local storage key to turn GC on / off.
|
|
15
|
+
const runGCKey = "FluidRunGC";
|
|
16
|
+
// Local storage key to turn GC test mode on / off.
|
|
17
|
+
const gcTestModeKey = "FluidGCTestMode";
|
|
18
|
+
// Local storage key to turn GC sweep on / off.
|
|
19
|
+
const runSweepKey = "FluidRunSweep";
|
|
20
|
+
/**
|
|
21
|
+
* The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains
|
|
22
|
+
* its state across summaries.
|
|
23
|
+
*/
|
|
24
|
+
class GarbageCollector {
|
|
25
|
+
constructor(provider, gcOptions,
|
|
26
|
+
/**
|
|
27
|
+
* After GC has run, called to delete objects in the runtime whose routes are unused. This is not part of the
|
|
28
|
+
* provider because its specific to this garbage collector implementation and is not part of the contract.
|
|
29
|
+
*/
|
|
30
|
+
deleteUnusedRoutes, baseLogger, existing, metadata) {
|
|
31
|
+
var _a, _b, _c;
|
|
32
|
+
this.provider = provider;
|
|
33
|
+
this.gcOptions = gcOptions;
|
|
34
|
+
this.deleteUnusedRoutes = deleteUnusedRoutes;
|
|
35
|
+
// The current GC version that this container is running.
|
|
36
|
+
this.currentGCVersion = GCVersion;
|
|
37
|
+
this.logger = telemetry_utils_1.ChildLogger.create(baseLogger, "GarbageCollector");
|
|
38
|
+
let prevSummaryGCVersion;
|
|
39
|
+
// GC can only be enabled during creation. After that, it can never be enabled again. So, for existing
|
|
40
|
+
// documents, we get this information from the metadata blob.
|
|
41
|
+
if (existing) {
|
|
42
|
+
prevSummaryGCVersion = summaryFormat_1.getGCVersion(metadata);
|
|
43
|
+
// Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
|
|
44
|
+
// other exsiting documents, GC is enabled.
|
|
45
|
+
this.gcEnabled = prevSummaryGCVersion > 0;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// For new documents, GC has to be exlicitly enabled via the gcAllowed flag in GC options.
|
|
49
|
+
this.gcEnabled = gcOptions.gcAllowed === true;
|
|
50
|
+
}
|
|
51
|
+
// For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
|
|
52
|
+
// latest tracked GC version. For new documents, we will be writing the first summary with the current version.
|
|
53
|
+
this.latestSummaryGCVersion = prevSummaryGCVersion !== null && prevSummaryGCVersion !== void 0 ? prevSummaryGCVersion : this.currentGCVersion;
|
|
54
|
+
// Whether GC should run or not. Can override with localStorage flag.
|
|
55
|
+
this.shouldRunGC = (_a = localStorageFeatureGates_1.getLocalStorageFeatureGate(runGCKey)) !== null && _a !== void 0 ? _a : (
|
|
56
|
+
// GC must be enabled for the document.
|
|
57
|
+
this.gcEnabled
|
|
58
|
+
// GC must not be disabled via GC options.
|
|
59
|
+
&& !gcOptions.disableGC);
|
|
60
|
+
// Whether GC sweep phase should run or not. If this is false, only GC mark phase is run. Can override with
|
|
61
|
+
// localStorage flag.
|
|
62
|
+
this.shouldRunSweep = this.shouldRunGC &&
|
|
63
|
+
((_b = localStorageFeatureGates_1.getLocalStorageFeatureGate(runSweepKey)) !== null && _b !== void 0 ? _b : gcOptions.runSweep === true);
|
|
64
|
+
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
65
|
+
this.testMode = (_c = localStorageFeatureGates_1.getLocalStorageFeatureGate(gcTestModeKey)) !== null && _c !== void 0 ? _c : gcOptions.runGCInTestMode === true;
|
|
66
|
+
}
|
|
67
|
+
static create(provider, gcOptions, deleteUnusedRoutes, baseLogger, existing, metadata) {
|
|
68
|
+
return new GarbageCollector(provider, gcOptions, deleteUnusedRoutes, baseLogger, existing, metadata);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* This tracks two things:
|
|
72
|
+
* 1. Whether GC is enabled - If this is 0, GC is disabled. If this is > 0, GC is enabled.
|
|
73
|
+
* 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.
|
|
74
|
+
*/
|
|
75
|
+
get gcSummaryFeatureVersion() {
|
|
76
|
+
return this.gcEnabled ? this.currentGCVersion : 0;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Tells whether the GC version has changed compared to the version in the latest summary.
|
|
80
|
+
*/
|
|
81
|
+
get hasGCVersionChanged() {
|
|
82
|
+
// The current version can differ from the latest summary version in two cases:
|
|
83
|
+
// 1. The summary this client loaded with has data from a different GC version.
|
|
84
|
+
// 2. This client's latest summary was updated from a snapshot that has a different GC version.
|
|
85
|
+
return this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Runs garbage collection and udpates the reference / used state of the nodes in the container.
|
|
89
|
+
* @returns the number of data stores that have been marked as unreferenced.
|
|
90
|
+
*/
|
|
91
|
+
async collectGarbage(options) {
|
|
92
|
+
const { logger = this.logger, runSweep = this.shouldRunSweep, fullGC = this.gcOptions.runFullGC === true || this.hasGCVersionChanged, } = options;
|
|
93
|
+
return telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, { eventName: "GarbageCollection" }, async (event) => {
|
|
94
|
+
const gcStats = {};
|
|
95
|
+
// Get the runtime's GC data and run GC on the reference graph in it.
|
|
96
|
+
const gcData = await this.provider.getGCData(fullGC);
|
|
97
|
+
const { referencedNodeIds, deletedNodeIds } = garbage_collector_1.runGarbageCollection(gcData.gcNodes, ["/"], logger);
|
|
98
|
+
// Remove this node's route ("/") and notify data stores of routes that are used in it.
|
|
99
|
+
const usedRoutes = referencedNodeIds.filter((id) => { return id !== "/"; });
|
|
100
|
+
const dataStoreUsedStateStats = this.provider.updateUsedRoutes(usedRoutes);
|
|
101
|
+
if (runSweep) {
|
|
102
|
+
// Placeholder for running sweep logic.
|
|
103
|
+
}
|
|
104
|
+
// Update stats to be reported in the peformance event.
|
|
105
|
+
gcStats.deletedNodes = deletedNodeIds.length;
|
|
106
|
+
gcStats.totalNodes = referencedNodeIds.length + deletedNodeIds.length;
|
|
107
|
+
gcStats.deletedDataStores = dataStoreUsedStateStats.unusedNodeCount;
|
|
108
|
+
gcStats.totalDataStores = dataStoreUsedStateStats.totalNodeCount;
|
|
109
|
+
// If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios
|
|
110
|
+
// involving access to deleted data.
|
|
111
|
+
if (this.testMode) {
|
|
112
|
+
this.deleteUnusedRoutes(deletedNodeIds);
|
|
113
|
+
}
|
|
114
|
+
event.end(gcStats);
|
|
115
|
+
return gcStats;
|
|
116
|
+
}, { end: true, cancel: "error" });
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Called when the latest summary of the system has been refreshed. This will be used to update the state of the
|
|
120
|
+
* latest summary tracked.
|
|
121
|
+
*/
|
|
122
|
+
async latestSummaryStateRefreshed(result, readAndParseBlob) {
|
|
123
|
+
if (!this.shouldRunGC || !result.latestSummaryUpdated) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// If the summary was tracked by this client, it was the one that generated the summary in the first place.
|
|
127
|
+
// Basically, it was written in the current GC version.
|
|
128
|
+
if (result.wasSummaryTracked) {
|
|
129
|
+
this.latestSummaryGCVersion = this.currentGCVersion;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// If the summary was not tracked by this client, update latest GC version from the snapshot in the result as
|
|
133
|
+
// that is now the latest summary.
|
|
134
|
+
await this.updateSummaryGCVersionFromSnapshot(result.snapshot, readAndParseBlob);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Update the latest summary GC version from the metadata blob in the given snapshot.
|
|
138
|
+
*/
|
|
139
|
+
async updateSummaryGCVersionFromSnapshot(snapshot, readAndParseBlob) {
|
|
140
|
+
const metadataBlobId = snapshot.blobs[summaryFormat_1.metadataBlobName];
|
|
141
|
+
if (metadataBlobId) {
|
|
142
|
+
const metadata = await readAndParseBlob(metadataBlobId);
|
|
143
|
+
this.latestSummaryGCVersion = summaryFormat_1.getGCVersion(metadata);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.GarbageCollector = GarbageCollector;
|
|
148
|
+
//# sourceMappingURL=garbageCollection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"garbageCollection.js","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { runGarbageCollection } from \"@fluidframework/garbage-collector\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { IGarbageCollectionData } from \"@fluidframework/runtime-definitions\";\nimport { ReadAndParseBlob, RefreshSummaryResult } from \"@fluidframework/runtime-utils\";\nimport { ChildLogger, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\n\nimport { IGCRuntimeOptions } from \"./containerRuntime\";\nimport { getLocalStorageFeatureGate } from \"./localStorageFeatureGates\";\nimport {\n getGCVersion,\n GCVersion,\n IContainerRuntimeMetadata,\n metadataBlobName,\n} from \"./summaryFormat\";\n\n/** This is the current version of garbage collection. */\nconst GCVersion = 1;\n\n// Local storage key to turn GC on / off.\nconst runGCKey = \"FluidRunGC\";\n// Local storage key to turn GC test mode on / off.\nconst gcTestModeKey = \"FluidGCTestMode\";\n// Local storage key to turn GC sweep on / off.\nconst runSweepKey = \"FluidRunSweep\";\n\n/** The used state statistics of a node. */\nexport interface IUsedStateStats {\n totalNodeCount: number;\n unusedNodeCount: number;\n}\n\n/** The statistics of the system state after a garbage collection run. */\nexport interface IGCStats {\n totalNodes: number;\n deletedNodes: number;\n totalDataStores: number;\n deletedDataStores: number;\n}\n\n/** Defines the APIs for the runtime object to be passed to the garbage collector. */\nexport interface IGarbageCollectionRuntime {\n /** Returns the garbage collection data of the runtime. */\n getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;\n /** After GC has run, called to notify the runtime of routes that are used in it. */\n updateUsedRoutes(usedRoutes: string[]): IUsedStateStats;\n}\n\n/** Defines the contract for the garbage collector. */\nexport interface IGarbageCollector {\n /** Tells whether GC should run or not. */\n readonly shouldRunGC: boolean;\n /**\n * This tracks two things:\n * 1. Whether GC is enabled - If this is 0, GC is disabled. If this is > 0, GC is enabled.\n * 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.\n */\n readonly gcSummaryFeatureVersion: number;\n /** Tells whether the GC version has changed compared to the version in the latest summary. */\n readonly hasGCVersionChanged: boolean;\n /** Run garbage collection and update the reference / used state of the system. */\n collectGarbage(\n options: { logger?: ITelemetryLogger, runGC?: boolean, runSweep?: boolean, fullGC?: boolean },\n ): Promise<IGCStats>;\n /** Called when the latest summary of the system has been refreshed. */\n latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;\n}\n\n/**\n * The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains\n * its state across summaries.\n */\nexport class GarbageCollector implements IGarbageCollector {\n public static create(\n provider: IGarbageCollectionRuntime,\n gcOptions: IGCRuntimeOptions,\n deleteUnusedRoutes: (unusedRoutes: string[]) => void,\n baseLogger: ITelemetryLogger,\n existing: boolean,\n metadata?: IContainerRuntimeMetadata,\n ): IGarbageCollector {\n return new GarbageCollector(provider, gcOptions, deleteUnusedRoutes, baseLogger, existing, metadata);\n }\n\n /**\n * Tells whether GC should be run based on the GC options and local storage flags.\n */\n public readonly shouldRunGC: boolean;\n\n /**\n * This tracks two things:\n * 1. Whether GC is enabled - If this is 0, GC is disabled. If this is > 0, GC is enabled.\n * 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.\n */\n public get gcSummaryFeatureVersion(): number {\n return this.gcEnabled ? this.currentGCVersion : 0;\n }\n\n /**\n * Tells whether the GC version has changed compared to the version in the latest summary.\n */\n public get hasGCVersionChanged(): boolean {\n // The current version can differ from the latest summary version in two cases:\n // 1. The summary this client loaded with has data from a different GC version.\n // 2. This client's latest summary was updated from a snapshot that has a different GC version.\n return this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion;\n }\n\n /**\n * Tracks if GC is enabled for this document. This is specified during document creation and doesn't change\n * throughout its lifetime.\n */\n private readonly gcEnabled: boolean;\n private readonly shouldRunSweep: boolean;\n private readonly testMode: boolean;\n private readonly logger: ITelemetryLogger;\n\n // The current GC version that this container is running.\n private readonly currentGCVersion = GCVersion;\n // This is the version of GC data in the latest summary being tracked.\n private latestSummaryGCVersion: GCVersion;\n\n protected constructor(\n private readonly provider: IGarbageCollectionRuntime,\n private readonly gcOptions: IGCRuntimeOptions,\n /**\n * After GC has run, called to delete objects in the runtime whose routes are unused. This is not part of the\n * provider because its specific to this garbage collector implementation and is not part of the contract.\n */\n private readonly deleteUnusedRoutes: (unusedRoutes: string[]) => void,\n baseLogger: ITelemetryLogger,\n existing: boolean,\n metadata?: IContainerRuntimeMetadata,\n ) {\n this.logger = ChildLogger.create(baseLogger, \"GarbageCollector\");\n\n let prevSummaryGCVersion: number | undefined;\n // GC can only be enabled during creation. After that, it can never be enabled again. So, for existing\n // documents, we get this information from the metadata blob.\n if (existing) {\n prevSummaryGCVersion = getGCVersion(metadata);\n // Existing documents which did not have metadata blob or had GC disabled have version as 0. For all\n // other exsiting documents, GC is enabled.\n this.gcEnabled = prevSummaryGCVersion > 0;\n } else {\n // For new documents, GC has to be exlicitly enabled via the gcAllowed flag in GC options.\n this.gcEnabled = gcOptions.gcAllowed === true;\n }\n // For existing document, the latest summary is the one that we loaded from. So, use its GC version as the\n // latest tracked GC version. For new documents, we will be writing the first summary with the current version.\n this.latestSummaryGCVersion = prevSummaryGCVersion ?? this.currentGCVersion;\n\n // Whether GC should run or not. Can override with localStorage flag.\n this.shouldRunGC = getLocalStorageFeatureGate(runGCKey) ?? (\n // GC must be enabled for the document.\n this.gcEnabled\n // GC must not be disabled via GC options.\n && !gcOptions.disableGC\n );\n\n // Whether GC sweep phase should run or not. If this is false, only GC mark phase is run. Can override with\n // localStorage flag.\n this.shouldRunSweep = this.shouldRunGC &&\n (getLocalStorageFeatureGate(runSweepKey) ?? gcOptions.runSweep === true);\n\n // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.\n this.testMode = getLocalStorageFeatureGate(gcTestModeKey) ?? gcOptions.runGCInTestMode === true;\n }\n\n /**\n * Runs garbage collection and udpates the reference / used state of the nodes in the container.\n * @returns the number of data stores that have been marked as unreferenced.\n */\n public async collectGarbage(\n options: {\n /** Logger to use for logging GC events */\n logger?: ITelemetryLogger,\n /** True to run GC sweep phase after the mark phase */\n runSweep?: boolean,\n /** True to generate full GC data */\n fullGC?: boolean,\n },\n ): Promise<IGCStats> {\n const {\n logger = this.logger,\n runSweep = this.shouldRunSweep,\n fullGC = this.gcOptions.runFullGC === true || this.hasGCVersionChanged,\n } = options;\n\n return PerformanceEvent.timedExecAsync(logger, { eventName: \"GarbageCollection\" }, async (event) => {\n const gcStats: {\n deletedNodes?: number,\n totalNodes?: number,\n deletedDataStores?: number,\n totalDataStores?: number,\n } = {};\n\n // Get the runtime's GC data and run GC on the reference graph in it.\n const gcData = await this.provider.getGCData(fullGC);\n const { referencedNodeIds, deletedNodeIds } = runGarbageCollection(\n gcData.gcNodes,\n [ \"/\" ],\n logger,\n );\n\n // Remove this node's route (\"/\") and notify data stores of routes that are used in it.\n const usedRoutes = referencedNodeIds.filter((id: string) => { return id !== \"/\"; });\n const dataStoreUsedStateStats = this.provider.updateUsedRoutes(usedRoutes);\n\n if (runSweep) {\n // Placeholder for running sweep logic.\n }\n\n // Update stats to be reported in the peformance event.\n gcStats.deletedNodes = deletedNodeIds.length;\n gcStats.totalNodes = referencedNodeIds.length + deletedNodeIds.length;\n gcStats.deletedDataStores = dataStoreUsedStateStats.unusedNodeCount;\n gcStats.totalDataStores = dataStoreUsedStateStats.totalNodeCount;\n\n // If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios\n // involving access to deleted data.\n if (this.testMode) {\n this.deleteUnusedRoutes(deletedNodeIds);\n }\n event.end(gcStats);\n return gcStats as IGCStats;\n },\n { end: true, cancel: \"error\" });\n }\n\n /**\n * Called when the latest summary of the system has been refreshed. This will be used to update the state of the\n * latest summary tracked.\n */\n public async latestSummaryStateRefreshed(\n result: RefreshSummaryResult,\n readAndParseBlob: ReadAndParseBlob,\n ): Promise<void> {\n if (!this.shouldRunGC || !result.latestSummaryUpdated) {\n return;\n }\n\n // If the summary was tracked by this client, it was the one that generated the summary in the first place.\n // Basically, it was written in the current GC version.\n if (result.wasSummaryTracked) {\n this.latestSummaryGCVersion = this.currentGCVersion;\n return;\n }\n // If the summary was not tracked by this client, update latest GC version from the snapshot in the result as\n // that is now the latest summary.\n await this.updateSummaryGCVersionFromSnapshot(result.snapshot, readAndParseBlob);\n }\n\n /**\n * Update the latest summary GC version from the metadata blob in the given snapshot.\n */\n private async updateSummaryGCVersionFromSnapshot(snapshot: ISnapshotTree, readAndParseBlob: ReadAndParseBlob) {\n const metadataBlobId = snapshot.blobs[metadataBlobName];\n if (metadataBlobId) {\n const metadata = await readAndParseBlob<IContainerRuntimeMetadata>(metadataBlobId);\n this.latestSummaryGCVersion = getGCVersion(metadata);\n }\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export * from "./containerRuntime";
|
|
6
6
|
export * from "./deltaScheduler";
|
|
7
7
|
export * from "./dataStoreRegistry";
|
|
8
|
+
export { IGarbageCollectionRuntime, IGCStats, IUsedStateStats } from "./garbageCollection";
|
|
8
9
|
export * from "./pendingStateManager";
|
|
9
10
|
export * from "./summarizer";
|
|
10
11
|
export * from "./summarizerTypes";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,yBAAyB,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3F,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;AAEH,qDAAmC;AACnC,mDAAiC;AACjC,sDAAoC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;AAEH,qDAAmC;AACnC,mDAAiC;AACjC,sDAAoC;AAEpC,wDAAsC;AACtC,+CAA6B;AAC7B,oDAAkC;AAClC,sDAAoC;AACpC,+EAA8G;AAAnE,0IAAA,0BAA0B,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./containerRuntime\";\nexport * from \"./deltaScheduler\";\nexport * from \"./dataStoreRegistry\";\nexport { IGarbageCollectionRuntime, IGCStats, IUsedStateStats } from \"./garbageCollection\";\nexport * from \"./pendingStateManager\";\nexport * from \"./summarizer\";\nexport * from \"./summarizerTypes\";\nexport * from \"./summaryCollection\";\nexport { ICancellableSummarizerController, neverCancelledSummaryToken } from \"./runWhileConnectedCoordinator\";\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/container-runtime";
|
|
8
|
-
export declare const pkgVersion = "0.51.
|
|
8
|
+
export declare const pkgVersion = "0.51.3";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,sCAAsC,CAAC;AAC3D,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,sCAAsC,CAAC;AAC3D,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/container-runtime";
|
|
11
|
-
exports.pkgVersion = "0.51.
|
|
11
|
+
exports.pkgVersion = "0.51.3";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"0.51.3\";\n"]}
|
|
@@ -61,7 +61,6 @@ export declare class PendingStateManager implements IDisposable {
|
|
|
61
61
|
private readonly initialStates;
|
|
62
62
|
private readonly previousClientIds;
|
|
63
63
|
private readonly firstStashedCSN;
|
|
64
|
-
private stashedCount;
|
|
65
64
|
private readonly disposeOnce;
|
|
66
65
|
private pendingMessagesCount;
|
|
67
66
|
private isProcessingBatch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAGjE,OAAO,EACH,yBAAyB,EAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAoB,MAAM,oBAAoB,CAAC;AAE9F;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,oBAAoB,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uBAAuB,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,GAAG,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CACnD;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,OAAO,CAAC;CACjB;AAED,oBAAY,aAAa,GAAG,eAAe,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAEhF,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,aAAa,EAAE,aAAa,EAAE,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAoB,YAAW,WAAW;
|
|
1
|
+
{"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,7 +30,6 @@ class PendingStateManager {
|
|
|
30
30
|
this.pendingStates = new double_ended_queue_1.default();
|
|
31
31
|
this.previousClientIds = new Set();
|
|
32
32
|
this.firstStashedCSN = -1;
|
|
33
|
-
this.stashedCount = 0;
|
|
34
33
|
this.disposeOnce = new common_utils_1.Lazy(() => {
|
|
35
34
|
this.initialStates.clear();
|
|
36
35
|
this.pendingStates.clear();
|
|
@@ -48,7 +47,6 @@ class PendingStateManager {
|
|
|
48
47
|
// get stashed op count and client sequence number of first op
|
|
49
48
|
const messages = initialState.pendingStates
|
|
50
49
|
.filter((state) => state.type === "message");
|
|
51
|
-
this.stashedCount = messages.length;
|
|
52
50
|
this.firstStashedCSN = messages[0].clientSequenceNumber;
|
|
53
51
|
}
|
|
54
52
|
}
|
|
@@ -208,7 +206,6 @@ class PendingStateManager {
|
|
|
208
206
|
// if it's not a message just drop it and keep looking
|
|
209
207
|
if (nextState.type === "message") {
|
|
210
208
|
this.assertOpMatch(nextState, message, isOriginalClientId);
|
|
211
|
-
--this.stashedCount;
|
|
212
209
|
return { localAck: true, localOpMetadata: nextState.localOpMetadata };
|
|
213
210
|
}
|
|
214
211
|
}
|
|
@@ -340,45 +337,12 @@ class PendingStateManager {
|
|
|
340
337
|
common_utils_1.assert(this.connected, 0x172 /* "The connection state is not consistent with the runtime" */);
|
|
341
338
|
// This assert suggests we are about to send same ops twice, which will result in data loss.
|
|
342
339
|
common_utils_1.assert(this.clientId !== this.containerRuntime.clientId, 0x173 /* "replayPendingStates called twice for same clientId!" */);
|
|
343
|
-
const prevClientId = this.clientId;
|
|
344
340
|
this.clientId = this.containerRuntime.clientId;
|
|
345
341
|
common_utils_1.assert(this.initialStates.isEmpty(), 0x174 /* "initial states should be empty before replaying pending" */);
|
|
346
342
|
let pendingStatesCount = this.pendingStates.length;
|
|
347
343
|
if (pendingStatesCount === 0) {
|
|
348
344
|
return;
|
|
349
345
|
}
|
|
350
|
-
if (!prevClientId && this.stashedCount > 0) {
|
|
351
|
-
// this is first connect, verify we are about to "resubmit" only stashed ops
|
|
352
|
-
common_utils_1.assert(this.pendingStates.toArray().filter((s) => s.type === "message").length === this.stashedCount, 0x290 /* "unexpected message queued before first connect" */);
|
|
353
|
-
Array.from(this.previousClientIds).map((id) => common_utils_1.assert(this.containerRuntime.getQuorum().getMember(id) === undefined, 0x291 /* "client with stashed ops already connected" */));
|
|
354
|
-
// send rejoin op with stashed client ID if we have it
|
|
355
|
-
if (this.previousClientIds.size > 0) {
|
|
356
|
-
const clientId = Array.from(this.previousClientIds)[0];
|
|
357
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
358
|
-
this.pendingStates.unshift({
|
|
359
|
-
type: "message",
|
|
360
|
-
messageType: containerRuntime_1.ContainerMessageType.Rejoin,
|
|
361
|
-
content: { clientId },
|
|
362
|
-
});
|
|
363
|
-
++pendingStatesCount;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
if (prevClientId) {
|
|
367
|
-
// add a rejoin op so future clients provided with our stashed pending ops can recognize them
|
|
368
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
369
|
-
const firstState = this.pendingStates.peekFront();
|
|
370
|
-
if (firstState.type !== "message" || firstState.messageType !== containerRuntime_1.ContainerMessageType.Rejoin) {
|
|
371
|
-
// if there is already a rejoin op in the queue, just resubmit same op under new client ID
|
|
372
|
-
// otherwise, add one to the queue
|
|
373
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
374
|
-
this.pendingStates.unshift({
|
|
375
|
-
type: "message",
|
|
376
|
-
messageType: containerRuntime_1.ContainerMessageType.Rejoin,
|
|
377
|
-
content: { clientId: prevClientId },
|
|
378
|
-
});
|
|
379
|
-
++pendingStatesCount;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
346
|
// Reset the pending message count because all these messages will be removed from the queue.
|
|
383
347
|
this.pendingMessagesCount = 0;
|
|
384
348
|
// Save the current FlushMode so that we can revert it back after replaying the states.
|