@fluidframework/container-runtime 2.11.0 → 2.12.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 +37 -0
- package/api-report/container-runtime.legacy.alpha.api.md +17 -15
- package/container-runtime.test-files.tar +0 -0
- package/dist/containerRuntime.d.ts +38 -5
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +28 -7
- package/dist/containerRuntime.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.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/summary/runWhileConnectedCoordinator.d.ts +2 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +8 -1
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +70 -8
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +5 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +39 -6
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +8 -4
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +5 -2
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +23 -6
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +38 -5
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +28 -7
- package/lib/containerRuntime.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.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/summary/runWhileConnectedCoordinator.d.ts +2 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +8 -1
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +70 -8
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +5 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +39 -6
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +8 -4
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +5 -2
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +23 -6
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +19 -19
- package/src/containerRuntime.ts +82 -23
- package/src/index.ts +1 -0
- package/src/packageVersion.ts +1 -1
- package/src/summary/runWhileConnectedCoordinator.ts +2 -5
- package/src/summary/runningSummarizer.ts +82 -11
- package/src/summary/summarizer.ts +49 -10
- package/src/summary/summarizerTypes.ts +11 -4
- package/src/summary/summaryManager.ts +30 -10
package/src/containerRuntime.ts
CHANGED
|
@@ -218,7 +218,6 @@ import {
|
|
|
218
218
|
ISubmitSummaryOptions,
|
|
219
219
|
ISummarizeResults,
|
|
220
220
|
ISummarizer,
|
|
221
|
-
ISummarizerEvents,
|
|
222
221
|
ISummarizerInternalsProvider,
|
|
223
222
|
ISummarizerRuntime,
|
|
224
223
|
ISummaryMetadataMessage,
|
|
@@ -475,6 +474,8 @@ export interface IContainerRuntimeOptions {
|
|
|
475
474
|
* send all operations to the driver layer, while in TurnBased the operations will be buffered
|
|
476
475
|
* and then sent them as a single batch at the end of the turn.
|
|
477
476
|
* By default, flush mode is TurnBased.
|
|
477
|
+
*
|
|
478
|
+
* @deprecated Only the default value TurnBased is supported. This option will be removed in the future.
|
|
478
479
|
*/
|
|
479
480
|
readonly flushMode?: FlushMode;
|
|
480
481
|
/**
|
|
@@ -516,9 +517,10 @@ export interface IContainerRuntimeOptions {
|
|
|
516
517
|
/**
|
|
517
518
|
* If enabled, the runtime will group messages within a batch into a single
|
|
518
519
|
* message to be sent to the service.
|
|
519
|
-
* The grouping
|
|
520
|
+
* The grouping and ungrouping of such messages is handled by the "OpGroupingManager".
|
|
520
521
|
*
|
|
521
522
|
* By default, the feature is enabled.
|
|
523
|
+
* @deprecated The ability to disable Grouped Batching is deprecated and will be removed in v2.20.0. This feature is required for the proper functioning of the Fluid Framework.
|
|
522
524
|
*/
|
|
523
525
|
readonly enableGroupedBatching?: boolean;
|
|
524
526
|
|
|
@@ -532,6 +534,31 @@ export interface IContainerRuntimeOptions {
|
|
|
532
534
|
readonly explicitSchemaControl?: boolean;
|
|
533
535
|
}
|
|
534
536
|
|
|
537
|
+
/**
|
|
538
|
+
* Internal extension of @see IContainerRuntimeOptions
|
|
539
|
+
*
|
|
540
|
+
* These options are not available to consumers when creating a new container runtime,
|
|
541
|
+
* but we do need to expose them for internal use, e.g. when configuring the container runtime
|
|
542
|
+
* to ensure compability with older versions.
|
|
543
|
+
*
|
|
544
|
+
* @internal
|
|
545
|
+
*/
|
|
546
|
+
export interface IContainerRuntimeOptionsInternal extends IContainerRuntimeOptions {
|
|
547
|
+
/**
|
|
548
|
+
* Sets the flush mode for the runtime. In Immediate flush mode the runtime will immediately
|
|
549
|
+
* send all operations to the driver layer, while in TurnBased the operations will be buffered
|
|
550
|
+
* and then sent them as a single batch at the end of the turn.
|
|
551
|
+
* By default, flush mode is TurnBased.
|
|
552
|
+
*/
|
|
553
|
+
readonly flushMode?: FlushMode;
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Allows Grouped Batching to be disabled by setting to false (default is true).
|
|
557
|
+
* In that case, batched messages will be sent individually (but still all at the same time).
|
|
558
|
+
*/
|
|
559
|
+
readonly enableGroupedBatching?: boolean;
|
|
560
|
+
}
|
|
561
|
+
|
|
535
562
|
/**
|
|
536
563
|
* Error responses when requesting a deleted object will have this header set to true
|
|
537
564
|
* @legacy
|
|
@@ -836,11 +863,15 @@ export async function loadContainerRuntime(
|
|
|
836
863
|
/**
|
|
837
864
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
838
865
|
* It will define the store level mappings.
|
|
866
|
+
*
|
|
867
|
+
* @deprecated To be removed from the Legacy-Alpha API in version 2.20.0.
|
|
868
|
+
* Use the loadContainerRuntime function and interfaces IContainerRuntime / IRuntime instead.
|
|
869
|
+
*
|
|
839
870
|
* @legacy
|
|
840
871
|
* @alpha
|
|
841
872
|
*/
|
|
842
873
|
export class ContainerRuntime
|
|
843
|
-
extends TypedEventEmitter<IContainerRuntimeEvents
|
|
874
|
+
extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
844
875
|
implements
|
|
845
876
|
IContainerRuntime,
|
|
846
877
|
IRuntime,
|
|
@@ -867,7 +898,7 @@ export class ContainerRuntime
|
|
|
867
898
|
context: IContainerContext;
|
|
868
899
|
registryEntries: NamedFluidDataStoreRegistryEntries;
|
|
869
900
|
existing: boolean;
|
|
870
|
-
runtimeOptions?: IContainerRuntimeOptions;
|
|
901
|
+
runtimeOptions?: IContainerRuntimeOptions; // May also include options from IContainerRuntimeOptionsInternal
|
|
871
902
|
containerScope?: FluidObject;
|
|
872
903
|
containerRuntimeCtor?: typeof ContainerRuntime;
|
|
873
904
|
/** @deprecated Will be removed once Loader LTS version is "2.0.0-internal.7.0.0". Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md */
|
|
@@ -914,7 +945,7 @@ export class ContainerRuntime
|
|
|
914
945
|
chunkSizeInBytes = defaultChunkSizeInBytes,
|
|
915
946
|
enableGroupedBatching = true,
|
|
916
947
|
explicitSchemaControl = false,
|
|
917
|
-
} = runtimeOptions;
|
|
948
|
+
}: IContainerRuntimeOptionsInternal = runtimeOptions;
|
|
918
949
|
|
|
919
950
|
const registry = new FluidDataStoreRegistry(registryEntries);
|
|
920
951
|
|
|
@@ -1093,6 +1124,21 @@ export class ContainerRuntime
|
|
|
1093
1124
|
|
|
1094
1125
|
const featureGatesForTelemetry: Record<string, boolean | number | undefined> = {};
|
|
1095
1126
|
|
|
1127
|
+
// Make sure we've got all the options including internal ones
|
|
1128
|
+
const internalRuntimeOptions: Readonly<Required<IContainerRuntimeOptionsInternal>> = {
|
|
1129
|
+
summaryOptions,
|
|
1130
|
+
gcOptions,
|
|
1131
|
+
loadSequenceNumberVerification,
|
|
1132
|
+
flushMode,
|
|
1133
|
+
compressionOptions,
|
|
1134
|
+
maxBatchSizeInBytes,
|
|
1135
|
+
chunkSizeInBytes,
|
|
1136
|
+
// Requires<> drops undefined from IdCompressorType
|
|
1137
|
+
enableRuntimeIdCompressor: enableRuntimeIdCompressor as "on" | "delayed",
|
|
1138
|
+
enableGroupedBatching,
|
|
1139
|
+
explicitSchemaControl,
|
|
1140
|
+
};
|
|
1141
|
+
|
|
1096
1142
|
const runtime = new containerRuntimeCtor(
|
|
1097
1143
|
context,
|
|
1098
1144
|
registry,
|
|
@@ -1100,19 +1146,7 @@ export class ContainerRuntime
|
|
|
1100
1146
|
electedSummarizerData,
|
|
1101
1147
|
chunks ?? [],
|
|
1102
1148
|
aliases ?? [],
|
|
1103
|
-
|
|
1104
|
-
summaryOptions,
|
|
1105
|
-
gcOptions,
|
|
1106
|
-
loadSequenceNumberVerification,
|
|
1107
|
-
flushMode,
|
|
1108
|
-
compressionOptions,
|
|
1109
|
-
maxBatchSizeInBytes,
|
|
1110
|
-
chunkSizeInBytes,
|
|
1111
|
-
// Requires<> drops undefined from IdCompressorType
|
|
1112
|
-
enableRuntimeIdCompressor: enableRuntimeIdCompressor as "on" | "delayed",
|
|
1113
|
-
enableGroupedBatching,
|
|
1114
|
-
explicitSchemaControl,
|
|
1115
|
-
},
|
|
1149
|
+
internalRuntimeOptions,
|
|
1116
1150
|
containerScope,
|
|
1117
1151
|
logger,
|
|
1118
1152
|
existing,
|
|
@@ -1474,6 +1508,11 @@ export class ContainerRuntime
|
|
|
1474
1508
|
expiry: { policy: "absolute", durationMs: 60000 },
|
|
1475
1509
|
});
|
|
1476
1510
|
|
|
1511
|
+
/**
|
|
1512
|
+
* The options to apply to this ContainerRuntime instance (including internal options hidden from the public API)
|
|
1513
|
+
*/
|
|
1514
|
+
private readonly runtimeOptions: Readonly<Required<IContainerRuntimeOptionsInternal>>;
|
|
1515
|
+
|
|
1477
1516
|
/***/
|
|
1478
1517
|
protected constructor(
|
|
1479
1518
|
context: IContainerContext,
|
|
@@ -1482,7 +1521,10 @@ export class ContainerRuntime
|
|
|
1482
1521
|
electedSummarizerData: ISerializedElection | undefined,
|
|
1483
1522
|
chunks: [string, string[]][],
|
|
1484
1523
|
dataStoreAliasMap: [string, string][],
|
|
1485
|
-
|
|
1524
|
+
runtimeOptions: Readonly<
|
|
1525
|
+
Required<Omit<IContainerRuntimeOptions, "flushMode" | "enableGroupedBatching">> &
|
|
1526
|
+
IContainerRuntimeOptions // Let flushMode and enabledGroupedBatching be optional now since they're soon to be removed
|
|
1527
|
+
>,
|
|
1486
1528
|
private readonly containerScope: FluidObject,
|
|
1487
1529
|
// Create a custom ITelemetryBaseLogger to output telemetry events.
|
|
1488
1530
|
public readonly baseLogger: ITelemetryBaseLogger,
|
|
@@ -1527,6 +1569,12 @@ export class ContainerRuntime
|
|
|
1527
1569
|
snapshotWithContents,
|
|
1528
1570
|
} = context;
|
|
1529
1571
|
|
|
1572
|
+
// Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
|
|
1573
|
+
this.runtimeOptions = {
|
|
1574
|
+
flushMode: defaultFlushMode,
|
|
1575
|
+
enableGroupedBatching: true,
|
|
1576
|
+
...runtimeOptions,
|
|
1577
|
+
};
|
|
1530
1578
|
this.logger = createChildLogger({ logger: this.baseLogger });
|
|
1531
1579
|
this.mc = createChildMonitoringContext({
|
|
1532
1580
|
logger: this.logger,
|
|
@@ -1697,14 +1745,15 @@ export class ContainerRuntime
|
|
|
1697
1745
|
this.defaultMaxConsecutiveReconnects;
|
|
1698
1746
|
|
|
1699
1747
|
if (
|
|
1700
|
-
runtimeOptions.flushMode ===
|
|
1748
|
+
this.runtimeOptions.flushMode ===
|
|
1749
|
+
(FlushModeExperimental.Async as unknown as FlushMode) &&
|
|
1701
1750
|
supportedFeatures?.get("referenceSequenceNumbers") !== true
|
|
1702
1751
|
) {
|
|
1703
1752
|
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
1704
1753
|
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
1705
1754
|
this._flushMode = FlushMode.TurnBased;
|
|
1706
1755
|
} else {
|
|
1707
|
-
this._flushMode = runtimeOptions.flushMode;
|
|
1756
|
+
this._flushMode = this.runtimeOptions.flushMode;
|
|
1708
1757
|
}
|
|
1709
1758
|
this.offlineEnabled =
|
|
1710
1759
|
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
|
|
@@ -2015,9 +2064,19 @@ export class ContainerRuntime
|
|
|
2015
2064
|
initialDelayMs: this.initialSummarizerDelayMs,
|
|
2016
2065
|
},
|
|
2017
2066
|
);
|
|
2018
|
-
|
|
2019
|
-
|
|
2067
|
+
// Forward events from SummaryManager
|
|
2068
|
+
[
|
|
2069
|
+
"summarize",
|
|
2070
|
+
"summarizeAllAttemptsFailed",
|
|
2071
|
+
"summarizerStop",
|
|
2072
|
+
"summarizerStart",
|
|
2073
|
+
"summarizerStartupFailed",
|
|
2074
|
+
].forEach((eventName) => {
|
|
2075
|
+
this.summaryManager?.on(eventName, (...args: any[]) => {
|
|
2076
|
+
this.emit(eventName, ...args);
|
|
2077
|
+
});
|
|
2020
2078
|
});
|
|
2079
|
+
|
|
2021
2080
|
this.summaryManager.start();
|
|
2022
2081
|
}
|
|
2023
2082
|
}
|
package/src/index.ts
CHANGED
package/src/packageVersion.ts
CHANGED
|
@@ -3,13 +3,10 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { SummarizerStopReason } from "@fluidframework/container-runtime-definitions/internal";
|
|
6
7
|
import { assert, Deferred } from "@fluidframework/core-utils/internal";
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
-
IConnectableRuntime,
|
|
10
|
-
ISummaryCancellationToken,
|
|
11
|
-
SummarizerStopReason,
|
|
12
|
-
} from "./summarizerTypes.js";
|
|
9
|
+
import { IConnectableRuntime, ISummaryCancellationToken } from "./summarizerTypes.js";
|
|
13
10
|
|
|
14
11
|
/**
|
|
15
12
|
* Similar to AbortController, but using promise instead of events
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
+
import type {
|
|
8
|
+
ISummarizeEventProps,
|
|
9
|
+
ISummarizerEvents,
|
|
10
|
+
ISummarizerObservabilityProps,
|
|
11
|
+
SummarizerStopReason,
|
|
12
|
+
} from "@fluidframework/container-runtime-definitions/internal";
|
|
7
13
|
import { IDisposable, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
14
|
import { assert, Deferred, PromiseTimer, delay } from "@fluidframework/core-utils/internal";
|
|
9
15
|
import {
|
|
@@ -29,18 +35,15 @@ import {
|
|
|
29
35
|
IOnDemandSummarizeOptions,
|
|
30
36
|
IRefreshSummaryAckOptions,
|
|
31
37
|
ISubmitSummaryOptions,
|
|
32
|
-
ISummarizeEventProps,
|
|
33
38
|
ISummarizeHeuristicData,
|
|
34
39
|
ISummarizeHeuristicRunner,
|
|
35
40
|
ISummarizeOptions,
|
|
36
41
|
ISummarizeResults,
|
|
37
42
|
ISummarizeRunnerTelemetry,
|
|
38
43
|
ISummarizeTelemetryProperties,
|
|
39
|
-
ISummarizerEvents,
|
|
40
44
|
ISummarizerRuntime,
|
|
41
45
|
ISummaryCancellationToken,
|
|
42
46
|
SubmitSummaryResult,
|
|
43
|
-
SummarizerStopReason,
|
|
44
47
|
type IRetriableFailureError,
|
|
45
48
|
} from "./summarizerTypes.js";
|
|
46
49
|
import {
|
|
@@ -189,6 +192,13 @@ export class RunningSummarizer
|
|
|
189
192
|
/** The maximum number of summary attempts to do when submit summary fails. */
|
|
190
193
|
private readonly maxAttemptsForSubmitFailures: number;
|
|
191
194
|
|
|
195
|
+
/**
|
|
196
|
+
* These are necessary to store outside of methods because of the logic around runnning a lastSummary.
|
|
197
|
+
* We want the lastSummary to also be captured as "all attempts failed".
|
|
198
|
+
*/
|
|
199
|
+
private lastSummarizeFailureEventProps: Omit<ISummarizeEventProps, "result"> | undefined =
|
|
200
|
+
undefined;
|
|
201
|
+
|
|
192
202
|
private constructor(
|
|
193
203
|
baseLogger: ITelemetryBaseLogger,
|
|
194
204
|
private readonly summaryWatcher: IClientSummaryWatcher,
|
|
@@ -492,6 +502,8 @@ export class RunningSummarizer
|
|
|
492
502
|
// summarizeProps
|
|
493
503
|
{ summarizeReason: "lastSummary" },
|
|
494
504
|
{},
|
|
505
|
+
undefined,
|
|
506
|
+
true /* isLastSummary */,
|
|
495
507
|
);
|
|
496
508
|
}
|
|
497
509
|
}
|
|
@@ -502,6 +514,15 @@ export class RunningSummarizer
|
|
|
502
514
|
// submit summary. We should reconsider this flow and make summarizer move to exit faster.
|
|
503
515
|
// This resolves when the current pending summary gets an ack or fails.
|
|
504
516
|
await this.summarizingLock;
|
|
517
|
+
|
|
518
|
+
if (this.lastSummarizeFailureEventProps !== undefined) {
|
|
519
|
+
this.emit("summarizeAllAttemptsFailed", {
|
|
520
|
+
...this.lastSummarizeFailureEventProps,
|
|
521
|
+
numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
|
|
522
|
+
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
this.lastSummarizeFailureEventProps = undefined;
|
|
505
526
|
}
|
|
506
527
|
|
|
507
528
|
private async waitStart() {
|
|
@@ -579,12 +600,14 @@ export class RunningSummarizer
|
|
|
579
600
|
* @param options - summary options
|
|
580
601
|
* @param cancellationToken - cancellation token to use to be able to cancel this summary, if needed
|
|
581
602
|
* @param resultsBuilder - optional, result builder to use.
|
|
603
|
+
* @param isLastSummary - optional, is the call to this method for a last summary when shutting down the summarizer?
|
|
582
604
|
* @returns ISummarizeResult - result of running a summary.
|
|
583
605
|
*/
|
|
584
606
|
private trySummarizeOnce(
|
|
585
607
|
summarizeProps: ISummarizeTelemetryProperties,
|
|
586
608
|
options: ISummarizeOptions,
|
|
587
609
|
resultsBuilder = new SummarizeResultBuilder(),
|
|
610
|
+
isLastSummary = false,
|
|
588
611
|
): ISummarizeResults {
|
|
589
612
|
this.lockedSummaryAction(
|
|
590
613
|
() => {
|
|
@@ -604,7 +627,28 @@ export class RunningSummarizer
|
|
|
604
627
|
const summarizeResult = this.generator.summarize(summaryOptions, resultsBuilder);
|
|
605
628
|
// ensure we wait till the end of the process
|
|
606
629
|
const result = await summarizeResult.receivedSummaryAckOrNack;
|
|
607
|
-
|
|
630
|
+
|
|
631
|
+
if (result.success) {
|
|
632
|
+
this.emit("summarize", {
|
|
633
|
+
result: "success",
|
|
634
|
+
currentAttempt: 1,
|
|
635
|
+
maxAttempts: 1,
|
|
636
|
+
numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
|
|
637
|
+
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
638
|
+
isLastSummary,
|
|
639
|
+
});
|
|
640
|
+
this.lastSummarizeFailureEventProps = undefined;
|
|
641
|
+
} else {
|
|
642
|
+
this.emit("summarize", {
|
|
643
|
+
result: "failure",
|
|
644
|
+
currentAttempt: 1,
|
|
645
|
+
maxAttempts: 1,
|
|
646
|
+
error: result.error,
|
|
647
|
+
failureMessage: result.message,
|
|
648
|
+
numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
|
|
649
|
+
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
650
|
+
isLastSummary,
|
|
651
|
+
});
|
|
608
652
|
this.mc.logger.sendErrorEvent(
|
|
609
653
|
{
|
|
610
654
|
eventName: "SummarizeFailed",
|
|
@@ -613,6 +657,14 @@ export class RunningSummarizer
|
|
|
613
657
|
},
|
|
614
658
|
result.error,
|
|
615
659
|
);
|
|
660
|
+
if (isLastSummary) {
|
|
661
|
+
this.lastSummarizeFailureEventProps = {
|
|
662
|
+
currentAttempt: (this.lastSummarizeFailureEventProps?.currentAttempt ?? 0) + 1,
|
|
663
|
+
maxAttempts: (this.lastSummarizeFailureEventProps?.currentAttempt ?? 0) + 1,
|
|
664
|
+
error: result.error,
|
|
665
|
+
failureMessage: result.message,
|
|
666
|
+
};
|
|
667
|
+
}
|
|
616
668
|
}
|
|
617
669
|
},
|
|
618
670
|
() => {
|
|
@@ -701,6 +753,7 @@ export class RunningSummarizer
|
|
|
701
753
|
let status: "success" | "failure" | "canceled" = "success";
|
|
702
754
|
let results: ISummarizeResults | undefined;
|
|
703
755
|
let error: IRetriableFailureError | undefined;
|
|
756
|
+
let failureMessage: string | undefined;
|
|
704
757
|
do {
|
|
705
758
|
currentAttempt++;
|
|
706
759
|
if (this.cancellationToken.cancelled) {
|
|
@@ -731,12 +784,16 @@ export class RunningSummarizer
|
|
|
731
784
|
// Emit "summarize" event for this failed attempt.
|
|
732
785
|
status = "failure";
|
|
733
786
|
error = ackNackResult.error;
|
|
787
|
+
failureMessage = ackNackResult.message;
|
|
734
788
|
retryAfterSeconds = error.retryAfterSeconds;
|
|
735
|
-
const eventProps: ISummarizeEventProps = {
|
|
789
|
+
const eventProps: ISummarizeEventProps & ISummarizerObservabilityProps = {
|
|
736
790
|
result: status,
|
|
737
791
|
currentAttempt,
|
|
738
792
|
maxAttempts,
|
|
739
793
|
error,
|
|
794
|
+
failureMessage,
|
|
795
|
+
numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
|
|
796
|
+
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
740
797
|
};
|
|
741
798
|
this.emit("summarize", eventProps);
|
|
742
799
|
|
|
@@ -761,7 +818,13 @@ export class RunningSummarizer
|
|
|
761
818
|
|
|
762
819
|
// If the attempt was successful, emit "summarize" event and return. A failed attempt may be retried below.
|
|
763
820
|
if (status !== "failure") {
|
|
764
|
-
this.emit("summarize", {
|
|
821
|
+
this.emit("summarize", {
|
|
822
|
+
result: status,
|
|
823
|
+
currentAttempt,
|
|
824
|
+
maxAttempts,
|
|
825
|
+
numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
|
|
826
|
+
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
827
|
+
});
|
|
765
828
|
return results;
|
|
766
829
|
}
|
|
767
830
|
|
|
@@ -772,14 +835,16 @@ export class RunningSummarizer
|
|
|
772
835
|
// Ack / nack is the final step, so if it succeeds we're done.
|
|
773
836
|
const ackNackResult = await summarizeResult.receivedSummaryAckOrNack;
|
|
774
837
|
status = ackNackResult.success ? "success" : "failure";
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
const eventProps: ISummarizeEventProps = {
|
|
838
|
+
error = ackNackResult.success ? undefined : ackNackResult.error;
|
|
839
|
+
failureMessage = ackNackResult.success ? undefined : ackNackResult.message;
|
|
840
|
+
const eventProps: ISummarizeEventProps & ISummarizerObservabilityProps = {
|
|
779
841
|
result: status,
|
|
780
842
|
currentAttempt,
|
|
781
843
|
maxAttempts,
|
|
782
|
-
error
|
|
844
|
+
error,
|
|
845
|
+
failureMessage,
|
|
846
|
+
numUnsummarizedRuntimeOps: this.heuristicData.numRuntimeOps,
|
|
847
|
+
numUnsummarizedNonRuntimeOps: this.heuristicData.numNonRuntimeOps,
|
|
783
848
|
};
|
|
784
849
|
this.emit("summarize", eventProps);
|
|
785
850
|
results = summarizeResult;
|
|
@@ -795,6 +860,12 @@ export class RunningSummarizer
|
|
|
795
860
|
},
|
|
796
861
|
error,
|
|
797
862
|
);
|
|
863
|
+
this.lastSummarizeFailureEventProps = {
|
|
864
|
+
currentAttempt,
|
|
865
|
+
maxAttempts,
|
|
866
|
+
error,
|
|
867
|
+
failureMessage,
|
|
868
|
+
};
|
|
798
869
|
this.stopSummarizerCallback("failToSummarize");
|
|
799
870
|
}
|
|
800
871
|
return results;
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
+
import type {
|
|
8
|
+
ISummarizerEvents,
|
|
9
|
+
SummarizerStopReason,
|
|
10
|
+
} from "@fluidframework/container-runtime-definitions/internal";
|
|
7
11
|
import { IFluidHandleContext } from "@fluidframework/core-interfaces/internal";
|
|
8
12
|
import { Deferred } from "@fluidframework/core-utils/internal";
|
|
9
13
|
import {
|
|
@@ -25,15 +29,12 @@ import {
|
|
|
25
29
|
IConnectableRuntime,
|
|
26
30
|
IEnqueueSummarizeOptions,
|
|
27
31
|
IOnDemandSummarizeOptions,
|
|
28
|
-
ISummarizeEventProps,
|
|
29
32
|
ISummarizeHeuristicData,
|
|
30
33
|
ISummarizeResults,
|
|
31
34
|
ISummarizer,
|
|
32
|
-
ISummarizerEvents,
|
|
33
35
|
ISummarizerInternalsProvider,
|
|
34
36
|
ISummarizerRuntime,
|
|
35
37
|
ISummarizingWarning,
|
|
36
|
-
SummarizerStopReason,
|
|
37
38
|
} from "./summarizerTypes.js";
|
|
38
39
|
import { SummaryCollection } from "./summaryCollection.js";
|
|
39
40
|
import { SummarizeResultBuilder } from "./summaryGenerator.js";
|
|
@@ -107,9 +108,21 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
107
108
|
|
|
108
109
|
public async run(onBehalfOf: string): Promise<SummarizerStopReason> {
|
|
109
110
|
try {
|
|
110
|
-
|
|
111
|
+
const stopReason = await this.runCore(onBehalfOf);
|
|
112
|
+
this.emit("summarizerStop", {
|
|
113
|
+
stopReason,
|
|
114
|
+
numUnsummarizedRuntimeOps: this._heuristicData?.numRuntimeOps,
|
|
115
|
+
numUnsummarizedNonRuntimeOps: this._heuristicData?.numNonRuntimeOps,
|
|
116
|
+
});
|
|
117
|
+
return stopReason;
|
|
111
118
|
} catch (error) {
|
|
112
119
|
this.stop("summarizerException");
|
|
120
|
+
this.emit("summarizerStop", {
|
|
121
|
+
stopReason: "summarizerException",
|
|
122
|
+
error,
|
|
123
|
+
numUnsummarizedRuntimeOps: this._heuristicData?.numRuntimeOps,
|
|
124
|
+
numUnsummarizedNonRuntimeOps: this._heuristicData?.numNonRuntimeOps,
|
|
125
|
+
});
|
|
113
126
|
throw SummarizingWarning.wrap(error, false /* logged */, this.logger);
|
|
114
127
|
} finally {
|
|
115
128
|
this.close();
|
|
@@ -148,9 +161,20 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
148
161
|
});
|
|
149
162
|
|
|
150
163
|
if (runCoordinator.cancelled) {
|
|
164
|
+
this.emit("summarizerStartupFailed", {
|
|
165
|
+
reason: await runCoordinator.waitCancelled,
|
|
166
|
+
numUnsummarizedRuntimeOps: this._heuristicData?.numRuntimeOps,
|
|
167
|
+
numUnsummarizedNonRuntimeOps: this._heuristicData?.numNonRuntimeOps,
|
|
168
|
+
});
|
|
151
169
|
return runCoordinator.waitCancelled;
|
|
152
170
|
}
|
|
153
171
|
|
|
172
|
+
this.emit("summarizerStart", {
|
|
173
|
+
onBehalfOf,
|
|
174
|
+
numUnsummarizedRuntimeOps: this._heuristicData?.numRuntimeOps,
|
|
175
|
+
numUnsummarizedNonRuntimeOps: this._heuristicData?.numNonRuntimeOps,
|
|
176
|
+
});
|
|
177
|
+
|
|
154
178
|
const runningSummarizer = await this.start(onBehalfOf, runCoordinator);
|
|
155
179
|
|
|
156
180
|
// Wait for either external signal to cancel, or loss of connectivity.
|
|
@@ -254,15 +278,11 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
254
278
|
this.runtime,
|
|
255
279
|
);
|
|
256
280
|
this.runningSummarizer = runningSummarizer;
|
|
257
|
-
this.
|
|
281
|
+
this.setupForwardedEvents();
|
|
258
282
|
this.starting = false;
|
|
259
283
|
return runningSummarizer;
|
|
260
284
|
}
|
|
261
285
|
|
|
262
|
-
private readonly handleSummarizeEvent = (eventProps: ISummarizeEventProps) => {
|
|
263
|
-
this.emit("summarize", eventProps);
|
|
264
|
-
};
|
|
265
|
-
|
|
266
286
|
/**
|
|
267
287
|
* Disposes of resources after running. This cleanup will
|
|
268
288
|
* clear any outstanding timers and reset some of the state
|
|
@@ -275,7 +295,7 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
275
295
|
|
|
276
296
|
this._disposed = true;
|
|
277
297
|
if (this.runningSummarizer) {
|
|
278
|
-
this.
|
|
298
|
+
this.cleanupForwardedEvents();
|
|
279
299
|
this.runningSummarizer.dispose();
|
|
280
300
|
this.runningSummarizer = undefined;
|
|
281
301
|
}
|
|
@@ -355,4 +375,23 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
355
375
|
public recordSummaryAttempt?(summaryRefSeqNum?: number) {
|
|
356
376
|
this._heuristicData?.recordAttempt(summaryRefSeqNum);
|
|
357
377
|
}
|
|
378
|
+
|
|
379
|
+
private readonly forwardedEvents = new Map<any, () => void>();
|
|
380
|
+
|
|
381
|
+
private setupForwardedEvents() {
|
|
382
|
+
["summarize", "summarizeAllAttemptsFailed"].forEach((event) => {
|
|
383
|
+
const listener = (...args: any[]) => {
|
|
384
|
+
this.emit(event, ...args);
|
|
385
|
+
};
|
|
386
|
+
this.runningSummarizer?.on(event as any, listener);
|
|
387
|
+
this.forwardedEvents.set(event, listener);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
private cleanupForwardedEvents() {
|
|
392
|
+
this.forwardedEvents.forEach((listener, event) =>
|
|
393
|
+
this.runningSummarizer?.off(event, listener),
|
|
394
|
+
);
|
|
395
|
+
this.forwardedEvents.clear();
|
|
396
|
+
}
|
|
358
397
|
}
|
|
@@ -7,6 +7,10 @@ import {
|
|
|
7
7
|
IDeltaManager,
|
|
8
8
|
ContainerWarning,
|
|
9
9
|
} from "@fluidframework/container-definitions/internal";
|
|
10
|
+
import type {
|
|
11
|
+
ISummarizerEvents as NewISummarizerEvents,
|
|
12
|
+
SummarizerStopReason as NewSummarizerStopReason,
|
|
13
|
+
} from "@fluidframework/container-runtime-definitions/internal";
|
|
10
14
|
import {
|
|
11
15
|
IEvent,
|
|
12
16
|
IEventProvider,
|
|
@@ -54,7 +58,7 @@ export interface ICancellationToken<T> {
|
|
|
54
58
|
* @legacy
|
|
55
59
|
* @alpha
|
|
56
60
|
*/
|
|
57
|
-
export type ISummaryCancellationToken = ICancellationToken<
|
|
61
|
+
export type ISummaryCancellationToken = ICancellationToken<NewSummarizerStopReason>;
|
|
58
62
|
|
|
59
63
|
/**
|
|
60
64
|
* Data required to update internal tracking state after receiving a Summary Ack.
|
|
@@ -397,6 +401,7 @@ export type EnqueueSummarizeResult =
|
|
|
397
401
|
/**
|
|
398
402
|
* @legacy
|
|
399
403
|
* @alpha
|
|
404
|
+
* @deprecated Use SummarizerStopReason from the "\@fluidframework/container-runtime-definitions" package
|
|
400
405
|
*/
|
|
401
406
|
export type SummarizerStopReason =
|
|
402
407
|
/** Summarizer client failed to summarize in all attempts. */
|
|
@@ -427,6 +432,7 @@ export type SummarizerStopReason =
|
|
|
427
432
|
/**
|
|
428
433
|
* @legacy
|
|
429
434
|
* @alpha
|
|
435
|
+
* @deprecated Use ISummarizeEventProps from the "\@fluidframework/container-runtime-definitions" package
|
|
430
436
|
*/
|
|
431
437
|
export interface ISummarizeEventProps {
|
|
432
438
|
result: "success" | "failure" | "canceled";
|
|
@@ -438,6 +444,7 @@ export interface ISummarizeEventProps {
|
|
|
438
444
|
/**
|
|
439
445
|
* @legacy
|
|
440
446
|
* @alpha
|
|
447
|
+
* @deprecated Use ISummarizerEvents from the "\@fluidframework/container-runtime-definitions" package
|
|
441
448
|
*/
|
|
442
449
|
export interface ISummarizerEvents extends IEvent {
|
|
443
450
|
(event: "summarize", listener: (props: ISummarizeEventProps) => void);
|
|
@@ -447,7 +454,7 @@ export interface ISummarizerEvents extends IEvent {
|
|
|
447
454
|
* @legacy
|
|
448
455
|
* @alpha
|
|
449
456
|
*/
|
|
450
|
-
export interface ISummarizer extends IEventProvider<
|
|
457
|
+
export interface ISummarizer extends IEventProvider<NewISummarizerEvents> {
|
|
451
458
|
/**
|
|
452
459
|
* Allows {@link ISummarizer} to be used with our {@link @fluidframework/core-interfaces#FluidObject} pattern.
|
|
453
460
|
*/
|
|
@@ -458,12 +465,12 @@ export interface ISummarizer extends IEventProvider<ISummarizerEvents> {
|
|
|
458
465
|
* Summarizer will finish current processes, which may take a while.
|
|
459
466
|
* For example, summarizer may complete last summary before exiting.
|
|
460
467
|
*/
|
|
461
|
-
stop(reason:
|
|
468
|
+
stop(reason: NewSummarizerStopReason): void;
|
|
462
469
|
|
|
463
470
|
/* Closes summarizer. Any pending processes (summary in flight) are abandoned. */
|
|
464
471
|
close(): void;
|
|
465
472
|
|
|
466
|
-
run(onBehalfOf: string): Promise<
|
|
473
|
+
run(onBehalfOf: string): Promise<NewSummarizerStopReason>;
|
|
467
474
|
|
|
468
475
|
/**
|
|
469
476
|
* Attempts to generate a summary on demand. If already running, takes no action.
|