@fluidframework/container-runtime 2.74.0 → 2.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts +0 -2
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +4 -5
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +3 -3
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js.map +1 -1
- package/dist/containerRuntime.d.ts +5 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +13 -7
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +2 -1
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +1 -0
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +1 -0
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runtimeLayerCompatState.d.ts +10 -6
- package/dist/runtimeLayerCompatState.d.ts.map +1 -1
- package/dist/runtimeLayerCompatState.js +16 -6
- package/dist/runtimeLayerCompatState.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js +1 -0
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +1 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +5 -0
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js +39 -18
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.js +13 -11
- package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +4 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js +37 -16
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +10 -9
- package/dist/summary/summaryManager.js.map +1 -1
- package/eslint.config.mts +4 -4
- package/lib/blobManager/blobManager.d.ts +0 -2
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +4 -5
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +3 -3
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js.map +1 -1
- package/lib/containerRuntime.d.ts +5 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +13 -7
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +2 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +1 -0
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +1 -0
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runtimeLayerCompatState.d.ts +10 -6
- package/lib/runtimeLayerCompatState.d.ts.map +1 -1
- package/lib/runtimeLayerCompatState.js +15 -5
- package/lib/runtimeLayerCompatState.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js +1 -0
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +1 -0
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +5 -0
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js +39 -18
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.js +13 -11
- package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +4 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js +34 -13
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +10 -9
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +27 -27
- package/src/blobManager/blobManager.ts +3 -7
- package/src/channelCollection.ts +3 -3
- package/src/containerRuntime.ts +19 -6
- package/src/dataStoreContext.ts +3 -2
- package/src/deltaScheduler.ts +1 -0
- package/src/gc/gcHelpers.ts +1 -0
- package/src/packageVersion.ts +1 -1
- package/src/runtimeLayerCompatState.ts +25 -9
- package/src/summary/summarizerClientElection.ts +1 -0
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +1 -0
- package/src/summary/summarizerTypes.ts +5 -0
- package/src/summary/summaryDelayLoadedModule/runningSummarizer.ts +54 -26
- package/src/summary/summaryDelayLoadedModule/summarizer.ts +13 -11
- package/src/summary/summaryDelayLoadedModule/summaryGenerator.ts +43 -13
- package/src/summary/summaryManager.ts +11 -10
- package/.eslintrc.cjs +0 -30
|
@@ -177,11 +177,6 @@ export class RunningSummarizer
|
|
|
177
177
|
private totalSuccessfulAttempts = 0;
|
|
178
178
|
private initialized = false;
|
|
179
179
|
|
|
180
|
-
private readonly runtimeListener: (
|
|
181
|
-
op: ISequencedDocumentMessage,
|
|
182
|
-
runtimeMessage?: boolean,
|
|
183
|
-
) => void;
|
|
184
|
-
|
|
185
180
|
/**
|
|
186
181
|
* The maximum number of summary attempts to do when submit summary fails.
|
|
187
182
|
*/
|
|
@@ -295,12 +290,6 @@ export class RunningSummarizer
|
|
|
295
290
|
this.mc.logger,
|
|
296
291
|
);
|
|
297
292
|
|
|
298
|
-
// Listen to runtime for ops
|
|
299
|
-
this.runtimeListener = (op: ISequencedDocumentMessage, runtimeMessage?: boolean) => {
|
|
300
|
-
this.handleOp(op, runtimeMessage === true);
|
|
301
|
-
};
|
|
302
|
-
this.runtime.on("op", this.runtimeListener);
|
|
303
|
-
|
|
304
293
|
// The max attempts for submit failures can be overridden via a feature flag. This allows us to
|
|
305
294
|
// tweak this as per telemetry data until we arrive at a stable number.
|
|
306
295
|
// If its set to a number higher than `defaultMaxAttemptsForSubmitFailures`, it will be ignored.
|
|
@@ -312,6 +301,8 @@ export class RunningSummarizer
|
|
|
312
301
|
overrideMaxAttempts < defaultMaxAttemptsForSubmitFailures
|
|
313
302
|
? overrideMaxAttempts
|
|
314
303
|
: defaultMaxAttemptsForSubmitFailures;
|
|
304
|
+
|
|
305
|
+
this.setupEventListeners();
|
|
315
306
|
}
|
|
316
307
|
|
|
317
308
|
private async handleSummaryAck(ack: IAckedSummary): Promise<void> {
|
|
@@ -397,7 +388,7 @@ export class RunningSummarizer
|
|
|
397
388
|
}
|
|
398
389
|
|
|
399
390
|
public dispose(): void {
|
|
400
|
-
this.
|
|
391
|
+
this.cleanupEventListeners();
|
|
401
392
|
this.summaryWatcher.dispose();
|
|
402
393
|
this.heuristicRunner?.dispose();
|
|
403
394
|
this.heuristicRunner = undefined;
|
|
@@ -408,6 +399,33 @@ export class RunningSummarizer
|
|
|
408
399
|
this.stopping = true;
|
|
409
400
|
}
|
|
410
401
|
|
|
402
|
+
private readonly eventsCleanup: (() => void)[] = [];
|
|
403
|
+
|
|
404
|
+
private setupEventListeners(): void {
|
|
405
|
+
const runtimeListener: (op: ISequencedDocumentMessage, runtimeMessage?: boolean) => void =
|
|
406
|
+
(op: ISequencedDocumentMessage, runtimeMessage?: boolean) => {
|
|
407
|
+
this.handleOp(op, runtimeMessage === true);
|
|
408
|
+
};
|
|
409
|
+
this.runtime.on("op", runtimeListener);
|
|
410
|
+
this.eventsCleanup.push(() => this.runtime.off("op", runtimeListener));
|
|
411
|
+
|
|
412
|
+
// Forward events
|
|
413
|
+
for (const event of ["summarizeTimeout"] as const) {
|
|
414
|
+
const listener = (...args: unknown[]): void => {
|
|
415
|
+
this.emit(event, ...args);
|
|
416
|
+
};
|
|
417
|
+
this.generator.on(event, listener);
|
|
418
|
+
this.eventsCleanup.push(() => this.generator.off(event, listener));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
private cleanupEventListeners(): void {
|
|
423
|
+
for (const cleanup of this.eventsCleanup) {
|
|
424
|
+
cleanup();
|
|
425
|
+
}
|
|
426
|
+
this.eventsCleanup.length = 0;
|
|
427
|
+
}
|
|
428
|
+
|
|
411
429
|
/**
|
|
412
430
|
* RunningSummarizer's logger includes the sequenced index of the current summary on each event.
|
|
413
431
|
* If some other Summarizer code wants that event on their logs they can get it here,
|
|
@@ -655,11 +673,12 @@ export class RunningSummarizer
|
|
|
655
673
|
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
656
674
|
isLastSummary,
|
|
657
675
|
});
|
|
658
|
-
|
|
676
|
+
summaryLogger.sendErrorEvent(
|
|
659
677
|
{
|
|
660
678
|
eventName: "SummarizeFailed",
|
|
661
679
|
maxAttempts: 1,
|
|
662
680
|
summaryAttempts: 1,
|
|
681
|
+
isLastSummary,
|
|
663
682
|
},
|
|
664
683
|
result.error,
|
|
665
684
|
);
|
|
@@ -708,7 +727,10 @@ export class RunningSummarizer
|
|
|
708
727
|
this.afterSummaryAction();
|
|
709
728
|
},
|
|
710
729
|
).catch((error) => {
|
|
711
|
-
this.mc.logger.sendErrorEvent(
|
|
730
|
+
this.mc.logger.sendErrorEvent(
|
|
731
|
+
{ eventName: "UnexpectedSummarizeError", summarizeReason: reason },
|
|
732
|
+
error,
|
|
733
|
+
);
|
|
712
734
|
});
|
|
713
735
|
}
|
|
714
736
|
|
|
@@ -718,6 +740,7 @@ export class RunningSummarizer
|
|
|
718
740
|
*/
|
|
719
741
|
private async trySummarizeWithRetries(
|
|
720
742
|
reason: SummarizeReason,
|
|
743
|
+
summarizeOptions: ISummarizeOptions = {},
|
|
721
744
|
): Promise<ISummarizeResults | undefined> {
|
|
722
745
|
// Helper to set summarize options, telemetry properties and call summarize.
|
|
723
746
|
const attemptSummarize = (
|
|
@@ -727,13 +750,13 @@ export class RunningSummarizer
|
|
|
727
750
|
summarizeProps: ISummarizeTelemetryProperties;
|
|
728
751
|
summarizeResult: ISummarizeResults;
|
|
729
752
|
} => {
|
|
730
|
-
const
|
|
731
|
-
fullTree: false,
|
|
753
|
+
const attemptSummarizeOptions: ISummarizeOptions = {
|
|
754
|
+
fullTree: summarizeOptions.fullTree ?? false,
|
|
732
755
|
};
|
|
733
756
|
const summarizeProps: ISummarizeTelemetryProperties = {
|
|
734
757
|
summarizeReason: reason,
|
|
735
758
|
summaryAttempts: attemptNumber,
|
|
736
|
-
...
|
|
759
|
+
...attemptSummarizeOptions,
|
|
737
760
|
finalAttempt,
|
|
738
761
|
};
|
|
739
762
|
const summaryLogger = createChildLogger({
|
|
@@ -742,7 +765,7 @@ export class RunningSummarizer
|
|
|
742
765
|
});
|
|
743
766
|
|
|
744
767
|
const summaryOptions: ISubmitSummaryOptions = {
|
|
745
|
-
...
|
|
768
|
+
...attemptSummarizeOptions,
|
|
746
769
|
summaryLogger,
|
|
747
770
|
cancellationToken: this.cancellationToken,
|
|
748
771
|
finalAttempt,
|
|
@@ -872,6 +895,8 @@ export class RunningSummarizer
|
|
|
872
895
|
eventName: "SummarizeFailed",
|
|
873
896
|
maxAttempts,
|
|
874
897
|
summaryAttempts: currentAttempt,
|
|
898
|
+
summarizeReason: reason,
|
|
899
|
+
isLastSummary: reason === "lastSummary",
|
|
875
900
|
},
|
|
876
901
|
error,
|
|
877
902
|
);
|
|
@@ -893,8 +918,9 @@ export class RunningSummarizer
|
|
|
893
918
|
private async summarizeOnDemandWithRetries(
|
|
894
919
|
reason: SummarizeReason,
|
|
895
920
|
resultsBuilder: SummarizeResultBuilder,
|
|
921
|
+
summarizeOptions: ISummarizeOptions = {},
|
|
896
922
|
): Promise<ISummarizeResults> {
|
|
897
|
-
const results = await this.trySummarizeWithRetries(reason);
|
|
923
|
+
const results = await this.trySummarizeWithRetries(reason, summarizeOptions);
|
|
898
924
|
if (results === undefined) {
|
|
899
925
|
resultsBuilder.fail(
|
|
900
926
|
"Summarization was canceled",
|
|
@@ -932,13 +958,15 @@ export class RunningSummarizer
|
|
|
932
958
|
throw new UsageError("Attempted to run an already-running summarizer on demand");
|
|
933
959
|
}
|
|
934
960
|
|
|
935
|
-
const { reason, ...summarizeOptions } = options;
|
|
936
|
-
if (
|
|
937
|
-
this.summarizeOnDemandWithRetries(
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
)
|
|
961
|
+
const { reason, retryOnFailure, ...summarizeOptions } = options;
|
|
962
|
+
if (retryOnFailure === true) {
|
|
963
|
+
this.summarizeOnDemandWithRetries(
|
|
964
|
+
`onDemand;${reason}`,
|
|
965
|
+
resultsBuilder,
|
|
966
|
+
summarizeOptions,
|
|
967
|
+
).catch((error: IRetriableFailureError) => {
|
|
968
|
+
resultsBuilder.fail("summarize failed", error);
|
|
969
|
+
});
|
|
942
970
|
} else {
|
|
943
971
|
this.trySummarizeOnce(
|
|
944
972
|
{ summarizeReason: `onDemand/${reason}` },
|
|
@@ -301,7 +301,7 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
301
301
|
this.runtime,
|
|
302
302
|
);
|
|
303
303
|
this.runningSummarizer = runningSummarizer;
|
|
304
|
-
this.setupForwardedEvents();
|
|
304
|
+
this.setupForwardedEvents(runningSummarizer);
|
|
305
305
|
this.starting = false;
|
|
306
306
|
return runningSummarizer;
|
|
307
307
|
}
|
|
@@ -399,24 +399,26 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
399
399
|
this._heuristicData?.recordAttempt(summaryRefSeqNum);
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
private readonly
|
|
402
|
+
private readonly forwardedEventsCleanup: (() => void)[] = [];
|
|
403
403
|
|
|
404
|
-
private setupForwardedEvents(): void {
|
|
405
|
-
for (const event of [
|
|
404
|
+
private setupForwardedEvents(runningSummarizer: RunningSummarizer): void {
|
|
405
|
+
for (const event of [
|
|
406
|
+
"summarize",
|
|
407
|
+
"summarizeAllAttemptsFailed",
|
|
408
|
+
"summarizeTimeout",
|
|
409
|
+
] as const) {
|
|
406
410
|
const listener = (...args: unknown[]): void => {
|
|
407
411
|
this.emit(event, ...args);
|
|
408
412
|
};
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
this.runningSummarizer?.on(event as any, listener);
|
|
412
|
-
this.forwardedEvents.set(event, listener);
|
|
413
|
+
runningSummarizer.on(event, listener);
|
|
414
|
+
this.forwardedEventsCleanup.push(() => runningSummarizer.off(event, listener));
|
|
413
415
|
}
|
|
414
416
|
}
|
|
415
417
|
|
|
416
418
|
private cleanupForwardedEvents(): void {
|
|
417
|
-
for (const
|
|
418
|
-
|
|
419
|
+
for (const cleanup of this.forwardedEventsCleanup) {
|
|
420
|
+
cleanup();
|
|
419
421
|
}
|
|
420
|
-
this.
|
|
422
|
+
this.forwardedEventsCleanup.length = 0;
|
|
421
423
|
}
|
|
422
424
|
}
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
+
import type { ISummarizerEvents } from "@fluidframework/container-runtime-definitions/internal";
|
|
6
8
|
import { assert, type IPromiseTimer, Timer } from "@fluidframework/core-utils/internal";
|
|
7
9
|
import { DriverErrorTypes, MessageType } from "@fluidframework/driver-definitions/internal";
|
|
8
10
|
import { getRetryDelaySecondsFromError } from "@fluidframework/driver-utils/internal";
|
|
11
|
+
import { TelemetryContext } from "@fluidframework/runtime-utils/internal";
|
|
9
12
|
import {
|
|
10
13
|
isFluidError,
|
|
11
14
|
type ITelemetryLoggerExt,
|
|
@@ -40,8 +43,9 @@ const maxSummarizeTimeoutCount = 5; // Double and resend 5 times
|
|
|
40
43
|
/**
|
|
41
44
|
* This class generates and tracks a summary attempt.
|
|
42
45
|
*/
|
|
43
|
-
export class SummaryGenerator {
|
|
46
|
+
export class SummaryGenerator extends TypedEventEmitter<ISummarizerEvents> {
|
|
44
47
|
private readonly summarizeTimer: Timer;
|
|
48
|
+
private activeTelemetryContext?: TelemetryContext;
|
|
45
49
|
constructor(
|
|
46
50
|
private readonly pendingAckTimer: IPromiseTimer,
|
|
47
51
|
private readonly heuristicData: ISummarizeHeuristicData,
|
|
@@ -55,6 +59,7 @@ export class SummaryGenerator {
|
|
|
55
59
|
private readonly summaryWatcher: Pick<IClientSummaryWatcher, "watchSummary">,
|
|
56
60
|
private readonly logger: ITelemetryLoggerExt,
|
|
57
61
|
) {
|
|
62
|
+
super();
|
|
58
63
|
this.summarizeTimer = new Timer(maxSummarizeTimeoutTime, () =>
|
|
59
64
|
this.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),
|
|
60
65
|
);
|
|
@@ -85,7 +90,16 @@ export class SummaryGenerator {
|
|
|
85
90
|
submitSummaryOptions: ISubmitSummaryOptions,
|
|
86
91
|
resultsBuilder: SummarizeResultBuilder,
|
|
87
92
|
): Promise<void> {
|
|
88
|
-
const {
|
|
93
|
+
const {
|
|
94
|
+
summaryLogger,
|
|
95
|
+
cancellationToken,
|
|
96
|
+
telemetryContext = new TelemetryContext(),
|
|
97
|
+
...summarizeOptions
|
|
98
|
+
} = submitSummaryOptions;
|
|
99
|
+
|
|
100
|
+
telemetryContext.setCurrentSummarizeStep("submitSummary");
|
|
101
|
+
const submitOptions = { ...submitSummaryOptions, telemetryContext };
|
|
102
|
+
this.activeTelemetryContext = telemetryContext;
|
|
89
103
|
|
|
90
104
|
// Note: timeSinceLastAttempt and timeSinceLastSummary for the
|
|
91
105
|
// first summary are basically the time since the summarizer was loaded.
|
|
@@ -97,6 +111,8 @@ export class SummaryGenerator {
|
|
|
97
111
|
fullTree: summarizeOptions.fullTree ?? false,
|
|
98
112
|
timeSinceLastAttempt,
|
|
99
113
|
timeSinceLastSummary,
|
|
114
|
+
nonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,
|
|
115
|
+
runtimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,
|
|
100
116
|
};
|
|
101
117
|
|
|
102
118
|
const summarizeEvent = PerformanceEvent.start(
|
|
@@ -115,7 +131,7 @@ export class SummaryGenerator {
|
|
|
115
131
|
* For submit failures, submitFailureResult should be provided. For nack failures, nackSummaryResult should
|
|
116
132
|
* be provided. For op broadcast failures, only errors / properties should be provided.
|
|
117
133
|
*/
|
|
118
|
-
const
|
|
134
|
+
const summaryFail = (
|
|
119
135
|
errorCode: SummarizeErrorCode,
|
|
120
136
|
error: IRetriableFailureError,
|
|
121
137
|
properties?: SummaryGeneratorTelemetry,
|
|
@@ -148,10 +164,12 @@ export class SummaryGenerator {
|
|
|
148
164
|
// Wait to generate and send summary
|
|
149
165
|
this.summarizeTimer.start();
|
|
150
166
|
try {
|
|
167
|
+
telemetryContext.setCurrentSummarizeStep("generateSummary");
|
|
151
168
|
// Need to save refSeqNum before we record new attempt (happens as part of submitSummaryCallback)
|
|
152
169
|
const lastAttemptRefSeqNum = this.heuristicData.lastAttempt.refSequenceNumber;
|
|
153
170
|
|
|
154
|
-
summaryData = await this.submitSummaryCallback(
|
|
171
|
+
summaryData = await this.submitSummaryCallback(submitOptions);
|
|
172
|
+
telemetryContext.setCurrentSummarizeStep("submitSummaryOp");
|
|
155
173
|
|
|
156
174
|
// Cumulatively add telemetry properties based on how far generateSummary went.
|
|
157
175
|
const referenceSequenceNumber = summaryData.referenceSequenceNumber;
|
|
@@ -173,7 +191,7 @@ export class SummaryGenerator {
|
|
|
173
191
|
const errorCode: SummarizeErrorCode = "submitSummaryFailure";
|
|
174
192
|
const retriableError =
|
|
175
193
|
summaryData.error ?? new RetriableSummaryError(getFailMessage(errorCode));
|
|
176
|
-
return
|
|
194
|
+
return summaryFail(errorCode, retriableError, summarizeTelemetryProps, {
|
|
177
195
|
stage: summaryData.stage,
|
|
178
196
|
});
|
|
179
197
|
}
|
|
@@ -189,6 +207,7 @@ export class SummaryGenerator {
|
|
|
189
207
|
* exceed the number of ops since last summary + number of data store whose reference state changed.
|
|
190
208
|
*/
|
|
191
209
|
if (submitSummaryOptions.fullTree !== true) {
|
|
210
|
+
telemetryContext.setCurrentSummarizeStep("watchSummary");
|
|
192
211
|
const { summarizedDataStoreCount, gcStateUpdatedDataStoreCount = 0 } =
|
|
193
212
|
summaryData.summaryStats;
|
|
194
213
|
if (
|
|
@@ -208,7 +227,7 @@ export class SummaryGenerator {
|
|
|
208
227
|
summarizeEvent.reportEvent("generate", { ...summarizeTelemetryProps });
|
|
209
228
|
resultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });
|
|
210
229
|
} catch (error) {
|
|
211
|
-
return
|
|
230
|
+
return summaryFail(
|
|
212
231
|
"submitSummaryFailure",
|
|
213
232
|
wrapError(
|
|
214
233
|
error,
|
|
@@ -227,6 +246,8 @@ export class SummaryGenerator {
|
|
|
227
246
|
this.summarizeTimer.clear();
|
|
228
247
|
}
|
|
229
248
|
|
|
249
|
+
telemetryContext.setCurrentSummarizeStep("waitForSummaryAck");
|
|
250
|
+
|
|
230
251
|
try {
|
|
231
252
|
const pendingTimeoutP = this.pendingAckTimer.start();
|
|
232
253
|
const summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);
|
|
@@ -239,13 +260,13 @@ export class SummaryGenerator {
|
|
|
239
260
|
);
|
|
240
261
|
if (waitBroadcastResult.result === "cancelled") {
|
|
241
262
|
const errorCode: SummarizeErrorCode = "disconnect";
|
|
242
|
-
return
|
|
263
|
+
return summaryFail(errorCode, new RetriableSummaryError(getFailMessage(errorCode)));
|
|
243
264
|
}
|
|
244
265
|
if (waitBroadcastResult.result !== "done") {
|
|
245
266
|
// The summary op may not have been received within the timeout due to a transient error. So,
|
|
246
267
|
// fail with a retriable error to re-attempt the summary if possible.
|
|
247
268
|
const errorCode: SummarizeErrorCode = "summaryOpWaitTimeout";
|
|
248
|
-
return
|
|
269
|
+
return summaryFail(
|
|
249
270
|
errorCode,
|
|
250
271
|
new RetriableSummaryError(getFailMessage(errorCode), 0 /* retryAfterSeconds */),
|
|
251
272
|
);
|
|
@@ -275,13 +296,13 @@ export class SummaryGenerator {
|
|
|
275
296
|
);
|
|
276
297
|
if (waitAckNackResult.result === "cancelled") {
|
|
277
298
|
const errorCode: SummarizeErrorCode = "disconnect";
|
|
278
|
-
return
|
|
299
|
+
return summaryFail(errorCode, new RetriableSummaryError(getFailMessage(errorCode)));
|
|
279
300
|
}
|
|
280
301
|
if (waitAckNackResult.result !== "done") {
|
|
281
302
|
const errorCode: SummarizeErrorCode = "summaryAckWaitTimeout";
|
|
282
303
|
// The summary ack may not have been received within the timeout due to a transient error. So,
|
|
283
304
|
// fail with a retriable error to re-attempt the summary if possible.
|
|
284
|
-
return
|
|
305
|
+
return summaryFail(
|
|
285
306
|
errorCode,
|
|
286
307
|
new RetriableSummaryError(getFailMessage(errorCode), 0 /* retryAfterSeconds */),
|
|
287
308
|
);
|
|
@@ -300,6 +321,7 @@ export class SummaryGenerator {
|
|
|
300
321
|
...summarizeTelemetryProps,
|
|
301
322
|
};
|
|
302
323
|
if (ackNackOp.type === MessageType.SummaryAck) {
|
|
324
|
+
telemetryContext.setCurrentSummarizeStep("ackReceived");
|
|
303
325
|
this.heuristicData.markLastAttemptAsSuccessful();
|
|
304
326
|
this.successfulSummaryCallback();
|
|
305
327
|
summarizeEvent.end({
|
|
@@ -324,6 +346,7 @@ export class SummaryGenerator {
|
|
|
324
346
|
} else {
|
|
325
347
|
// Check for retryDelay in summaryNack response.
|
|
326
348
|
assert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* "type check" */);
|
|
349
|
+
telemetryContext.setCurrentSummarizeStep("nackReceived");
|
|
327
350
|
const summaryNack = ackNackOp.contents;
|
|
328
351
|
const errorMessage = summaryNack?.message;
|
|
329
352
|
const retryAfterSeconds = summaryNack?.retryAfter;
|
|
@@ -340,7 +363,7 @@ export class SummaryGenerator {
|
|
|
340
363
|
0x25f /* "retryAfterSeconds" */,
|
|
341
364
|
);
|
|
342
365
|
// This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.
|
|
343
|
-
return
|
|
366
|
+
return summaryFail(
|
|
344
367
|
errorCode,
|
|
345
368
|
error,
|
|
346
369
|
{ ...summarizeTelemetryProps, nackRetryAfter: retryAfterSeconds },
|
|
@@ -350,6 +373,7 @@ export class SummaryGenerator {
|
|
|
350
373
|
}
|
|
351
374
|
} finally {
|
|
352
375
|
this.pendingAckTimer.clear();
|
|
376
|
+
this.activeTelemetryContext = undefined;
|
|
353
377
|
}
|
|
354
378
|
}
|
|
355
379
|
|
|
@@ -390,8 +414,6 @@ export class SummaryGenerator {
|
|
|
390
414
|
clientSequenceNumber: summaryData.clientSequenceNumber,
|
|
391
415
|
hasMissingOpData: this.heuristicData.hasMissingOpData,
|
|
392
416
|
opsSizesSinceLastSummary: this.heuristicData.totalOpsSize,
|
|
393
|
-
nonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,
|
|
394
|
-
runtimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,
|
|
395
417
|
};
|
|
396
418
|
}
|
|
397
419
|
|
|
@@ -408,6 +430,13 @@ export class SummaryGenerator {
|
|
|
408
430
|
eventName: "SummarizeTimeout",
|
|
409
431
|
timeoutTime: time,
|
|
410
432
|
timeoutCount: count,
|
|
433
|
+
currentSummarizeStep: this.activeTelemetryContext?.getCurrentSummarizeStep(),
|
|
434
|
+
});
|
|
435
|
+
this.emit("summarizeTimeout", {
|
|
436
|
+
timeoutCount: count,
|
|
437
|
+
currentSummarizeStep: this.activeTelemetryContext?.getCurrentSummarizeStep(),
|
|
438
|
+
numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
|
|
439
|
+
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
411
440
|
});
|
|
412
441
|
if (count < maxSummarizeTimeoutCount) {
|
|
413
442
|
// Double and start a new timer
|
|
@@ -420,5 +449,6 @@ export class SummaryGenerator {
|
|
|
420
449
|
|
|
421
450
|
public dispose(): void {
|
|
422
451
|
this.summarizeTimer.clear();
|
|
452
|
+
this.activeTelemetryContext = undefined;
|
|
423
453
|
}
|
|
424
454
|
}
|
|
@@ -274,7 +274,7 @@ export class SummaryManager
|
|
|
274
274
|
|
|
275
275
|
const summarizer = await this.createSummarizerFn();
|
|
276
276
|
this.summarizer = summarizer;
|
|
277
|
-
this.setupForwardedEvents();
|
|
277
|
+
this.setupForwardedEvents(summarizer);
|
|
278
278
|
|
|
279
279
|
// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore
|
|
280
280
|
// If we can't run the LastSummary, simply return as to avoid paying the cost of launching
|
|
@@ -456,31 +456,32 @@ export class SummaryManager
|
|
|
456
456
|
this._disposed = true;
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
-
private readonly
|
|
459
|
+
private readonly forwardedEventsCleanup: (() => void)[] = [];
|
|
460
460
|
|
|
461
|
-
private setupForwardedEvents(): void {
|
|
461
|
+
private setupForwardedEvents(summarizer: ISummarizer): void {
|
|
462
462
|
for (const event of [
|
|
463
463
|
"summarize",
|
|
464
464
|
"summarizeAllAttemptsFailed",
|
|
465
465
|
"summarizerStop",
|
|
466
466
|
"summarizerStart",
|
|
467
467
|
"summarizerStartupFailed",
|
|
468
|
-
|
|
468
|
+
"summarizeTimeout",
|
|
469
|
+
] as const) {
|
|
469
470
|
const listener = (...args: unknown[]): void => {
|
|
470
471
|
this.emit(event, ...args);
|
|
471
472
|
};
|
|
472
473
|
// TODO: better typing here
|
|
473
474
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
474
|
-
|
|
475
|
-
|
|
475
|
+
summarizer.on(event as any, listener);
|
|
476
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
477
|
+
this.forwardedEventsCleanup.push(() => summarizer.off(event as any, listener));
|
|
476
478
|
}
|
|
477
479
|
}
|
|
478
480
|
|
|
479
481
|
private cleanupForwardedEvents(): void {
|
|
480
|
-
for (const
|
|
481
|
-
|
|
482
|
-
this.summarizer?.off(event as any, listener);
|
|
482
|
+
for (const cleanup of this.forwardedEventsCleanup) {
|
|
483
|
+
cleanup();
|
|
483
484
|
}
|
|
484
|
-
this.
|
|
485
|
+
this.forwardedEventsCleanup.length = 0;
|
|
485
486
|
}
|
|
486
487
|
}
|
package/.eslintrc.cjs
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
extends: [require.resolve("@fluidframework/eslint-config-fluid/recommended"), "prettier"],
|
|
8
|
-
parserOptions: {
|
|
9
|
-
project: ["./tsconfig.json", "./src/test/tsconfig.json"],
|
|
10
|
-
},
|
|
11
|
-
rules: {
|
|
12
|
-
// AB#51780: temporarily disabled because of crashes in typescript-eslint on destructuring in promise chains.
|
|
13
|
-
// See: channelCollection.ts:1070
|
|
14
|
-
"@typescript-eslint/unbound-method": "off",
|
|
15
|
-
},
|
|
16
|
-
overrides: [
|
|
17
|
-
{
|
|
18
|
-
// Rules only for test files
|
|
19
|
-
files: ["*.spec.ts", "src/test/**"],
|
|
20
|
-
rules: {
|
|
21
|
-
// TODO: remove these overrides and fix violations
|
|
22
|
-
"@typescript-eslint/explicit-function-return-type": "off",
|
|
23
|
-
"unicorn/consistent-function-scoping": "off",
|
|
24
|
-
|
|
25
|
-
// Test files are run in node only so additional node libraries can be used.
|
|
26
|
-
"import-x/no-nodejs-modules": ["error", { allow: ["node:assert", "node:crypto"] }],
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
};
|