@fluidframework/container-runtime 2.74.0 → 2.80.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/container-runtime.test-files.tar +0 -0
  3. package/dist/blobManager/blobManager.d.ts +0 -2
  4. package/dist/blobManager/blobManager.d.ts.map +1 -1
  5. package/dist/blobManager/blobManager.js +4 -5
  6. package/dist/blobManager/blobManager.js.map +1 -1
  7. package/dist/channelCollection.d.ts +3 -3
  8. package/dist/channelCollection.d.ts.map +1 -1
  9. package/dist/channelCollection.js.map +1 -1
  10. package/dist/containerRuntime.d.ts +5 -0
  11. package/dist/containerRuntime.d.ts.map +1 -1
  12. package/dist/containerRuntime.js +13 -7
  13. package/dist/containerRuntime.js.map +1 -1
  14. package/dist/dataStoreContext.d.ts +1 -1
  15. package/dist/dataStoreContext.d.ts.map +1 -1
  16. package/dist/dataStoreContext.js +1 -1
  17. package/dist/dataStoreContext.js.map +1 -1
  18. package/dist/packageVersion.d.ts +1 -1
  19. package/dist/packageVersion.js +1 -1
  20. package/dist/packageVersion.js.map +1 -1
  21. package/dist/runtimeLayerCompatState.d.ts +9 -5
  22. package/dist/runtimeLayerCompatState.d.ts.map +1 -1
  23. package/dist/runtimeLayerCompatState.js +16 -6
  24. package/dist/runtimeLayerCompatState.js.map +1 -1
  25. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  26. package/dist/summary/summarizerClientElection.js +1 -0
  27. package/dist/summary/summarizerClientElection.js.map +1 -1
  28. package/dist/summary/summarizerTypes.d.ts +5 -0
  29. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  30. package/dist/summary/summarizerTypes.js.map +1 -1
  31. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -1
  32. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
  33. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js +39 -18
  34. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
  35. package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts +1 -1
  36. package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
  37. package/dist/summary/summaryDelayLoadedModule/summarizer.js +13 -11
  38. package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
  39. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +4 -1
  40. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
  41. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js +30 -9
  42. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
  43. package/dist/summary/summaryManager.d.ts +1 -1
  44. package/dist/summary/summaryManager.d.ts.map +1 -1
  45. package/dist/summary/summaryManager.js +10 -9
  46. package/dist/summary/summaryManager.js.map +1 -1
  47. package/lib/blobManager/blobManager.d.ts +0 -2
  48. package/lib/blobManager/blobManager.d.ts.map +1 -1
  49. package/lib/blobManager/blobManager.js +4 -5
  50. package/lib/blobManager/blobManager.js.map +1 -1
  51. package/lib/channelCollection.d.ts +3 -3
  52. package/lib/channelCollection.d.ts.map +1 -1
  53. package/lib/channelCollection.js.map +1 -1
  54. package/lib/containerRuntime.d.ts +5 -0
  55. package/lib/containerRuntime.d.ts.map +1 -1
  56. package/lib/containerRuntime.js +13 -7
  57. package/lib/containerRuntime.js.map +1 -1
  58. package/lib/dataStoreContext.d.ts +1 -1
  59. package/lib/dataStoreContext.d.ts.map +1 -1
  60. package/lib/dataStoreContext.js +1 -1
  61. package/lib/dataStoreContext.js.map +1 -1
  62. package/lib/packageVersion.d.ts +1 -1
  63. package/lib/packageVersion.js +1 -1
  64. package/lib/packageVersion.js.map +1 -1
  65. package/lib/runtimeLayerCompatState.d.ts +9 -5
  66. package/lib/runtimeLayerCompatState.d.ts.map +1 -1
  67. package/lib/runtimeLayerCompatState.js +15 -5
  68. package/lib/runtimeLayerCompatState.js.map +1 -1
  69. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  70. package/lib/summary/summarizerClientElection.js +1 -0
  71. package/lib/summary/summarizerClientElection.js.map +1 -1
  72. package/lib/summary/summarizerTypes.d.ts +5 -0
  73. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  74. package/lib/summary/summarizerTypes.js.map +1 -1
  75. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -1
  76. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
  77. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js +39 -18
  78. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
  79. package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts +1 -1
  80. package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
  81. package/lib/summary/summaryDelayLoadedModule/summarizer.js +13 -11
  82. package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
  83. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +4 -1
  84. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
  85. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js +26 -5
  86. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
  87. package/lib/summary/summaryManager.d.ts +1 -1
  88. package/lib/summary/summaryManager.d.ts.map +1 -1
  89. package/lib/summary/summaryManager.js +10 -9
  90. package/lib/summary/summaryManager.js.map +1 -1
  91. package/package.json +26 -26
  92. package/src/blobManager/blobManager.ts +3 -7
  93. package/src/channelCollection.ts +3 -3
  94. package/src/containerRuntime.ts +19 -6
  95. package/src/dataStoreContext.ts +2 -2
  96. package/src/packageVersion.ts +1 -1
  97. package/src/runtimeLayerCompatState.ts +25 -9
  98. package/src/summary/summarizerClientElection.ts +1 -0
  99. package/src/summary/summarizerTypes.ts +5 -0
  100. package/src/summary/summaryDelayLoadedModule/runningSummarizer.ts +54 -26
  101. package/src/summary/summaryDelayLoadedModule/summarizer.ts +13 -11
  102. package/src/summary/summaryDelayLoadedModule/summaryGenerator.ts +35 -5
  103. package/src/summary/summaryManager.ts +11 -10
@@ -2,9 +2,11 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import { TypedEventEmitter } from "@fluid-internal/client-utils";
5
6
  import { assert, Timer } from "@fluidframework/core-utils/internal";
6
7
  import { DriverErrorTypes, MessageType } from "@fluidframework/driver-definitions/internal";
7
8
  import { getRetryDelaySecondsFromError } from "@fluidframework/driver-utils/internal";
9
+ import { TelemetryContext } from "@fluidframework/runtime-utils/internal";
8
10
  import { isFluidError, PerformanceEvent, wrapError, } from "@fluidframework/telemetry-utils/internal";
9
11
  import { RetriableSummaryError, getFailMessage, raceTimer, } from "../summarizerUtils.js";
10
12
  import { SummarizeResultBuilder } from "./summaryResultBuilder.js";
@@ -14,8 +16,9 @@ const maxSummarizeTimeoutCount = 5; // Double and resend 5 times
14
16
  /**
15
17
  * This class generates and tracks a summary attempt.
16
18
  */
