@fluidframework/container-runtime 2.0.0-internal.4.3.0 → 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.
Files changed (103) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager.js +3 -2
  4. package/dist/blobManager.js.map +1 -1
  5. package/dist/containerRuntime.d.ts.map +1 -1
  6. package/dist/containerRuntime.js +13 -7
  7. package/dist/containerRuntime.js.map +1 -1
  8. package/dist/dataStoreContext.d.ts.map +1 -1
  9. package/dist/dataStoreContext.js +1 -2
  10. package/dist/dataStoreContext.js.map +1 -1
  11. package/dist/gc/garbageCollection.d.ts +55 -43
  12. package/dist/gc/garbageCollection.d.ts.map +1 -1
  13. package/dist/gc/garbageCollection.js +219 -203
  14. package/dist/gc/garbageCollection.js.map +1 -1
  15. package/dist/gc/gcConfigs.d.ts.map +1 -1
  16. package/dist/gc/gcConfigs.js +8 -10
  17. package/dist/gc/gcConfigs.js.map +1 -1
  18. package/dist/gc/gcDefinitions.d.ts +2 -0
  19. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  20. package/dist/gc/gcDefinitions.js.map +1 -1
  21. package/dist/gc/gcHelpers.d.ts +11 -1
  22. package/dist/gc/gcHelpers.d.ts.map +1 -1
  23. package/dist/gc/gcHelpers.js +18 -3
  24. package/dist/gc/gcHelpers.js.map +1 -1
  25. package/dist/gc/gcSummaryStateTracker.d.ts +6 -2
  26. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  27. package/dist/gc/gcSummaryStateTracker.js +16 -6
  28. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  29. package/dist/gc/gcTelemetry.d.ts +2 -2
  30. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  31. package/dist/gc/gcTelemetry.js +42 -22
  32. package/dist/gc/gcTelemetry.js.map +1 -1
  33. package/dist/gc/index.d.ts +1 -2
  34. package/dist/gc/index.d.ts.map +1 -1
  35. package/dist/gc/index.js +2 -5
  36. package/dist/gc/index.js.map +1 -1
  37. package/dist/packageVersion.d.ts +1 -1
  38. package/dist/packageVersion.js +1 -1
  39. package/dist/packageVersion.js.map +1 -1
  40. package/dist/scheduleManager.js +15 -4
  41. package/dist/scheduleManager.js.map +1 -1
  42. package/lib/blobManager.d.ts.map +1 -1
  43. package/lib/blobManager.js +3 -2
  44. package/lib/blobManager.js.map +1 -1
  45. package/lib/containerRuntime.d.ts.map +1 -1
  46. package/lib/containerRuntime.js +13 -7
  47. package/lib/containerRuntime.js.map +1 -1
  48. package/lib/dataStoreContext.d.ts.map +1 -1
  49. package/lib/dataStoreContext.js +1 -2
  50. package/lib/dataStoreContext.js.map +1 -1
  51. package/lib/gc/garbageCollection.d.ts +55 -43
  52. package/lib/gc/garbageCollection.d.ts.map +1 -1
  53. package/lib/gc/garbageCollection.js +219 -203
  54. package/lib/gc/garbageCollection.js.map +1 -1
  55. package/lib/gc/gcConfigs.d.ts.map +1 -1
  56. package/lib/gc/gcConfigs.js +8 -10
  57. package/lib/gc/gcConfigs.js.map +1 -1
  58. package/lib/gc/gcDefinitions.d.ts +2 -0
  59. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  60. package/lib/gc/gcDefinitions.js.map +1 -1
  61. package/lib/gc/gcHelpers.d.ts +11 -1
  62. package/lib/gc/gcHelpers.d.ts.map +1 -1
  63. package/lib/gc/gcHelpers.js +16 -2
  64. package/lib/gc/gcHelpers.js.map +1 -1
  65. package/lib/gc/gcSummaryStateTracker.d.ts +6 -2
  66. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  67. package/lib/gc/gcSummaryStateTracker.js +16 -6
  68. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  69. package/lib/gc/gcTelemetry.d.ts +2 -2
  70. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  71. package/lib/gc/gcTelemetry.js +43 -23
  72. package/lib/gc/gcTelemetry.js.map +1 -1
  73. package/lib/gc/index.d.ts +1 -2
  74. package/lib/gc/index.d.ts.map +1 -1
  75. package/lib/gc/index.js +1 -2
  76. package/lib/gc/index.js.map +1 -1
  77. package/lib/packageVersion.d.ts +1 -1
  78. package/lib/packageVersion.js +1 -1
  79. package/lib/packageVersion.js.map +1 -1
  80. package/lib/scheduleManager.js +15 -4
  81. package/lib/scheduleManager.js.map +1 -1
  82. package/package.json +15 -16
  83. package/src/blobManager.ts +3 -2
  84. package/src/containerRuntime.ts +10 -4
  85. package/src/dataStoreContext.ts +1 -2
  86. package/src/gc/garbageCollection.ts +274 -257
  87. package/src/gc/gcConfigs.ts +12 -11
  88. package/src/gc/gcDefinitions.ts +2 -0
  89. package/src/gc/gcHelpers.ts +20 -2
  90. package/src/gc/gcSummaryStateTracker.ts +19 -7
  91. package/src/gc/gcTelemetry.ts +52 -37
  92. package/src/gc/index.ts +1 -5
  93. package/src/packageVersion.ts +1 -1
  94. package/src/scheduleManager.ts +19 -7
  95. package/dist/gc/gcSweepReadyUsageDetection.d.ts +0 -53
  96. package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +0 -1
  97. package/dist/gc/gcSweepReadyUsageDetection.js +0 -130
  98. package/dist/gc/gcSweepReadyUsageDetection.js.map +0 -1
  99. package/lib/gc/gcSweepReadyUsageDetection.d.ts +0 -53
  100. package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +0 -1
  101. package/lib/gc/gcSweepReadyUsageDetection.js +0 -125
  102. package/lib/gc/gcSweepReadyUsageDetection.js.map +0 -1
  103. 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
- }