@fluidframework/container-runtime 2.0.0-internal.4.2.1 → 2.0.0-internal.4.4.0
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/CHANGELOG.md +4 -0
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +3 -2
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +1 -0
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +20 -11
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +1 -2
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +5 -5
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +3 -6
- package/dist/dataStores.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +56 -70
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +227 -408
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +8 -10
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +2 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +11 -11
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +18 -22
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +6 -2
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +16 -6
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +91 -0
- package/dist/gc/gcTelemetry.d.ts.map +1 -0
- package/dist/gc/gcTelemetry.js +282 -0
- package/dist/gc/gcTelemetry.js.map +1 -0
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +5 -6
- package/dist/gc/index.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +1 -1
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/outbox.js +1 -1
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +25 -22
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +1 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.js +15 -4
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +14 -17
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/summarizer.d.ts +2 -0
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +9 -4
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +8 -9
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js +15 -16
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +2 -0
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +4 -3
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +3 -2
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +1 -0
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +20 -11
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +1 -2
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +5 -5
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +3 -6
- package/lib/dataStores.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +56 -70
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +231 -412
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +8 -10
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +2 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +11 -11
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +16 -20
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +6 -2
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +16 -6
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +91 -0
- package/lib/gc/gcTelemetry.d.ts.map +1 -0
- package/lib/gc/gcTelemetry.js +277 -0
- package/lib/gc/gcTelemetry.js.map +1 -0
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +1 -1
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/outbox.js +1 -1
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +25 -22
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +1 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.js +15 -4
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +14 -17
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/summarizer.d.ts +2 -0
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +9 -4
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +8 -9
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js +15 -16
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +2 -0
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +4 -3
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/package.json +15 -16
- package/src/blobManager.ts +3 -2
- package/src/connectionTelemetry.ts +1 -0
- package/src/containerRuntime.ts +22 -15
- package/src/dataStoreContext.ts +1 -2
- package/src/dataStores.ts +4 -7
- package/src/gc/garbageCollection.ts +316 -561
- package/src/gc/gcConfigs.ts +12 -11
- package/src/gc/gcDefinitions.ts +2 -0
- package/src/gc/gcHelpers.ts +21 -40
- package/src/gc/gcSummaryStateTracker.ts +19 -7
- package/src/gc/gcTelemetry.ts +408 -0
- package/src/gc/index.ts +2 -6
- package/src/opLifecycle/README.md +13 -0
- package/src/opLifecycle/opGroupingManager.ts +1 -1
- package/src/opLifecycle/outbox.ts +2 -2
- package/src/opLifecycle/remoteMessageProcessor.ts +37 -28
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +1 -4
- package/src/scheduleManager.ts +19 -7
- package/src/summary/orderedClientElection.ts +14 -17
- package/src/summary/summarizer.ts +17 -5
- package/src/summary/summarizerHeuristics.ts +15 -16
- package/src/summary/summarizerTypes.ts +2 -0
- package/src/summary/summaryGenerator.ts +5 -4
- package/dist/gc/gcSweepReadyUsageDetection.d.ts +0 -53
- package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/dist/gc/gcSweepReadyUsageDetection.js +0 -130
- package/dist/gc/gcSweepReadyUsageDetection.js.map +0 -1
- package/lib/gc/gcSweepReadyUsageDetection.d.ts +0 -53
- package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/lib/gc/gcSweepReadyUsageDetection.js +0 -125
- package/lib/gc/gcSweepReadyUsageDetection.js.map +0 -1
- package/src/gc/gcSweepReadyUsageDetection.ts +0 -145
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { ITelemetryProperties } from "@fluidframework/common-definitions";
|
|
6
|
-
import { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
7
|
-
import { IFluidErrorBase, LoggingError, MonitoringContext } from "@fluidframework/telemetry-utils";
|
|
8
|
-
/**
|
|
9
|
-
* Feature Gate Key -
|
|
10
|
-
* How many days between closing the container from this error (avoids locking user out of their file altogether)
|
|
11
|
-
*/
|
|
12
|
-
export declare const skipClosureForXDaysKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.SkipClosureForXDays";
|
|
13
|
-
/**
|
|
14
|
-
* LocalStorage key (NOT via feature gate / monitoring context)
|
|
15
|
-
* A map from docId to info about the last time we closed due to this error
|
|
16
|
-
*/
|
|
17
|
-
export declare const closuresMapLocalStorageKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.Closures";
|
|
18
|
-
/**
|
|
19
|
-
* Error class raised when a SweepReady object is used, indicating a bug in how
|
|
20
|
-
* references are managed in the container by the application, or a bug in how
|
|
21
|
-
* GC tracks those references.
|
|
22
|
-
*
|
|
23
|
-
* There's a chance for false positives when this error is raised by an Interactive Container,
|
|
24
|
-
* since only the Summarizer has the latest truth about unreferenced node tracking
|
|
25
|
-
*/
|
|
26
|
-
export declare class SweepReadyUsageError extends LoggingError implements IFluidErrorBase {
|
|
27
|
-
/** This errorType will be in temporary use (until Sweep is fully implemented) so don't add to any errorType type */
|
|
28
|
-
errorType: string;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* This class encapsulates the logic around what to do when a SweepReady object is used.
|
|
32
|
-
* There are several tactics we plan to use in Dogfood environments to aid diagnosis of these cases:
|
|
33
|
-
* - Closing the interactive container when either the interactive or summarizer client detects this kind of violation
|
|
34
|
-
* (via sweepReadyUsageDetectionSetting above)
|
|
35
|
-
* - Throttling the frequency of these crashes via a "Skip Closure Period" per container per device
|
|
36
|
-
* (via skipClosureForXDaysKey above. Uses localStorage and closuresMapLocalStorageKey to implement this behavior)
|
|
37
|
-
*/
|
|
38
|
-
export declare class SweepReadyUsageDetectionHandler {
|
|
39
|
-
private readonly uniqueContainerKey;
|
|
40
|
-
private readonly mc;
|
|
41
|
-
private readonly closeFn;
|
|
42
|
-
private readonly localStorage;
|
|
43
|
-
constructor(uniqueContainerKey: string, mc: MonitoringContext, closeFn: (error?: ICriticalContainerError) => void, localStorageOverride?: Pick<Storage, "getItem" | "setItem">);
|
|
44
|
-
/**
|
|
45
|
-
* If SweepReady Usage Detection is enabled, close the interactive container.
|
|
46
|
-
* If the SkipClosureForXDays setting is set, don't close the container more than once in that period.
|
|
47
|
-
*
|
|
48
|
-
* Once Sweep is fully implemented, this will be removed since the objects will be gone
|
|
49
|
-
* and errors will arise elsewhere in the runtime
|
|
50
|
-
*/
|
|
51
|
-
usageDetectedInInteractiveClient(errorProps: ITelemetryProperties): void;
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=gcSweepReadyUsageDetection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gcSweepReadyUsageDetection.d.ts","sourceRoot":"","sources":["../../src/gc/gcSweepReadyUsageDetection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAEN,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,MAAM,iCAAiC,CAAC;AAGzC;;;GAGG;AACH,eAAO,MAAM,sBAAsB,iFAC4C,CAAC;AAEhF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,sEAC6B,CAAC;AAqBrE;;;;;;;GAOG;AACH,qBAAa,oBAAqB,SAAQ,YAAa,YAAW,eAAe;IAChF,oHAAoH;IAC7G,SAAS,EAAE,MAAM,CAAiD;CACzE;AAED;;;;;;;GAOG;AACH,qBAAa,+BAA+B;IAI1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO;IALzB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuC;gBAGlD,kBAAkB,EAAE,MAAM,EAC1B,EAAE,EAAE,iBAAiB,EACrB,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,uBAAuB,KAAK,IAAI,EACnE,oBAAoB,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,CAAC;IAc5D;;;;;;OAMG;IACI,gCAAgC,CAAC,UAAU,EAAE,oBAAoB;CA+CxE"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { LoggingError, } from "@fluidframework/telemetry-utils";
|
|
6
|
-
import { oneDayMs } from "./gcDefinitions";
|
|
7
|
-
/**
|
|
8
|
-
* Feature Gate Key -
|
|
9
|
-
* How many days between closing the container from this error (avoids locking user out of their file altogether)
|
|
10
|
-
*/
|
|
11
|
-
export const skipClosureForXDaysKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.SkipClosureForXDays";
|
|
12
|
-
/**
|
|
13
|
-
* LocalStorage key (NOT via feature gate / monitoring context)
|
|
14
|
-
* A map from docId to info about the last time we closed due to this error
|
|
15
|
-
*/
|
|
16
|
-
export const closuresMapLocalStorageKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.Closures";
|
|
17
|
-
/**
|
|
18
|
-
* Feature gate key to enable closing the container if SweepReady objects are used.
|
|
19
|
-
* Value should contain keywords "interactiveClient" and/or "summarizer" to enable detection in each container type
|
|
20
|
-
*/
|
|
21
|
-
const sweepReadyUsageDetectionSetting = {
|
|
22
|
-
read(config) {
|
|
23
|
-
const sweepReadyUsageDetectionKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection";
|
|
24
|
-
const value = config.getString(sweepReadyUsageDetectionKey);
|
|
25
|
-
if (value === undefined) {
|
|
26
|
-
return { interactiveClient: false, summarizer: false };
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
interactiveClient: value.includes("interactiveClient"),
|
|
30
|
-
summarizer: value.includes("summarizer"),
|
|
31
|
-
};
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Error class raised when a SweepReady object is used, indicating a bug in how
|
|
36
|
-
* references are managed in the container by the application, or a bug in how
|
|
37
|
-
* GC tracks those references.
|
|
38
|
-
*
|
|
39
|
-
* There's a chance for false positives when this error is raised by an Interactive Container,
|
|
40
|
-
* since only the Summarizer has the latest truth about unreferenced node tracking
|
|
41
|
-
*/
|
|
42
|
-
export class SweepReadyUsageError extends LoggingError {
|
|
43
|
-
constructor() {
|
|
44
|
-
super(...arguments);
|
|
45
|
-
/** This errorType will be in temporary use (until Sweep is fully implemented) so don't add to any errorType type */
|
|
46
|
-
this.errorType = "unreferencedObjectUsedAfterGarbageCollected";
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* This class encapsulates the logic around what to do when a SweepReady object is used.
|
|
51
|
-
* There are several tactics we plan to use in Dogfood environments to aid diagnosis of these cases:
|
|
52
|
-
* - Closing the interactive container when either the interactive or summarizer client detects this kind of violation
|
|
53
|
-
* (via sweepReadyUsageDetectionSetting above)
|
|
54
|
-
* - Throttling the frequency of these crashes via a "Skip Closure Period" per container per device
|
|
55
|
-
* (via skipClosureForXDaysKey above. Uses localStorage and closuresMapLocalStorageKey to implement this behavior)
|
|
56
|
-
*/
|
|
57
|
-
export class SweepReadyUsageDetectionHandler {
|
|
58
|
-
constructor(uniqueContainerKey, mc, closeFn, localStorageOverride) {
|
|
59
|
-
var _a;
|
|
60
|
-
this.uniqueContainerKey = uniqueContainerKey;
|
|
61
|
-
this.mc = mc;
|
|
62
|
-
this.closeFn = closeFn;
|
|
63
|
-
const noopStorage = { getItem: () => null, setItem: () => { } };
|
|
64
|
-
// localStorage is not defined in Node environment, so fall back to noopStorage if needed.
|
|
65
|
-
this.localStorage = (_a = localStorageOverride !== null && localStorageOverride !== void 0 ? localStorageOverride : globalThis.localStorage) !== null && _a !== void 0 ? _a : noopStorage;
|
|
66
|
-
if (this.localStorage === noopStorage) {
|
|
67
|
-
// This means the Skip Closure Period logic will not work.
|
|
68
|
-
this.mc.logger.sendTelemetryEvent({
|
|
69
|
-
eventName: "SweepReadyUsageDetectionHandlerNoopStorage",
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* If SweepReady Usage Detection is enabled, close the interactive container.
|
|
75
|
-
* If the SkipClosureForXDays setting is set, don't close the container more than once in that period.
|
|
76
|
-
*
|
|
77
|
-
* Once Sweep is fully implemented, this will be removed since the objects will be gone
|
|
78
|
-
* and errors will arise elsewhere in the runtime
|
|
79
|
-
*/
|
|
80
|
-
usageDetectedInInteractiveClient(errorProps) {
|
|
81
|
-
var _a;
|
|
82
|
-
if (!sweepReadyUsageDetectionSetting.read(this.mc.config).interactiveClient) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
// Default stance is we close every time - this reflects the severity of SweepReady Object Usage.
|
|
86
|
-
// However, we may choose to "throttle" the closures by setting the SkipClosureForXDays setting,
|
|
87
|
-
// which will only allow the container to close once during that period, to avoid locking users out.
|
|
88
|
-
let shouldClose = true;
|
|
89
|
-
let pastClosuresMap = {};
|
|
90
|
-
let lastCloseTime;
|
|
91
|
-
const skipClosureForXDays = this.mc.config.getNumber(skipClosureForXDaysKey);
|
|
92
|
-
if (skipClosureForXDays !== undefined) {
|
|
93
|
-
// Read pastClosuresMap from localStorage then extract the lastCloseTime from the map
|
|
94
|
-
try {
|
|
95
|
-
const rawValue = this.localStorage.getItem(closuresMapLocalStorageKey);
|
|
96
|
-
const parsedValue = rawValue === null ? {} : JSON.parse(rawValue);
|
|
97
|
-
if (typeof parsedValue === "object") {
|
|
98
|
-
pastClosuresMap = parsedValue;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch (e) { }
|
|
102
|
-
lastCloseTime = (_a = pastClosuresMap[this.uniqueContainerKey]) === null || _a === void 0 ? void 0 : _a.lastCloseTime;
|
|
103
|
-
// Don't close if we did already within the Skip Closure Period
|
|
104
|
-
if (lastCloseTime !== undefined &&
|
|
105
|
-
Date.now() < lastCloseTime + skipClosureForXDays * oneDayMs) {
|
|
106
|
-
shouldClose = false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
const error = new SweepReadyUsageError("SweepReady object used in Non-Summarizer Client", {
|
|
110
|
-
errorDetails: JSON.stringify(Object.assign(Object.assign({}, errorProps), { lastCloseTime, skipClosureForXDays })),
|
|
111
|
-
});
|
|
112
|
-
if (shouldClose) {
|
|
113
|
-
// Update closures map in localStorage before closing
|
|
114
|
-
// Note there is a race condition between different tabs updating localStorage and overwriting
|
|
115
|
-
// each others' updates. If so, some tab will crash again. Just reload one at a time to get unstuck
|
|
116
|
-
pastClosuresMap[this.uniqueContainerKey] = { lastCloseTime: Date.now() };
|
|
117
|
-
this.localStorage.setItem(closuresMapLocalStorageKey, JSON.stringify(pastClosuresMap));
|
|
118
|
-
this.closeFn(error);
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
this.mc.logger.sendErrorEvent({ eventName: "SweepReadyObject_UsageAllowed" }, error);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=gcSweepReadyUsageDetection.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gcSweepReadyUsageDetection.js","sourceRoot":"","sources":["../../src/gc/gcSweepReadyUsageDetection.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 { ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport {\n\tIConfigProvider,\n\tIFluidErrorBase,\n\tLoggingError,\n\tMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { oneDayMs } from \"./gcDefinitions\";\n\n/**\n * Feature Gate Key -\n * How many days between closing the container from this error (avoids locking user out of their file altogether)\n */\nexport const skipClosureForXDaysKey =\n\t\"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.SkipClosureForXDays\";\n\n/**\n * LocalStorage key (NOT via feature gate / monitoring context)\n * A map from docId to info about the last time we closed due to this error\n */\nexport const closuresMapLocalStorageKey =\n\t\"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.Closures\";\n\n/**\n * Feature gate key to enable closing the container if SweepReady objects are used.\n * Value should contain keywords \"interactiveClient\" and/or \"summarizer\" to enable detection in each container type\n */\nconst sweepReadyUsageDetectionSetting = {\n\tread(config: IConfigProvider) {\n\t\tconst sweepReadyUsageDetectionKey =\n\t\t\t\"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection\";\n\t\tconst value = config.getString(sweepReadyUsageDetectionKey);\n\t\tif (value === undefined) {\n\t\t\treturn { interactiveClient: false, summarizer: false };\n\t\t}\n\t\treturn {\n\t\t\tinteractiveClient: value.includes(\"interactiveClient\"),\n\t\t\tsummarizer: value.includes(\"summarizer\"),\n\t\t};\n\t},\n};\n\n/**\n * Error class raised when a SweepReady object is used, indicating a bug in how\n * references are managed in the container by the application, or a bug in how\n * GC tracks those references.\n *\n * There's a chance for false positives when this error is raised by an Interactive Container,\n * since only the Summarizer has the latest truth about unreferenced node tracking\n */\nexport class SweepReadyUsageError extends LoggingError implements IFluidErrorBase {\n\t/** This errorType will be in temporary use (until Sweep is fully implemented) so don't add to any errorType type */\n\tpublic errorType: string = \"unreferencedObjectUsedAfterGarbageCollected\";\n}\n\n/**\n * This class encapsulates the logic around what to do when a SweepReady object is used.\n * There are several tactics we plan to use in Dogfood environments to aid diagnosis of these cases:\n * - Closing the interactive container when either the interactive or summarizer client detects this kind of violation\n * (via sweepReadyUsageDetectionSetting above)\n * - Throttling the frequency of these crashes via a \"Skip Closure Period\" per container per device\n * (via skipClosureForXDaysKey above. Uses localStorage and closuresMapLocalStorageKey to implement this behavior)\n */\nexport class SweepReadyUsageDetectionHandler {\n\tprivate readonly localStorage: Pick<Storage, \"getItem\" | \"setItem\">;\n\n\tconstructor(\n\t\tprivate readonly uniqueContainerKey: string,\n\t\tprivate readonly mc: MonitoringContext,\n\t\tprivate readonly closeFn: (error?: ICriticalContainerError) => void,\n\t\tlocalStorageOverride?: Pick<Storage, \"getItem\" | \"setItem\">,\n\t) {\n\t\tconst noopStorage = { getItem: () => null, setItem: () => {} };\n\t\t// localStorage is not defined in Node environment, so fall back to noopStorage if needed.\n\t\tthis.localStorage = localStorageOverride ?? globalThis.localStorage ?? noopStorage;\n\n\t\tif (this.localStorage === noopStorage) {\n\t\t\t// This means the Skip Closure Period logic will not work.\n\t\t\tthis.mc.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"SweepReadyUsageDetectionHandlerNoopStorage\",\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * If SweepReady Usage Detection is enabled, close the interactive container.\n\t * If the SkipClosureForXDays setting is set, don't close the container more than once in that period.\n\t *\n\t * Once Sweep is fully implemented, this will be removed since the objects will be gone\n\t * and errors will arise elsewhere in the runtime\n\t */\n\tpublic usageDetectedInInteractiveClient(errorProps: ITelemetryProperties) {\n\t\tif (!sweepReadyUsageDetectionSetting.read(this.mc.config).interactiveClient) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Default stance is we close every time - this reflects the severity of SweepReady Object Usage.\n\t\t// However, we may choose to \"throttle\" the closures by setting the SkipClosureForXDays setting,\n\t\t// which will only allow the container to close once during that period, to avoid locking users out.\n\t\tlet shouldClose: boolean = true;\n\t\tlet pastClosuresMap: Record<string, { lastCloseTime: number } | undefined> = {};\n\t\tlet lastCloseTime: number | undefined;\n\t\tconst skipClosureForXDays = this.mc.config.getNumber(skipClosureForXDaysKey);\n\t\tif (skipClosureForXDays !== undefined) {\n\t\t\t// Read pastClosuresMap from localStorage then extract the lastCloseTime from the map\n\t\t\ttry {\n\t\t\t\tconst rawValue = this.localStorage.getItem(closuresMapLocalStorageKey);\n\t\t\t\tconst parsedValue = rawValue === null ? {} : JSON.parse(rawValue);\n\t\t\t\tif (typeof parsedValue === \"object\") {\n\t\t\t\t\tpastClosuresMap = parsedValue;\n\t\t\t\t}\n\t\t\t} catch (e) {}\n\t\t\tlastCloseTime = pastClosuresMap[this.uniqueContainerKey]?.lastCloseTime;\n\n\t\t\t// Don't close if we did already within the Skip Closure Period\n\t\t\tif (\n\t\t\t\tlastCloseTime !== undefined &&\n\t\t\t\tDate.now() < lastCloseTime + skipClosureForXDays * oneDayMs\n\t\t\t) {\n\t\t\t\tshouldClose = false;\n\t\t\t}\n\t\t}\n\n\t\tconst error = new SweepReadyUsageError(\"SweepReady object used in Non-Summarizer Client\", {\n\t\t\terrorDetails: JSON.stringify({ ...errorProps, lastCloseTime, skipClosureForXDays }),\n\t\t});\n\t\tif (shouldClose) {\n\t\t\t// Update closures map in localStorage before closing\n\t\t\t// Note there is a race condition between different tabs updating localStorage and overwriting\n\t\t\t// each others' updates. If so, some tab will crash again. Just reload one at a time to get unstuck\n\t\t\tpastClosuresMap[this.uniqueContainerKey] = { lastCloseTime: Date.now() };\n\t\t\tthis.localStorage.setItem(closuresMapLocalStorageKey, JSON.stringify(pastClosuresMap));\n\n\t\t\tthis.closeFn(error);\n\t\t} else {\n\t\t\tthis.mc.logger.sendErrorEvent({ eventName: \"SweepReadyObject_UsageAllowed\" }, error);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ITelemetryProperties } from "@fluidframework/common-definitions";
|
|
7
|
-
import { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
8
|
-
import {
|
|
9
|
-
IConfigProvider,
|
|
10
|
-
IFluidErrorBase,
|
|
11
|
-
LoggingError,
|
|
12
|
-
MonitoringContext,
|
|
13
|
-
} from "@fluidframework/telemetry-utils";
|
|
14
|
-
import { oneDayMs } from "./gcDefinitions";
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Feature Gate Key -
|
|
18
|
-
* How many days between closing the container from this error (avoids locking user out of their file altogether)
|
|
19
|
-
*/
|
|
20
|
-
export const skipClosureForXDaysKey =
|
|
21
|
-
"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.SkipClosureForXDays";
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* LocalStorage key (NOT via feature gate / monitoring context)
|
|
25
|
-
* A map from docId to info about the last time we closed due to this error
|
|
26
|
-
*/
|
|
27
|
-
export const closuresMapLocalStorageKey =
|
|
28
|
-
"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.Closures";
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Feature gate key to enable closing the container if SweepReady objects are used.
|
|
32
|
-
* Value should contain keywords "interactiveClient" and/or "summarizer" to enable detection in each container type
|
|
33
|
-
*/
|
|
34
|
-
const sweepReadyUsageDetectionSetting = {
|
|
35
|
-
read(config: IConfigProvider) {
|
|
36
|
-
const sweepReadyUsageDetectionKey =
|
|
37
|
-
"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection";
|
|
38
|
-
const value = config.getString(sweepReadyUsageDetectionKey);
|
|
39
|
-
if (value === undefined) {
|
|
40
|
-
return { interactiveClient: false, summarizer: false };
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
interactiveClient: value.includes("interactiveClient"),
|
|
44
|
-
summarizer: value.includes("summarizer"),
|
|
45
|
-
};
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Error class raised when a SweepReady object is used, indicating a bug in how
|
|
51
|
-
* references are managed in the container by the application, or a bug in how
|
|
52
|
-
* GC tracks those references.
|
|
53
|
-
*
|
|
54
|
-
* There's a chance for false positives when this error is raised by an Interactive Container,
|
|
55
|
-
* since only the Summarizer has the latest truth about unreferenced node tracking
|
|
56
|
-
*/
|
|
57
|
-
export class SweepReadyUsageError extends LoggingError implements IFluidErrorBase {
|
|
58
|
-
/** This errorType will be in temporary use (until Sweep is fully implemented) so don't add to any errorType type */
|
|
59
|
-
public errorType: string = "unreferencedObjectUsedAfterGarbageCollected";
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* This class encapsulates the logic around what to do when a SweepReady object is used.
|
|
64
|
-
* There are several tactics we plan to use in Dogfood environments to aid diagnosis of these cases:
|
|
65
|
-
* - Closing the interactive container when either the interactive or summarizer client detects this kind of violation
|
|
66
|
-
* (via sweepReadyUsageDetectionSetting above)
|
|
67
|
-
* - Throttling the frequency of these crashes via a "Skip Closure Period" per container per device
|
|
68
|
-
* (via skipClosureForXDaysKey above. Uses localStorage and closuresMapLocalStorageKey to implement this behavior)
|
|
69
|
-
*/
|
|
70
|
-
export class SweepReadyUsageDetectionHandler {
|
|
71
|
-
private readonly localStorage: Pick<Storage, "getItem" | "setItem">;
|
|
72
|
-
|
|
73
|
-
constructor(
|
|
74
|
-
private readonly uniqueContainerKey: string,
|
|
75
|
-
private readonly mc: MonitoringContext,
|
|
76
|
-
private readonly closeFn: (error?: ICriticalContainerError) => void,
|
|
77
|
-
localStorageOverride?: Pick<Storage, "getItem" | "setItem">,
|
|
78
|
-
) {
|
|
79
|
-
const noopStorage = { getItem: () => null, setItem: () => {} };
|
|
80
|
-
// localStorage is not defined in Node environment, so fall back to noopStorage if needed.
|
|
81
|
-
this.localStorage = localStorageOverride ?? globalThis.localStorage ?? noopStorage;
|
|
82
|
-
|
|
83
|
-
if (this.localStorage === noopStorage) {
|
|
84
|
-
// This means the Skip Closure Period logic will not work.
|
|
85
|
-
this.mc.logger.sendTelemetryEvent({
|
|
86
|
-
eventName: "SweepReadyUsageDetectionHandlerNoopStorage",
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* If SweepReady Usage Detection is enabled, close the interactive container.
|
|
93
|
-
* If the SkipClosureForXDays setting is set, don't close the container more than once in that period.
|
|
94
|
-
*
|
|
95
|
-
* Once Sweep is fully implemented, this will be removed since the objects will be gone
|
|
96
|
-
* and errors will arise elsewhere in the runtime
|
|
97
|
-
*/
|
|
98
|
-
public usageDetectedInInteractiveClient(errorProps: ITelemetryProperties) {
|
|
99
|
-
if (!sweepReadyUsageDetectionSetting.read(this.mc.config).interactiveClient) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Default stance is we close every time - this reflects the severity of SweepReady Object Usage.
|
|
104
|
-
// However, we may choose to "throttle" the closures by setting the SkipClosureForXDays setting,
|
|
105
|
-
// which will only allow the container to close once during that period, to avoid locking users out.
|
|
106
|
-
let shouldClose: boolean = true;
|
|
107
|
-
let pastClosuresMap: Record<string, { lastCloseTime: number } | undefined> = {};
|
|
108
|
-
let lastCloseTime: number | undefined;
|
|
109
|
-
const skipClosureForXDays = this.mc.config.getNumber(skipClosureForXDaysKey);
|
|
110
|
-
if (skipClosureForXDays !== undefined) {
|
|
111
|
-
// Read pastClosuresMap from localStorage then extract the lastCloseTime from the map
|
|
112
|
-
try {
|
|
113
|
-
const rawValue = this.localStorage.getItem(closuresMapLocalStorageKey);
|
|
114
|
-
const parsedValue = rawValue === null ? {} : JSON.parse(rawValue);
|
|
115
|
-
if (typeof parsedValue === "object") {
|
|
116
|
-
pastClosuresMap = parsedValue;
|
|
117
|
-
}
|
|
118
|
-
} catch (e) {}
|
|
119
|
-
lastCloseTime = pastClosuresMap[this.uniqueContainerKey]?.lastCloseTime;
|
|
120
|
-
|
|
121
|
-
// Don't close if we did already within the Skip Closure Period
|
|
122
|
-
if (
|
|
123
|
-
lastCloseTime !== undefined &&
|
|
124
|
-
Date.now() < lastCloseTime + skipClosureForXDays * oneDayMs
|
|
125
|
-
) {
|
|
126
|
-
shouldClose = false;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const error = new SweepReadyUsageError("SweepReady object used in Non-Summarizer Client", {
|
|
131
|
-
errorDetails: JSON.stringify({ ...errorProps, lastCloseTime, skipClosureForXDays }),
|
|
132
|
-
});
|
|
133
|
-
if (shouldClose) {
|
|
134
|
-
// Update closures map in localStorage before closing
|
|
135
|
-
// Note there is a race condition between different tabs updating localStorage and overwriting
|
|
136
|
-
// each others' updates. If so, some tab will crash again. Just reload one at a time to get unstuck
|
|
137
|
-
pastClosuresMap[this.uniqueContainerKey] = { lastCloseTime: Date.now() };
|
|
138
|
-
this.localStorage.setItem(closuresMapLocalStorageKey, JSON.stringify(pastClosuresMap));
|
|
139
|
-
|
|
140
|
-
this.closeFn(error);
|
|
141
|
-
} else {
|
|
142
|
-
this.mc.logger.sendErrorEvent({ eventName: "SweepReadyObject_UsageAllowed" }, error);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|