@fluidframework/container-runtime 2.0.0-internal.1.1.2 → 2.0.0-internal.1.2.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 (137) hide show
  1. package/dist/batchManager.d.ts +37 -0
  2. package/dist/batchManager.d.ts.map +1 -0
  3. package/dist/batchManager.js +73 -0
  4. package/dist/batchManager.js.map +1 -0
  5. package/dist/batchTracker.d.ts +1 -2
  6. package/dist/batchTracker.d.ts.map +1 -1
  7. package/dist/batchTracker.js +1 -2
  8. package/dist/batchTracker.js.map +1 -1
  9. package/dist/containerRuntime.d.ts +52 -20
  10. package/dist/containerRuntime.d.ts.map +1 -1
  11. package/dist/containerRuntime.js +252 -126
  12. package/dist/containerRuntime.js.map +1 -1
  13. package/dist/dataStoreContext.d.ts +18 -9
  14. package/dist/dataStoreContext.d.ts.map +1 -1
  15. package/dist/dataStoreContext.js +24 -16
  16. package/dist/dataStoreContext.js.map +1 -1
  17. package/dist/dataStores.d.ts +6 -2
  18. package/dist/dataStores.d.ts.map +1 -1
  19. package/dist/dataStores.js +7 -9
  20. package/dist/dataStores.js.map +1 -1
  21. package/dist/deltaScheduler.d.ts +6 -4
  22. package/dist/deltaScheduler.d.ts.map +1 -1
  23. package/dist/deltaScheduler.js +6 -4
  24. package/dist/deltaScheduler.js.map +1 -1
  25. package/dist/garbageCollection.d.ts +41 -12
  26. package/dist/garbageCollection.d.ts.map +1 -1
  27. package/dist/garbageCollection.js +176 -98
  28. package/dist/garbageCollection.js.map +1 -1
  29. package/dist/gcSweepReadyUsageDetection.d.ts +53 -0
  30. package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -0
  31. package/dist/gcSweepReadyUsageDetection.js +135 -0
  32. package/dist/gcSweepReadyUsageDetection.js.map +1 -0
  33. package/dist/orderedClientElection.d.ts +28 -10
  34. package/dist/orderedClientElection.d.ts.map +1 -1
  35. package/dist/orderedClientElection.js +14 -4
  36. package/dist/orderedClientElection.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/pendingStateManager.d.ts +0 -11
  41. package/dist/pendingStateManager.d.ts.map +1 -1
  42. package/dist/pendingStateManager.js +9 -44
  43. package/dist/pendingStateManager.js.map +1 -1
  44. package/dist/runningSummarizer.js +1 -1
  45. package/dist/runningSummarizer.js.map +1 -1
  46. package/dist/scheduleManager.d.ts +6 -3
  47. package/dist/scheduleManager.d.ts.map +1 -1
  48. package/dist/scheduleManager.js +22 -14
  49. package/dist/scheduleManager.js.map +1 -1
  50. package/dist/summarizerTypes.d.ts +16 -9
  51. package/dist/summarizerTypes.d.ts.map +1 -1
  52. package/dist/summarizerTypes.js +1 -1
  53. package/dist/summarizerTypes.js.map +1 -1
  54. package/dist/summaryCollection.d.ts +1 -0
  55. package/dist/summaryCollection.d.ts.map +1 -1
  56. package/dist/summaryCollection.js +29 -13
  57. package/dist/summaryCollection.js.map +1 -1
  58. package/dist/summaryManager.d.ts +2 -2
  59. package/dist/summaryManager.js +2 -2
  60. package/dist/summaryManager.js.map +1 -1
  61. package/lib/batchManager.d.ts +37 -0
  62. package/lib/batchManager.d.ts.map +1 -0
  63. package/lib/batchManager.js +69 -0
  64. package/lib/batchManager.js.map +1 -0
  65. package/lib/batchTracker.d.ts +1 -2
  66. package/lib/batchTracker.d.ts.map +1 -1
  67. package/lib/batchTracker.js +1 -2
  68. package/lib/batchTracker.js.map +1 -1
  69. package/lib/containerRuntime.d.ts +52 -20
  70. package/lib/containerRuntime.d.ts.map +1 -1
  71. package/lib/containerRuntime.js +255 -129
  72. package/lib/containerRuntime.js.map +1 -1
  73. package/lib/dataStoreContext.d.ts +18 -9
  74. package/lib/dataStoreContext.d.ts.map +1 -1
  75. package/lib/dataStoreContext.js +25 -17
  76. package/lib/dataStoreContext.js.map +1 -1
  77. package/lib/dataStores.d.ts +6 -2
  78. package/lib/dataStores.d.ts.map +1 -1
  79. package/lib/dataStores.js +7 -9
  80. package/lib/dataStores.js.map +1 -1
  81. package/lib/deltaScheduler.d.ts +6 -4
  82. package/lib/deltaScheduler.d.ts.map +1 -1
  83. package/lib/deltaScheduler.js +6 -4
  84. package/lib/deltaScheduler.js.map +1 -1
  85. package/lib/garbageCollection.d.ts +41 -12
  86. package/lib/garbageCollection.d.ts.map +1 -1
  87. package/lib/garbageCollection.js +175 -97
  88. package/lib/garbageCollection.js.map +1 -1
  89. package/lib/gcSweepReadyUsageDetection.d.ts +53 -0
  90. package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -0
  91. package/lib/gcSweepReadyUsageDetection.js +130 -0
  92. package/lib/gcSweepReadyUsageDetection.js.map +1 -0
  93. package/lib/orderedClientElection.d.ts +28 -10
  94. package/lib/orderedClientElection.d.ts.map +1 -1
  95. package/lib/orderedClientElection.js +14 -4
  96. package/lib/orderedClientElection.js.map +1 -1
  97. package/lib/packageVersion.d.ts +1 -1
  98. package/lib/packageVersion.js +1 -1
  99. package/lib/packageVersion.js.map +1 -1
  100. package/lib/pendingStateManager.d.ts +0 -11
  101. package/lib/pendingStateManager.d.ts.map +1 -1
  102. package/lib/pendingStateManager.js +9 -44
  103. package/lib/pendingStateManager.js.map +1 -1
  104. package/lib/runningSummarizer.js +1 -1
  105. package/lib/runningSummarizer.js.map +1 -1
  106. package/lib/scheduleManager.d.ts +6 -3
  107. package/lib/scheduleManager.d.ts.map +1 -1
  108. package/lib/scheduleManager.js +24 -16
  109. package/lib/scheduleManager.js.map +1 -1
  110. package/lib/summarizerTypes.d.ts +16 -9
  111. package/lib/summarizerTypes.d.ts.map +1 -1
  112. package/lib/summarizerTypes.js +1 -1
  113. package/lib/summarizerTypes.js.map +1 -1
  114. package/lib/summaryCollection.d.ts +1 -0
  115. package/lib/summaryCollection.d.ts.map +1 -1
  116. package/lib/summaryCollection.js +29 -13
  117. package/lib/summaryCollection.js.map +1 -1
  118. package/lib/summaryManager.d.ts +2 -2
  119. package/lib/summaryManager.js +2 -2
  120. package/lib/summaryManager.js.map +1 -1
  121. package/package.json +21 -18
  122. package/src/batchManager.ts +91 -0
  123. package/src/batchTracker.ts +1 -2
  124. package/src/containerRuntime.ts +331 -176
  125. package/src/dataStoreContext.ts +27 -17
  126. package/src/dataStores.ts +7 -8
  127. package/src/deltaScheduler.ts +6 -4
  128. package/src/garbageCollection.ts +224 -134
  129. package/src/gcSweepReadyUsageDetection.ts +147 -0
  130. package/src/orderedClientElection.ts +31 -10
  131. package/src/packageVersion.ts +1 -1
  132. package/src/pendingStateManager.ts +9 -57
  133. package/src/runningSummarizer.ts +1 -1
  134. package/src/scheduleManager.ts +32 -12
  135. package/src/summarizerTypes.ts +17 -9
  136. package/src/summaryCollection.ts +31 -16
  137. package/src/summaryManager.ts +2 -2
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ /*!
3
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
+ * Licensed under the MIT License.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SweepReadyUsageDetectionHandler = exports.SweepReadyUsageError = exports.closuresMapLocalStorageKey = exports.skipClosureForXDaysKey = void 0;
8
+ const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
9
+ const garbageCollection_1 = require("./garbageCollection");
10
+ /**
11
+ * Feature Gate Key -
12
+ * How many days between closing the container from this error (avoids locking user out of their file altogether)
13
+ */
14
+ exports.skipClosureForXDaysKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.SkipClosureForXDays";
15
+ /**
16
+ * LocalStorage key (NOT via feature gate / monitoring context)
17
+ * A map from docId to info about the last time we closed due to this error
18
+ */
19
+ exports.closuresMapLocalStorageKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.Closures";
20
+ /**
21
+ * Feature gate key to enable closing the container if SweepReady objects are used.
22
+ * Value should contain keywords "interactiveClient" and/or "summarizer" to enable detection in each container type
23
+ */
24
+ const sweepReadyUsageDetectionSetting = {
25
+ read(config) {
26
+ const sweepReadyUsageDetectionKey = "Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection";
27
+ const value = config.getString(sweepReadyUsageDetectionKey);
28
+ if (value === undefined) {
29
+ return { interactiveClient: false, summarizer: false };
30
+ }
31
+ return {
32
+ interactiveClient: value.includes("interactiveClient"),
33
+ summarizer: value.includes("summarizer"),
34
+ };
35
+ },
36
+ };
37
+ /**
38
+ * Error class raised when a SweepReady object is used, indicating a bug in how
39
+ * references are managed in the container by the application, or a bug in how
40
+ * GC tracks those references.
41
+ *
42
+ * There's a chance for false positives when this error is raised by an Interactive Container,
43
+ * since only the Summarizer has the latest truth about unreferenced node tracking
44
+ */
45
+ class SweepReadyUsageError extends telemetry_utils_1.LoggingError {
46
+ constructor() {
47
+ super(...arguments);
48
+ /** This errorType will be in temporary use (until Sweep is fully implemented) so don't add to any errorType type */
49
+ this.errorType = "unreferencedObjectUsedAfterGarbageCollected";
50
+ }
51
+ }
52
+ exports.SweepReadyUsageError = SweepReadyUsageError;
53
+ /**
54
+ * This class encapsulates the logic around what to do when a SweepReady object is used.
55
+ * There are several tactics we plan to use in Dogfood environments to aid diagnosis of these cases:
56
+ * - Closing the interactive container when either the interactive or summarizer client detects this kind of violation
57
+ * (via sweepReadyUsageDetectionSetting above)
58
+ * - Throttling the frequency of these crashes via a "Skip Closure Period" per container per device
59
+ * (via skipClosureForXDaysKey above. Uses localStorage and closuresMapLocalStorageKey to implement this behavior)
60
+ */
61
+ class SweepReadyUsageDetectionHandler {
62
+ constructor(uniqueContainerKey, mc, closeFn, localStorageOverride) {
63
+ this.uniqueContainerKey = uniqueContainerKey;
64
+ this.mc = mc;
65
+ this.closeFn = closeFn;
66
+ const noopStorage = { getItem: () => null, setItem: () => { } };
67
+ if (localStorageOverride !== undefined) {
68
+ this.localStorage = localStorageOverride;
69
+ }
70
+ else {
71
+ try {
72
+ // localStorage is not defined in Node environment so this throws
73
+ this.localStorage = localStorage !== null && localStorage !== void 0 ? localStorage : noopStorage;
74
+ }
75
+ catch (error) {
76
+ this.localStorage = noopStorage;
77
+ }
78
+ }
79
+ if (this.localStorage === noopStorage) {
80
+ // This means the Skip Closure Period logic will not work.
81
+ this.mc.logger.sendTelemetryEvent({ eventName: "SweepReadyUsageDetectionHandlerNoopStorage" });
82
+ }
83
+ }
84
+ /**
85
+ * If SweepReady Usage Detection is enabled, close the interactive container.
86
+ * If the SkipClosureForXDays setting is set, don't close the container more than once in that period.
87
+ *
88
+ * Once Sweep is fully implemented, this will be removed since the objects will be gone
89
+ * and errors will arise elsewhere in the runtime
90
+ */
91
+ usageDetectedInInteractiveClient(errorProps) {
92
+ var _a;
93
+ if (!sweepReadyUsageDetectionSetting.read(this.mc.config).interactiveClient) {
94
+ return;
95
+ }
96
+ // Default stance is we close every time - this reflects the severity of SweepReady Object Usage.
97
+ // However, we may choose to "throttle" the closures by setting the SkipClosureForXDays setting,
98
+ // which will only allow the container to close once during that period, to avoid locking users out.
99
+ let shouldClose = true;
100
+ let pastClosuresMap = {};
101
+ let lastCloseTime;
102
+ const skipClosureForXDays = this.mc.config.getNumber(exports.skipClosureForXDaysKey);
103
+ if (skipClosureForXDays !== undefined) {
104
+ // Read pastClosuresMap from localStorage then extract the lastCloseTime from the map
105
+ try {
106
+ const rawValue = this.localStorage.getItem(exports.closuresMapLocalStorageKey);
107
+ const parsedValue = rawValue === null ? {} : JSON.parse(rawValue);
108
+ if (typeof parsedValue === "object") {
109
+ pastClosuresMap = parsedValue;
110
+ }
111
+ }
112
+ catch (e) {
113
+ }
114
+ lastCloseTime = (_a = pastClosuresMap[this.uniqueContainerKey]) === null || _a === void 0 ? void 0 : _a.lastCloseTime;
115
+ // Don't close if we did already within the Skip Closure Period
116
+ if (lastCloseTime !== undefined && Date.now() < lastCloseTime + skipClosureForXDays * garbageCollection_1.oneDayMs) {
117
+ shouldClose = false;
118
+ }
119
+ }
120
+ const error = new SweepReadyUsageError("SweepReady object used in Non-Summarizer Client", { errorDetails: JSON.stringify(Object.assign(Object.assign({}, errorProps), { lastCloseTime, skipClosureForXDays })) });
121
+ if (shouldClose) {
122
+ // Update closures map in localStorage before closing
123
+ // Note there is a race condition between different tabs updating localStorage and overwriting
124
+ // each others' updates. If so, some tab will crash again. Just reload one at a time to get unstuck
125
+ pastClosuresMap[this.uniqueContainerKey] = { lastCloseTime: Date.now() };
126
+ this.localStorage.setItem(exports.closuresMapLocalStorageKey, JSON.stringify(pastClosuresMap));
127
+ this.closeFn(error);
128
+ }
129
+ else {
130
+ this.mc.logger.sendErrorEvent({ eventName: "SweepReadyObject_UsageAllowed" }, error);
131
+ }
132
+ }
133
+ }
134
+ exports.SweepReadyUsageDetectionHandler = SweepReadyUsageDetectionHandler;
135
+ //# sourceMappingURL=gcSweepReadyUsageDetection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcSweepReadyUsageDetection.js","sourceRoot":"","sources":["../src/gcSweepReadyUsageDetection.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,qEAKyC;AACzC,2DAA+C;AAE/C;;;GAGG;AACU,QAAA,sBAAsB,GAAG,8EAA8E,CAAC;AAErH;;;GAGG;AACU,QAAA,0BAA0B,GAAG,mEAAmE,CAAC;AAE9G;;;GAGG;AACH,MAAM,+BAA+B,GAAG;IACpC,IAAI,CAAC,MAAuB;QACxB,MAAM,2BAA2B,GAAG,0DAA0D,CAAC;QAC/F,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;QAC5D,IAAI,KAAK,KAAK,SAAS,EAAE;YACrB,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;SAC1D;QACD,OAAO;YACH,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACtD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;SAC3C,CAAC;IACN,CAAC;CACJ,CAAC;AAEF;;;;;;;GAOG;AACH,MAAa,oBAAqB,SAAQ,8BAAY;IAAtD;;QACI,oHAAoH;QAC7G,cAAS,GAAW,6CAA6C,CAAC;IAC7E,CAAC;CAAA;AAHD,oDAGC;AAED;;;;;;;GAOG;AACH,MAAa,+BAA+B;IAGxC,YACqB,kBAA0B,EAC1B,EAAqB,EACrB,OAAkD,EACnE,oBAA2D;QAH1C,uBAAkB,GAAlB,kBAAkB,CAAQ;QAC1B,OAAE,GAAF,EAAE,CAAmB;QACrB,YAAO,GAAP,OAAO,CAA2C;QAGnE,MAAM,WAAW,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;QAC/D,IAAI,oBAAoB,KAAK,SAAS,EAAE;YACpC,IAAI,CAAC,YAAY,GAAG,oBAAoB,CAAC;SAC5C;aAAM;YACH,IAAI;gBACA,iEAAiE;gBACjE,IAAI,CAAC,YAAY,GAAG,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,WAAW,CAAC;aACnD;YAAC,OAAO,KAAK,EAAE;gBACZ,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;aACnC;SACJ;QAED,IAAI,IAAI,CAAC,YAAY,KAAK,WAAW,EAAE;YACnC,0DAA0D;YAC1D,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,4CAA4C,EAAE,CAAC,CAAC;SAClG;IACL,CAAC;IAED;;;;;;OAMG;IACI,gCAAgC,CAAC,UAAgC;;QACpE,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,iBAAiB,EAAE;YACzE,OAAO;SACV;QAED,iGAAiG;QACjG,gGAAgG;QAChG,oGAAoG;QACpG,IAAI,WAAW,GAAY,IAAI,CAAC;QAChC,IAAI,eAAe,GAA2D,EAAE,CAAC;QACjF,IAAI,aAAiC,CAAC;QACtC,MAAM,mBAAmB,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,8BAAsB,CAAC,CAAC;QAC7E,IAAI,mBAAmB,KAAK,SAAS,EAAE;YACnC,qFAAqF;YACrF,IAAI;gBACA,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,kCAA0B,CAAC,CAAC;gBACvE,MAAM,WAAW,GAAG,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAClE,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE;oBACjC,eAAe,GAAG,WAAW,CAAC;iBACjC;aACJ;YAAC,OAAO,CAAC,EAAE;aACX;YACD,aAAa,GAAG,MAAA,eAAe,CAAC,IAAI,CAAC,kBAAkB,CAAC,0CAAE,aAAa,CAAC;YAExE,+DAA+D;YAC/D,IAAI,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,GAAG,mBAAmB,GAAG,4BAAQ,EAAE;gBAC5F,WAAW,GAAG,KAAK,CAAC;aACvB;SACJ;QAED,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAClC,iDAAiD,EACjD,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,iCAAM,UAAU,KAAE,aAAa,EAAE,mBAAmB,IAAG,EAAE,CAC1F,CAAC;QACF,IAAI,WAAW,EAAE;YACb,qDAAqD;YACrD,8FAA8F;YAC9F,mGAAmG;YACnG,eAAe,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACzE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,kCAA0B,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC;YAEvF,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SACvB;aAAM;YACH,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,+BAA+B,EAAE,EAAE,KAAK,CAAC,CAAC;SACxF;IACL,CAAC;CACJ;AAhFD,0EAgFC","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 IConfigProvider,\n IFluidErrorBase,\n LoggingError,\n MonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { oneDayMs } from \"./garbageCollection\";\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 = \"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 = \"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 read(config: IConfigProvider) {\n const sweepReadyUsageDetectionKey = \"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection\";\n const value = config.getString(sweepReadyUsageDetectionKey);\n if (value === undefined) {\n return { interactiveClient: false, summarizer: false };\n }\n return {\n interactiveClient: value.includes(\"interactiveClient\"),\n summarizer: value.includes(\"summarizer\"),\n };\n },\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 /** This errorType will be in temporary use (until Sweep is fully implemented) so don't add to any errorType type */\n public 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 private readonly localStorage: Pick<Storage, \"getItem\" | \"setItem\">;\n\n constructor(\n private readonly uniqueContainerKey: string,\n private readonly mc: MonitoringContext,\n private readonly closeFn: (error?: ICriticalContainerError) => void,\n localStorageOverride?: Pick<Storage, \"getItem\" | \"setItem\">,\n ) {\n const noopStorage = { getItem: () => null, setItem: () => {} };\n if (localStorageOverride !== undefined) {\n this.localStorage = localStorageOverride;\n } else {\n try {\n // localStorage is not defined in Node environment so this throws\n this.localStorage = localStorage ?? noopStorage;\n } catch (error) {\n this.localStorage = noopStorage;\n }\n }\n\n if (this.localStorage === noopStorage) {\n // This means the Skip Closure Period logic will not work.\n this.mc.logger.sendTelemetryEvent({ eventName: \"SweepReadyUsageDetectionHandlerNoopStorage\" });\n }\n }\n\n /**\n * If SweepReady Usage Detection is enabled, close the interactive container.\n * If the SkipClosureForXDays setting is set, don't close the container more than once in that period.\n *\n * Once Sweep is fully implemented, this will be removed since the objects will be gone\n * and errors will arise elsewhere in the runtime\n */\n public usageDetectedInInteractiveClient(errorProps: ITelemetryProperties) {\n if (!sweepReadyUsageDetectionSetting.read(this.mc.config).interactiveClient) {\n return;\n }\n\n // Default stance is we close every time - this reflects the severity of SweepReady Object Usage.\n // However, we may choose to \"throttle\" the closures by setting the SkipClosureForXDays setting,\n // which will only allow the container to close once during that period, to avoid locking users out.\n let shouldClose: boolean = true;\n let pastClosuresMap: Record<string, { lastCloseTime: number; } | undefined> = {};\n let lastCloseTime: number | undefined;\n const skipClosureForXDays = this.mc.config.getNumber(skipClosureForXDaysKey);\n if (skipClosureForXDays !== undefined) {\n // Read pastClosuresMap from localStorage then extract the lastCloseTime from the map\n try {\n const rawValue = this.localStorage.getItem(closuresMapLocalStorageKey);\n const parsedValue = rawValue === null ? {} : JSON.parse(rawValue);\n if (typeof parsedValue === \"object\") {\n pastClosuresMap = parsedValue;\n }\n } catch (e) {\n }\n lastCloseTime = pastClosuresMap[this.uniqueContainerKey]?.lastCloseTime;\n\n // Don't close if we did already within the Skip Closure Period\n if (lastCloseTime !== undefined && Date.now() < lastCloseTime + skipClosureForXDays * oneDayMs) {\n shouldClose = false;\n }\n }\n\n const error = new SweepReadyUsageError(\n \"SweepReady object used in Non-Summarizer Client\",\n { errorDetails: JSON.stringify({ ...errorProps, lastCloseTime, skipClosureForXDays }) },\n );\n if (shouldClose) {\n // Update closures map in localStorage before closing\n // Note there is a race condition between different tabs updating localStorage and overwriting\n // each others' updates. If so, some tab will crash again. Just reload one at a time to get unstuck\n pastClosuresMap[this.uniqueContainerKey] = { lastCloseTime: Date.now() };\n this.localStorage.setItem(closuresMapLocalStorageKey, JSON.stringify(pastClosuresMap));\n\n this.closeFn(error);\n } else {\n this.mc.logger.sendErrorEvent({ eventName: \"SweepReadyObject_UsageAllowed\" }, error);\n }\n }\n}\n"]}
@@ -84,10 +84,14 @@ export interface IOrderedClientElectionEvents extends IEvent {
84
84
  export interface ISerializedElection {
85
85
  /** Sequence number at the time of the latest election. */
86
86
  readonly electionSequenceNumber: number;
87
- /** Most recently elected client id. This is either:
87
+ /**
88
+ * Most recently elected client id. This is either:
89
+ *
88
90
  * 1. the interactive elected parent client, in which case electedClientId === electedParentId,
89
- * and the SummaryManager on the elected client will spawn a summarizer client, or
90
- * 2. the non-interactive summarizer client itself. */
91
+ * and the SummaryManager on the elected client will spawn a summarizer client, or
92
+ *
93
+ * 2. the non-interactive summarizer client itself.
94
+ */
91
95
  readonly electedClientId: string | undefined;
92
96
  /** Most recently elected parent client id. This is always an interactive client. */
93
97
  readonly electedParentId: string | undefined;
@@ -96,10 +100,14 @@ export interface ISerializedElection {
96
100
  export interface IOrderedClientElection extends IEventProvider<IOrderedClientElectionEvents> {
97
101
  /** Count of eligible clients in the collection. */
98
102
  readonly eligibleCount: number;
99
- /** Currently elected client. This is either:
103
+ /**
104
+ * Currently elected client. This is either:
105
+ *
100
106
  * 1. the interactive elected parent client, in which case electedClientId === electedParentId,
101
- * and the SummaryManager on the elected client will spawn a summarizer client, or
102
- * 2. the non-interactive summarizer client itself. */
107
+ * and the SummaryManager on the elected client will spawn a summarizer client, or
108
+ *
109
+ * 2. the non-interactive summarizer client itself.
110
+ */
103
111
  readonly electedClient: ITrackedClient | undefined;
104
112
  /** Currently elected parent client. This is always an interactive client. */
105
113
  readonly electedParent: ITrackedClient | undefined;
@@ -151,13 +159,20 @@ export declare class OrderedClientElection extends TypedEventEmitter<IOrderedCli
151
159
  * electedClient leaves the quorum.
152
160
  *
153
161
  * A typical sequence looks like this:
162
+ *
154
163
  * i. Begin by electing A. electedParent === A, electedClient === A.
164
+ *
155
165
  * ii. SummaryManager running on A spawns a summarizer client, A'. electedParent === A, electedClient === A'
166
+ *
156
167
  * iii. A' stops producing summaries. A new parent client, B, is elected. electedParent === B, electedClient === A'
168
+ *
157
169
  * iv. SummaryManager running on A detects the change to electedParent and tells the summarizer to stop, but A'
158
- * is in mid-summarization. No new summarizer is spawned, as electedParent !== electedClient.
170
+ * is in mid-summarization. No new summarizer is spawned, as electedParent !== electedClient.
171
+ *
159
172
  * v. A' completes its summary, and the summarizer and backing client are torn down.
173
+ *
160
174
  * vi. A' leaves the quorum, and B takes its place as electedClient. electedParent === B, electedClient === B
175
+ *
161
176
  * vii. SummaryManager running on B spawns a summarizer client, B'. electedParent === B, electedClient === B'
162
177
  */
163
178
  get electedClient(): ILinkedClient | undefined;
@@ -165,7 +180,8 @@ export declare class OrderedClientElection extends TypedEventEmitter<IOrderedCli
165
180
  constructor(logger: ITelemetryLogger, orderedClientCollection: IOrderedClientCollection,
166
181
  /** Serialized state from summary or current sequence number at time of load if new. */
167
182
  initialState: ISerializedElection | number, isEligibleFn: (c: ITrackedClient) => boolean);
168
- /** Tries changing the elected client, raising an event if it is different.
183
+ /**
184
+ * Tries changing the elected client, raising an event if it is different.
169
185
  * Note that this function does no eligibility or suitability checks. If we get here, then
170
186
  * we will set _electedClient, and we will set _electedParent if this is an interactive client.
171
187
  */
@@ -193,11 +209,13 @@ export declare class OrderedClientElection extends TypedEventEmitter<IOrderedCli
193
209
  */
194
210
  private removeClient;
195
211
  getAllEligibleClients(): ITrackedClient[];
196
- /** Advance election to the next-oldest client. This is called if the current parent is leaving the quorum,
212
+ /**
213
+ * Advance election to the next-oldest client. This is called if the current parent is leaving the quorum,
197
214
  * or if the current summarizer is not responsive and we want to stop it and spawn a new one.
198
215
  */
199
216
  incrementElectedClient(sequenceNumber: number): void;
200
- /** (Re-)start election with the oldest client in the quorum. This is called if we need to summarize
217
+ /**
218
+ * (Re-)start election with the oldest client in the quorum. This is called if we need to summarize
201
219
  * and no client has been elected.
202
220
  */
203
221
  resetElectedClient(sequenceNumber: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"orderedClientElection.d.ts","sourceRoot":"","sources":["../src/orderedClientElection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orderedClientElection.d.ts","sourceRoot":"","sources":["../src/orderedClientElection.ts"],"names":[],"mappings":"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"}
@@ -202,13 +202,20 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
202
202
  * electedClient leaves the quorum.
203
203
  *
204
204
  * A typical sequence looks like this:
205
+ *
205
206
  * i. Begin by electing A. electedParent === A, electedClient === A.
207
+ *
206
208
  * ii. SummaryManager running on A spawns a summarizer client, A'. electedParent === A, electedClient === A'
209
+ *
207
210
  * iii. A' stops producing summaries. A new parent client, B, is elected. electedParent === B, electedClient === A'
211
+ *
208
212
  * iv. SummaryManager running on A detects the change to electedParent and tells the summarizer to stop, but A'
209
- * is in mid-summarization. No new summarizer is spawned, as electedParent !== electedClient.
213
+ * is in mid-summarization. No new summarizer is spawned, as electedParent !== electedClient.
214
+ *
210
215
  * v. A' completes its summary, and the summarizer and backing client are torn down.
216
+ *
211
217
  * vi. A' leaves the quorum, and B takes its place as electedClient. electedParent === B, electedClient === B
218
+ *
212
219
  * vii. SummaryManager running on B spawns a summarizer client, B'. electedParent === B, electedClient === B'
213
220
  */
214
221
  get electedClient() {
@@ -217,7 +224,8 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
217
224
  get electedParent() {
218
225
  return this._electedParent;
219
226
  }
220
- /** Tries changing the elected client, raising an event if it is different.
227
+ /**
228
+ * Tries changing the elected client, raising an event if it is different.
221
229
  * Note that this function does no eligibility or suitability checks. If we get here, then
222
230
  * we will set _electedClient, and we will set _electedParent if this is an interactive client.
223
231
  */
@@ -324,7 +332,8 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
324
332
  getAllEligibleClients() {
325
333
  return this.orderedClientCollection.getAllClients().filter(this.isEligibleFn);
326
334
  }
327
- /** Advance election to the next-oldest client. This is called if the current parent is leaving the quorum,
335
+ /**
336
+ * Advance election to the next-oldest client. This is called if the current parent is leaving the quorum,
328
337
  * or if the current summarizer is not responsive and we want to stop it and spawn a new one.
329
338
  */
330
339
  incrementElectedClient(sequenceNumber) {
@@ -339,7 +348,8 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
339
348
  this.tryElectingParent(nextClient, sequenceNumber);
340
349
  }
341
350
  }
342
- /** (Re-)start election with the oldest client in the quorum. This is called if we need to summarize
351
+ /**
352
+ * (Re-)start election with the oldest client in the quorum. This is called if we need to summarize
343
353
  * and no client has been elected.
344
354
  */
345
355
  resetElectedClient(sequenceNumber) {
@@ -1 +1 @@
1
- {"version":3,"file":"orderedClientElection.js","sourceRoot":"","sources":["../src/orderedClientElection.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/* eslint-disable @rushstack/no-new-null */\nimport { IEvent, IEventProvider, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { IDeltaManager } from \"@fluidframework/container-definitions\";\nimport { UsageError } from \"@fluidframework/container-utils\";\nimport { IClient, IQuorumClients, ISequencedClient } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { summarizerClientType } from \"./summarizerClientElection\";\n\n// helper types for recursive readonly.\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport type ImmutablePrimitives = undefined | null | boolean | string | number | Function;\nexport type Immutable<T> = T extends ImmutablePrimitives\n ? T\n : T extends (infer A)[]\n ? readonly Immutable<A>[]\n : T extends Map<infer K, infer V>\n ? ReadonlyMap<Immutable<K>, Immutable<V>>\n : T extends Set<infer V>\n ? ReadonlySet<Immutable<V>>\n : { readonly [K in keyof T]: Immutable<T[K]> };\n\n/** Minimum information for a client tracked for election consideration. */\nexport interface ITrackedClient {\n readonly clientId: string;\n readonly sequenceNumber: number;\n readonly client: Immutable<IClient>;\n}\n\n/** Common contract for link nodes within an OrderedClientCollection. */\nexport interface ILinkNode {\n readonly sequenceNumber: number;\n youngerClient: ILinkedClient | undefined;\n}\n\n/** Placeholder root node within an OrderedClientCollection; does not represent a client. */\nexport interface IRootLinkNode extends ILinkNode {\n readonly sequenceNumber: -1;\n readonly olderClient: undefined;\n}\n\n/** Additional information required to keep track of the client within the doubly-linked list. */\nexport interface ILinkedClient extends ILinkNode, ITrackedClient {\n olderClient: LinkNode;\n}\n\n/** Any link node within OrderedClientCollection including the placeholder root node. */\nexport type LinkNode = IRootLinkNode | ILinkedClient;\n\n/** Events raised by an OrderedClientCollection. */\nexport interface IOrderedClientCollectionEvents extends IEvent {\n /** Event fires when client is being added. */\n (event: \"addClient\" | \"removeClient\", listener: (client: ILinkedClient, sequenceNumber: number) => void);\n}\n\n/** Contract for a sorted collection of all clients in the quorum. */\nexport interface IOrderedClientCollection extends IEventProvider<IOrderedClientCollectionEvents> {\n /** Count of clients in the collection. */\n readonly count: number;\n /** Pointer to the oldest client in the collection. */\n readonly oldestClient: ILinkedClient | undefined;\n /** Returns a sorted array of all the clients in the collection. */\n getAllClients(): ILinkedClient[];\n}\n\n/**\n * Tracks clients in the Quorum. It maintains their order using their join op\n * sequence numbers.\n * Internally, the collection of clients is maintained in a doubly-linked list,\n * with pointers to both the first and last nodes.\n * The first (root) node is a placeholder to simplify logic and reduce null checking.\n */\nexport class OrderedClientCollection\n extends TypedEventEmitter<IOrderedClientCollectionEvents>\n implements IOrderedClientCollection {\n /** Collection of ALL clients currently in the quorum, with client ids as keys. */\n private readonly clientMap = new Map<string, ILinkedClient>();\n /** Placeholder head node of linked list, for simplified null checking. */\n private readonly rootNode: IRootLinkNode = {\n sequenceNumber: -1,\n olderClient: undefined,\n youngerClient: undefined,\n };\n /** Pointer to end of linked list, for optimized client adds. */\n private _youngestClient: LinkNode = this.rootNode;\n private readonly logger: ITelemetryLogger;\n\n public get count() {\n return this.clientMap.size;\n }\n public get oldestClient() {\n return this.rootNode.youngerClient;\n }\n\n constructor(\n logger: ITelemetryLogger,\n deltaManager: Pick<IDeltaManager<unknown, unknown>, \"lastSequenceNumber\">,\n quorum: Pick<IQuorumClients, \"getMembers\" | \"on\">,\n ) {\n super();\n this.logger = ChildLogger.create(logger, \"OrderedClientCollection\");\n const members = quorum.getMembers();\n for (const [clientId, client] of members) {\n this.addClient(clientId, client);\n }\n\n quorum.on(\"addMember\", (clientId, client) => {\n const newClient = this.addClient(clientId, client);\n this.emit(\"addClient\", newClient, deltaManager.lastSequenceNumber);\n });\n quorum.on(\"removeMember\", (clientId) => {\n const sequenceNumber = deltaManager.lastSequenceNumber;\n const removeClient = this.removeClient(clientId);\n if (removeClient === undefined) {\n this.logger.sendErrorEvent({ eventName: \"ClientNotFound\", clientId, sequenceNumber });\n } else {\n this.emit(\"removeClient\", removeClient, sequenceNumber);\n }\n });\n }\n\n private addClient(clientId: string, client: ISequencedClient): ITrackedClient {\n // Normal case is adding the latest client, which will bypass loop.\n // Find where it belongs otherwise (maybe possible during initial load?).\n assert(client.sequenceNumber > -1, 0x1f6 /* \"Negative client sequence number not allowed\" */);\n let currClient = this._youngestClient;\n while (currClient.sequenceNumber > client.sequenceNumber) {\n assert(currClient.olderClient !== undefined, 0x1f7 /* \"Previous client should always be defined\" */);\n // Note: If adding a client older than the elected client, it will not be automatically elected.\n currClient = currClient.olderClient;\n }\n\n // Now currClient is the node right before where the new client node should be.\n const newClient: ILinkedClient = {\n clientId,\n sequenceNumber: client.sequenceNumber,\n client: { ...client.client }, // shallow clone\n olderClient: currClient,\n youngerClient: currClient.youngerClient,\n };\n\n // Update prev node to point to this new node.\n newClient.olderClient.youngerClient = newClient;\n\n if (newClient.youngerClient === undefined) {\n // Update linked list end pointer to youngest client.\n this._youngestClient = newClient;\n } else {\n // Update next node to point back to this new node.\n newClient.youngerClient.olderClient = newClient;\n }\n\n this.clientMap.set(clientId, newClient);\n return newClient;\n }\n\n private removeClient(clientId: string): ITrackedClient | undefined {\n const removeClient = this.clientMap.get(clientId);\n if (removeClient === undefined) {\n return;\n }\n\n // Update prev node to point to next node.\n removeClient.olderClient.youngerClient = removeClient.youngerClient;\n\n if (removeClient.youngerClient === undefined) {\n // Update linked list end pointer to youngest client.\n this._youngestClient = removeClient.olderClient;\n } else {\n // Update next node to point back to previous node.\n removeClient.youngerClient.olderClient = removeClient.olderClient;\n }\n\n this.clientMap.delete(clientId);\n return removeClient;\n }\n\n /** Returns an array of all clients being tracked in order from oldest to newest. */\n public getAllClients(): ILinkedClient[] {\n const result: ILinkedClient[] = [];\n let currClient: LinkNode = this.rootNode;\n while (currClient.youngerClient !== undefined) {\n result.push(currClient.youngerClient);\n currClient = currClient.youngerClient;\n }\n return result;\n }\n}\n\n/** Events raised by an OrderedClientElection. */\nexport interface IOrderedClientElectionEvents extends IEvent {\n /** Event fires when the currently elected client changes. */\n (event: \"election\", listener: (\n /** Newly elected client. */\n client: ITrackedClient | undefined,\n /** Sequence number where election took place. */\n sequenceNumber: number,\n /** Previously elected client. */\n prevClient: ITrackedClient | undefined,\n ) => void);\n}\n\n/** Serialized state of IOrderedClientElection. */\nexport interface ISerializedElection {\n /** Sequence number at the time of the latest election. */\n readonly electionSequenceNumber: number;\n /** Most recently elected client id. This is either:\n * 1. the interactive elected parent client, in which case electedClientId === electedParentId,\n * and the SummaryManager on the elected client will spawn a summarizer client, or\n * 2. the non-interactive summarizer client itself. */\n readonly electedClientId: string | undefined;\n /** Most recently elected parent client id. This is always an interactive client. */\n readonly electedParentId: string | undefined;\n}\n\n/** Contract for maintaining a deterministic client election based on eligibility. */\nexport interface IOrderedClientElection extends IEventProvider<IOrderedClientElectionEvents> {\n /** Count of eligible clients in the collection. */\n readonly eligibleCount: number;\n /** Currently elected client. This is either:\n * 1. the interactive elected parent client, in which case electedClientId === electedParentId,\n * and the SummaryManager on the elected client will spawn a summarizer client, or\n * 2. the non-interactive summarizer client itself. */\n readonly electedClient: ITrackedClient | undefined;\n /** Currently elected parent client. This is always an interactive client. */\n readonly electedParent: ITrackedClient | undefined;\n /** Sequence number of most recent election. */\n readonly electionSequenceNumber: number;\n /** Marks the currently elected client as invalid, and elects the next eligible client. */\n incrementElectedClient(sequenceNumber: number): void;\n /** Resets the currently elected client back to the oldest eligible client. */\n resetElectedClient(sequenceNumber: number): void;\n /** Peeks at what the next elected client would be if incrementElectedClient were called. */\n peekNextElectedClient(): ITrackedClient | undefined;\n /** Returns a sorted array of all the eligible clients in the collection. */\n getAllEligibleClients(): ITrackedClient[];\n /** Serialize election data */\n serialize(): ISerializedElection;\n}\n\n/**\n * Adapter for OrderedClientCollection, with the purpose of deterministically maintaining\n * a currently elected client, excluding ineligible clients, in a distributed fashion.\n * This can be true as long as incrementElectedClient and resetElectedClient calls\n * are called under the same conditions for all clients.\n */\nexport class OrderedClientElection\n extends TypedEventEmitter<IOrderedClientElectionEvents>\n implements IOrderedClientElection {\n private _eligibleCount: number = 0;\n private _electedClient: ILinkedClient | undefined;\n private _electedParent: ILinkedClient | undefined;\n private _electionSequenceNumber: number;\n\n public get eligibleCount() {\n return this._eligibleCount;\n }\n public get electionSequenceNumber() {\n return this._electionSequenceNumber;\n }\n\n /**\n * OrderedClientCollection tracks electedClient and electedParent separately. This allows us to handle the case\n * where a new interactive parent client has been elected, but the summarizer is still doing work, so\n * a new summarizer should not yet be spawned. In this case, changing electedParent will cause SummaryManager\n * to stop the current summarizer, but a new summarizer will not be spawned until the old summarizer client has\n * left the quorum.\n *\n * Details:\n *\n * electedParent is the interactive client that has been elected to spawn a summarizer. It is typically the oldest\n * eligible interactive client in the quorum. Only the electedParent is permitted to spawn a summarizer.\n * Once elected, this client will remain the electedParent until it leaves the quorum or the summarizer that\n * it spawned stops producing summaries, at which point a new electedParent will be chosen.\n *\n * electedClient is the non-interactive summarizer client if one exists. If not, then electedClient is equal to\n * electedParent. If electedParent === electedClient, this is the signal for electedParent to spawn a new\n * electedClient. Once a summarizer client becomes electedClient, a new summarizer will not be spawned until\n * electedClient leaves the quorum.\n *\n * A typical sequence looks like this:\n * i. Begin by electing A. electedParent === A, electedClient === A.\n * ii. SummaryManager running on A spawns a summarizer client, A'. electedParent === A, electedClient === A'\n * iii. A' stops producing summaries. A new parent client, B, is elected. electedParent === B, electedClient === A'\n * iv. SummaryManager running on A detects the change to electedParent and tells the summarizer to stop, but A'\n * is in mid-summarization. No new summarizer is spawned, as electedParent !== electedClient.\n * v. A' completes its summary, and the summarizer and backing client are torn down.\n * vi. A' leaves the quorum, and B takes its place as electedClient. electedParent === B, electedClient === B\n * vii. SummaryManager running on B spawns a summarizer client, B'. electedParent === B, electedClient === B'\n */\n public get electedClient() {\n return this._electedClient;\n }\n public get electedParent() {\n return this._electedParent;\n }\n\n constructor(\n logger: ITelemetryLogger,\n private readonly orderedClientCollection: IOrderedClientCollection,\n /** Serialized state from summary or current sequence number at time of load if new. */\n initialState: ISerializedElection | number,\n private readonly isEligibleFn: (c: ITrackedClient) => boolean,\n ) {\n super();\n let initialClient: ILinkedClient | undefined;\n let initialParent: ILinkedClient | undefined;\n for (const client of orderedClientCollection.getAllClients()) {\n this.addClient(client, 0);\n if (typeof initialState !== \"number\") {\n if (client.clientId === initialState.electedClientId) {\n initialClient = client;\n if (initialState.electedParentId === undefined &&\n client.client.details.type !== summarizerClientType) {\n // If there was no elected parent in the serialized data, use this one.\n initialParent = client;\n }\n }\n if (client.clientId === initialState.electedParentId) {\n initialParent = client;\n }\n }\n }\n orderedClientCollection.on(\"addClient\", (client, seq) => this.addClient(client, seq));\n orderedClientCollection.on(\"removeClient\", (client, seq) => this.removeClient(client, seq));\n\n if (typeof initialState === \"number\") {\n this._electionSequenceNumber = initialState;\n } else {\n // Override the initially elected client with the initial state.\n if (initialClient?.clientId !== initialState.electedClientId) {\n // Cannot find initially elected client, so elect undefined.\n logger.sendErrorEvent({\n eventName: \"InitialElectedClientNotFound\",\n electionSequenceNumber: initialState.electionSequenceNumber,\n expectedClientId: initialState.electedClientId,\n electedClientId: initialClient?.clientId,\n clientCount: orderedClientCollection.count,\n });\n } else if (initialClient !== undefined && !isEligibleFn(initialClient)) {\n // Initially elected client is ineligible, so elect next eligible client.\n initialClient = initialParent = this.findFirstEligibleParent(initialParent);\n logger.sendErrorEvent({\n eventName: \"InitialElectedClientIneligible\",\n electionSequenceNumber: initialState.electionSequenceNumber,\n expectedClientId: initialState.electedClientId,\n electedClientId: initialClient?.clientId,\n });\n }\n this._electedParent = initialParent;\n this._electedClient = initialClient;\n this._electionSequenceNumber = initialState.electionSequenceNumber;\n }\n }\n\n /** Tries changing the elected client, raising an event if it is different.\n * Note that this function does no eligibility or suitability checks. If we get here, then\n * we will set _electedClient, and we will set _electedParent if this is an interactive client.\n */\n private tryElectingClient(client: ILinkedClient | undefined, sequenceNumber: number): void {\n let change = false;\n const isSummarizerClient = client?.client.details.type === summarizerClientType;\n const prevClient = this._electedClient;\n if (this._electedClient !== client) {\n // Changing the elected client. Record the sequence number and note that we have to fire an event.\n this._electionSequenceNumber = sequenceNumber;\n this._electedClient = client;\n change = true;\n }\n if (this._electedParent !== client && !isSummarizerClient) {\n // Changing the elected parent as well.\n this._electedParent = client;\n change = true;\n }\n if (change) {\n this.emit(\"election\", client, sequenceNumber, prevClient);\n }\n }\n\n private tryElectingParent(client: ILinkedClient | undefined, sequenceNumber: number): void {\n if (this._electedParent !== client) {\n this._electedParent = client;\n this.emit(\"election\", this._electedClient, sequenceNumber, this._electedClient);\n }\n }\n\n /**\n * Helper function to find the first eligible parent client starting with the passed in client,\n * or undefined if none are eligible.\n * @param client - client to start checking\n * @returns oldest eligible client starting with passed in client or undefined if none.\n */\n private findFirstEligibleParent(client: ILinkedClient | undefined): ILinkedClient | undefined {\n let candidateClient = client;\n while (candidateClient !== undefined &&\n (!this.isEligibleFn(candidateClient) || candidateClient.client.details.type === summarizerClientType)) {\n candidateClient = candidateClient.youngerClient;\n }\n return candidateClient;\n }\n\n /**\n * Updates tracking for when a new client is added to the collection.\n * Will automatically elect that new client if none is elected currently.\n * @param client - client added to the collection\n * @param sequenceNumber - sequence number when client was added\n */\n private addClient(client: ILinkedClient, sequenceNumber: number): void {\n if (this.isEligibleFn(client)) {\n this._eligibleCount++;\n const newClientIsSummarizer = client.client.details.type === summarizerClientType;\n const electedClientIsSummarizer = this._electedClient?.client.details.type === summarizerClientType;\n // Note that we allow a summarizer client to supercede an interactive client as elected client.\n if (this._electedClient === undefined || (!electedClientIsSummarizer && newClientIsSummarizer)) {\n this.tryElectingClient(client, sequenceNumber);\n } else if (this._electedParent === undefined && !newClientIsSummarizer) {\n // This is an odd case. If the _electedClient is set, the _electedParent should be as well.\n this.tryElectingParent(client, sequenceNumber);\n }\n }\n }\n\n /**\n * Updates tracking for when an existing client is removed from the collection.\n * Will automatically elect next oldest client if currently elected is removed.\n * @param client - client removed from the collection\n * @param sequenceNumber - sequence number when client was removed\n */\n private removeClient(client: ILinkedClient, sequenceNumber: number): void {\n if (this.isEligibleFn(client)) {\n this._eligibleCount--;\n if (this._electedClient === client) {\n // Removing the _electedClient. There are 2 possible cases:\n if (this._electedParent !== client) {\n // 1. The _electedClient is a summarizer that we've been allowing to finish its work.\n // Let the _electedParent become the _electedClient so that it can start its own summarizer.\n if (this._electedClient.client.details.type !== summarizerClientType) {\n throw new UsageError(\"Elected client should be a summarizer client 1\");\n }\n this.tryElectingClient(this._electedParent, sequenceNumber);\n } else {\n // 2. The _electedClient is an interactive client that has left the quorum.\n // Automatically shift to next oldest client.\n const nextClient = this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n this.tryElectingClient(nextClient, sequenceNumber);\n }\n } else if (this._electedParent === client) {\n // Removing the _electedParent (but not _electedClient).\n // Shift to the next oldest parent, but do not replace the _electedClient,\n // which is a summarizer that is still doing work.\n if (this._electedClient?.client.details.type !== summarizerClientType) {\n throw new UsageError(\"Elected client should be a summarizer client 2\");\n }\n const nextParent = this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n this.tryElectingParent(nextParent, sequenceNumber);\n }\n }\n }\n\n public getAllEligibleClients(): ITrackedClient[] {\n return this.orderedClientCollection.getAllClients().filter(this.isEligibleFn);\n }\n\n /** Advance election to the next-oldest client. This is called if the current parent is leaving the quorum,\n * or if the current summarizer is not responsive and we want to stop it and spawn a new one.\n */\n public incrementElectedClient(sequenceNumber: number): void {\n const nextClient = this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n if (this._electedClient === undefined || this._electedClient === this._electedParent) {\n this.tryElectingClient(nextClient, sequenceNumber);\n } else {\n // The _electedClient is a summarizer and should not be replaced until it leaves the quorum.\n // Changing the _electedParent will stop the summarizer.\n this.tryElectingParent(nextClient, sequenceNumber);\n }\n }\n\n /** (Re-)start election with the oldest client in the quorum. This is called if we need to summarize\n * and no client has been elected.\n */\n public resetElectedClient(sequenceNumber: number): void {\n const firstClient = this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n if (this._electedClient === undefined || this._electedClient === this._electedParent) {\n this.tryElectingClient(firstClient, sequenceNumber);\n } else {\n // The _electedClient is a summarizer and should not be replaced until it leaves the quorum.\n // Changing the _electedParent will stop the summarizer.\n this.tryElectingParent(firstClient, sequenceNumber);\n }\n }\n\n public peekNextElectedClient(): ITrackedClient | undefined {\n return this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n }\n\n public serialize(): ISerializedElection {\n return {\n electionSequenceNumber: this.electionSequenceNumber,\n electedClientId: this.electedClient?.clientId,\n electedParentId: this.electedParent?.clientId,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"orderedClientElection.js","sourceRoot":"","sources":["../src/orderedClientElection.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/* eslint-disable @rushstack/no-new-null */\nimport { IEvent, IEventProvider, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { IDeltaManager } from \"@fluidframework/container-definitions\";\nimport { UsageError } from \"@fluidframework/container-utils\";\nimport { IClient, IQuorumClients, ISequencedClient } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { summarizerClientType } from \"./summarizerClientElection\";\n\n// helper types for recursive readonly.\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport type ImmutablePrimitives = undefined | null | boolean | string | number | Function;\nexport type Immutable<T> = T extends ImmutablePrimitives\n ? T\n : T extends (infer A)[]\n ? readonly Immutable<A>[]\n : T extends Map<infer K, infer V>\n ? ReadonlyMap<Immutable<K>, Immutable<V>>\n : T extends Set<infer V>\n ? ReadonlySet<Immutable<V>>\n : { readonly [K in keyof T]: Immutable<T[K]> };\n\n/** Minimum information for a client tracked for election consideration. */\nexport interface ITrackedClient {\n readonly clientId: string;\n readonly sequenceNumber: number;\n readonly client: Immutable<IClient>;\n}\n\n/** Common contract for link nodes within an OrderedClientCollection. */\nexport interface ILinkNode {\n readonly sequenceNumber: number;\n youngerClient: ILinkedClient | undefined;\n}\n\n/** Placeholder root node within an OrderedClientCollection; does not represent a client. */\nexport interface IRootLinkNode extends ILinkNode {\n readonly sequenceNumber: -1;\n readonly olderClient: undefined;\n}\n\n/** Additional information required to keep track of the client within the doubly-linked list. */\nexport interface ILinkedClient extends ILinkNode, ITrackedClient {\n olderClient: LinkNode;\n}\n\n/** Any link node within OrderedClientCollection including the placeholder root node. */\nexport type LinkNode = IRootLinkNode | ILinkedClient;\n\n/** Events raised by an OrderedClientCollection. */\nexport interface IOrderedClientCollectionEvents extends IEvent {\n /** Event fires when client is being added. */\n (event: \"addClient\" | \"removeClient\", listener: (client: ILinkedClient, sequenceNumber: number) => void);\n}\n\n/** Contract for a sorted collection of all clients in the quorum. */\nexport interface IOrderedClientCollection extends IEventProvider<IOrderedClientCollectionEvents> {\n /** Count of clients in the collection. */\n readonly count: number;\n /** Pointer to the oldest client in the collection. */\n readonly oldestClient: ILinkedClient | undefined;\n /** Returns a sorted array of all the clients in the collection. */\n getAllClients(): ILinkedClient[];\n}\n\n/**\n * Tracks clients in the Quorum. It maintains their order using their join op\n * sequence numbers.\n * Internally, the collection of clients is maintained in a doubly-linked list,\n * with pointers to both the first and last nodes.\n * The first (root) node is a placeholder to simplify logic and reduce null checking.\n */\nexport class OrderedClientCollection\n extends TypedEventEmitter<IOrderedClientCollectionEvents>\n implements IOrderedClientCollection {\n /** Collection of ALL clients currently in the quorum, with client ids as keys. */\n private readonly clientMap = new Map<string, ILinkedClient>();\n /** Placeholder head node of linked list, for simplified null checking. */\n private readonly rootNode: IRootLinkNode = {\n sequenceNumber: -1,\n olderClient: undefined,\n youngerClient: undefined,\n };\n /** Pointer to end of linked list, for optimized client adds. */\n private _youngestClient: LinkNode = this.rootNode;\n private readonly logger: ITelemetryLogger;\n\n public get count() {\n return this.clientMap.size;\n }\n public get oldestClient() {\n return this.rootNode.youngerClient;\n }\n\n constructor(\n logger: ITelemetryLogger,\n deltaManager: Pick<IDeltaManager<unknown, unknown>, \"lastSequenceNumber\">,\n quorum: Pick<IQuorumClients, \"getMembers\" | \"on\">,\n ) {\n super();\n this.logger = ChildLogger.create(logger, \"OrderedClientCollection\");\n const members = quorum.getMembers();\n for (const [clientId, client] of members) {\n this.addClient(clientId, client);\n }\n\n quorum.on(\"addMember\", (clientId, client) => {\n const newClient = this.addClient(clientId, client);\n this.emit(\"addClient\", newClient, deltaManager.lastSequenceNumber);\n });\n quorum.on(\"removeMember\", (clientId) => {\n const sequenceNumber = deltaManager.lastSequenceNumber;\n const removeClient = this.removeClient(clientId);\n if (removeClient === undefined) {\n this.logger.sendErrorEvent({ eventName: \"ClientNotFound\", clientId, sequenceNumber });\n } else {\n this.emit(\"removeClient\", removeClient, sequenceNumber);\n }\n });\n }\n\n private addClient(clientId: string, client: ISequencedClient): ITrackedClient {\n // Normal case is adding the latest client, which will bypass loop.\n // Find where it belongs otherwise (maybe possible during initial load?).\n assert(client.sequenceNumber > -1, 0x1f6 /* \"Negative client sequence number not allowed\" */);\n let currClient = this._youngestClient;\n while (currClient.sequenceNumber > client.sequenceNumber) {\n assert(currClient.olderClient !== undefined, 0x1f7 /* \"Previous client should always be defined\" */);\n // Note: If adding a client older than the elected client, it will not be automatically elected.\n currClient = currClient.olderClient;\n }\n\n // Now currClient is the node right before where the new client node should be.\n const newClient: ILinkedClient = {\n clientId,\n sequenceNumber: client.sequenceNumber,\n client: { ...client.client }, // shallow clone\n olderClient: currClient,\n youngerClient: currClient.youngerClient,\n };\n\n // Update prev node to point to this new node.\n newClient.olderClient.youngerClient = newClient;\n\n if (newClient.youngerClient === undefined) {\n // Update linked list end pointer to youngest client.\n this._youngestClient = newClient;\n } else {\n // Update next node to point back to this new node.\n newClient.youngerClient.olderClient = newClient;\n }\n\n this.clientMap.set(clientId, newClient);\n return newClient;\n }\n\n private removeClient(clientId: string): ITrackedClient | undefined {\n const removeClient = this.clientMap.get(clientId);\n if (removeClient === undefined) {\n return;\n }\n\n // Update prev node to point to next node.\n removeClient.olderClient.youngerClient = removeClient.youngerClient;\n\n if (removeClient.youngerClient === undefined) {\n // Update linked list end pointer to youngest client.\n this._youngestClient = removeClient.olderClient;\n } else {\n // Update next node to point back to previous node.\n removeClient.youngerClient.olderClient = removeClient.olderClient;\n }\n\n this.clientMap.delete(clientId);\n return removeClient;\n }\n\n /** Returns an array of all clients being tracked in order from oldest to newest. */\n public getAllClients(): ILinkedClient[] {\n const result: ILinkedClient[] = [];\n let currClient: LinkNode = this.rootNode;\n while (currClient.youngerClient !== undefined) {\n result.push(currClient.youngerClient);\n currClient = currClient.youngerClient;\n }\n return result;\n }\n}\n\n/** Events raised by an OrderedClientElection. */\nexport interface IOrderedClientElectionEvents extends IEvent {\n /** Event fires when the currently elected client changes. */\n (event: \"election\", listener: (\n /** Newly elected client. */\n client: ITrackedClient | undefined,\n /** Sequence number where election took place. */\n sequenceNumber: number,\n /** Previously elected client. */\n prevClient: ITrackedClient | undefined,\n ) => void);\n}\n\n/** Serialized state of IOrderedClientElection. */\nexport interface ISerializedElection {\n /** Sequence number at the time of the latest election. */\n readonly electionSequenceNumber: number;\n\n /**\n * Most recently elected client id. This is either:\n *\n * 1. the interactive elected parent client, in which case electedClientId === electedParentId,\n * and the SummaryManager on the elected client will spawn a summarizer client, or\n *\n * 2. the non-interactive summarizer client itself.\n */\n readonly electedClientId: string | undefined;\n\n /** Most recently elected parent client id. This is always an interactive client. */\n readonly electedParentId: string | undefined;\n}\n\n/** Contract for maintaining a deterministic client election based on eligibility. */\nexport interface IOrderedClientElection extends IEventProvider<IOrderedClientElectionEvents> {\n /** Count of eligible clients in the collection. */\n readonly eligibleCount: number;\n\n /**\n * Currently elected client. This is either:\n *\n * 1. the interactive elected parent client, in which case electedClientId === electedParentId,\n * and the SummaryManager on the elected client will spawn a summarizer client, or\n *\n * 2. the non-interactive summarizer client itself.\n */\n readonly electedClient: ITrackedClient | undefined;\n /** Currently elected parent client. This is always an interactive client. */\n readonly electedParent: ITrackedClient | undefined;\n /** Sequence number of most recent election. */\n readonly electionSequenceNumber: number;\n /** Marks the currently elected client as invalid, and elects the next eligible client. */\n incrementElectedClient(sequenceNumber: number): void;\n /** Resets the currently elected client back to the oldest eligible client. */\n resetElectedClient(sequenceNumber: number): void;\n /** Peeks at what the next elected client would be if incrementElectedClient were called. */\n peekNextElectedClient(): ITrackedClient | undefined;\n /** Returns a sorted array of all the eligible clients in the collection. */\n getAllEligibleClients(): ITrackedClient[];\n /** Serialize election data */\n serialize(): ISerializedElection;\n}\n\n/**\n * Adapter for OrderedClientCollection, with the purpose of deterministically maintaining\n * a currently elected client, excluding ineligible clients, in a distributed fashion.\n * This can be true as long as incrementElectedClient and resetElectedClient calls\n * are called under the same conditions for all clients.\n */\nexport class OrderedClientElection\n extends TypedEventEmitter<IOrderedClientElectionEvents>\n implements IOrderedClientElection {\n private _eligibleCount: number = 0;\n private _electedClient: ILinkedClient | undefined;\n private _electedParent: ILinkedClient | undefined;\n private _electionSequenceNumber: number;\n\n public get eligibleCount() {\n return this._eligibleCount;\n }\n public get electionSequenceNumber() {\n return this._electionSequenceNumber;\n }\n\n /**\n * OrderedClientCollection tracks electedClient and electedParent separately. This allows us to handle the case\n * where a new interactive parent client has been elected, but the summarizer is still doing work, so\n * a new summarizer should not yet be spawned. In this case, changing electedParent will cause SummaryManager\n * to stop the current summarizer, but a new summarizer will not be spawned until the old summarizer client has\n * left the quorum.\n *\n * Details:\n *\n * electedParent is the interactive client that has been elected to spawn a summarizer. It is typically the oldest\n * eligible interactive client in the quorum. Only the electedParent is permitted to spawn a summarizer.\n * Once elected, this client will remain the electedParent until it leaves the quorum or the summarizer that\n * it spawned stops producing summaries, at which point a new electedParent will be chosen.\n *\n * electedClient is the non-interactive summarizer client if one exists. If not, then electedClient is equal to\n * electedParent. If electedParent === electedClient, this is the signal for electedParent to spawn a new\n * electedClient. Once a summarizer client becomes electedClient, a new summarizer will not be spawned until\n * electedClient leaves the quorum.\n *\n * A typical sequence looks like this:\n *\n * i. Begin by electing A. electedParent === A, electedClient === A.\n *\n * ii. SummaryManager running on A spawns a summarizer client, A'. electedParent === A, electedClient === A'\n *\n * iii. A' stops producing summaries. A new parent client, B, is elected. electedParent === B, electedClient === A'\n *\n * iv. SummaryManager running on A detects the change to electedParent and tells the summarizer to stop, but A'\n * is in mid-summarization. No new summarizer is spawned, as electedParent !== electedClient.\n *\n * v. A' completes its summary, and the summarizer and backing client are torn down.\n *\n * vi. A' leaves the quorum, and B takes its place as electedClient. electedParent === B, electedClient === B\n *\n * vii. SummaryManager running on B spawns a summarizer client, B'. electedParent === B, electedClient === B'\n */\n public get electedClient() {\n return this._electedClient;\n }\n public get electedParent() {\n return this._electedParent;\n }\n\n constructor(\n logger: ITelemetryLogger,\n private readonly orderedClientCollection: IOrderedClientCollection,\n /** Serialized state from summary or current sequence number at time of load if new. */\n initialState: ISerializedElection | number,\n private readonly isEligibleFn: (c: ITrackedClient) => boolean,\n ) {\n super();\n let initialClient: ILinkedClient | undefined;\n let initialParent: ILinkedClient | undefined;\n for (const client of orderedClientCollection.getAllClients()) {\n this.addClient(client, 0);\n if (typeof initialState !== \"number\") {\n if (client.clientId === initialState.electedClientId) {\n initialClient = client;\n if (initialState.electedParentId === undefined &&\n client.client.details.type !== summarizerClientType) {\n // If there was no elected parent in the serialized data, use this one.\n initialParent = client;\n }\n }\n if (client.clientId === initialState.electedParentId) {\n initialParent = client;\n }\n }\n }\n orderedClientCollection.on(\"addClient\", (client, seq) => this.addClient(client, seq));\n orderedClientCollection.on(\"removeClient\", (client, seq) => this.removeClient(client, seq));\n\n if (typeof initialState === \"number\") {\n this._electionSequenceNumber = initialState;\n } else {\n // Override the initially elected client with the initial state.\n if (initialClient?.clientId !== initialState.electedClientId) {\n // Cannot find initially elected client, so elect undefined.\n logger.sendErrorEvent({\n eventName: \"InitialElectedClientNotFound\",\n electionSequenceNumber: initialState.electionSequenceNumber,\n expectedClientId: initialState.electedClientId,\n electedClientId: initialClient?.clientId,\n clientCount: orderedClientCollection.count,\n });\n } else if (initialClient !== undefined && !isEligibleFn(initialClient)) {\n // Initially elected client is ineligible, so elect next eligible client.\n initialClient = initialParent = this.findFirstEligibleParent(initialParent);\n logger.sendErrorEvent({\n eventName: \"InitialElectedClientIneligible\",\n electionSequenceNumber: initialState.electionSequenceNumber,\n expectedClientId: initialState.electedClientId,\n electedClientId: initialClient?.clientId,\n });\n }\n this._electedParent = initialParent;\n this._electedClient = initialClient;\n this._electionSequenceNumber = initialState.electionSequenceNumber;\n }\n }\n\n /**\n * Tries changing the elected client, raising an event if it is different.\n * Note that this function does no eligibility or suitability checks. If we get here, then\n * we will set _electedClient, and we will set _electedParent if this is an interactive client.\n */\n private tryElectingClient(client: ILinkedClient | undefined, sequenceNumber: number): void {\n let change = false;\n const isSummarizerClient = client?.client.details.type === summarizerClientType;\n const prevClient = this._electedClient;\n if (this._electedClient !== client) {\n // Changing the elected client. Record the sequence number and note that we have to fire an event.\n this._electionSequenceNumber = sequenceNumber;\n this._electedClient = client;\n change = true;\n }\n if (this._electedParent !== client && !isSummarizerClient) {\n // Changing the elected parent as well.\n this._electedParent = client;\n change = true;\n }\n if (change) {\n this.emit(\"election\", client, sequenceNumber, prevClient);\n }\n }\n\n private tryElectingParent(client: ILinkedClient | undefined, sequenceNumber: number): void {\n if (this._electedParent !== client) {\n this._electedParent = client;\n this.emit(\"election\", this._electedClient, sequenceNumber, this._electedClient);\n }\n }\n\n /**\n * Helper function to find the first eligible parent client starting with the passed in client,\n * or undefined if none are eligible.\n * @param client - client to start checking\n * @returns oldest eligible client starting with passed in client or undefined if none.\n */\n private findFirstEligibleParent(client: ILinkedClient | undefined): ILinkedClient | undefined {\n let candidateClient = client;\n while (candidateClient !== undefined &&\n (!this.isEligibleFn(candidateClient) || candidateClient.client.details.type === summarizerClientType)) {\n candidateClient = candidateClient.youngerClient;\n }\n return candidateClient;\n }\n\n /**\n * Updates tracking for when a new client is added to the collection.\n * Will automatically elect that new client if none is elected currently.\n * @param client - client added to the collection\n * @param sequenceNumber - sequence number when client was added\n */\n private addClient(client: ILinkedClient, sequenceNumber: number): void {\n if (this.isEligibleFn(client)) {\n this._eligibleCount++;\n const newClientIsSummarizer = client.client.details.type === summarizerClientType;\n const electedClientIsSummarizer = this._electedClient?.client.details.type === summarizerClientType;\n // Note that we allow a summarizer client to supercede an interactive client as elected client.\n if (this._electedClient === undefined || (!electedClientIsSummarizer && newClientIsSummarizer)) {\n this.tryElectingClient(client, sequenceNumber);\n } else if (this._electedParent === undefined && !newClientIsSummarizer) {\n // This is an odd case. If the _electedClient is set, the _electedParent should be as well.\n this.tryElectingParent(client, sequenceNumber);\n }\n }\n }\n\n /**\n * Updates tracking for when an existing client is removed from the collection.\n * Will automatically elect next oldest client if currently elected is removed.\n * @param client - client removed from the collection\n * @param sequenceNumber - sequence number when client was removed\n */\n private removeClient(client: ILinkedClient, sequenceNumber: number): void {\n if (this.isEligibleFn(client)) {\n this._eligibleCount--;\n if (this._electedClient === client) {\n // Removing the _electedClient. There are 2 possible cases:\n if (this._electedParent !== client) {\n // 1. The _electedClient is a summarizer that we've been allowing to finish its work.\n // Let the _electedParent become the _electedClient so that it can start its own summarizer.\n if (this._electedClient.client.details.type !== summarizerClientType) {\n throw new UsageError(\"Elected client should be a summarizer client 1\");\n }\n this.tryElectingClient(this._electedParent, sequenceNumber);\n } else {\n // 2. The _electedClient is an interactive client that has left the quorum.\n // Automatically shift to next oldest client.\n const nextClient = this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n this.tryElectingClient(nextClient, sequenceNumber);\n }\n } else if (this._electedParent === client) {\n // Removing the _electedParent (but not _electedClient).\n // Shift to the next oldest parent, but do not replace the _electedClient,\n // which is a summarizer that is still doing work.\n if (this._electedClient?.client.details.type !== summarizerClientType) {\n throw new UsageError(\"Elected client should be a summarizer client 2\");\n }\n const nextParent = this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n this.tryElectingParent(nextParent, sequenceNumber);\n }\n }\n }\n\n public getAllEligibleClients(): ITrackedClient[] {\n return this.orderedClientCollection.getAllClients().filter(this.isEligibleFn);\n }\n\n /**\n * Advance election to the next-oldest client. This is called if the current parent is leaving the quorum,\n * or if the current summarizer is not responsive and we want to stop it and spawn a new one.\n */\n public incrementElectedClient(sequenceNumber: number): void {\n const nextClient = this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n if (this._electedClient === undefined || this._electedClient === this._electedParent) {\n this.tryElectingClient(nextClient, sequenceNumber);\n } else {\n // The _electedClient is a summarizer and should not be replaced until it leaves the quorum.\n // Changing the _electedParent will stop the summarizer.\n this.tryElectingParent(nextClient, sequenceNumber);\n }\n }\n\n /**\n * (Re-)start election with the oldest client in the quorum. This is called if we need to summarize\n * and no client has been elected.\n */\n public resetElectedClient(sequenceNumber: number): void {\n const firstClient = this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n if (this._electedClient === undefined || this._electedClient === this._electedParent) {\n this.tryElectingClient(firstClient, sequenceNumber);\n } else {\n // The _electedClient is a summarizer and should not be replaced until it leaves the quorum.\n // Changing the _electedParent will stop the summarizer.\n this.tryElectingParent(firstClient, sequenceNumber);\n }\n }\n\n public peekNextElectedClient(): ITrackedClient | undefined {\n return this.findFirstEligibleParent(this._electedParent?.youngerClient) ??\n this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);\n }\n\n public serialize(): ISerializedElection {\n return {\n electionSequenceNumber: this.electionSequenceNumber,\n electedClientId: this.electedClient?.clientId,\n electedParentId: this.electedParent?.clientId,\n };\n }\n}\n"]}
@@ -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.1.1.2";
8
+ export declare const pkgVersion = "2.0.0-internal.1.2.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluidframework/container-runtime";
11
- exports.pkgVersion = "2.0.0-internal.1.1.2";
11
+ exports.pkgVersion = "2.0.0-internal.1.2.0";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,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.1.1.2\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,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.1.2.0\";\n"]}
@@ -51,7 +51,6 @@ export interface IRuntimeStateHandler {
51
51
  applyStashedOp: (type: ContainerMessageType, content: ISequencedDocumentMessage) => Promise<unknown>;
52
52
  flush(): void;
53
53
  reSubmit(type: ContainerMessageType, content: any, localOpMetadata: unknown, opMetadata: Record<string, unknown> | undefined): void;
54
- rollback(type: ContainerMessageType, content: any, localOpMetadata: unknown): void;
55
54
  }
56
55
  /**
57
56
  * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been
@@ -126,20 +125,10 @@ export declare class PendingStateManager implements IDisposable {
126
125
  * @param message - The message that is being processed.
127
126
  */
128
127
  private maybeProcessBatchEnd;
129
- /**
130
- * Capture the pending state at this point
131
- */
132
- checkpoint(): {
133
- rollback: () => void;
134
- };
135
128
  /**
136
129
  * Returns the next pending state from the pending state queue.
137
130
  */
138
131
  private peekNextPendingState;
139
- /**
140
- * Undo the last pending state
141
- */
142
- private rollbackNextPendingState;
143
132
  /**
144
133
  * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending
145
134
  * states in its queue. This includes setting the FlushMode and triggering resubmission of unacked ops.
@@ -1 +1 @@
1
- {"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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"}