@fluidframework/container-runtime 2.0.0-internal.4.0.0 → 2.0.0-internal.4.0.2
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/gc/garbageCollection.d.ts +0 -2
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +3 -10
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +1 -9
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +1 -52
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +1 -2
- package/dist/gc/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +0 -2
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +4 -11
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +1 -9
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +0 -50
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/index.d.ts +1 -1
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +16 -53
- package/src/gc/garbageCollection.ts +4 -27
- package/src/gc/gcHelpers.ts +1 -75
- package/src/gc/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
package/lib/gc/gcHelpers.js
CHANGED
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { assert } from "@fluidframework/common-utils";
|
|
6
|
-
import { gcTreeKey, } from "@fluidframework/runtime-definitions";
|
|
7
5
|
import { packagePathToTelemetryProperty } from "@fluidframework/runtime-utils";
|
|
8
|
-
import { getSummaryForDatastores } from "../dataStores";
|
|
9
|
-
import { dataStoreAttributesBlobName, } from "../summary";
|
|
10
6
|
import { disableTombstoneKey, runSweepKey, throwOnTombstoneLoadKey, throwOnTombstoneUsageKey, } from "./gcDefinitions";
|
|
11
7
|
export function getGCVersion(metadata) {
|
|
12
8
|
var _a;
|
|
@@ -94,50 +90,4 @@ export function generateSortedGCState(gcState) {
|
|
|
94
90
|
}
|
|
95
91
|
return sortedGCState;
|
|
96
92
|
}
|
|
97
|
-
/**
|
|
98
|
-
* This is for back-compat only - Before GC data was written at the root of the summary tree, individual GC blobs were
|
|
99
|
-
* written at data store's snapshot tree. This function consolidates them into the new IGarbageCollectionState format.
|
|
100
|
-
*/
|
|
101
|
-
export async function getSnapshotDataFromOldSnapshotFormat(oldSnapshot, metadata, readAndParseBlob) {
|
|
102
|
-
var _a;
|
|
103
|
-
// Add a node for the root node that is not present in older snapshot format.
|
|
104
|
-
const gcState = {
|
|
105
|
-
gcNodes: { "/": { outboundRoutes: [] } },
|
|
106
|
-
};
|
|
107
|
-
const dataStoreSnapshotTree = getSummaryForDatastores(oldSnapshot, metadata);
|
|
108
|
-
assert(dataStoreSnapshotTree !== undefined, 0x2a8 /* "Expected data store snapshot tree in base snapshot" */);
|
|
109
|
-
for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnapshotTree.trees)) {
|
|
110
|
-
const blobId = dsSnapshotTree.blobs[gcTreeKey];
|
|
111
|
-
if (blobId === undefined) {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
const gcSummaryDetails = await readAndParseBlob(blobId);
|
|
115
|
-
// If there are no nodes for this data store, skip it.
|
|
116
|
-
if (((_a = gcSummaryDetails.gcData) === null || _a === void 0 ? void 0 : _a.gcNodes) === undefined) {
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
const dsRootId = `/${dsId}`;
|
|
120
|
-
// Since we used to write GC data at data store level, we won't have an entry for the root ("/").
|
|
121
|
-
// Construct that entry by adding root data store ids to its outbound routes.
|
|
122
|
-
const initialSnapshotDetails = await readAndParseBlob(dsSnapshotTree.blobs[dataStoreAttributesBlobName]);
|
|
123
|
-
if (initialSnapshotDetails.isRootDataStore) {
|
|
124
|
-
gcState.gcNodes["/"].outboundRoutes.push(dsRootId);
|
|
125
|
-
}
|
|
126
|
-
for (const [id, outboundRoutes] of Object.entries(gcSummaryDetails.gcData.gcNodes)) {
|
|
127
|
-
// Prefix the data store id to the GC node ids to make them relative to the root from being
|
|
128
|
-
// relative to the data store. Similar to how its done in DataStore::getGCData.
|
|
129
|
-
const rootId = id === "/" ? dsRootId : `${dsRootId}${id}`;
|
|
130
|
-
gcState.gcNodes[rootId] = {
|
|
131
|
-
outboundRoutes: Array.from(outboundRoutes),
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
assert(gcState.gcNodes[dsRootId] !== undefined, 0x2a9 /* GC nodes for data store not in GC blob */);
|
|
135
|
-
gcState.gcNodes[dsRootId].unreferencedTimestampMs = gcSummaryDetails.unrefTimestamp;
|
|
136
|
-
}
|
|
137
|
-
// If there is only one node (root node just added above), either GC is disabled or we are loading from
|
|
138
|
-
// the first summary generated by detached container. In both cases, GC was not run - return undefined.
|
|
139
|
-
return Object.keys(gcState.gcNodes).length === 1
|
|
140
|
-
? undefined
|
|
141
|
-
: { gcState, tombstones: undefined, deletedNodes: undefined };
|
|
142
|
-
}
|
|
143
93
|
//# sourceMappingURL=gcHelpers.js.map
|
package/lib/gc/gcHelpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcHelpers.js","sourceRoot":"","sources":["../../src/gc/gcHelpers.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 { ITelemetryGenericEvent } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tgcTreeKey,\n\tIGarbageCollectionNodeData,\n\tIGarbageCollectionSnapshotData,\n\tIGarbageCollectionState,\n\tIGarbageCollectionSummaryDetailsLegacy,\n} from \"@fluidframework/runtime-definitions\";\nimport { packagePathToTelemetryProperty, ReadAndParseBlob } from \"@fluidframework/runtime-utils\";\nimport { MonitoringContext } from \"@fluidframework/telemetry-utils\";\nimport { getSummaryForDatastores } from \"../dataStores\";\nimport {\n\tdataStoreAttributesBlobName,\n\tIContainerRuntimeMetadata,\n\tReadFluidDataStoreAttributes,\n} from \"../summary\";\nimport {\n\tdisableTombstoneKey,\n\tGCFeatureMatrix,\n\tGCVersion,\n\tIGCMetadata,\n\trunSweepKey,\n\tthrowOnTombstoneLoadKey,\n\tthrowOnTombstoneUsageKey,\n} from \"./gcDefinitions\";\n\nexport function getGCVersion(metadata?: IGCMetadata): GCVersion {\n\tif (!metadata) {\n\t\t// Force to 0/disallowed in prior versions\n\t\treturn 0;\n\t}\n\treturn metadata.gcFeature ?? 0;\n}\n\n/**\n * Consolidates info / logic for logging when we encounter unexpected usage of GC'd objects. For example, when a\n * tombstoned or deleted object is loaded.\n */\nexport function sendGCUnexpectedUsageEvent(\n\tmc: MonitoringContext,\n\tevent: ITelemetryGenericEvent & {\n\t\tcategory: \"error\" | \"generic\";\n\t\tgcTombstoneEnforcementAllowed: boolean | undefined;\n\t},\n\tpackagePath: readonly string[] | undefined,\n\terror?: unknown,\n) {\n\tevent.pkg = packagePathToTelemetryProperty(packagePath);\n\tevent.tombstoneFlags = JSON.stringify({\n\t\tDisableTombstone: mc.config.getBoolean(disableTombstoneKey),\n\t\tThrowOnTombstoneUsage: mc.config.getBoolean(throwOnTombstoneUsageKey),\n\t\tThrowOnTombstoneLoad: mc.config.getBoolean(throwOnTombstoneLoadKey),\n\t});\n\tevent.sweepFlags = JSON.stringify({\n\t\tEnableSweepFlag: mc.config.getBoolean(runSweepKey),\n\t});\n\n\tmc.logger.sendTelemetryEvent(event, error);\n}\n\n/**\n * Indicates whether Tombstone Enforcement is allowed for this document based on the current/persisted\n * TombstoneGeneration values\n *\n * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants\n * such that enforcing GC Tombstone (Failing on Tombstone load/usage) would cause legitimate data loss,\n * the container author may increment the generation value for Tombstone such that containers created\n * with a different value will not be subjected to GC enforcement.\n *\n * If no generation is provided at runtime, this defaults to return true to maintain expected default behavior\n *\n * @param persistedGeneration - The persisted tombstoneGeneration value\n * @param currentGeneration - The current app-provided tombstoneGeneration value\n * @returns true if GC Tombstone enforcement (Fail on Tombstone load/usage) should be allowed for this document\n */\nexport function shouldAllowGcTombstoneEnforcement(\n\tpersistedGeneration: number | undefined,\n\tcurrentGeneration: number | undefined,\n): boolean {\n\t// If no Generation value is provided for this session, then we should default to letting Tombstone feature behave as intended.\n\tif (currentGeneration === undefined) {\n\t\treturn true;\n\t}\n\treturn persistedGeneration === currentGeneration;\n}\n\n/**\n * Indicates whether Sweep is allowed for this document based on the GC Feature Matrix and current SweepGeneration\n *\n * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants\n * such that enforcing GC Sweep would cause legitimate data loss, the container author may increment the generation value for Sweep\n * such that containers created with a different value will not be subjected to GC Sweep.\n *\n * If no generation is provided, Sweep will be disabled.\n * Passing 0 is a special case: Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.\n *\n * @param persistedGenerations - The persisted sweep/tombstone generations from the GC Feature Matrix\n * @param currentGeneration - The current app-provided sweepGeneration value\n * @returns true if GC Sweep should be allowed for this document\n */\nexport function shouldAllowGcSweep(\n\tpersistedGenerations: Pick<GCFeatureMatrix, \"sweepGeneration\" | \"tombstoneGeneration\">,\n\tcurrentGeneration: number | undefined,\n): boolean {\n\t// If no Generation value is provided for this session, default to false\n\tif (currentGeneration === undefined) {\n\t\treturn false;\n\t}\n\n\t// 0 is a special case: It matches both SweepGeneration and TombstoneGeneration\n\t// This is an optimistic measure to maximize coverage of GC Sweep if no bumps to TombstoneGeneration are needed before enabling Sweep.\n\tif (currentGeneration === 0) {\n\t\treturn (\n\t\t\tpersistedGenerations.sweepGeneration === 0 ||\n\t\t\tpersistedGenerations.tombstoneGeneration === 0\n\t\t);\n\t}\n\n\treturn persistedGenerations.sweepGeneration === currentGeneration;\n}\n\n/**\n * Sorts the given GC state as per the id of the GC nodes. It also sorts the outbound routes array of each node.\n */\nexport function generateSortedGCState(gcState: IGarbageCollectionState): IGarbageCollectionState {\n\tconst sortableArray: [string, IGarbageCollectionNodeData][] = Object.entries(gcState.gcNodes);\n\tsortableArray.sort(([a], [b]) => a.localeCompare(b));\n\tconst sortedGCState: IGarbageCollectionState = { gcNodes: {} };\n\tfor (const [nodeId, nodeData] of sortableArray) {\n\t\tnodeData.outboundRoutes.sort();\n\t\tsortedGCState.gcNodes[nodeId] = nodeData;\n\t}\n\treturn sortedGCState;\n}\n\n/**\n * This is for back-compat only - Before GC data was written at the root of the summary tree, individual GC blobs were\n * written at data store's snapshot tree. This function consolidates them into the new IGarbageCollectionState format.\n */\nexport async function getSnapshotDataFromOldSnapshotFormat(\n\toldSnapshot: ISnapshotTree,\n\tmetadata: IContainerRuntimeMetadata | undefined,\n\treadAndParseBlob: ReadAndParseBlob,\n): Promise<IGarbageCollectionSnapshotData | undefined> {\n\t// Add a node for the root node that is not present in older snapshot format.\n\tconst gcState: IGarbageCollectionState = {\n\t\tgcNodes: { \"/\": { outboundRoutes: [] } },\n\t};\n\tconst dataStoreSnapshotTree = getSummaryForDatastores(oldSnapshot, metadata);\n\tassert(\n\t\tdataStoreSnapshotTree !== undefined,\n\t\t0x2a8 /* \"Expected data store snapshot tree in base snapshot\" */,\n\t);\n\tfor (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnapshotTree.trees)) {\n\t\tconst blobId = dsSnapshotTree.blobs[gcTreeKey];\n\t\tif (blobId === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst gcSummaryDetails = await readAndParseBlob<IGarbageCollectionSummaryDetailsLegacy>(\n\t\t\tblobId,\n\t\t);\n\t\t// If there are no nodes for this data store, skip it.\n\t\tif (gcSummaryDetails.gcData?.gcNodes === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst dsRootId = `/${dsId}`;\n\t\t// Since we used to write GC data at data store level, we won't have an entry for the root (\"/\").\n\t\t// Construct that entry by adding root data store ids to its outbound routes.\n\t\tconst initialSnapshotDetails = await readAndParseBlob<ReadFluidDataStoreAttributes>(\n\t\t\tdsSnapshotTree.blobs[dataStoreAttributesBlobName],\n\t\t);\n\t\tif (initialSnapshotDetails.isRootDataStore) {\n\t\t\tgcState.gcNodes[\"/\"].outboundRoutes.push(dsRootId);\n\t\t}\n\n\t\tfor (const [id, outboundRoutes] of Object.entries(gcSummaryDetails.gcData.gcNodes)) {\n\t\t\t// Prefix the data store id to the GC node ids to make them relative to the root from being\n\t\t\t// relative to the data store. Similar to how its done in DataStore::getGCData.\n\t\t\tconst rootId = id === \"/\" ? dsRootId : `${dsRootId}${id}`;\n\t\t\tgcState.gcNodes[rootId] = {\n\t\t\t\toutboundRoutes: Array.from(outboundRoutes),\n\t\t\t};\n\t\t}\n\t\tassert(\n\t\t\tgcState.gcNodes[dsRootId] !== undefined,\n\t\t\t0x2a9 /* GC nodes for data store not in GC blob */,\n\t\t);\n\t\tgcState.gcNodes[dsRootId].unreferencedTimestampMs = gcSummaryDetails.unrefTimestamp;\n\t}\n\t// If there is only one node (root node just added above), either GC is disabled or we are loading from\n\t// the first summary generated by detached container. In both cases, GC was not run - return undefined.\n\treturn Object.keys(gcState.gcNodes).length === 1\n\t\t? undefined\n\t\t: { gcState, tombstones: undefined, deletedNodes: undefined };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"gcHelpers.js","sourceRoot":"","sources":["../../src/gc/gcHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAE/E,OAAO,EACN,mBAAmB,EAInB,WAAW,EACX,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,UAAU,YAAY,CAAC,QAAsB;;IAClD,IAAI,CAAC,QAAQ,EAAE;QACd,0CAA0C;QAC1C,OAAO,CAAC,CAAC;KACT;IACD,OAAO,MAAA,QAAQ,CAAC,SAAS,mCAAI,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACzC,EAAqB,EACrB,KAGC,EACD,WAA0C,EAC1C,KAAe;IAEf,KAAK,CAAC,GAAG,GAAG,8BAA8B,CAAC,WAAW,CAAC,CAAC;IACxD,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC;QACrC,gBAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;QAC3D,qBAAqB,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC;QACrE,oBAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,uBAAuB,CAAC;KACnE,CAAC,CAAC;IACH,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,eAAe,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC;KAClD,CAAC,CAAC;IAEH,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iCAAiC,CAChD,mBAAuC,EACvC,iBAAqC;IAErC,+HAA+H;IAC/H,IAAI,iBAAiB,KAAK,SAAS,EAAE;QACpC,OAAO,IAAI,CAAC;KACZ;IACD,OAAO,mBAAmB,KAAK,iBAAiB,CAAC;AAClD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CACjC,oBAAsF,EACtF,iBAAqC;IAErC,wEAAwE;IACxE,IAAI,iBAAiB,KAAK,SAAS,EAAE;QACpC,OAAO,KAAK,CAAC;KACb;IAED,+EAA+E;IAC/E,sIAAsI;IACtI,IAAI,iBAAiB,KAAK,CAAC,EAAE;QAC5B,OAAO,CACN,oBAAoB,CAAC,eAAe,KAAK,CAAC;YAC1C,oBAAoB,CAAC,mBAAmB,KAAK,CAAC,CAC9C,CAAC;KACF;IAED,OAAO,oBAAoB,CAAC,eAAe,KAAK,iBAAiB,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgC;IACrE,MAAM,aAAa,GAA2C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9F,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,aAAa,GAA4B,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC/D,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,aAAa,EAAE;QAC/C,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC/B,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC;KACzC;IACD,OAAO,aAAa,CAAC;AACtB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryGenericEvent } from \"@fluidframework/common-definitions\";\nimport {\n\tIGarbageCollectionNodeData,\n\tIGarbageCollectionState,\n} from \"@fluidframework/runtime-definitions\";\nimport { packagePathToTelemetryProperty } from \"@fluidframework/runtime-utils\";\nimport { MonitoringContext } from \"@fluidframework/telemetry-utils\";\nimport {\n\tdisableTombstoneKey,\n\tGCFeatureMatrix,\n\tGCVersion,\n\tIGCMetadata,\n\trunSweepKey,\n\tthrowOnTombstoneLoadKey,\n\tthrowOnTombstoneUsageKey,\n} from \"./gcDefinitions\";\n\nexport function getGCVersion(metadata?: IGCMetadata): GCVersion {\n\tif (!metadata) {\n\t\t// Force to 0/disallowed in prior versions\n\t\treturn 0;\n\t}\n\treturn metadata.gcFeature ?? 0;\n}\n\n/**\n * Consolidates info / logic for logging when we encounter unexpected usage of GC'd objects. For example, when a\n * tombstoned or deleted object is loaded.\n */\nexport function sendGCUnexpectedUsageEvent(\n\tmc: MonitoringContext,\n\tevent: ITelemetryGenericEvent & {\n\t\tcategory: \"error\" | \"generic\";\n\t\tgcTombstoneEnforcementAllowed: boolean | undefined;\n\t},\n\tpackagePath: readonly string[] | undefined,\n\terror?: unknown,\n) {\n\tevent.pkg = packagePathToTelemetryProperty(packagePath);\n\tevent.tombstoneFlags = JSON.stringify({\n\t\tDisableTombstone: mc.config.getBoolean(disableTombstoneKey),\n\t\tThrowOnTombstoneUsage: mc.config.getBoolean(throwOnTombstoneUsageKey),\n\t\tThrowOnTombstoneLoad: mc.config.getBoolean(throwOnTombstoneLoadKey),\n\t});\n\tevent.sweepFlags = JSON.stringify({\n\t\tEnableSweepFlag: mc.config.getBoolean(runSweepKey),\n\t});\n\n\tmc.logger.sendTelemetryEvent(event, error);\n}\n\n/**\n * Indicates whether Tombstone Enforcement is allowed for this document based on the current/persisted\n * TombstoneGeneration values\n *\n * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants\n * such that enforcing GC Tombstone (Failing on Tombstone load/usage) would cause legitimate data loss,\n * the container author may increment the generation value for Tombstone such that containers created\n * with a different value will not be subjected to GC enforcement.\n *\n * If no generation is provided at runtime, this defaults to return true to maintain expected default behavior\n *\n * @param persistedGeneration - The persisted tombstoneGeneration value\n * @param currentGeneration - The current app-provided tombstoneGeneration value\n * @returns true if GC Tombstone enforcement (Fail on Tombstone load/usage) should be allowed for this document\n */\nexport function shouldAllowGcTombstoneEnforcement(\n\tpersistedGeneration: number | undefined,\n\tcurrentGeneration: number | undefined,\n): boolean {\n\t// If no Generation value is provided for this session, then we should default to letting Tombstone feature behave as intended.\n\tif (currentGeneration === undefined) {\n\t\treturn true;\n\t}\n\treturn persistedGeneration === currentGeneration;\n}\n\n/**\n * Indicates whether Sweep is allowed for this document based on the GC Feature Matrix and current SweepGeneration\n *\n * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants\n * such that enforcing GC Sweep would cause legitimate data loss, the container author may increment the generation value for Sweep\n * such that containers created with a different value will not be subjected to GC Sweep.\n *\n * If no generation is provided, Sweep will be disabled.\n * Passing 0 is a special case: Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.\n *\n * @param persistedGenerations - The persisted sweep/tombstone generations from the GC Feature Matrix\n * @param currentGeneration - The current app-provided sweepGeneration value\n * @returns true if GC Sweep should be allowed for this document\n */\nexport function shouldAllowGcSweep(\n\tpersistedGenerations: Pick<GCFeatureMatrix, \"sweepGeneration\" | \"tombstoneGeneration\">,\n\tcurrentGeneration: number | undefined,\n): boolean {\n\t// If no Generation value is provided for this session, default to false\n\tif (currentGeneration === undefined) {\n\t\treturn false;\n\t}\n\n\t// 0 is a special case: It matches both SweepGeneration and TombstoneGeneration\n\t// This is an optimistic measure to maximize coverage of GC Sweep if no bumps to TombstoneGeneration are needed before enabling Sweep.\n\tif (currentGeneration === 0) {\n\t\treturn (\n\t\t\tpersistedGenerations.sweepGeneration === 0 ||\n\t\t\tpersistedGenerations.tombstoneGeneration === 0\n\t\t);\n\t}\n\n\treturn persistedGenerations.sweepGeneration === currentGeneration;\n}\n\n/**\n * Sorts the given GC state as per the id of the GC nodes. It also sorts the outbound routes array of each node.\n */\nexport function generateSortedGCState(gcState: IGarbageCollectionState): IGarbageCollectionState {\n\tconst sortableArray: [string, IGarbageCollectionNodeData][] = Object.entries(gcState.gcNodes);\n\tsortableArray.sort(([a], [b]) => a.localeCompare(b));\n\tconst sortedGCState: IGarbageCollectionState = { gcNodes: {} };\n\tfor (const [nodeId, nodeData] of sortableArray) {\n\t\tnodeData.outboundRoutes.sort();\n\t\tsortedGCState.gcNodes[nodeId] = nodeData;\n\t}\n\treturn sortedGCState;\n}\n"]}
|
package/lib/gc/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { GarbageCollector } from "./garbageCollection";
|
|
6
6
|
export { currentGCVersion, defaultInactiveTimeoutMs, defaultSessionExpiryDurationMs, disableSweepLogKey, GCNodeType, gcTestModeKey, gcTombstoneGenerationOptionName, gcSweepGenerationOptionName, GCFeatureMatrix, GCVersion, gcVersionUpgradeToV2Key, IGarbageCollectionRuntime, IGarbageCollector, IGarbageCollectorConfigs, IGarbageCollectorCreateParams, IGCMetadata, IGCRuntimeOptions, IGCStats, oneDayMs, runGCKey, runSessionExpiryKey, runSweepKey, stableGCVersion, sweepAttachmentBlobsKey, sweepDatastoresKey, throwOnTombstoneLoadKey, throwOnTombstoneUsageKey, UnreferencedState, } from "./gcDefinitions";
|
|
7
|
-
export {
|
|
7
|
+
export { sendGCUnexpectedUsageEvent, shouldAllowGcTombstoneEnforcement, shouldAllowGcSweep, } from "./gcHelpers";
|
|
8
8
|
export { GCSummaryStateTracker } from "./gcSummaryStateTracker";
|
|
9
9
|
export { skipClosureForXDaysKey, closuresMapLocalStorageKey, SweepReadyUsageDetectionHandler, } from "./gcSweepReadyUsageDetection";
|
|
10
10
|
export { UnreferencedStateTracker } from "./gcUnreferencedStateTracker";
|
package/lib/gc/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gc/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EACN,gBAAgB,EAChB,wBAAwB,EACxB,8BAA8B,EAC9B,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,+BAA+B,EAC/B,2BAA2B,EAC3B,eAAe,EACf,SAAS,EACT,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,wBAAwB,EACxB,6BAA6B,EAC7B,WAAW,EACX,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gc/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EACN,gBAAgB,EAChB,wBAAwB,EACxB,8BAA8B,EAC9B,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,+BAA+B,EAC/B,2BAA2B,EAC3B,eAAe,EACf,SAAS,EACT,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,wBAAwB,EACxB,6BAA6B,EAC7B,WAAW,EACX,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,0BAA0B,EAC1B,iCAAiC,EACjC,kBAAkB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EACN,sBAAsB,EACtB,0BAA0B,EAC1B,+BAA+B,GAC/B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/lib/gc/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { GarbageCollector } from "./garbageCollection";
|
|
6
6
|
export { currentGCVersion, defaultInactiveTimeoutMs, defaultSessionExpiryDurationMs, disableSweepLogKey, GCNodeType, gcTestModeKey, gcTombstoneGenerationOptionName, gcSweepGenerationOptionName, gcVersionUpgradeToV2Key, oneDayMs, runGCKey, runSessionExpiryKey, runSweepKey, stableGCVersion, sweepAttachmentBlobsKey, sweepDatastoresKey, throwOnTombstoneLoadKey, throwOnTombstoneUsageKey, UnreferencedState, } from "./gcDefinitions";
|
|
7
|
-
export {
|
|
7
|
+
export { sendGCUnexpectedUsageEvent, shouldAllowGcTombstoneEnforcement, shouldAllowGcSweep, } from "./gcHelpers";
|
|
8
8
|
export { GCSummaryStateTracker } from "./gcSummaryStateTracker";
|
|
9
9
|
export { skipClosureForXDaysKey, closuresMapLocalStorageKey, SweepReadyUsageDetectionHandler, } from "./gcSweepReadyUsageDetection";
|
|
10
10
|
export { UnreferencedStateTracker } from "./gcUnreferencedStateTracker";
|
package/lib/gc/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gc/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EACN,gBAAgB,EAChB,wBAAwB,EACxB,8BAA8B,EAC9B,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,+BAA+B,EAC/B,2BAA2B,EAG3B,uBAAuB,EAQvB,QAAQ,EACR,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gc/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EACN,gBAAgB,EAChB,wBAAwB,EACxB,8BAA8B,EAC9B,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,+BAA+B,EAC/B,2BAA2B,EAG3B,uBAAuB,EAQvB,QAAQ,EACR,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,0BAA0B,EAC1B,iCAAiC,EACjC,kBAAkB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EACN,sBAAsB,EACtB,0BAA0B,EAC1B,+BAA+B,GAC/B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { GarbageCollector } from \"./garbageCollection\";\nexport {\n\tcurrentGCVersion,\n\tdefaultInactiveTimeoutMs,\n\tdefaultSessionExpiryDurationMs,\n\tdisableSweepLogKey,\n\tGCNodeType,\n\tgcTestModeKey,\n\tgcTombstoneGenerationOptionName,\n\tgcSweepGenerationOptionName,\n\tGCFeatureMatrix,\n\tGCVersion,\n\tgcVersionUpgradeToV2Key,\n\tIGarbageCollectionRuntime,\n\tIGarbageCollector,\n\tIGarbageCollectorConfigs,\n\tIGarbageCollectorCreateParams,\n\tIGCMetadata,\n\tIGCRuntimeOptions,\n\tIGCStats,\n\toneDayMs,\n\trunGCKey,\n\trunSessionExpiryKey,\n\trunSweepKey,\n\tstableGCVersion,\n\tsweepAttachmentBlobsKey,\n\tsweepDatastoresKey,\n\tthrowOnTombstoneLoadKey,\n\tthrowOnTombstoneUsageKey,\n\tUnreferencedState,\n} from \"./gcDefinitions\";\nexport {\n\tsendGCUnexpectedUsageEvent,\n\tshouldAllowGcTombstoneEnforcement,\n\tshouldAllowGcSweep,\n} from \"./gcHelpers\";\nexport { GCSummaryStateTracker } from \"./gcSummaryStateTracker\";\nexport {\n\tskipClosureForXDaysKey,\n\tclosuresMapLocalStorageKey,\n\tSweepReadyUsageDetectionHandler,\n} from \"./gcSweepReadyUsageDetection\";\nexport { UnreferencedStateTracker } from \"./gcUnreferencedStateTracker\";\n"]}
|
package/lib/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 = "2.0.0-internal.4.0.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.4.0.2";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluidframework/container-runtime";
|
|
8
|
-
export const pkgVersion = "2.0.0-internal.4.0.
|
|
8
|
+
export const pkgVersion = "2.0.0-internal.4.0.2";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,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 = \"2.0.0-internal.4.0.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,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 = \"2.0.0-internal.4.0.2\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-runtime",
|
|
3
|
-
"version": "2.0.0-internal.4.0.
|
|
3
|
+
"version": "2.0.0-internal.4.0.2",
|
|
4
4
|
"description": "Fluid container runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -37,19 +37,19 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
39
39
|
"@fluidframework/common-utils": "^1.1.1",
|
|
40
|
-
"@fluidframework/container-definitions": ">=2.0.0-internal.4.0.
|
|
41
|
-
"@fluidframework/container-runtime-definitions": ">=2.0.0-internal.4.0.
|
|
42
|
-
"@fluidframework/container-utils": ">=2.0.0-internal.4.0.
|
|
43
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.4.0.
|
|
44
|
-
"@fluidframework/datastore": ">=2.0.0-internal.4.0.
|
|
45
|
-
"@fluidframework/driver-definitions": ">=2.0.0-internal.4.0.
|
|
46
|
-
"@fluidframework/driver-utils": ">=2.0.0-internal.4.0.
|
|
47
|
-
"@fluidframework/garbage-collector": ">=2.0.0-internal.4.0.
|
|
40
|
+
"@fluidframework/container-definitions": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
41
|
+
"@fluidframework/container-runtime-definitions": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
42
|
+
"@fluidframework/container-utils": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
43
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
44
|
+
"@fluidframework/datastore": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
45
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
46
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
47
|
+
"@fluidframework/garbage-collector": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
48
48
|
"@fluidframework/protocol-base": "^0.1038.4000",
|
|
49
49
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
50
|
-
"@fluidframework/runtime-definitions": ">=2.0.0-internal.4.0.
|
|
51
|
-
"@fluidframework/runtime-utils": ">=2.0.0-internal.4.0.
|
|
52
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.4.0.
|
|
50
|
+
"@fluidframework/runtime-definitions": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
51
|
+
"@fluidframework/runtime-utils": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
52
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
53
53
|
"double-ended-queue": "^2.1.0-0",
|
|
54
54
|
"events": "^3.1.0",
|
|
55
55
|
"lz4js": "^0.2.0",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"@fluid-tools/build-cli": "^0.13.0",
|
|
60
60
|
"@fluidframework/build-common": "^1.1.0",
|
|
61
61
|
"@fluidframework/build-tools": "^0.13.0",
|
|
62
|
-
"@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.0.0-internal.
|
|
62
|
+
"@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.0.0-internal.4.0.0",
|
|
63
63
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
64
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.0.
|
|
65
|
-
"@fluidframework/test-runtime-utils": ">=2.0.0-internal.4.0.
|
|
64
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
65
|
+
"@fluidframework/test-runtime-utils": ">=2.0.0-internal.4.0.2 <2.0.0-internal.5.0.0",
|
|
66
66
|
"@microsoft/api-extractor": "^7.34.4",
|
|
67
67
|
"@types/double-ended-queue": "^2.1.0",
|
|
68
68
|
"@types/events": "^3.0.0",
|
|
@@ -81,44 +81,7 @@
|
|
|
81
81
|
"typescript": "~4.5.5"
|
|
82
82
|
},
|
|
83
83
|
"typeValidation": {
|
|
84
|
-
"broken": {
|
|
85
|
-
"ClassDeclaration_ContainerRuntime": {
|
|
86
|
-
"backCompat": false
|
|
87
|
-
},
|
|
88
|
-
"RemovedInterfaceDeclaration_IPendingFlush": {
|
|
89
|
-
"backCompat": false,
|
|
90
|
-
"forwardCompat": false
|
|
91
|
-
},
|
|
92
|
-
"RemovedInterfaceDeclaration_IPendingLocalState": {
|
|
93
|
-
"backCompat": false,
|
|
94
|
-
"forwardCompat": false
|
|
95
|
-
},
|
|
96
|
-
"RemovedInterfaceDeclaration_IPendingMessage": {
|
|
97
|
-
"backCompat": false,
|
|
98
|
-
"forwardCompat": false
|
|
99
|
-
},
|
|
100
|
-
"RemovedTypeAliasDeclaration_IPendingState": {
|
|
101
|
-
"backCompat": false,
|
|
102
|
-
"forwardCompat": false
|
|
103
|
-
},
|
|
104
|
-
"InterfaceDeclaration_IConnectableRuntime": {
|
|
105
|
-
"backCompat": false
|
|
106
|
-
},
|
|
107
|
-
"RemovedInterfaceDeclaration_IProvideSummarizer": {
|
|
108
|
-
"forwardCompat": false,
|
|
109
|
-
"backCompat": false
|
|
110
|
-
},
|
|
111
|
-
"RemovedVariableDeclaration_ISummarizer": {
|
|
112
|
-
"forwardCompat": false,
|
|
113
|
-
"backCompat": false
|
|
114
|
-
},
|
|
115
|
-
"InterfaceDeclaration_ISummarizer": {
|
|
116
|
-
"backCompat": false
|
|
117
|
-
},
|
|
118
|
-
"ClassDeclaration_Summarizer": {
|
|
119
|
-
"backCompat": false
|
|
120
|
-
}
|
|
121
|
-
}
|
|
84
|
+
"broken": {}
|
|
122
85
|
},
|
|
123
86
|
"scripts": {
|
|
124
87
|
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
|
|
@@ -48,9 +48,8 @@ import {
|
|
|
48
48
|
IGCMetadata,
|
|
49
49
|
IGarbageCollectorConfigs,
|
|
50
50
|
} from "./gcDefinitions";
|
|
51
|
-
import {
|
|
51
|
+
import { sendGCUnexpectedUsageEvent } from "./gcHelpers";
|
|
52
52
|
import { GCSummaryStateTracker } from "./gcSummaryStateTracker";
|
|
53
|
-
import { SweepReadyUsageDetectionHandler } from "./gcSweepReadyUsageDetection";
|
|
54
53
|
import { UnreferencedStateTracker } from "./gcUnreferencedStateTracker";
|
|
55
54
|
|
|
56
55
|
/** The event that is logged when unreferenced node is used after a certain time. */
|
|
@@ -152,9 +151,6 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
152
151
|
return this.summaryStateTracker.doesSummaryStateNeedReset;
|
|
153
152
|
}
|
|
154
153
|
|
|
155
|
-
/** Handler to respond to when a SweepReady object is used */
|
|
156
|
-
private readonly sweepReadyUsageHandler: SweepReadyUsageDetectionHandler;
|
|
157
|
-
|
|
158
154
|
protected constructor(createParams: IGarbageCollectorCreateParams) {
|
|
159
155
|
this.runtime = createParams.runtime;
|
|
160
156
|
this.isSummarizerClient = createParams.isSummarizerClient;
|
|
@@ -172,12 +168,6 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
172
168
|
}),
|
|
173
169
|
);
|
|
174
170
|
|
|
175
|
-
this.sweepReadyUsageHandler = new SweepReadyUsageDetectionHandler(
|
|
176
|
-
createParams.getContainerDiagnosticId(),
|
|
177
|
-
this.mc,
|
|
178
|
-
this.runtime.closeFn,
|
|
179
|
-
);
|
|
180
|
-
|
|
181
171
|
this.configs = generateGCConfigs(this.mc, createParams);
|
|
182
172
|
|
|
183
173
|
// If session expiry is enabled, we need to close the container when the session expiry timeout expires.
|
|
@@ -216,12 +206,9 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
216
206
|
return getGCDataFromSnapshot(gcSnapshotTree, readAndParseBlob);
|
|
217
207
|
}
|
|
218
208
|
|
|
219
|
-
// back-compat - Older documents
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
createParams.metadata,
|
|
223
|
-
readAndParseBlob,
|
|
224
|
-
);
|
|
209
|
+
// back-compat - Older documents get their gc data reset for simplicity as there are few of them
|
|
210
|
+
// incremental gc summary will not work with older gc data as well
|
|
211
|
+
return undefined;
|
|
225
212
|
} catch (error) {
|
|
226
213
|
const dpe = DataProcessingError.wrapIfUnrecognized(
|
|
227
214
|
error,
|
|
@@ -1199,16 +1186,6 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
1199
1186
|
this.mc.logger.sendErrorEvent(event);
|
|
1200
1187
|
}
|
|
1201
1188
|
}
|
|
1202
|
-
|
|
1203
|
-
// If SweepReady Usage Detection is enabled, the handler may close the interactive container.
|
|
1204
|
-
// Once Sweep is fully implemented, this will be removed since the objects will be gone
|
|
1205
|
-
// and errors will arise elsewhere in the runtime
|
|
1206
|
-
if (state === UnreferencedState.SweepReady) {
|
|
1207
|
-
this.sweepReadyUsageHandler.usageDetectedInInteractiveClient({
|
|
1208
|
-
...propsToLog,
|
|
1209
|
-
usageType,
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
1189
|
}
|
|
1213
1190
|
}
|
|
1214
1191
|
|
package/src/gc/gcHelpers.ts
CHANGED
|
@@ -4,23 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ITelemetryGenericEvent } from "@fluidframework/common-definitions";
|
|
7
|
-
import { assert } from "@fluidframework/common-utils";
|
|
8
|
-
import { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
9
7
|
import {
|
|
10
|
-
gcTreeKey,
|
|
11
8
|
IGarbageCollectionNodeData,
|
|
12
|
-
IGarbageCollectionSnapshotData,
|
|
13
9
|
IGarbageCollectionState,
|
|
14
|
-
IGarbageCollectionSummaryDetailsLegacy,
|
|
15
10
|
} from "@fluidframework/runtime-definitions";
|
|
16
|
-
import { packagePathToTelemetryProperty
|
|
11
|
+
import { packagePathToTelemetryProperty } from "@fluidframework/runtime-utils";
|
|
17
12
|
import { MonitoringContext } from "@fluidframework/telemetry-utils";
|
|
18
|
-
import { getSummaryForDatastores } from "../dataStores";
|
|
19
|
-
import {
|
|
20
|
-
dataStoreAttributesBlobName,
|
|
21
|
-
IContainerRuntimeMetadata,
|
|
22
|
-
ReadFluidDataStoreAttributes,
|
|
23
|
-
} from "../summary";
|
|
24
13
|
import {
|
|
25
14
|
disableTombstoneKey,
|
|
26
15
|
GCFeatureMatrix,
|
|
@@ -139,66 +128,3 @@ export function generateSortedGCState(gcState: IGarbageCollectionState): IGarbag
|
|
|
139
128
|
}
|
|
140
129
|
return sortedGCState;
|
|
141
130
|
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* This is for back-compat only - Before GC data was written at the root of the summary tree, individual GC blobs were
|
|
145
|
-
* written at data store's snapshot tree. This function consolidates them into the new IGarbageCollectionState format.
|
|
146
|
-
*/
|
|
147
|
-
export async function getSnapshotDataFromOldSnapshotFormat(
|
|
148
|
-
oldSnapshot: ISnapshotTree,
|
|
149
|
-
metadata: IContainerRuntimeMetadata | undefined,
|
|
150
|
-
readAndParseBlob: ReadAndParseBlob,
|
|
151
|
-
): Promise<IGarbageCollectionSnapshotData | undefined> {
|
|
152
|
-
// Add a node for the root node that is not present in older snapshot format.
|
|
153
|
-
const gcState: IGarbageCollectionState = {
|
|
154
|
-
gcNodes: { "/": { outboundRoutes: [] } },
|
|
155
|
-
};
|
|
156
|
-
const dataStoreSnapshotTree = getSummaryForDatastores(oldSnapshot, metadata);
|
|
157
|
-
assert(
|
|
158
|
-
dataStoreSnapshotTree !== undefined,
|
|
159
|
-
0x2a8 /* "Expected data store snapshot tree in base snapshot" */,
|
|
160
|
-
);
|
|
161
|
-
for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnapshotTree.trees)) {
|
|
162
|
-
const blobId = dsSnapshotTree.blobs[gcTreeKey];
|
|
163
|
-
if (blobId === undefined) {
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const gcSummaryDetails = await readAndParseBlob<IGarbageCollectionSummaryDetailsLegacy>(
|
|
168
|
-
blobId,
|
|
169
|
-
);
|
|
170
|
-
// If there are no nodes for this data store, skip it.
|
|
171
|
-
if (gcSummaryDetails.gcData?.gcNodes === undefined) {
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const dsRootId = `/${dsId}`;
|
|
176
|
-
// Since we used to write GC data at data store level, we won't have an entry for the root ("/").
|
|
177
|
-
// Construct that entry by adding root data store ids to its outbound routes.
|
|
178
|
-
const initialSnapshotDetails = await readAndParseBlob<ReadFluidDataStoreAttributes>(
|
|
179
|
-
dsSnapshotTree.blobs[dataStoreAttributesBlobName],
|
|
180
|
-
);
|
|
181
|
-
if (initialSnapshotDetails.isRootDataStore) {
|
|
182
|
-
gcState.gcNodes["/"].outboundRoutes.push(dsRootId);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
for (const [id, outboundRoutes] of Object.entries(gcSummaryDetails.gcData.gcNodes)) {
|
|
186
|
-
// Prefix the data store id to the GC node ids to make them relative to the root from being
|
|
187
|
-
// relative to the data store. Similar to how its done in DataStore::getGCData.
|
|
188
|
-
const rootId = id === "/" ? dsRootId : `${dsRootId}${id}`;
|
|
189
|
-
gcState.gcNodes[rootId] = {
|
|
190
|
-
outboundRoutes: Array.from(outboundRoutes),
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
assert(
|
|
194
|
-
gcState.gcNodes[dsRootId] !== undefined,
|
|
195
|
-
0x2a9 /* GC nodes for data store not in GC blob */,
|
|
196
|
-
);
|
|
197
|
-
gcState.gcNodes[dsRootId].unreferencedTimestampMs = gcSummaryDetails.unrefTimestamp;
|
|
198
|
-
}
|
|
199
|
-
// If there is only one node (root node just added above), either GC is disabled or we are loading from
|
|
200
|
-
// the first summary generated by detached container. In both cases, GC was not run - return undefined.
|
|
201
|
-
return Object.keys(gcState.gcNodes).length === 1
|
|
202
|
-
? undefined
|
|
203
|
-
: { gcState, tombstones: undefined, deletedNodes: undefined };
|
|
204
|
-
}
|
package/src/gc/index.ts
CHANGED
package/src/packageVersion.ts
CHANGED