17
- export class SummaryGenerator {
19
+ export class SummaryGenerator extends TypedEventEmitter {
18
20
  constructor(pendingAckTimer, heuristicData, submitSummaryCallback, successfulSummaryCallback, refreshLatestSummaryCallback, summaryWatcher, logger) {
21
+ super();
19
22
  this.pendingAckTimer = pendingAckTimer;
20
23
  this.heuristicData = heuristicData;
21
24
  this.submitSummaryCallback = submitSummaryCallback;
@@ -40,7 +43,10 @@ export class SummaryGenerator {
40
43
  return resultsBuilder.build();
41
44
  }
42
45
  async summarizeCore(submitSummaryOptions, resultsBuilder) {
43
- const { summaryLogger, cancellationToken, ...summarizeOptions } = submitSummaryOptions;
46
+ const { summaryLogger, cancellationToken, telemetryContext = new TelemetryContext(), ...summarizeOptions } = submitSummaryOptions;
47
+ telemetryContext.setCurrentSummarizeStep("submitSummary");
48
+ const submitOptions = { ...submitSummaryOptions, telemetryContext };
49
+ this.activeTelemetryContext = telemetryContext;
44
50
  // Note: timeSinceLastAttempt and timeSinceLastSummary for the
45
51
  // first summary are basically the time since the summarizer was loaded.
46
52
  const timeSinceLastAttempt = Date.now() - this.heuristicData.lastAttempt.summaryTime;
@@ -50,6 +56,8 @@ export class SummaryGenerator {
50
56
  fullTree: summarizeOptions.fullTree ?? false,
51
57
  timeSinceLastAttempt,
52
58
  timeSinceLastSummary,
59
+ nonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,
60
+ runtimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,
53
61
  };
54
62
  const summarizeEvent = PerformanceEvent.start(summaryLogger, {
55
63
  eventName: "Summarize",
@@ -81,9 +89,11 @@ export class SummaryGenerator {
81
89
  // Wait to generate and send summary
82
90
  this.summarizeTimer.start();
83
91
  try {
92
+ telemetryContext.setCurrentSummarizeStep("generateSummary");
84
93
  // Need to save refSeqNum before we record new attempt (happens as part of submitSummaryCallback)
85
94
  const lastAttemptRefSeqNum = this.heuristicData.lastAttempt.refSequenceNumber;
86
- summaryData = await this.submitSummaryCallback(submitSummaryOptions);
95
+ summaryData = await this.submitSummaryCallback(submitOptions);
96
+ telemetryContext.setCurrentSummarizeStep("submitSummaryOp");
87
97
  // Cumulatively add telemetry properties based on how far generateSummary went.
88
98
  const referenceSequenceNumber = summaryData.referenceSequenceNumber;
89
99
  summarizeTelemetryProps = {
@@ -113,6 +123,7 @@ export class SummaryGenerator {
113
123
  * exceed the number of ops since last summary + number of data store whose reference state changed.
114
124
  */
115
125
  if (submitSummaryOptions.fullTree !== true) {
126
+ telemetryContext.setCurrentSummarizeStep("watchSummary");
116
127
  const { summarizedDataStoreCount, gcStateUpdatedDataStoreCount = 0 } = summaryData.summaryStats;
117
128
  if (summarizedDataStoreCount >
118
129
  gcStateUpdatedDataStoreCount + this.heuristicData.opsSinceLastSummary) {
@@ -139,6 +150,7 @@ export class SummaryGenerator {
139
150
  }
140
151
  this.summarizeTimer.clear();
141
152
  }
153
+ telemetryContext.setCurrentSummarizeStep("waitForSummaryAck");
142
154
  try {
143
155
  const pendingTimeoutP = this.pendingAckTimer.start();
144
156
  const summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);
@@ -192,6 +204,7 @@ export class SummaryGenerator {
192
204
  ...summarizeTelemetryProps,
193
205
  };
194
206
  if (ackNackOp.type === MessageType.SummaryAck) {
207
+ telemetryContext.setCurrentSummarizeStep("ackReceived");
195
208
  this.heuristicData.markLastAttemptAsSuccessful();
196
209
  this.successfulSummaryCallback();
197
210
  summarizeEvent.end({
@@ -217,6 +230,7 @@ export class SummaryGenerator {
217
230
  else {
218
231
  // Check for retryDelay in summaryNack response.
219
232
  assert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* "type check" */);
233
+ telemetryContext.setCurrentSummarizeStep("nackReceived");
220
234
  const summaryNack = ackNackOp.contents;
221
235
  const errorMessage = summaryNack?.message;
222
236
  const retryAfterSeconds = summaryNack?.retryAfter;
@@ -232,6 +246,7 @@ export class SummaryGenerator {
232
246
  }
233
247
  finally {
234
248
  this.pendingAckTimer.clear();
249
+ this.activeTelemetryContext = undefined;
235
250
  }
236
251
  }
237
252
  addSummaryDataToTelemetryProps(summaryData, initialProps) {
@@ -265,8 +280,6 @@ export class SummaryGenerator {
265
280
  clientSequenceNumber: summaryData.clientSequenceNumber,
266
281
  hasMissingOpData: this.heuristicData.hasMissingOpData,
267
282
  opsSizesSinceLastSummary: this.heuristicData.totalOpsSize,
268
- nonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,
269
- runtimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,
270
283
  };
271
284
  }
272
285
  default: {
@@ -280,6 +293,13 @@ export class SummaryGenerator {
280
293
  eventName: "SummarizeTimeout",
281
294
  timeoutTime: time,
282
295
  timeoutCount: count,
296
+ currentSummarizeStep: this.activeTelemetryContext?.getCurrentSummarizeStep(),
297
+ });
298
+ this.emit("summarizeTimeout", {
299
+ timeoutCount: count,
300
+ currentSummarizeStep: this.activeTelemetryContext?.getCurrentSummarizeStep(),
301
+ numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
302
+ numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
283
303
  });
284
304
  if (count < maxSummarizeTimeoutCount) {
285
305
  // Double and start a new timer
@@ -289,6 +309,7 @@ export class SummaryGenerator {
289
309
  }
290
310
  dispose() {
291
311
  this.summarizeTimer.clear();
312
+ this.activeTelemetryContext = undefined;
292
313
  }
293
314
  }
294
315
  //# sourceMappingURL=summaryGenerator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"summaryGenerator.js","sourceRoot":"","sources":["../../../src/summary/summaryDelayLoadedModule/summaryGenerator.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 { assert, type IPromiseTimer, Timer } from \"@fluidframework/core-utils/internal\";\nimport { DriverErrorTypes, MessageType } from \"@fluidframework/driver-definitions/internal\";\nimport { getRetryDelaySecondsFromError } from \"@fluidframework/driver-utils/internal\";\nimport {\n\tisFluidError,\n\ttype ITelemetryLoggerExt,\n\tPerformanceEvent,\n\twrapError,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type {\n\tIRefreshSummaryAckOptions,\n\tIRetriableFailureError,\n\tISubmitSummaryOptions,\n\tISummarizeHeuristicData,\n\tSubmitSummaryFailureData,\n\tSubmitSummaryResult,\n\tSummaryGeneratorTelemetry,\n} from \"../summarizerTypes.js\";\nimport {\n\tRetriableSummaryError,\n\tgetFailMessage,\n\traceTimer,\n\ttype SummarizeErrorCode,\n} from \"../summarizerUtils.js\";\nimport type { IClientSummaryWatcher } from \"../summaryCollection.js\";\n\nimport { SummarizeResultBuilder } from \"./summaryResultBuilder.js\";\nimport type { INackSummaryResult, ISummarizeResults } from \"./summaryResultTypes.js\";\n\n// Send some telemetry if generate summary takes too long\nconst maxSummarizeTimeoutTime = 20000; // 20 sec\nconst maxSummarizeTimeoutCount = 5; // Double and resend 5 times\n\n/**\n * This class generates and tracks a summary attempt.\n */\nexport class SummaryGenerator {\n\tprivate readonly summarizeTimer: Timer;\n\tconstructor(\n\t\tprivate readonly pendingAckTimer: IPromiseTimer,\n\t\tprivate readonly heuristicData: ISummarizeHeuristicData,\n\t\tprivate readonly submitSummaryCallback: (\n\t\t\toptions: ISubmitSummaryOptions,\n\t\t) => Promise<SubmitSummaryResult>,\n\t\tprivate readonly successfulSummaryCallback: () => void,\n\t\tprivate readonly refreshLatestSummaryCallback: (\n\t\t\toptions: IRefreshSummaryAckOptions,\n\t\t) => Promise<void>,\n\t\tprivate readonly summaryWatcher: Pick<IClientSummaryWatcher, \"watchSummary\">,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tthis.summarizeTimer = new Timer(maxSummarizeTimeoutTime, () =>\n\t\t\tthis.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),\n\t\t);\n\t}\n\n\t/**\n\t * Generates summary and listens for broadcast and ack/nack.\n\t * Returns true for ack, false for nack, and undefined for failure or timeout.\n\t * @param summaryOptions - options controlling how the summary is generated or submitted.\n\t * @param resultsBuilder - optional, result builder to use to build pass or fail result.\n\t */\n\tpublic summarize(\n\t\tsummaryOptions: ISubmitSummaryOptions,\n\t\tresultsBuilder = new SummarizeResultBuilder(),\n\t): ISummarizeResults {\n\t\tthis.summarizeCore(summaryOptions, resultsBuilder).catch(\n\t\t\t(error: IRetriableFailureError) => {\n\t\t\t\tconst message = \"UnexpectedSummarizeError\";\n\t\t\t\tsummaryOptions.summaryLogger.sendErrorEvent({ eventName: message }, error);\n\t\t\t\tresultsBuilder.fail(message, error);\n\t\t\t},\n\t\t);\n\n\t\treturn resultsBuilder.build();\n\t}\n\n\tprivate async summarizeCore(\n\t\tsubmitSummaryOptions: ISubmitSummaryOptions,\n\t\tresultsBuilder: SummarizeResultBuilder,\n\t): Promise<void> {\n\t\tconst { summaryLogger, cancellationToken, ...summarizeOptions } = submitSummaryOptions;\n\n\t\t// Note: timeSinceLastAttempt and timeSinceLastSummary for the\n\t\t// first summary are basically the time since the summarizer was loaded.\n\t\tconst timeSinceLastAttempt = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\tconst timeSinceLastSummary =\n\t\t\tDate.now() - this.heuristicData.lastSuccessfulSummary.summaryTime;\n\t\tlet summarizeTelemetryProps: SummaryGeneratorTelemetry = {\n\t\t\t...summarizeOptions,\n\t\t\tfullTree: summarizeOptions.fullTree ?? false,\n\t\t\ttimeSinceLastAttempt,\n\t\t\ttimeSinceLastSummary,\n\t\t};\n\n\t\tconst summarizeEvent = PerformanceEvent.start(\n\t\t\tsummaryLogger,\n\t\t\t{\n\t\t\t\teventName: \"Summarize\",\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t},\n\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t);\n\n\t\tlet summaryData: SubmitSummaryResult | undefined;\n\n\t\t/**\n\t\t * Summarization can fail during submit, during op broadcast or during nack.\n\t\t * For submit failures, submitFailureResult should be provided. For nack failures, nackSummaryResult should\n\t\t * be provided. For op broadcast failures, only errors / properties should be provided.\n\t\t */\n\t\tconst fail = (\n\t\t\terrorCode: SummarizeErrorCode,\n\t\t\terror: IRetriableFailureError,\n\t\t\tproperties?: SummaryGeneratorTelemetry,\n\t\t\tsubmitFailureResult?: SubmitSummaryFailureData,\n\t\t\tnackSummaryResult?: INackSummaryResult,\n\t\t): void => {\n\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t// If failure happened on upload, we may not yet realized that socket disconnected, so check\n\t\t\t// offlineError too.\n\t\t\tconst category =\n\t\t\t\tcancellationToken.cancelled ||\n\t\t\t\t(isFluidError(error) && error?.errorType === DriverErrorTypes.offlineError)\n\t\t\t\t\t? \"generic\"\n\t\t\t\t\t: \"error\";\n\n\t\t\tconst reason = getFailMessage(errorCode);\n\t\t\tsummarizeEvent.cancel(\n\t\t\t\t{\n\t\t\t\t\t...properties,\n\t\t\t\t\treason,\n\t\t\t\t\tcategory,\n\t\t\t\t\tretryAfterSeconds: error.retryAfterSeconds,\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t); // disconnect & summaryAckTimeout do not have proper error.\n\n\t\t\tresultsBuilder.fail(reason, error, submitFailureResult, nackSummaryResult);\n\t\t};\n\n\t\t// Wait to generate and send summary\n\t\tthis.summarizeTimer.start();\n\t\ttry {\n\t\t\t// Need to save refSeqNum before we record new attempt (happens as part of submitSummaryCallback)\n\t\t\tconst lastAttemptRefSeqNum = this.heuristicData.lastAttempt.refSequenceNumber;\n\n\t\t\tsummaryData = await this.submitSummaryCallback(submitSummaryOptions);\n\n\t\t\t// Cumulatively add telemetry properties based on how far generateSummary went.\n\t\t\tconst referenceSequenceNumber = summaryData.referenceSequenceNumber;\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t\tminimumSequenceNumber: summaryData.minimumSequenceNumber,\n\t\t\t\topsSinceLastAttempt: referenceSequenceNumber - lastAttemptRefSeqNum,\n\t\t\t\topsSinceLastSummary:\n\t\t\t\t\treferenceSequenceNumber - this.heuristicData.lastSuccessfulSummary.refSequenceNumber,\n\t\t\t\tstage: summaryData.stage,\n\t\t\t};\n\t\t\tsummarizeTelemetryProps = this.addSummaryDataToTelemetryProps(\n\t\t\t\tsummaryData,\n\t\t\t\tsummarizeTelemetryProps,\n\t\t\t);\n\n\t\t\tif (summaryData.stage !== \"submit\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"submitSummaryFailure\";\n\t\t\t\tconst retriableError =\n\t\t\t\t\tsummaryData.error ?? new RetriableSummaryError(getFailMessage(errorCode));\n\t\t\t\treturn fail(errorCode, retriableError, summarizeTelemetryProps, {\n\t\t\t\t\tstage: summaryData.stage,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * With incremental summaries, if the full tree was not summarized, only data stores that changed should\n\t\t\t * be summarized. A data store is considered changed if either or both of the following is true:\n\t\t\t * - It has received an op.\n\t\t\t * - Its reference state changed, i.e., it went from referenced to unreferenced or vice-versa.\n\t\t\t *\n\t\t\t * In the extreme case, every op can be for a different data store and each op can result in the reference\n\t\t\t * state change of multiple data stores. So, the total number of data stores that are summarized should not\n\t\t\t * exceed the number of ops since last summary + number of data store whose reference state changed.\n\t\t\t */\n\t\t\tif (submitSummaryOptions.fullTree !== true) {\n\t\t\t\tconst { summarizedDataStoreCount, gcStateUpdatedDataStoreCount = 0 } =\n\t\t\t\t\tsummaryData.summaryStats;\n\t\t\t\tif (\n\t\t\t\t\tsummarizedDataStoreCount >\n\t\t\t\t\tgcStateUpdatedDataStoreCount + this.heuristicData.opsSinceLastSummary\n\t\t\t\t) {\n\t\t\t\t\tsummaryLogger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"IncrementalSummaryViolation\",\n\t\t\t\t\t\tsummarizedDataStoreCount,\n\t\t\t\t\t\tgcStateUpdatedDataStoreCount,\n\t\t\t\t\t\topsSinceLastSummary: this.heuristicData.opsSinceLastSummary,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Log event here on summary success only, as Summarize_cancel duplicates failure logging.\n\t\t\tsummarizeEvent.reportEvent(\"generate\", { ...summarizeTelemetryProps });\n\t\t\tresultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });\n\t\t} catch (error) {\n\t\t\treturn fail(\n\t\t\t\t\"submitSummaryFailure\",\n\t\t\t\twrapError(\n\t\t\t\t\terror,\n\t\t\t\t\t(message) =>\n\t\t\t\t\t\tnew RetriableSummaryError(message, getRetryDelaySecondsFromError(error)),\n\t\t\t\t),\n\t\t\t\tundefined /* properties */,\n\t\t\t\t{\n\t\t\t\t\tstage: \"unknown\",\n\t\t\t\t},\n\t\t\t);\n\t\t} finally {\n\t\t\tif (summaryData === undefined) {\n\t\t\t\tthis.heuristicData.recordAttempt();\n\t\t\t}\n\t\t\tthis.summarizeTimer.clear();\n\t\t}\n\n\t\ttry {\n\t\t\tconst pendingTimeoutP = this.pendingAckTimer.start();\n\t\t\tconst summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);\n\n\t\t\t// Wait for broadcast\n\t\t\tconst waitBroadcastResult = await raceTimer(\n\t\t\t\tsummary.waitBroadcast(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitBroadcastResult.result === \"cancelled\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"disconnect\";\n\t\t\t\treturn fail(errorCode, new RetriableSummaryError(getFailMessage(errorCode)));\n\t\t\t}\n\t\t\tif (waitBroadcastResult.result !== \"done\") {\n\t\t\t\t// The summary op may not have been received within the timeout due to a transient error. So,\n\t\t\t\t// fail with a retriable error to re-attempt the summary if possible.\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"summaryOpWaitTimeout\";\n\t\t\t\treturn fail(\n\t\t\t\t\terrorCode,\n\t\t\t\t\tnew RetriableSummaryError(getFailMessage(errorCode), 0 /* retryAfterSeconds */),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst summarizeOp = waitBroadcastResult.value;\n\n\t\t\tconst broadcastDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\t\tresultsBuilder.summaryOpBroadcasted.resolve({\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: { summarizeOp, broadcastDuration },\n\t\t\t});\n\n\t\t\tthis.heuristicData.lastAttempt.summarySequenceNumber = summarizeOp.sequenceNumber;\n\t\t\tsummaryLogger.sendTelemetryEvent({\n\t\t\t\teventName: \"Summarize_Op\",\n\t\t\t\tduration: broadcastDuration,\n\t\t\t\treferenceSequenceNumber: summarizeOp.referenceSequenceNumber,\n\t\t\t\tsummarySequenceNumber: summarizeOp.sequenceNumber,\n\t\t\t\thandle: summarizeOp.contents.handle,\n\t\t\t});\n\n\t\t\t// Wait for ack/nack\n\t\t\tconst waitAckNackResult = await raceTimer(\n\t\t\t\tsummary.waitAckNack(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitAckNackResult.result === \"cancelled\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"disconnect\";\n\t\t\t\treturn fail(errorCode, new RetriableSummaryError(getFailMessage(errorCode)));\n\t\t\t}\n\t\t\tif (waitAckNackResult.result !== \"done\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"summaryAckWaitTimeout\";\n\t\t\t\t// The summary ack may not have been received within the timeout due to a transient error. So,\n\t\t\t\t// fail with a retriable error to re-attempt the summary if possible.\n\t\t\t\treturn fail(\n\t\t\t\t\terrorCode,\n\t\t\t\t\tnew RetriableSummaryError(getFailMessage(errorCode), 0 /* retryAfterSeconds */),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst ackNackOp = waitAckNackResult.value;\n\t\t\tthis.pendingAckTimer.clear();\n\n\t\t\t// Update for success/failure\n\t\t\tconst ackNackDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\n\t\t\t// adding new properties\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\tackWaitDuration: ackNackDuration,\n\t\t\t\tackNackSequenceNumber: ackNackOp.sequenceNumber,\n\t\t\t\tsummarySequenceNumber: ackNackOp.contents.summaryProposal.summarySequenceNumber,\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t};\n\t\t\tif (ackNackOp.type === MessageType.SummaryAck) {\n\t\t\t\tthis.heuristicData.markLastAttemptAsSuccessful();\n\t\t\t\tthis.successfulSummaryCallback();\n\t\t\t\tsummarizeEvent.end({\n\t\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\t\thandle: ackNackOp.contents.handle,\n\t\t\t\t});\n\t\t\t\t// This processes the summary ack of the successful summary. This is so that the next summary does not\n\t\t\t\t// start before the ack of the previous summary is processed.\n\t\t\t\tawait this.refreshLatestSummaryCallback({\n\t\t\t\t\tproposalHandle: summarizeOp.contents.handle,\n\t\t\t\t\tackHandle: ackNackOp.contents.handle,\n\t\t\t\t\tsummaryRefSeq: summarizeOp.referenceSequenceNumber,\n\t\t\t\t\tsummaryLogger,\n\t\t\t\t});\n\t\t\t\tresultsBuilder.receivedSummaryAckOrNack.resolve({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tsummaryAckOp: ackNackOp,\n\t\t\t\t\t\tackNackDuration,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Check for retryDelay in summaryNack response.\n\t\t\t\tassert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* \"type check\" */);\n\t\t\t\tconst summaryNack = ackNackOp.contents;\n\t\t\t\tconst errorMessage = summaryNack?.message;\n\t\t\t\tconst retryAfterSeconds = summaryNack?.retryAfter;\n\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"summaryNack\";\n\n\t\t\t\t// pre-0.58 error message prefix: summaryNack\n\t\t\t\tconst error = new RetriableSummaryError(getFailMessage(errorCode), retryAfterSeconds, {\n\t\t\t\t\terrorMessage,\n\t\t\t\t});\n\n\t\t\t\tassert(\n\t\t\t\t\tgetRetryDelaySecondsFromError(error) === retryAfterSeconds,\n\t\t\t\t\t0x25f /* \"retryAfterSeconds\" */,\n\t\t\t\t);\n\t\t\t\t// This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.\n\t\t\t\treturn fail(\n\t\t\t\t\terrorCode,\n\t\t\t\t\terror,\n\t\t\t\t\t{ ...summarizeTelemetryProps, nackRetryAfter: retryAfterSeconds },\n\t\t\t\t\tundefined /* submitFailureResult */,\n\t\t\t\t\t{ summaryNackOp: ackNackOp, ackNackDuration },\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.pendingAckTimer.clear();\n\t\t}\n\t}\n\n\tprivate addSummaryDataToTelemetryProps(\n\t\tsummaryData: SubmitSummaryResult,\n\t\tinitialProps: SummaryGeneratorTelemetry,\n\t): SummaryGeneratorTelemetry {\n\t\tswitch (summaryData.stage) {\n\t\t\tcase \"base\": {\n\t\t\t\treturn initialProps;\n\t\t\t}\n\n\t\t\tcase \"generate\": {\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tcase \"upload\": {\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tcase \"submit\": {\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t\tclientSequenceNumber: summaryData.clientSequenceNumber,\n\t\t\t\t\thasMissingOpData: this.heuristicData.hasMissingOpData,\n\t\t\t\t\topsSizesSinceLastSummary: this.heuristicData.totalOpsSize,\n\t\t\t\t\tnonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,\n\t\t\t\t\truntimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tassert(true, 0x397 /* Unexpected summary stage */);\n\t\t\t}\n\t\t}\n\n\t\treturn initialProps;\n\t}\n\n\tprivate summarizeTimerHandler(time: number, count: number): void {\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"SummarizeTimeout\",\n\t\t\ttimeoutTime: time,\n\t\t\ttimeoutCount: count,\n\t\t});\n\t\tif (count < maxSummarizeTimeoutCount) {\n\t\t\t// Double and start a new timer\n\t\t\tconst nextTime = time * 2;\n\t\t\tthis.summarizeTimer.start(nextTime, () =>\n\t\t\t\tthis.summarizeTimerHandler(nextTime, count + 1),\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.summarizeTimer.clear();\n\t}\n}\n"]}
1
+ {"version":3,"file":"summaryGenerator.js","sourceRoot":"","sources":["../../../src/summary/summaryDelayLoadedModule/summaryGenerator.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { ISummarizerEvents } from \"@fluidframework/container-runtime-definitions/internal\";\nimport { assert, type IPromiseTimer, Timer } from \"@fluidframework/core-utils/internal\";\nimport { DriverErrorTypes, MessageType } from \"@fluidframework/driver-definitions/internal\";\nimport { getRetryDelaySecondsFromError } from \"@fluidframework/driver-utils/internal\";\nimport { TelemetryContext } from \"@fluidframework/runtime-utils/internal\";\nimport {\n\tisFluidError,\n\ttype ITelemetryLoggerExt,\n\tPerformanceEvent,\n\twrapError,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type {\n\tIRefreshSummaryAckOptions,\n\tIRetriableFailureError,\n\tISubmitSummaryOptions,\n\tISummarizeHeuristicData,\n\tSubmitSummaryFailureData,\n\tSubmitSummaryResult,\n\tSummaryGeneratorTelemetry,\n} from \"../summarizerTypes.js\";\nimport {\n\tRetriableSummaryError,\n\tgetFailMessage,\n\traceTimer,\n\ttype SummarizeErrorCode,\n} from \"../summarizerUtils.js\";\nimport type { IClientSummaryWatcher } from \"../summaryCollection.js\";\n\nimport { SummarizeResultBuilder } from \"./summaryResultBuilder.js\";\nimport type { INackSummaryResult, ISummarizeResults } from \"./summaryResultTypes.js\";\n\n// Send some telemetry if generate summary takes too long\nconst maxSummarizeTimeoutTime = 20000; // 20 sec\nconst maxSummarizeTimeoutCount = 5; // Double and resend 5 times\n\n/**\n * This class generates and tracks a summary attempt.\n */\nexport class SummaryGenerator extends TypedEventEmitter<ISummarizerEvents> {\n\tprivate readonly summarizeTimer: Timer;\n\tprivate activeTelemetryContext?: TelemetryContext;\n\tconstructor(\n\t\tprivate readonly pendingAckTimer: IPromiseTimer,\n\t\tprivate readonly heuristicData: ISummarizeHeuristicData,\n\t\tprivate readonly submitSummaryCallback: (\n\t\t\toptions: ISubmitSummaryOptions,\n\t\t) => Promise<SubmitSummaryResult>,\n\t\tprivate readonly successfulSummaryCallback: () => void,\n\t\tprivate readonly refreshLatestSummaryCallback: (\n\t\t\toptions: IRefreshSummaryAckOptions,\n\t\t) => Promise<void>,\n\t\tprivate readonly summaryWatcher: Pick<IClientSummaryWatcher, \"watchSummary\">,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tsuper();\n\t\tthis.summarizeTimer = new Timer(maxSummarizeTimeoutTime, () =>\n\t\t\tthis.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),\n\t\t);\n\t}\n\n\t/**\n\t * Generates summary and listens for broadcast and ack/nack.\n\t * Returns true for ack, false for nack, and undefined for failure or timeout.\n\t * @param summaryOptions - options controlling how the summary is generated or submitted.\n\t * @param resultsBuilder - optional, result builder to use to build pass or fail result.\n\t */\n\tpublic summarize(\n\t\tsummaryOptions: ISubmitSummaryOptions,\n\t\tresultsBuilder = new SummarizeResultBuilder(),\n\t): ISummarizeResults {\n\t\tthis.summarizeCore(summaryOptions, resultsBuilder).catch(\n\t\t\t(error: IRetriableFailureError) => {\n\t\t\t\tconst message = \"UnexpectedSummarizeError\";\n\t\t\t\tsummaryOptions.summaryLogger.sendErrorEvent({ eventName: message }, error);\n\t\t\t\tresultsBuilder.fail(message, error);\n\t\t\t},\n\t\t);\n\n\t\treturn resultsBuilder.build();\n\t}\n\n\tprivate async summarizeCore(\n\t\tsubmitSummaryOptions: ISubmitSummaryOptions,\n\t\tresultsBuilder: SummarizeResultBuilder,\n\t): Promise<void> {\n\t\tconst {\n\t\t\tsummaryLogger,\n\t\t\tcancellationToken,\n\t\t\ttelemetryContext = new TelemetryContext(),\n\t\t\t...summarizeOptions\n\t\t} = submitSummaryOptions;\n\n\t\ttelemetryContext.setCurrentSummarizeStep(\"submitSummary\");\n\t\tconst submitOptions = { ...submitSummaryOptions, telemetryContext };\n\t\tthis.activeTelemetryContext = telemetryContext;\n\n\t\t// Note: timeSinceLastAttempt and timeSinceLastSummary for the\n\t\t// first summary are basically the time since the summarizer was loaded.\n\t\tconst timeSinceLastAttempt = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\tconst timeSinceLastSummary =\n\t\t\tDate.now() - this.heuristicData.lastSuccessfulSummary.summaryTime;\n\t\tlet summarizeTelemetryProps: SummaryGeneratorTelemetry = {\n\t\t\t...summarizeOptions,\n\t\t\tfullTree: summarizeOptions.fullTree ?? false,\n\t\t\ttimeSinceLastAttempt,\n\t\t\ttimeSinceLastSummary,\n\t\t\tnonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,\n\t\t\truntimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,\n\t\t};\n\n\t\tconst summarizeEvent = PerformanceEvent.start(\n\t\t\tsummaryLogger,\n\t\t\t{\n\t\t\t\teventName: \"Summarize\",\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t},\n\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t);\n\n\t\tlet summaryData: SubmitSummaryResult | undefined;\n\n\t\t/**\n\t\t * Summarization can fail during submit, during op broadcast or during nack.\n\t\t * For submit failures, submitFailureResult should be provided. For nack failures, nackSummaryResult should\n\t\t * be provided. For op broadcast failures, only errors / properties should be provided.\n\t\t */\n\t\tconst fail = (\n\t\t\terrorCode: SummarizeErrorCode,\n\t\t\terror: IRetriableFailureError,\n\t\t\tproperties?: SummaryGeneratorTelemetry,\n\t\t\tsubmitFailureResult?: SubmitSummaryFailureData,\n\t\t\tnackSummaryResult?: INackSummaryResult,\n\t\t): void => {\n\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t// If failure happened on upload, we may not yet realized that socket disconnected, so check\n\t\t\t// offlineError too.\n\t\t\tconst category =\n\t\t\t\tcancellationToken.cancelled ||\n\t\t\t\t(isFluidError(error) && error?.errorType === DriverErrorTypes.offlineError)\n\t\t\t\t\t? \"generic\"\n\t\t\t\t\t: \"error\";\n\n\t\t\tconst reason = getFailMessage(errorCode);\n\t\t\tsummarizeEvent.cancel(\n\t\t\t\t{\n\t\t\t\t\t...properties,\n\t\t\t\t\treason,\n\t\t\t\t\tcategory,\n\t\t\t\t\tretryAfterSeconds: error.retryAfterSeconds,\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t); // disconnect & summaryAckTimeout do not have proper error.\n\n\t\t\tresultsBuilder.fail(reason, error, submitFailureResult, nackSummaryResult);\n\t\t};\n\n\t\t// Wait to generate and send summary\n\t\tthis.summarizeTimer.start();\n\t\ttry {\n\t\t\ttelemetryContext.setCurrentSummarizeStep(\"generateSummary\");\n\t\t\t// Need to save refSeqNum before we record new attempt (happens as part of submitSummaryCallback)\n\t\t\tconst lastAttemptRefSeqNum = this.heuristicData.lastAttempt.refSequenceNumber;\n\n\t\t\tsummaryData = await this.submitSummaryCallback(submitOptions);\n\t\t\ttelemetryContext.setCurrentSummarizeStep(\"submitSummaryOp\");\n\n\t\t\t// Cumulatively add telemetry properties based on how far generateSummary went.\n\t\t\tconst referenceSequenceNumber = summaryData.referenceSequenceNumber;\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t\tminimumSequenceNumber: summaryData.minimumSequenceNumber,\n\t\t\t\topsSinceLastAttempt: referenceSequenceNumber - lastAttemptRefSeqNum,\n\t\t\t\topsSinceLastSummary:\n\t\t\t\t\treferenceSequenceNumber - this.heuristicData.lastSuccessfulSummary.refSequenceNumber,\n\t\t\t\tstage: summaryData.stage,\n\t\t\t};\n\t\t\tsummarizeTelemetryProps = this.addSummaryDataToTelemetryProps(\n\t\t\t\tsummaryData,\n\t\t\t\tsummarizeTelemetryProps,\n\t\t\t);\n\n\t\t\tif (summaryData.stage !== \"submit\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"submitSummaryFailure\";\n\t\t\t\tconst retriableError =\n\t\t\t\t\tsummaryData.error ?? new RetriableSummaryError(getFailMessage(errorCode));\n\t\t\t\treturn fail(errorCode, retriableError, summarizeTelemetryProps, {\n\t\t\t\t\tstage: summaryData.stage,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * With incremental summaries, if the full tree was not summarized, only data stores that changed should\n\t\t\t * be summarized. A data store is considered changed if either or both of the following is true:\n\t\t\t * - It has received an op.\n\t\t\t * - Its reference state changed, i.e., it went from referenced to unreferenced or vice-versa.\n\t\t\t *\n\t\t\t * In the extreme case, every op can be for a different data store and each op can result in the reference\n\t\t\t * state change of multiple data stores. So, the total number of data stores that are summarized should not\n\t\t\t * exceed the number of ops since last summary + number of data store whose reference state changed.\n\t\t\t */\n\t\t\tif (submitSummaryOptions.fullTree !== true) {\n\t\t\t\ttelemetryContext.setCurrentSummarizeStep(\"watchSummary\");\n\t\t\t\tconst { summarizedDataStoreCount, gcStateUpdatedDataStoreCount = 0 } =\n\t\t\t\t\tsummaryData.summaryStats;\n\t\t\t\tif (\n\t\t\t\t\tsummarizedDataStoreCount >\n\t\t\t\t\tgcStateUpdatedDataStoreCount + this.heuristicData.opsSinceLastSummary\n\t\t\t\t) {\n\t\t\t\t\tsummaryLogger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"IncrementalSummaryViolation\",\n\t\t\t\t\t\tsummarizedDataStoreCount,\n\t\t\t\t\t\tgcStateUpdatedDataStoreCount,\n\t\t\t\t\t\topsSinceLastSummary: this.heuristicData.opsSinceLastSummary,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Log event here on summary success only, as Summarize_cancel duplicates failure logging.\n\t\t\tsummarizeEvent.reportEvent(\"generate\", { ...summarizeTelemetryProps });\n\t\t\tresultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });\n\t\t} catch (error) {\n\t\t\treturn fail(\n\t\t\t\t\"submitSummaryFailure\",\n\t\t\t\twrapError(\n\t\t\t\t\terror,\n\t\t\t\t\t(message) =>\n\t\t\t\t\t\tnew RetriableSummaryError(message, getRetryDelaySecondsFromError(error)),\n\t\t\t\t),\n\t\t\t\tundefined /* properties */,\n\t\t\t\t{\n\t\t\t\t\tstage: \"unknown\",\n\t\t\t\t},\n\t\t\t);\n\t\t} finally {\n\t\t\tif (summaryData === undefined) {\n\t\t\t\tthis.heuristicData.recordAttempt();\n\t\t\t}\n\t\t\tthis.summarizeTimer.clear();\n\t\t}\n\n\t\ttelemetryContext.setCurrentSummarizeStep(\"waitForSummaryAck\");\n\n\t\ttry {\n\t\t\tconst pendingTimeoutP = this.pendingAckTimer.start();\n\t\t\tconst summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);\n\n\t\t\t// Wait for broadcast\n\t\t\tconst waitBroadcastResult = await raceTimer(\n\t\t\t\tsummary.waitBroadcast(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitBroadcastResult.result === \"cancelled\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"disconnect\";\n\t\t\t\treturn fail(errorCode, new RetriableSummaryError(getFailMessage(errorCode)));\n\t\t\t}\n\t\t\tif (waitBroadcastResult.result !== \"done\") {\n\t\t\t\t// The summary op may not have been received within the timeout due to a transient error. So,\n\t\t\t\t// fail with a retriable error to re-attempt the summary if possible.\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"summaryOpWaitTimeout\";\n\t\t\t\treturn fail(\n\t\t\t\t\terrorCode,\n\t\t\t\t\tnew RetriableSummaryError(getFailMessage(errorCode), 0 /* retryAfterSeconds */),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst summarizeOp = waitBroadcastResult.value;\n\n\t\t\tconst broadcastDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\t\tresultsBuilder.summaryOpBroadcasted.resolve({\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: { summarizeOp, broadcastDuration },\n\t\t\t});\n\n\t\t\tthis.heuristicData.lastAttempt.summarySequenceNumber = summarizeOp.sequenceNumber;\n\t\t\tsummaryLogger.sendTelemetryEvent({\n\t\t\t\teventName: \"Summarize_Op\",\n\t\t\t\tduration: broadcastDuration,\n\t\t\t\treferenceSequenceNumber: summarizeOp.referenceSequenceNumber,\n\t\t\t\tsummarySequenceNumber: summarizeOp.sequenceNumber,\n\t\t\t\thandle: summarizeOp.contents.handle,\n\t\t\t});\n\n\t\t\t// Wait for ack/nack\n\t\t\tconst waitAckNackResult = await raceTimer(\n\t\t\t\tsummary.waitAckNack(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitAckNackResult.result === \"cancelled\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"disconnect\";\n\t\t\t\treturn fail(errorCode, new RetriableSummaryError(getFailMessage(errorCode)));\n\t\t\t}\n\t\t\tif (waitAckNackResult.result !== \"done\") {\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"summaryAckWaitTimeout\";\n\t\t\t\t// The summary ack may not have been received within the timeout due to a transient error. So,\n\t\t\t\t// fail with a retriable error to re-attempt the summary if possible.\n\t\t\t\treturn fail(\n\t\t\t\t\terrorCode,\n\t\t\t\t\tnew RetriableSummaryError(getFailMessage(errorCode), 0 /* retryAfterSeconds */),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst ackNackOp = waitAckNackResult.value;\n\t\t\tthis.pendingAckTimer.clear();\n\n\t\t\t// Update for success/failure\n\t\t\tconst ackNackDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\n\t\t\t// adding new properties\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\tackWaitDuration: ackNackDuration,\n\t\t\t\tackNackSequenceNumber: ackNackOp.sequenceNumber,\n\t\t\t\tsummarySequenceNumber: ackNackOp.contents.summaryProposal.summarySequenceNumber,\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t};\n\t\t\tif (ackNackOp.type === MessageType.SummaryAck) {\n\t\t\t\ttelemetryContext.setCurrentSummarizeStep(\"ackReceived\");\n\t\t\t\tthis.heuristicData.markLastAttemptAsSuccessful();\n\t\t\t\tthis.successfulSummaryCallback();\n\t\t\t\tsummarizeEvent.end({\n\t\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\t\thandle: ackNackOp.contents.handle,\n\t\t\t\t});\n\t\t\t\t// This processes the summary ack of the successful summary. This is so that the next summary does not\n\t\t\t\t// start before the ack of the previous summary is processed.\n\t\t\t\tawait this.refreshLatestSummaryCallback({\n\t\t\t\t\tproposalHandle: summarizeOp.contents.handle,\n\t\t\t\t\tackHandle: ackNackOp.contents.handle,\n\t\t\t\t\tsummaryRefSeq: summarizeOp.referenceSequenceNumber,\n\t\t\t\t\tsummaryLogger,\n\t\t\t\t});\n\t\t\t\tresultsBuilder.receivedSummaryAckOrNack.resolve({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tsummaryAckOp: ackNackOp,\n\t\t\t\t\t\tackNackDuration,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Check for retryDelay in summaryNack response.\n\t\t\t\tassert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* \"type check\" */);\n\t\t\t\ttelemetryContext.setCurrentSummarizeStep(\"nackReceived\");\n\t\t\t\tconst summaryNack = ackNackOp.contents;\n\t\t\t\tconst errorMessage = summaryNack?.message;\n\t\t\t\tconst retryAfterSeconds = summaryNack?.retryAfter;\n\n\t\t\t\tconst errorCode: SummarizeErrorCode = \"summaryNack\";\n\n\t\t\t\t// pre-0.58 error message prefix: summaryNack\n\t\t\t\tconst error = new RetriableSummaryError(getFailMessage(errorCode), retryAfterSeconds, {\n\t\t\t\t\terrorMessage,\n\t\t\t\t});\n\n\t\t\t\tassert(\n\t\t\t\t\tgetRetryDelaySecondsFromError(error) === retryAfterSeconds,\n\t\t\t\t\t0x25f /* \"retryAfterSeconds\" */,\n\t\t\t\t);\n\t\t\t\t// This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.\n\t\t\t\treturn fail(\n\t\t\t\t\terrorCode,\n\t\t\t\t\terror,\n\t\t\t\t\t{ ...summarizeTelemetryProps, nackRetryAfter: retryAfterSeconds },\n\t\t\t\t\tundefined /* submitFailureResult */,\n\t\t\t\t\t{ summaryNackOp: ackNackOp, ackNackDuration },\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.pendingAckTimer.clear();\n\t\t\tthis.activeTelemetryContext = undefined;\n\t\t}\n\t}\n\n\tprivate addSummaryDataToTelemetryProps(\n\t\tsummaryData: SubmitSummaryResult,\n\t\tinitialProps: SummaryGeneratorTelemetry,\n\t): SummaryGeneratorTelemetry {\n\t\tswitch (summaryData.stage) {\n\t\t\tcase \"base\": {\n\t\t\t\treturn initialProps;\n\t\t\t}\n\n\t\t\tcase \"generate\": {\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tcase \"upload\": {\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tcase \"submit\": {\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t\tclientSequenceNumber: summaryData.clientSequenceNumber,\n\t\t\t\t\thasMissingOpData: this.heuristicData.hasMissingOpData,\n\t\t\t\t\topsSizesSinceLastSummary: this.heuristicData.totalOpsSize,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tassert(true, 0x397 /* Unexpected summary stage */);\n\t\t\t}\n\t\t}\n\n\t\treturn initialProps;\n\t}\n\n\tprivate summarizeTimerHandler(time: number, count: number): void {\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"SummarizeTimeout\",\n\t\t\ttimeoutTime: time,\n\t\t\ttimeoutCount: count,\n\t\t\tcurrentSummarizeStep: this.activeTelemetryContext?.getCurrentSummarizeStep(),\n\t\t});\n\t\tthis.emit(\"summarizeTimeout\", {\n\t\t\ttimeoutCount: count,\n\t\t\tcurrentSummarizeStep: this.activeTelemetryContext?.getCurrentSummarizeStep(),\n\t\t\tnumUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,\n\t\t\tnumUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,\n\t\t});\n\t\tif (count < maxSummarizeTimeoutCount) {\n\t\t\t// Double and start a new timer\n\t\t\tconst nextTime = time * 2;\n\t\t\tthis.summarizeTimer.start(nextTime, () =>\n\t\t\t\tthis.summarizeTimerHandler(nextTime, count + 1),\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.summarizeTimer.clear();\n\t\tthis.activeTelemetryContext = undefined;\n\t}\n}\n"]}
@@ -92,7 +92,7 @@ export declare class SummaryManager extends TypedEventEmitter<ISummarizerEvents>
92
92
  summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults;
93
93
  enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult;
94
94
  dispose(): void;
95
- private readonly forwardedEvents;
95
+ private readonly forwardedEventsCleanup;
96
96
  private setupForwardedEvents;
97
97
  private cleanupForwardedEvents;
98
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../../src/summary/summaryManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../../src/summary/summaryManager.ts"],"names":[],"mappings":"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"}
@@ -84,7 +84,7 @@ export class SummaryManager extends TypedEventEmitter {
84
84
  }
85
85
  }
86
86
  };
87
- this.forwardedEvents = new Map();
87
+ this.forwardedEventsCleanup = [];
88
88
  this.logger = createChildLogger({
89
89
  logger: parentLogger,
90
90
  namespace: "SummaryManager",
@@ -157,7 +157,7 @@ export class SummaryManager extends TypedEventEmitter {
157
157
  this.state = SummaryManagerState.Running;
158
158
  const summarizer = await this.createSummarizerFn();
159
159
  this.summarizer = summarizer;
160
- this.setupForwardedEvents();
160
+ this.setupForwardedEvents(summarizer);
161
161
  // Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore
162
162
  // If we can't run the LastSummary, simply return as to avoid paying the cost of launching
163
163
  // the summarizer at all.
@@ -311,29 +311,30 @@ export class SummaryManager extends TypedEventEmitter {
311
311
  this.cleanupForwardedEvents();
312
312
  this._disposed = true;
313
313
  }
314
- setupForwardedEvents() {
314
+ setupForwardedEvents(summarizer) {
315
315
  for (const event of [
316
316
  "summarize",
317
317
  "summarizeAllAttemptsFailed",
318
318
  "summarizerStop",
319
319
  "summarizerStart",
320
320
  "summarizerStartupFailed",
321
+ "summarizeTimeout",
321
322
  ]) {
322
323
  const listener = (...args) => {
323
324
  this.emit(event, ...args);
324
325
  };
325
326
  // TODO: better typing here
326
327
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
327
- this.summarizer?.on(event, listener);
328
- this.forwardedEvents.set(event, listener);
328
+ summarizer.on(event, listener);
329
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
330
+ this.forwardedEventsCleanup.push(() => summarizer.off(event, listener));
329
331
  }
330
332
  }
331
333
  cleanupForwardedEvents() {
332
- for (const [event, listener] of this.forwardedEvents.entries()) {
333
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
334
- this.summarizer?.off(event, listener);
334
+ for (const cleanup of this.forwardedEventsCleanup) {
335
+ cleanup();
335
336
  }
336
- this.forwardedEvents.clear();
337
+ this.forwardedEventsCleanup.length = 0;
337
338
  }
338
339
  }
339
340
  SummaryManager.isStartingOrRunning = (state) => state === SummaryManagerState.Starting || state === SummaryManagerState.Running;
@@ -1 +1 @@
1
- {"version":3,"file":"summaryManager.js","sourceRoot":"","sources":["../../src/summary/summaryManager.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type {\n\tISummarizerEvents,\n\tSummarizerStopReason,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type {\n\tIDisposable,\n\tIEvent,\n\tIEventProvider,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tPerformanceEvent,\n\tcreateChildLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { IThrottler } from \"../throttler.js\";\n\nimport type { ISummarizerClientElection } from \"./summarizerClientElection.js\";\nimport type {\n\tIEnqueueSummarizeOptions,\n\tIOnDemandSummarizeOptions,\n\tISummarizer,\n} from \"./summarizerTypes.js\";\nimport { stopReasonCanRunLastSummary } from \"./summarizerUtils.js\";\nimport type { SummaryCollection } from \"./summaryCollection.js\";\nimport type {\n\tEnqueueSummarizeResult,\n\tISummarizeResults,\n} from \"./summaryDelayLoadedModule/index.js\";\n\nconst defaultInitialDelayMs = 5000;\nconst defaultOpsToBypassInitialDelay = 4000;\n\nexport enum SummaryManagerState {\n\tOff = 0,\n\tStarting = 1,\n\tRunning = 2,\n\tStopping = 3,\n}\n\n// Please note that all reasons in this list are not errors,\n// and thus they are not raised today to parent container as error.\n// If this needs to be changed in future, we should re-evaluate what and how we raise to summarizer\ntype StopReason = Extract<\n\tSummarizerStopReason,\n\t\"parentNotConnected\" | \"notElectedParent\" | \"notElectedClient\"\n>;\ntype ShouldSummarizeState =\n\t| { shouldSummarize: true }\n\t| { shouldSummarize: false; stopReason: StopReason };\n\nexport interface IConnectedEvents extends IEvent {\n\t(event: \"connected\", listener: (clientId: string) => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * IConnectedState describes an object that SummaryManager can watch to observe connection/disconnection.\n *\n * Under current implementation, its role will be fulfilled by the ContainerRuntime, but this could be replaced\n * with anything else that fulfills the contract if we want to shift the layer that the SummaryManager lives at.\n */\nexport interface IConnectedState extends IEventProvider<IConnectedEvents> {\n\treadonly connected: boolean;\n\n\t/**\n\t * Under current implementation this is undefined if we've never connected, otherwise it's the clientId from our\n\t * latest connection (even if we've since disconnected!). Although this happens to be the behavior we want in\n\t * SummaryManager, I suspect that globally we may eventually want to modify this behavior (e.g. make clientId\n\t * undefined while disconnected). To protect against this, let's assume this field can't be trusted while\n\t * disconnected and instead separately track \"latest clientId\" in SummaryManager.\n\t */\n\treadonly clientId: string | undefined;\n}\n\nexport interface ISummaryManagerConfig {\n\tinitialDelayMs: number;\n\topsToBypassInitialDelay: number;\n}\n\n/**\n * SummaryManager is created by parent container (i.e. interactive container with clientType !== \"summarizer\") only.\n * It observes changes in calculated summarizer and reacts to changes by either creating summarizer client or\n * stopping existing summarizer client.\n */\nexport class SummaryManager\n\textends TypedEventEmitter<ISummarizerEvents>\n\timplements IDisposable\n{\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly opsToBypassInitialDelay: number;\n\tprivate readonly initialDelayMs: number;\n\tprivate latestClientId: string | undefined;\n\tprivate state = SummaryManagerState.Off;\n\tprivate summarizer?: ISummarizer;\n\tprivate _disposed = false;\n\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\n\tpublic get currentState(): SummaryManagerState {\n\t\treturn this.state;\n\t}\n\n\tconstructor(\n\t\tprivate readonly clientElection: ISummarizerClientElection,\n\t\tprivate readonly connectedState: IConnectedState,\n\t\tprivate readonly summaryCollection: Pick<\n\t\t\tSummaryCollection,\n\t\t\t\"opsSinceLastAck\" | \"addOpListener\" | \"removeOpListener\"\n\t\t>,\n\t\tparentLogger: ITelemetryBaseLogger,\n\t\t/**\n\t\t * Creates summarizer by asking interactive container to spawn summarizing container and\n\t\t * get back its Summarizer instance.\n\t\t */\n\t\tprivate readonly createSummarizerFn: () => Promise<ISummarizer>,\n\t\tprivate readonly startThrottler: IThrottler,\n\t\t{\n\t\t\tinitialDelayMs = defaultInitialDelayMs,\n\t\t\topsToBypassInitialDelay = defaultOpsToBypassInitialDelay,\n\t\t}: Readonly<Partial<ISummaryManagerConfig>> = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.logger = createChildLogger({\n\t\t\tlogger: parentLogger,\n\t\t\tnamespace: \"SummaryManager\",\n\t\t\tproperties: {\n\t\t\t\tall: { clientId: () => this.latestClientId },\n\t\t\t},\n\t\t});\n\n\t\tthis.connectedState.on(\"connected\", this.handleConnected);\n\t\tthis.connectedState.on(\"disconnected\", this.handleDisconnected);\n\t\tthis.latestClientId = this.connectedState.clientId;\n\n\t\tthis.opsToBypassInitialDelay = opsToBypassInitialDelay;\n\t\tthis.initialDelayMs = initialDelayMs;\n\t}\n\n\t/**\n\t * Until start is called, the SummaryManager won't begin attempting to start summarization. This ensures there's\n\t * a window between construction and starting where the caller can attach listeners.\n\t */\n\tpublic start(): void {\n\t\tthis.clientElection.on(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.refreshSummarizer();\n\t}\n\n\tprivate readonly handleConnected = (clientId: string): void => {\n\t\tthis.latestClientId = clientId;\n\t\t// If we have a summarizer, it should have been either cancelled on disconnected by now.\n\t\t// But because of lastSummary process, it can still hang around, so there is not much we can\n\t\t// check or assert.\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate readonly handleDisconnected = (): void => {\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate static readonly isStartingOrRunning = (\n\t\tstate: SummaryManagerState,\n\t): state is SummaryManagerState.Starting | SummaryManagerState.Running =>\n\t\tstate === SummaryManagerState.Starting || state === SummaryManagerState.Running;\n\n\tprivate getShouldSummarizeState(): ShouldSummarizeState {\n\t\tif (this.disposed) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n\t\t}\n\n\t\t// Note that if we're in the Running state, the electedClient may be a summarizer client, so we can't\n\t\t// enforce connectedState.clientId === clientElection.electedClientId. But once we're Running, we should\n\t\t// only transition to Stopping when the electedParentId changes. Stopping the summarizer without\n\t\t// changing the electedParent will just cause us to transition to Starting again.\n\n\t\t// New Parent has been elected and it is not the current client, or\n\t\tif (this.connectedState.clientId !== this.clientElection.electedParentId) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedParent\" };\n\t\t}\n\n\t\t// We are not already running the summarizer and we are not the current elected client id.\n\t\tif (\n\t\t\tthis.state !== SummaryManagerState.Running &&\n\t\t\tthis.connectedState.clientId !== this.clientElection.electedClientId\n\t\t) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedClient\" };\n\t\t}\n\n\t\tif (!this.connectedState.connected) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n\t\t}\n\n\t\treturn { shouldSummarize: true };\n\t}\n\n\tprivate readonly refreshSummarizer = (): void => {\n\t\t// Transition states depending on shouldSummarize, which is a calculated property\n\t\t// that is only true if this client is connected and is the elected summarizer.\n\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\tswitch (this.state) {\n\t\t\tcase SummaryManagerState.Off: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Starting: {\n\t\t\t\t// Cannot take any action until summarizer is created\n\t\t\t\t// state transition will occur after creation\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Running: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\tthis.stop(shouldSummarizeState.stopReason);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Stopping: {\n\t\t\t\t// Cannot take any action until running summarizer finishes\n\t\t\t\t// state transition will occur after it stops\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate startSummarization(): void {\n\t\tassert(this.state === SummaryManagerState.Off, 0x261 /* \"Expected: off\" */);\n\t\tthis.state = SummaryManagerState.Starting;\n\n\t\tassert(this.summarizer === undefined, 0x262 /* \"Old summarizer is still working!\" */);\n\n\t\tthis.delayBeforeCreatingSummarizer()\n\t\t\t.then(async (startWithInitialDelay: boolean) => {\n\t\t\t\tif (this.disposed) {\n\t\t\t\t\treturn \"early exit (disposed)\";\n\t\t\t\t}\n\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// but only if creation was delayed. If it was not, then we want to ensure we always create\n\t\t\t\t// a summarizer to kick off lastSummary. Without that, we would not be able to summarize and get\n\t\t\t\t// document out of broken state if it has too many ops and ordering service keeps nacking main\n\t\t\t\t// container (and thus it goes into cycle of reconnects)\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeStateEarlyStage = this.getShouldSummarizeState();\n\t\t\t\tif (\n\t\t\t\t\tstartWithInitialDelay &&\n\t\t\t\t\tshouldSummarizeStateEarlyStage.shouldSummarize === false\n\t\t\t\t) {\n\t\t\t\t\treturn `early exit ${shouldSummarizeStateEarlyStage.stopReason}`;\n\t\t\t\t}\n\n\t\t\t\t// We transition to Running before requesting the summarizer, because after requesting we can't predict\n\t\t\t\t// when the electedClient will be replaced with the new summarizer client.\n\t\t\t\t// The alternative would be to let connectedState.clientId !== clientElection.electedClientId when\n\t\t\t\t// state === Starting || state === Running.\n\t\t\t\tassert(this.state === SummaryManagerState.Starting, 0x263 /* \"Expected: starting\" */);\n\t\t\t\tthis.state = SummaryManagerState.Running;\n\n\t\t\t\tconst summarizer = await this.createSummarizerFn();\n\t\t\t\tthis.summarizer = summarizer;\n\t\t\t\tthis.setupForwardedEvents();\n\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\t// In order to allow the last summary to run, we not only need a stop reason that would\n\t\t\t\t\t// allow it but also, startWithInitialDelay to be false (start the summarization immediately),\n\t\t\t\t\t// which would happen when we have a high enough number of unsummarized ops.\n\t\t\t\t\tif (\n\t\t\t\t\t\tstartWithInitialDelay ||\n\t\t\t\t\t\t!stopReasonCanRunLastSummary(shouldSummarizeState.stopReason)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.state = SummaryManagerState.Starting;\n\t\t\t\t\t\tsummarizer.stop(shouldSummarizeState.stopReason);\n\t\t\t\t\t\treturn `early exit after starting summarizer ${shouldSummarizeState.stopReason}`;\n\t\t\t\t\t}\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"LastAttemptToSummarize\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst clientId = this.latestClientId!;\n\n\t\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\t\tthis.logger,\n\t\t\t\t\t{ eventName: \"RunningSummarizer\", attempt: this.startThrottler.numAttempts },\n\t\t\t\t\tasync () => summarizer.run(clientId),\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then((reason: string) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\treason,\n\t\t\t\t});\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\t\treason: \"exception\",\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\n\t\t\t\t// Most of exceptions happen due to container being closed while loading it, due to\n\t\t\t\t// summarizer container loosing connection while load.\n\t\t\t\t// Not worth reporting such errors as errors. That said, we might miss some real errors if\n\t\t\t\t// we ignore blindly, so try to narrow signature we are looking for - skip logging\n\t\t\t\t// error only if this client should no longer be a summarizer (which in practice\n\t\t\t\t// means it also lost connection), and error happened on load (we do not have summarizer).\n\t\t\t\t// We could annotate the error raised in Container.load where the container closed during load with no error\n\t\t\t\t// and check for that case here, but that does not seem to be necessary.\n\t\t\t\tif (this.getShouldSummarizeState().shouldSummarize || this.summarizer !== undefined) {\n\t\t\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t\t\t// If failure happened on container load, we may not yet realized that socket disconnected, so check\n\t\t\t\t\t// offlineError.\n\t\t\t\t\tconst category =\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\t\terror?.errorType === DriverErrorTypes.offlineError ? \"generic\" : \"error\";\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"SummarizerException\",\n\t\t\t\t\t\t\tcategory,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tassert(this.state !== SummaryManagerState.Off, 0x264 /* \"Expected: Not Off\" */);\n\t\t\t\tthis.state = SummaryManagerState.Off;\n\n\t\t\t\tthis.cleanupForwardedEvents();\n\t\t\t\tthis.summarizer?.close();\n\t\t\t\tthis.summarizer = undefined;\n\n\t\t\t\tif (this.getShouldSummarizeState().shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tprivate stop(reason: SummarizerStopReason): void {\n\t\tif (!SummaryManager.isStartingOrRunning(this.state)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.state = SummaryManagerState.Stopping;\n\n\t\t// Stopping the running summarizer client should trigger a change\n\t\t// in states when the running summarizer closes\n\t\tthis.summarizer?.stop(reason);\n\t}\n\n\t/**\n\t * Implements initial delay before creating summarizer\n\t * @returns `true`, if creation is delayed due to heuristics (not many ops to summarize).\n\t * `false` if summarizer should start immediately due to too many unsummarized ops.\n\t */\n\tprivate async delayBeforeCreatingSummarizer(): Promise<boolean> {\n\t\t// throttle creation of new summarizer containers to prevent spamming the server with websocket connections\n\t\tlet delayMs = this.startThrottler.getDelay();\n\n\t\t// We have been elected the summarizer. Some day we may be able to summarize with a live document but for\n\t\t// now we play it safe and launch a second copy.\n\t\tthis.logger.sendTelemetryEvent({\n\t\t\teventName: \"CreatingSummarizer\",\n\t\t\tthrottlerDelay: delayMs,\n\t\t\tinitialDelay: this.initialDelayMs,\n\t\t\tstartThrottlerMaxDelayMs: this.startThrottler.maxDelayMs,\n\t\t\topsSinceLastAck: this.summaryCollection.opsSinceLastAck,\n\t\t\topsToBypassInitialDelay: this.opsToBypassInitialDelay,\n\t\t\telectedParentId: this.clientElection.electedParentId,\n\t\t\telectedClientId: this.clientElection.electedClientId,\n\t\t});\n\n\t\t// This delay helps ensure that last summarizer that might be left from previous client\n\t\t// has enough time to complete its last summary and thus new summarizer not conflict with previous one.\n\t\t// If, however, there are too many unsummarized ops, try to resolve it as quickly as possible, with\n\t\t// understanding that we may see nacks because of such quick action.\n\t\t// A better design would be for summarizer election logic to always select current summarizer as\n\t\t// summarizing client (i.e. clientType === \"summarizer\" can be elected) to ensure that nobody else can\n\t\t// summarizer while it finishes its work and moves to exit.\n\t\t// It also helps with pure boot scenario (single client) to offset expensive work a bit out from\n\t\t// critical boot sequence.\n\t\tlet startWithInitialDelay = false;\n\t\tif (this.summaryCollection.opsSinceLastAck < this.opsToBypassInitialDelay) {\n\t\t\tstartWithInitialDelay = true;\n\t\t\tdelayMs = Math.max(delayMs, this.initialDelayMs);\n\t\t}\n\n\t\tif (delayMs > 0) {\n\t\t\tlet timer: number | undefined;\n\t\t\tlet resolveOpPromiseFn: (value: void | PromiseLike<void>) => void;\n\t\t\t// Create a listener that will break the delay if we've exceeded the initial delay ops count.\n\t\t\tconst opsListenerFn = (): void => {\n\t\t\t\tif (this.summaryCollection.opsSinceLastAck >= this.opsToBypassInitialDelay) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolveOpPromiseFn();\n\t\t\t\t}\n\t\t\t};\n\t\t\t// Create a Promise that will resolve when the delay expires.\n\t\t\tconst delayPromise = new Promise<void>((resolve) => {\n\t\t\t\ttimer = setTimeout(() => resolve(), delayMs);\n\t\t\t});\n\t\t\t// Create a Promise that will resolve if the ops count passes the threshold.\n\t\t\tconst opPromise = new Promise<void>((resolve) => {\n\t\t\t\tresolveOpPromiseFn = resolve;\n\t\t\t});\n\t\t\tthis.summaryCollection.addOpListener(opsListenerFn);\n\t\t\tawait Promise.race([delayPromise, opPromise]);\n\t\t\tthis.summaryCollection.removeOpListener(opsListenerFn);\n\t\t}\n\t\treturn startWithInitialDelay;\n\t}\n\n\tpublic summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow new Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.summarizeOnDemand(options);\n\t}\n\n\tpublic enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow new Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.enqueueSummarize(options);\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.clientElection.off(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.connectedState.off(\"connected\", this.handleConnected);\n\t\tthis.connectedState.off(\"disconnected\", this.handleDisconnected);\n\t\tthis.cleanupForwardedEvents();\n\t\tthis._disposed = true;\n\t}\n\n\tprivate readonly forwardedEvents = new Map<string, () => void>();\n\n\tprivate setupForwardedEvents(): void {\n\t\tfor (const event of [\n\t\t\t\"summarize\",\n\t\t\t\"summarizeAllAttemptsFailed\",\n\t\t\t\"summarizerStop\",\n\t\t\t\"summarizerStart\",\n\t\t\t\"summarizerStartupFailed\",\n\t\t]) {\n\t\t\tconst listener = (...args: unknown[]): void => {\n\t\t\t\tthis.emit(event, ...args);\n\t\t\t};\n\t\t\t// TODO: better typing here\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument\n\t\t\tthis.summarizer?.on(event as any, listener);\n\t\t\tthis.forwardedEvents.set(event, listener);\n\t\t}\n\t}\n\n\tprivate cleanupForwardedEvents(): void {\n\t\tfor (const [event, listener] of this.forwardedEvents.entries()) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument\n\t\t\tthis.summarizer?.off(event as any, listener);\n\t\t}\n\t\tthis.forwardedEvents.clear();\n\t}\n}\n"]}
1
+ {"version":3,"file":"summaryManager.js","sourceRoot":"","sources":["../../src/summary/summaryManager.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type {\n\tISummarizerEvents,\n\tSummarizerStopReason,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type {\n\tIDisposable,\n\tIEvent,\n\tIEventProvider,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tPerformanceEvent,\n\tcreateChildLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { IThrottler } from \"../throttler.js\";\n\nimport type { ISummarizerClientElection } from \"./summarizerClientElection.js\";\nimport type {\n\tIEnqueueSummarizeOptions,\n\tIOnDemandSummarizeOptions,\n\tISummarizer,\n} from \"./summarizerTypes.js\";\nimport { stopReasonCanRunLastSummary } from \"./summarizerUtils.js\";\nimport type { SummaryCollection } from \"./summaryCollection.js\";\nimport type {\n\tEnqueueSummarizeResult,\n\tISummarizeResults,\n} from \"./summaryDelayLoadedModule/index.js\";\n\nconst defaultInitialDelayMs = 5000;\nconst defaultOpsToBypassInitialDelay = 4000;\n\nexport enum SummaryManagerState {\n\tOff = 0,\n\tStarting = 1,\n\tRunning = 2,\n\tStopping = 3,\n}\n\n// Please note that all reasons in this list are not errors,\n// and thus they are not raised today to parent container as error.\n// If this needs to be changed in future, we should re-evaluate what and how we raise to summarizer\ntype StopReason = Extract<\n\tSummarizerStopReason,\n\t\"parentNotConnected\" | \"notElectedParent\" | \"notElectedClient\"\n>;\ntype ShouldSummarizeState =\n\t| { shouldSummarize: true }\n\t| { shouldSummarize: false; stopReason: StopReason };\n\nexport interface IConnectedEvents extends IEvent {\n\t(event: \"connected\", listener: (clientId: string) => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * IConnectedState describes an object that SummaryManager can watch to observe connection/disconnection.\n *\n * Under current implementation, its role will be fulfilled by the ContainerRuntime, but this could be replaced\n * with anything else that fulfills the contract if we want to shift the layer that the SummaryManager lives at.\n */\nexport interface IConnectedState extends IEventProvider<IConnectedEvents> {\n\treadonly connected: boolean;\n\n\t/**\n\t * Under current implementation this is undefined if we've never connected, otherwise it's the clientId from our\n\t * latest connection (even if we've since disconnected!). Although this happens to be the behavior we want in\n\t * SummaryManager, I suspect that globally we may eventually want to modify this behavior (e.g. make clientId\n\t * undefined while disconnected). To protect against this, let's assume this field can't be trusted while\n\t * disconnected and instead separately track \"latest clientId\" in SummaryManager.\n\t */\n\treadonly clientId: string | undefined;\n}\n\nexport interface ISummaryManagerConfig {\n\tinitialDelayMs: number;\n\topsToBypassInitialDelay: number;\n}\n\n/**\n * SummaryManager is created by parent container (i.e. interactive container with clientType !== \"summarizer\") only.\n * It observes changes in calculated summarizer and reacts to changes by either creating summarizer client or\n * stopping existing summarizer client.\n */\nexport class SummaryManager\n\textends TypedEventEmitter<ISummarizerEvents>\n\timplements IDisposable\n{\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly opsToBypassInitialDelay: number;\n\tprivate readonly initialDelayMs: number;\n\tprivate latestClientId: string | undefined;\n\tprivate state = SummaryManagerState.Off;\n\tprivate summarizer?: ISummarizer;\n\tprivate _disposed = false;\n\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\n\tpublic get currentState(): SummaryManagerState {\n\t\treturn this.state;\n\t}\n\n\tconstructor(\n\t\tprivate readonly clientElection: ISummarizerClientElection,\n\t\tprivate readonly connectedState: IConnectedState,\n\t\tprivate readonly summaryCollection: Pick<\n\t\t\tSummaryCollection,\n\t\t\t\"opsSinceLastAck\" | \"addOpListener\" | \"removeOpListener\"\n\t\t>,\n\t\tparentLogger: ITelemetryBaseLogger,\n\t\t/**\n\t\t * Creates summarizer by asking interactive container to spawn summarizing container and\n\t\t * get back its Summarizer instance.\n\t\t */\n\t\tprivate readonly createSummarizerFn: () => Promise<ISummarizer>,\n\t\tprivate readonly startThrottler: IThrottler,\n\t\t{\n\t\t\tinitialDelayMs = defaultInitialDelayMs,\n\t\t\topsToBypassInitialDelay = defaultOpsToBypassInitialDelay,\n\t\t}: Readonly<Partial<ISummaryManagerConfig>> = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.logger = createChildLogger({\n\t\t\tlogger: parentLogger,\n\t\t\tnamespace: \"SummaryManager\",\n\t\t\tproperties: {\n\t\t\t\tall: { clientId: () => this.latestClientId },\n\t\t\t},\n\t\t});\n\n\t\tthis.connectedState.on(\"connected\", this.handleConnected);\n\t\tthis.connectedState.on(\"disconnected\", this.handleDisconnected);\n\t\tthis.latestClientId = this.connectedState.clientId;\n\n\t\tthis.opsToBypassInitialDelay = opsToBypassInitialDelay;\n\t\tthis.initialDelayMs = initialDelayMs;\n\t}\n\n\t/**\n\t * Until start is called, the SummaryManager won't begin attempting to start summarization. This ensures there's\n\t * a window between construction and starting where the caller can attach listeners.\n\t */\n\tpublic start(): void {\n\t\tthis.clientElection.on(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.refreshSummarizer();\n\t}\n\n\tprivate readonly handleConnected = (clientId: string): void => {\n\t\tthis.latestClientId = clientId;\n\t\t// If we have a summarizer, it should have been either cancelled on disconnected by now.\n\t\t// But because of lastSummary process, it can still hang around, so there is not much we can\n\t\t// check or assert.\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate readonly handleDisconnected = (): void => {\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate static readonly isStartingOrRunning = (\n\t\tstate: SummaryManagerState,\n\t): state is SummaryManagerState.Starting | SummaryManagerState.Running =>\n\t\tstate === SummaryManagerState.Starting || state === SummaryManagerState.Running;\n\n\tprivate getShouldSummarizeState(): ShouldSummarizeState {\n\t\tif (this.disposed) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n\t\t}\n\n\t\t// Note that if we're in the Running state, the electedClient may be a summarizer client, so we can't\n\t\t// enforce connectedState.clientId === clientElection.electedClientId. But once we're Running, we should\n\t\t// only transition to Stopping when the electedParentId changes. Stopping the summarizer without\n\t\t// changing the electedParent will just cause us to transition to Starting again.\n\n\t\t// New Parent has been elected and it is not the current client, or\n\t\tif (this.connectedState.clientId !== this.clientElection.electedParentId) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedParent\" };\n\t\t}\n\n\t\t// We are not already running the summarizer and we are not the current elected client id.\n\t\tif (\n\t\t\tthis.state !== SummaryManagerState.Running &&\n\t\t\tthis.connectedState.clientId !== this.clientElection.electedClientId\n\t\t) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedClient\" };\n\t\t}\n\n\t\tif (!this.connectedState.connected) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n\t\t}\n\n\t\treturn { shouldSummarize: true };\n\t}\n\n\tprivate readonly refreshSummarizer = (): void => {\n\t\t// Transition states depending on shouldSummarize, which is a calculated property\n\t\t// that is only true if this client is connected and is the elected summarizer.\n\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\tswitch (this.state) {\n\t\t\tcase SummaryManagerState.Off: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Starting: {\n\t\t\t\t// Cannot take any action until summarizer is created\n\t\t\t\t// state transition will occur after creation\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Running: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\tthis.stop(shouldSummarizeState.stopReason);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Stopping: {\n\t\t\t\t// Cannot take any action until running summarizer finishes\n\t\t\t\t// state transition will occur after it stops\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate startSummarization(): void {\n\t\tassert(this.state === SummaryManagerState.Off, 0x261 /* \"Expected: off\" */);\n\t\tthis.state = SummaryManagerState.Starting;\n\n\t\tassert(this.summarizer === undefined, 0x262 /* \"Old summarizer is still working!\" */);\n\n\t\tthis.delayBeforeCreatingSummarizer()\n\t\t\t.then(async (startWithInitialDelay: boolean) => {\n\t\t\t\tif (this.disposed) {\n\t\t\t\t\treturn \"early exit (disposed)\";\n\t\t\t\t}\n\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// but only if creation was delayed. If it was not, then we want to ensure we always create\n\t\t\t\t// a summarizer to kick off lastSummary. Without that, we would not be able to summarize and get\n\t\t\t\t// document out of broken state if it has too many ops and ordering service keeps nacking main\n\t\t\t\t// container (and thus it goes into cycle of reconnects)\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeStateEarlyStage = this.getShouldSummarizeState();\n\t\t\t\tif (\n\t\t\t\t\tstartWithInitialDelay &&\n\t\t\t\t\tshouldSummarizeStateEarlyStage.shouldSummarize === false\n\t\t\t\t) {\n\t\t\t\t\treturn `early exit ${shouldSummarizeStateEarlyStage.stopReason}`;\n\t\t\t\t}\n\n\t\t\t\t// We transition to Running before requesting the summarizer, because after requesting we can't predict\n\t\t\t\t// when the electedClient will be replaced with the new summarizer client.\n\t\t\t\t// The alternative would be to let connectedState.clientId !== clientElection.electedClientId when\n\t\t\t\t// state === Starting || state === Running.\n\t\t\t\tassert(this.state === SummaryManagerState.Starting, 0x263 /* \"Expected: starting\" */);\n\t\t\t\tthis.state = SummaryManagerState.Running;\n\n\t\t\t\tconst summarizer = await this.createSummarizerFn();\n\t\t\t\tthis.summarizer = summarizer;\n\t\t\t\tthis.setupForwardedEvents(summarizer);\n\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\t// In order to allow the last summary to run, we not only need a stop reason that would\n\t\t\t\t\t// allow it but also, startWithInitialDelay to be false (start the summarization immediately),\n\t\t\t\t\t// which would happen when we have a high enough number of unsummarized ops.\n\t\t\t\t\tif (\n\t\t\t\t\t\tstartWithInitialDelay ||\n\t\t\t\t\t\t!stopReasonCanRunLastSummary(shouldSummarizeState.stopReason)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.state = SummaryManagerState.Starting;\n\t\t\t\t\t\tsummarizer.stop(shouldSummarizeState.stopReason);\n\t\t\t\t\t\treturn `early exit after starting summarizer ${shouldSummarizeState.stopReason}`;\n\t\t\t\t\t}\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"LastAttemptToSummarize\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst clientId = this.latestClientId!;\n\n\t\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\t\tthis.logger,\n\t\t\t\t\t{ eventName: \"RunningSummarizer\", attempt: this.startThrottler.numAttempts },\n\t\t\t\t\tasync () => summarizer.run(clientId),\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then((reason: string) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\treason,\n\t\t\t\t});\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\t\treason: \"exception\",\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\n\t\t\t\t// Most of exceptions happen due to container being closed while loading it, due to\n\t\t\t\t// summarizer container loosing connection while load.\n\t\t\t\t// Not worth reporting such errors as errors. That said, we might miss some real errors if\n\t\t\t\t// we ignore blindly, so try to narrow signature we are looking for - skip logging\n\t\t\t\t// error only if this client should no longer be a summarizer (which in practice\n\t\t\t\t// means it also lost connection), and error happened on load (we do not have summarizer).\n\t\t\t\t// We could annotate the error raised in Container.load where the container closed during load with no error\n\t\t\t\t// and check for that case here, but that does not seem to be necessary.\n\t\t\t\tif (this.getShouldSummarizeState().shouldSummarize || this.summarizer !== undefined) {\n\t\t\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t\t\t// If failure happened on container load, we may not yet realized that socket disconnected, so check\n\t\t\t\t\t// offlineError.\n\t\t\t\t\tconst category =\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\t\terror?.errorType === DriverErrorTypes.offlineError ? \"generic\" : \"error\";\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"SummarizerException\",\n\t\t\t\t\t\t\tcategory,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tassert(this.state !== SummaryManagerState.Off, 0x264 /* \"Expected: Not Off\" */);\n\t\t\t\tthis.state = SummaryManagerState.Off;\n\n\t\t\t\tthis.cleanupForwardedEvents();\n\t\t\t\tthis.summarizer?.close();\n\t\t\t\tthis.summarizer = undefined;\n\n\t\t\t\tif (this.getShouldSummarizeState().shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tprivate stop(reason: SummarizerStopReason): void {\n\t\tif (!SummaryManager.isStartingOrRunning(this.state)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.state = SummaryManagerState.Stopping;\n\n\t\t// Stopping the running summarizer client should trigger a change\n\t\t// in states when the running summarizer closes\n\t\tthis.summarizer?.stop(reason);\n\t}\n\n\t/**\n\t * Implements initial delay before creating summarizer\n\t * @returns `true`, if creation is delayed due to heuristics (not many ops to summarize).\n\t * `false` if summarizer should start immediately due to too many unsummarized ops.\n\t */\n\tprivate async delayBeforeCreatingSummarizer(): Promise<boolean> {\n\t\t// throttle creation of new summarizer containers to prevent spamming the server with websocket connections\n\t\tlet delayMs = this.startThrottler.getDelay();\n\n\t\t// We have been elected the summarizer. Some day we may be able to summarize with a live document but for\n\t\t// now we play it safe and launch a second copy.\n\t\tthis.logger.sendTelemetryEvent({\n\t\t\teventName: \"CreatingSummarizer\",\n\t\t\tthrottlerDelay: delayMs,\n\t\t\tinitialDelay: this.initialDelayMs,\n\t\t\tstartThrottlerMaxDelayMs: this.startThrottler.maxDelayMs,\n\t\t\topsSinceLastAck: this.summaryCollection.opsSinceLastAck,\n\t\t\topsToBypassInitialDelay: this.opsToBypassInitialDelay,\n\t\t\telectedParentId: this.clientElection.electedParentId,\n\t\t\telectedClientId: this.clientElection.electedClientId,\n\t\t});\n\n\t\t// This delay helps ensure that last summarizer that might be left from previous client\n\t\t// has enough time to complete its last summary and thus new summarizer not conflict with previous one.\n\t\t// If, however, there are too many unsummarized ops, try to resolve it as quickly as possible, with\n\t\t// understanding that we may see nacks because of such quick action.\n\t\t// A better design would be for summarizer election logic to always select current summarizer as\n\t\t// summarizing client (i.e. clientType === \"summarizer\" can be elected) to ensure that nobody else can\n\t\t// summarizer while it finishes its work and moves to exit.\n\t\t// It also helps with pure boot scenario (single client) to offset expensive work a bit out from\n\t\t// critical boot sequence.\n\t\tlet startWithInitialDelay = false;\n\t\tif (this.summaryCollection.opsSinceLastAck < this.opsToBypassInitialDelay) {\n\t\t\tstartWithInitialDelay = true;\n\t\t\tdelayMs = Math.max(delayMs, this.initialDelayMs);\n\t\t}\n\n\t\tif (delayMs > 0) {\n\t\t\tlet timer: number | undefined;\n\t\t\tlet resolveOpPromiseFn: (value: void | PromiseLike<void>) => void;\n\t\t\t// Create a listener that will break the delay if we've exceeded the initial delay ops count.\n\t\t\tconst opsListenerFn = (): void => {\n\t\t\t\tif (this.summaryCollection.opsSinceLastAck >= this.opsToBypassInitialDelay) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolveOpPromiseFn();\n\t\t\t\t}\n\t\t\t};\n\t\t\t// Create a Promise that will resolve when the delay expires.\n\t\t\tconst delayPromise = new Promise<void>((resolve) => {\n\t\t\t\ttimer = setTimeout(() => resolve(), delayMs);\n\t\t\t});\n\t\t\t// Create a Promise that will resolve if the ops count passes the threshold.\n\t\t\tconst opPromise = new Promise<void>((resolve) => {\n\t\t\t\tresolveOpPromiseFn = resolve;\n\t\t\t});\n\t\t\tthis.summaryCollection.addOpListener(opsListenerFn);\n\t\t\tawait Promise.race([delayPromise, opPromise]);\n\t\t\tthis.summaryCollection.removeOpListener(opsListenerFn);\n\t\t}\n\t\treturn startWithInitialDelay;\n\t}\n\n\tpublic summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow new Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.summarizeOnDemand(options);\n\t}\n\n\tpublic enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow new Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.enqueueSummarize(options);\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.clientElection.off(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.connectedState.off(\"connected\", this.handleConnected);\n\t\tthis.connectedState.off(\"disconnected\", this.handleDisconnected);\n\t\tthis.cleanupForwardedEvents();\n\t\tthis._disposed = true;\n\t}\n\n\tprivate readonly forwardedEventsCleanup: (() => void)[] = [];\n\n\tprivate setupForwardedEvents(summarizer: ISummarizer): void {\n\t\tfor (const event of [\n\t\t\t\"summarize\",\n\t\t\t\"summarizeAllAttemptsFailed\",\n\t\t\t\"summarizerStop\",\n\t\t\t\"summarizerStart\",\n\t\t\t\"summarizerStartupFailed\",\n\t\t\t\"summarizeTimeout\",\n\t\t] as const) {\n\t\t\tconst listener = (...args: unknown[]): void => {\n\t\t\t\tthis.emit(event, ...args);\n\t\t\t};\n\t\t\t// TODO: better typing here\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument\n\t\t\tsummarizer.on(event as any, listener);\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument\n\t\t\tthis.forwardedEventsCleanup.push(() => summarizer.off(event as any, listener));\n\t\t}\n\t}\n\n\tprivate cleanupForwardedEvents(): void {\n\t\tfor (const cleanup of this.forwardedEventsCleanup) {\n\t\t\tcleanup();\n\t\t}\n\t\tthis.forwardedEventsCleanup.length = 0;\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-runtime",
3
- "version": "2.74.0",
3
+ "version": "2.80.0",
4
4
  "description": "Fluid container runtime",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -119,18 +119,18 @@
119
119
  "temp-directory": "nyc/.nyc_output"
120
120
  },
121
121
  "dependencies": {
122
- "@fluid-internal/client-utils": "~2.74.0",
123
- "@fluidframework/container-definitions": "~2.74.0",
124
- "@fluidframework/container-runtime-definitions": "~2.74.0",
125
- "@fluidframework/core-interfaces": "~2.74.0",
126
- "@fluidframework/core-utils": "~2.74.0",
127
- "@fluidframework/datastore": "~2.74.0",
128
- "@fluidframework/driver-definitions": "~2.74.0",
129
- "@fluidframework/driver-utils": "~2.74.0",
130
- "@fluidframework/id-compressor": "~2.74.0",
131
- "@fluidframework/runtime-definitions": "~2.74.0",
132
- "@fluidframework/runtime-utils": "~2.74.0",
133
- "@fluidframework/telemetry-utils": "~2.74.0",
122
+ "@fluid-internal/client-utils": "~2.80.0",
123
+ "@fluidframework/container-definitions": "~2.80.0",
124
+ "@fluidframework/container-runtime-definitions": "~2.80.0",
125
+ "@fluidframework/core-interfaces": "~2.80.0",
126
+ "@fluidframework/core-utils": "~2.80.0",
127
+ "@fluidframework/datastore": "~2.80.0",
128
+ "@fluidframework/driver-definitions": "~2.80.0",
129
+ "@fluidframework/driver-utils": "~2.80.0",
130
+ "@fluidframework/id-compressor": "~2.80.0",
131
+ "@fluidframework/runtime-definitions": "~2.80.0",
132
+ "@fluidframework/runtime-utils": "~2.80.0",
133
+ "@fluidframework/telemetry-utils": "~2.80.0",
134
134
  "@tylerbu/sorted-btree-es6": "^1.8.0",
135
135
  "double-ended-queue": "^2.1.0-0",
136
136
  "lz4js": "^0.2.0",
@@ -138,18 +138,18 @@
138
138
  "uuid": "^11.1.0"
139
139
  },
140
140
  "devDependencies": {
141
- "@arethetypeswrong/cli": "^0.17.1",
141
+ "@arethetypeswrong/cli": "^0.18.2",
142
142
  "@biomejs/biome": "~1.9.3",
143
- "@fluid-internal/mocha-test-setup": "~2.74.0",
144
- "@fluid-private/stochastic-test-utils": "~2.74.0",
145
- "@fluid-private/test-pairwise-generator": "~2.74.0",
143
+ "@fluid-internal/mocha-test-setup": "~2.80.0",
144
+ "@fluid-private/stochastic-test-utils": "~2.80.0",
145
+ "@fluid-private/test-pairwise-generator": "~2.80.0",
146
146
  "@fluid-tools/benchmark": "^0.51.0",
147
- "@fluid-tools/build-cli": "^0.61.0",
147
+ "@fluid-tools/build-cli": "^0.62.0",
148
148
  "@fluidframework/build-common": "^2.0.3",
149
- "@fluidframework/build-tools": "^0.61.0",
150
- "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.73.0",
151
- "@fluidframework/eslint-config-fluid": "~2.74.0",
152
- "@fluidframework/test-runtime-utils": "~2.74.0",
149
+ "@fluidframework/build-tools": "^0.62.0",
150
+ "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.74.0",
151
+ "@fluidframework/eslint-config-fluid": "~2.80.0",
152
+ "@fluidframework/test-runtime-utils": "~2.80.0",
153
153
  "@microsoft/api-extractor": "7.52.11",
154
154
  "@types/double-ended-queue": "^2.1.0",
155
155
  "@types/lz4js": "^0.2.0",
@@ -157,14 +157,14 @@
157
157
  "@types/node": "^18.19.0",
158
158
  "@types/sinon": "^17.0.3",
159
159
  "c8": "^10.1.3",
160
- "concurrently": "^8.2.1",
160
+ "concurrently": "^9.2.1",
161
161
  "copyfiles": "^2.4.1",
162
- "cross-env": "^7.0.3",
163
- "eslint": "~8.57.1",
162
+ "cross-env": "^10.1.0",
163
+ "eslint": "~9.39.1",
164
164
  "jiti": "^2.6.1",
165
165
  "mocha": "^10.8.2",
166
166
  "mocha-multi-reporters": "^1.5.1",
167
- "rimraf": "^4.4.0",
167
+ "rimraf": "^6.1.2",
168
168
  "sinon": "^18.0.1",
169
169
  "typescript": "~5.4.5"
170
170
  },