@fluidframework/container-runtime 2.0.0-internal.6.2.0 → 2.0.0-internal.6.3.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 +4 -0
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +4 -3
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +1 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +81 -69
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +13 -12
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +18 -3
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +185 -145
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +3 -3
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +2 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +36 -36
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -8
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +19 -20
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.d.ts +1 -1
- package/dist/deltaManagerProxyBase.js +2 -2
- package/dist/deltaManagerProxyBase.js.map +1 -1
- package/dist/deltaScheduler.js +6 -6
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +3 -5
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +4 -21
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +2 -2
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.js +7 -7
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +4 -7
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +15 -52
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +4 -4
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +1 -2
- package/dist/gc/index.js.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.js +2 -2
- package/dist/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/finalSpace.js +2 -2
- package/dist/id-compressor/finalSpace.js.map +1 -1
- package/dist/id-compressor/idCompressor.d.ts.map +1 -1
- package/dist/id-compressor/idCompressor.js +16 -15
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/sessions.js +5 -5
- package/dist/id-compressor/sessions.js.map +1 -1
- package/dist/id-compressor/utilities.js +2 -2
- package/dist/id-compressor/utilities.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +4 -3
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +11 -10
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +3 -3
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.js +12 -12
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.js +6 -6
- package/dist/opLifecycle/outbox.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/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +12 -13
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +19 -18
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/index.d.ts +1 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +1 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +6 -5
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +3 -3
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +1 -1
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +13 -12
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +1 -1
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +4 -3
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +1 -1
- package/dist/summary/summarizerClientElection.js +2 -2
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +2 -2
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts +1 -1
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +5 -14
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +32 -109
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +6 -30
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +0 -11
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +5 -88
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +1 -1
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +9 -8
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.js +2 -2
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +1 -1
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +10 -10
- package/dist/summary/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 +9 -8
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +1 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +52 -40
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +2 -1
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +18 -3
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +147 -107
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +1 -1
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +2 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +2 -2
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +1 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +1 -2
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.d.ts +1 -1
- package/lib/deltaManagerProxyBase.js +1 -1
- package/lib/deltaManagerProxyBase.js.map +1 -1
- package/lib/deltaScheduler.js +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +3 -5
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +5 -22
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +2 -2
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.js +1 -1
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +4 -7
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +16 -53
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +1 -1
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.js +1 -1
- package/lib/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/finalSpace.js +1 -1
- package/lib/id-compressor/finalSpace.js.map +1 -1
- package/lib/id-compressor/idCompressor.d.ts.map +1 -1
- package/lib/id-compressor/idCompressor.js +2 -1
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/sessions.js +1 -1
- package/lib/id-compressor/sessions.js.map +1 -1
- package/lib/id-compressor/utilities.js +1 -1
- package/lib/id-compressor/utilities.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +2 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +2 -1
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +1 -1
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.js +1 -1
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.js +1 -1
- package/lib/opLifecycle/outbox.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/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +1 -2
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +2 -1
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/index.d.ts +1 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +1 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +2 -1
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +1 -1
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +5 -4
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +1 -1
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +2 -1
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +1 -1
- package/lib/summary/summarizerClientElection.js +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/index.d.ts +1 -1
- package/lib/summary/summarizerNode/index.d.ts.map +1 -1
- package/lib/summary/summarizerNode/index.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +5 -14
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +16 -93
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +6 -30
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +0 -11
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -86
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +1 -1
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +2 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.js +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +1 -1
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +3 -3
- package/lib/summary/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 +4 -3
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +22 -24
- package/src/batchTracker.ts +2 -1
- package/src/blobManager.ts +57 -48
- package/src/connectionTelemetry.ts +2 -1
- package/src/containerRuntime.ts +207 -166
- package/src/dataStore.ts +1 -1
- package/src/dataStoreContext.ts +2 -2
- package/src/dataStoreContexts.ts +1 -2
- package/src/dataStores.ts +1 -2
- package/src/deltaManagerProxyBase.ts +1 -1
- package/src/deltaScheduler.ts +1 -1
- package/src/gc/garbageCollection.ts +6 -41
- package/src/gc/gcDefinitions.ts +2 -6
- package/src/gc/gcHelpers.ts +1 -1
- package/src/gc/gcSummaryStateTracker.ts +19 -65
- package/src/gc/gcUnreferencedStateTracker.ts +1 -1
- package/src/gc/index.ts +0 -1
- package/src/id-compressor/appendOnlySortedMap.ts +1 -1
- package/src/id-compressor/finalSpace.ts +1 -1
- package/src/id-compressor/idCompressor.ts +2 -1
- package/src/id-compressor/sessions.ts +1 -1
- package/src/id-compressor/utilities.ts +1 -1
- package/src/opLifecycle/opCompressor.ts +2 -1
- package/src/opLifecycle/opDecompressor.ts +2 -1
- package/src/opLifecycle/opGroupingManager.ts +1 -1
- package/src/opLifecycle/opSplitter.ts +1 -1
- package/src/opLifecycle/outbox.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +1 -2
- package/src/scheduleManager.ts +2 -1
- package/src/summary/index.ts +1 -2
- package/src/summary/orderedClientElection.ts +2 -1
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +5 -10
- package/src/summary/summarizer.ts +2 -1
- package/src/summary/summarizerClientElection.ts +1 -1
- package/src/summary/summarizerHeuristics.ts +1 -1
- package/src/summary/summarizerNode/index.ts +1 -2
- package/src/summary/summarizerNode/summarizerNode.ts +23 -145
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +7 -38
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +3 -123
- package/src/summary/summaryCollection.ts +2 -1
- package/src/summary/summaryFormat.ts +1 -1
- package/src/summary/summaryGenerator.ts +3 -3
- package/src/summary/summaryManager.ts +4 -3
package/lib/containerRuntime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
2
|
-
import { assert, delay,
|
|
3
|
-
import {
|
|
2
|
+
import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
|
|
3
|
+
import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
4
4
|
import { createChildLogger, createChildMonitoringContext, DataCorruptionError, DataProcessingError, GenericError, raiseConnectedEvent, PerformanceEvent,
|
|
5
5
|
// eslint-disable-next-line import/no-deprecated
|
|
6
6
|
TaggedLoggerAdapter, wrapError, UsageError, } from "@fluidframework/telemetry-utils";
|
|
@@ -116,6 +116,10 @@ const defaultCompressionConfig = {
|
|
|
116
116
|
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
117
117
|
};
|
|
118
118
|
const defaultChunkSizeInBytes = 204800;
|
|
119
|
+
/** The default time to wait for pending ops to be processed during summarization */
|
|
120
|
+
export const defaultPendingOpsWaitTimeoutMs = 1000;
|
|
121
|
+
/** The default time to delay a summarization retry attempt when there are pending ops */
|
|
122
|
+
export const defaultPendingOpsRetryDelayMs = 1000;
|
|
119
123
|
/**
|
|
120
124
|
* Instead of refreshing from latest because we do not have 100% confidence in the state
|
|
121
125
|
* of the current system, we should close the summarizer and let it recover.
|
|
@@ -431,12 +435,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
431
435
|
});
|
|
432
436
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
433
437
|
this._audience = audience;
|
|
434
|
-
this.summaryStateUpdateMethod = this.mc.config.getString("Fluid.ContainerRuntime.Test.SummaryStateUpdateMethodV2");
|
|
435
438
|
const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
|
|
436
439
|
this.closeSummarizerDelayMs = closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
437
440
|
this.validateSummaryBeforeUpload =
|
|
438
|
-
this.mc.config.getBoolean("Fluid.
|
|
439
|
-
false;
|
|
441
|
+
this.mc.config.getBoolean("Fluid.Summarizer.ValidateSummaryBeforeUpload") ?? false;
|
|
440
442
|
this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
|
|
441
443
|
this.dirtyContainer =
|
|
442
444
|
this.attachState !== AttachState.Attached || this.hasPendingMessages();
|
|
@@ -534,7 +536,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
534
536
|
disableAttachReorder: this.disableAttachReorder,
|
|
535
537
|
disablePartialFlush,
|
|
536
538
|
idCompressorEnabled: this.idCompressorEnabled,
|
|
537
|
-
summaryStateUpdateMethod: this.summaryStateUpdateMethod,
|
|
538
539
|
closeSummarizerDelayOverride,
|
|
539
540
|
}),
|
|
540
541
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
@@ -1710,6 +1711,40 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1710
1711
|
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
1711
1712
|
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
1712
1713
|
}
|
|
1714
|
+
// If there are pending (unacked ops), the summary will not be eventual consistent and it may even be
|
|
1715
|
+
// incorrect. So, wait for the container to be saved with a timeout. If the container is not saved
|
|
1716
|
+
// within the timeout, check if it should be failed or can continue.
|
|
1717
|
+
if (this.validateSummaryBeforeUpload && this.hasPendingMessages()) {
|
|
1718
|
+
const countBefore = this.pendingMessagesCount;
|
|
1719
|
+
// The timeout for waiting for pending ops can be overridden via configurations.
|
|
1720
|
+
const pendingOpsTimeout = this.mc.config.getNumber("Fluid.Summarizer.waitForPendingOpsTimeoutMs") ??
|
|
1721
|
+
defaultPendingOpsWaitTimeoutMs;
|
|
1722
|
+
await new Promise((resolve, reject) => {
|
|
1723
|
+
const timeoutId = setTimeout(() => resolve(), pendingOpsTimeout);
|
|
1724
|
+
this.once("saved", () => {
|
|
1725
|
+
clearTimeout(timeoutId);
|
|
1726
|
+
resolve();
|
|
1727
|
+
});
|
|
1728
|
+
this.once("dispose", () => {
|
|
1729
|
+
clearTimeout(timeoutId);
|
|
1730
|
+
reject(new Error("Runtime is disposed while summarizing"));
|
|
1731
|
+
});
|
|
1732
|
+
});
|
|
1733
|
+
// Log that there are pending ops while summarizing. This will help us gather data on how often this
|
|
1734
|
+
// happens, whether we attempted to wait for these ops to be acked and what was the result.
|
|
1735
|
+
summaryNumberLogger.sendTelemetryEvent({
|
|
1736
|
+
eventName: "PendingOpsWhileSummarizing",
|
|
1737
|
+
saved: this.hasPendingMessages() ? false : true,
|
|
1738
|
+
timeout: pendingOpsTimeout,
|
|
1739
|
+
countBefore,
|
|
1740
|
+
countAfter: this.pendingMessagesCount,
|
|
1741
|
+
});
|
|
1742
|
+
// There could still be pending ops. Check if summary should fail or continue.
|
|
1743
|
+
const pendingMessagesFailResult = await this.shouldFailSummaryOnPendingOps(summaryNumberLogger, this.deltaManager.lastSequenceNumber, this.deltaManager.minimumSequenceNumber, finalAttempt, true /* beforeSummaryGeneration */);
|
|
1744
|
+
if (pendingMessagesFailResult !== undefined) {
|
|
1745
|
+
return pendingMessagesFailResult;
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1713
1748
|
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1714
1749
|
let summaryRefSeqNum;
|
|
1715
1750
|
try {
|
|
@@ -1799,33 +1834,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1799
1834
|
error,
|
|
1800
1835
|
};
|
|
1801
1836
|
}
|
|
1802
|
-
|
|
1803
|
-
if (
|
|
1804
|
-
|
|
1805
|
-
// This is a fallback to make progress in documents where there are consistently pending ops in
|
|
1806
|
-
// the summarizer.
|
|
1807
|
-
if (finalAttempt &&
|
|
1808
|
-
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary")) {
|
|
1809
|
-
const error = DataProcessingError.create("Pending ops during summarization", "submitSummary", undefined, { pendingMessages: this.pendingMessagesCount });
|
|
1810
|
-
summaryNumberLogger.sendErrorEvent({
|
|
1811
|
-
eventName: "SkipFailingIncorrectSummary",
|
|
1812
|
-
referenceSequenceNumber: summaryRefSeqNum,
|
|
1813
|
-
minimumSequenceNumber,
|
|
1814
|
-
}, error);
|
|
1815
|
-
}
|
|
1816
|
-
else {
|
|
1817
|
-
// Default retry delay is 1 second. This can be overridden via config so that we can adjust it
|
|
1818
|
-
// based on telemetry while we decide on a stable number.
|
|
1819
|
-
const retryDelayMs = this.mc.config.getNumber("Fluid.Summarizer.PendingOpsRetryDelayMs") ??
|
|
1820
|
-
1000;
|
|
1821
|
-
const error = new RetriableSummaryError("PendingMessagesInSummary", retryDelayMs / 1000, { count: this.pendingMessagesCount });
|
|
1822
|
-
return {
|
|
1823
|
-
stage: "base",
|
|
1824
|
-
referenceSequenceNumber: summaryRefSeqNum,
|
|
1825
|
-
minimumSequenceNumber,
|
|
1826
|
-
error,
|
|
1827
|
-
};
|
|
1828
|
-
}
|
|
1837
|
+
const pendingMessagesFailResult = await this.shouldFailSummaryOnPendingOps(summaryNumberLogger, summaryRefSeqNum, minimumSequenceNumber, finalAttempt, false /* beforeSummaryGeneration */);
|
|
1838
|
+
if (pendingMessagesFailResult !== undefined) {
|
|
1839
|
+
return pendingMessagesFailResult;
|
|
1829
1840
|
}
|
|
1830
1841
|
}
|
|
1831
1842
|
const { summary: summaryTree, stats: partialStats } = summarizeResult;
|
|
@@ -1947,6 +1958,50 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1947
1958
|
}
|
|
1948
1959
|
}
|
|
1949
1960
|
}
|
|
1961
|
+
/**
|
|
1962
|
+
* This helper is called during summarization. If there are pending ops, it will return a failed summarize result
|
|
1963
|
+
* (IBaseSummarizeResult) unless this is the final summarize attempt and SkipFailingIncorrectSummary option is set.
|
|
1964
|
+
* @param logger - The logger to be used for sending telemetry.
|
|
1965
|
+
* @param referenceSequenceNumber - The reference sequence number of the summary attempt.
|
|
1966
|
+
* @param minimumSequenceNumber - The minimum sequence number of the summary attempt.
|
|
1967
|
+
* @param finalAttempt - Whether this is the final summary attempt.
|
|
1968
|
+
* @param beforeSummaryGeneration - Whether this is called before summary generation or after.
|
|
1969
|
+
* @returns failed summarize result (IBaseSummarizeResult) if summary should be failed, undefined otherwise.
|
|
1970
|
+
*/
|
|
1971
|
+
async shouldFailSummaryOnPendingOps(logger, referenceSequenceNumber, minimumSequenceNumber, finalAttempt, beforeSummaryGeneration) {
|
|
1972
|
+
if (!this.hasPendingMessages()) {
|
|
1973
|
+
return;
|
|
1974
|
+
}
|
|
1975
|
+
// If "SkipFailingIncorrectSummary" option is true, don't fail the summary in the last attempt.
|
|
1976
|
+
// This is a fallback to make progress in documents where there are consistently pending ops in
|
|
1977
|
+
// the summarizer.
|
|
1978
|
+
if (finalAttempt &&
|
|
1979
|
+
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary")) {
|
|
1980
|
+
const error = DataProcessingError.create("Pending ops during summarization", "submitSummary", undefined, { pendingMessages: this.pendingMessagesCount });
|
|
1981
|
+
logger.sendErrorEvent({
|
|
1982
|
+
eventName: "SkipFailingIncorrectSummary",
|
|
1983
|
+
referenceSequenceNumber,
|
|
1984
|
+
minimumSequenceNumber,
|
|
1985
|
+
beforeGenerate: beforeSummaryGeneration,
|
|
1986
|
+
}, error);
|
|
1987
|
+
}
|
|
1988
|
+
else {
|
|
1989
|
+
// The retry delay when there are pending ops can be overridden via config so that we can adjust it
|
|
1990
|
+
// based on telemetry while we decide on a stable number.
|
|
1991
|
+
const retryDelayMs = this.mc.config.getNumber("Fluid.Summarizer.PendingOpsRetryDelayMs") ??
|
|
1992
|
+
defaultPendingOpsRetryDelayMs;
|
|
1993
|
+
const error = new RetriableSummaryError("PendingOpsWhileSummarizing", retryDelayMs / 1000, {
|
|
1994
|
+
count: this.pendingMessagesCount,
|
|
1995
|
+
beforeGenerate: beforeSummaryGeneration,
|
|
1996
|
+
});
|
|
1997
|
+
return {
|
|
1998
|
+
stage: "base",
|
|
1999
|
+
referenceSequenceNumber,
|
|
2000
|
+
minimumSequenceNumber,
|
|
2001
|
+
error,
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
1950
2005
|
get pendingMessagesCount() {
|
|
1951
2006
|
return this.pendingStateManager.pendingMessagesCount + this.outbox.messageCount;
|
|
1952
2007
|
}
|
|
@@ -2265,29 +2320,22 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2265
2320
|
/** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
|
|
2266
2321
|
async refreshLatestSummaryAck(options) {
|
|
2267
2322
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
2323
|
+
// proposalHandle is always passed from RunningSummarizer.
|
|
2324
|
+
assert(proposalHandle !== undefined, 0x766 /* proposalHandle should be available */);
|
|
2268
2325
|
const readAndParseBlob = async (id) => readAndParse(this.storage, id);
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2326
|
+
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq);
|
|
2327
|
+
/**
|
|
2328
|
+
* When refreshing a summary ack, this check indicates a new ack of a summary that is newer than the
|
|
2329
|
+
* current summary that is tracked, but this summarizer runtime did not produce/track that summary. Thus
|
|
2330
|
+
* it needs to refresh its state. Today refresh is done by fetching the latest snapshot to update the cache
|
|
2331
|
+
* and then close as the current main client is likely to be re-elected as the parent summarizer again.
|
|
2332
|
+
*/
|
|
2333
|
+
if (!result.isSummaryTracked && result.isSummaryNewer) {
|
|
2334
|
+
const fetchResult = await this.fetchSnapshotFromStorage(summaryLogger, {
|
|
2274
2335
|
eventName: "RefreshLatestSummaryAckFetch",
|
|
2275
2336
|
ackHandle,
|
|
2276
2337
|
targetSequenceNumber: summaryRefSeq,
|
|
2277
2338
|
}, readAndParseBlob, null);
|
|
2278
|
-
/**
|
|
2279
|
-
* back-compat - Older loaders and drivers (pre 2.0.0-internal.1.4) don't have fetchSource as a param in the
|
|
2280
|
-
* getVersions API. So, they will not fetch the latest snapshot from network in the previous fetch call. For
|
|
2281
|
-
* these scenarios, fetch the snapshot corresponding to the ack handle to have the same behavior before the
|
|
2282
|
-
* change that started fetching latest snapshot always.
|
|
2283
|
-
*/
|
|
2284
|
-
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
2285
|
-
fetchResult = await this.fetchSnapshotFromStorageAndMaybeClose(summaryLogger, {
|
|
2286
|
-
eventName: "RefreshLatestSummaryAckFetchBackCompat",
|
|
2287
|
-
ackHandle,
|
|
2288
|
-
targetSequenceNumber: summaryRefSeq,
|
|
2289
|
-
}, readAndParseBlob, ackHandle);
|
|
2290
|
-
}
|
|
2291
2339
|
/**
|
|
2292
2340
|
* If the fetched snapshot is older than the one for which the ack was received, close the container.
|
|
2293
2341
|
* This should never happen because an ack should be sent after the latest summary is updated in the server.
|
|
@@ -2307,17 +2355,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2307
2355
|
this.disposeFn(error);
|
|
2308
2356
|
throw error;
|
|
2309
2357
|
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
return {
|
|
2314
|
-
snapshotTree: fetchResult.snapshotTree,
|
|
2315
|
-
snapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
2316
|
-
};
|
|
2317
|
-
};
|
|
2318
|
-
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq, fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
2358
|
+
await this.closeStaleSummarizer("RefreshLatestSummaryAckFetch");
|
|
2359
|
+
return;
|
|
2360
|
+
}
|
|
2319
2361
|
// Notify the garbage collector so it can update its latest summary state.
|
|
2320
|
-
await this.garbageCollector.refreshLatestSummary(
|
|
2362
|
+
await this.garbageCollector.refreshLatestSummary(result);
|
|
2321
2363
|
}
|
|
2322
2364
|
/**
|
|
2323
2365
|
* Fetches the latest snapshot from storage and uses it to refresh SummarizerNode's
|
|
@@ -2327,25 +2369,31 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2327
2369
|
*/
|
|
2328
2370
|
async refreshLatestSummaryAckFromServer(summaryLogger) {
|
|
2329
2371
|
const readAndParseBlob = async (id) => readAndParse(this.storage, id);
|
|
2330
|
-
const {
|
|
2372
|
+
const { versionId, latestSnapshotRefSeq } = await this.fetchSnapshotFromStorage(summaryLogger, {
|
|
2331
2373
|
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
2332
2374
|
}, readAndParseBlob, null);
|
|
2333
|
-
|
|
2334
|
-
snapshotTree,
|
|
2335
|
-
snapshotRefSeq: latestSnapshotRefSeq,
|
|
2336
|
-
};
|
|
2337
|
-
const result = await this.summarizerNode.refreshLatestSummary(undefined /* proposalHandle */, latestSnapshotRefSeq, async () => fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
2338
|
-
// Notify the garbage collector so it can update its latest summary state.
|
|
2339
|
-
await this.garbageCollector.refreshLatestSummary(undefined /* proposalHandle */, result, readAndParseBlob);
|
|
2375
|
+
await this.closeStaleSummarizer("RefreshLatestSummaryFromServerFetch");
|
|
2340
2376
|
return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
|
|
2341
2377
|
}
|
|
2378
|
+
async closeStaleSummarizer(codePath) {
|
|
2379
|
+
this.mc.logger.sendTelemetryEvent({
|
|
2380
|
+
eventName: "ClosingSummarizerOnSummaryStale",
|
|
2381
|
+
codePath,
|
|
2382
|
+
message: "Stopping fetch from storage",
|
|
2383
|
+
closeSummarizerDelayMs: this.closeSummarizerDelayMs,
|
|
2384
|
+
}, new GenericError("Restarting summarizer instead of refreshing"));
|
|
2385
|
+
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2386
|
+
await delay(this.closeSummarizerDelayMs);
|
|
2387
|
+
this._summarizer?.stop("latestSummaryStateStale");
|
|
2388
|
+
this.disposeFn();
|
|
2389
|
+
}
|
|
2342
2390
|
/**
|
|
2343
2391
|
* Downloads snapshot from storage with the given versionId or latest if versionId is null.
|
|
2344
2392
|
* By default, it also closes the container after downloading the snapshot. However, this may be
|
|
2345
2393
|
* overridden via options.
|
|
2346
2394
|
*/
|
|
2347
|
-
async
|
|
2348
|
-
|
|
2395
|
+
async fetchSnapshotFromStorage(logger, event, readAndParseBlob, versionId) {
|
|
2396
|
+
return PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2349
2397
|
const stats = {};
|
|
2350
2398
|
const trace = Trace.start();
|
|
2351
2399
|
const versions = await this.storage.getVersions(versionId, 1, "refreshLatestSummaryAckFromServer", versionId === null ? FetchSource.noCache : undefined);
|
|
@@ -2364,45 +2412,37 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2364
2412
|
latestSnapshotRefSeq,
|
|
2365
2413
|
};
|
|
2366
2414
|
});
|
|
2367
|
-
// We choose to close the summarizer after the snapshot cache is updated to avoid
|
|
2368
|
-
// situations which the main client (which is likely to be re-elected as the leader again)
|
|
2369
|
-
// loads the summarizer from cache.
|
|
2370
|
-
if (this.summaryStateUpdateMethod !== "refreshFromSnapshot") {
|
|
2371
|
-
this.mc.logger.sendTelemetryEvent({
|
|
2372
|
-
...event,
|
|
2373
|
-
eventName: "ClosingSummarizerOnSummaryStale",
|
|
2374
|
-
codePath: event.eventName,
|
|
2375
|
-
message: "Stopping fetch from storage",
|
|
2376
|
-
versionId: versionId != null ? versionId : undefined,
|
|
2377
|
-
closeSummarizerDelayMs: this.closeSummarizerDelayMs,
|
|
2378
|
-
}, new GenericError("Restarting summarizer instead of refreshing"));
|
|
2379
|
-
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2380
|
-
await delay(this.closeSummarizerDelayMs);
|
|
2381
|
-
this._summarizer?.stop("latestSummaryStateStale");
|
|
2382
|
-
this.disposeFn();
|
|
2383
|
-
}
|
|
2384
|
-
return snapshotResults;
|
|
2385
2415
|
}
|
|
2386
2416
|
notifyAttaching() { } // do nothing (deprecated method)
|
|
2387
2417
|
async getPendingLocalState(props) {
|
|
2388
|
-
this.
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
pending
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2418
|
+
return PerformanceEvent.timedExecAsync(this.mc.logger, {
|
|
2419
|
+
eventName: "getPendingLocalState",
|
|
2420
|
+
notifyImminentClosure: props?.notifyImminentClosure,
|
|
2421
|
+
}, async (event) => {
|
|
2422
|
+
this.verifyNotClosed();
|
|
2423
|
+
const waitBlobsToAttach = props?.notifyImminentClosure;
|
|
2424
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
2425
|
+
throw new UsageError("can't get state during orderSequentially");
|
|
2426
|
+
}
|
|
2427
|
+
const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(waitBlobsToAttach);
|
|
2428
|
+
const pending = this.pendingStateManager.getLocalState();
|
|
2429
|
+
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
2430
|
+
return; // no pending state to save
|
|
2431
|
+
}
|
|
2432
|
+
// Flush pending batch.
|
|
2433
|
+
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2434
|
+
// to close current batch.
|
|
2435
|
+
this.flush();
|
|
2436
|
+
const pendingState = {
|
|
2437
|
+
pending,
|
|
2438
|
+
pendingAttachmentBlobs,
|
|
2439
|
+
};
|
|
2440
|
+
event.end({
|
|
2441
|
+
attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
|
|
2442
|
+
pendingOpsSize: pending?.pendingStates.length,
|
|
2443
|
+
});
|
|
2444
|
+
return pendingState;
|
|
2445
|
+
});
|
|
2406
2446
|
}
|
|
2407
2447
|
summarizeOnDemand(options) {
|
|
2408
2448
|
if (this.isSummarizerClient) {
|