@fluidframework/container-runtime 2.0.0-internal.6.2.0 → 2.0.0-internal.6.3.1
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/dist/containerRuntime.js
CHANGED
|
@@ -19,10 +19,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.AllowInactiveRequestHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
|
|
22
|
+
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.AllowInactiveRequestHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
|
|
23
23
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
24
|
-
const common_utils_1 = require("@fluidframework/common-utils");
|
|
25
24
|
const core_utils_1 = require("@fluidframework/core-utils");
|
|
25
|
+
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
26
26
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
27
27
|
const driver_definitions_1 = require("@fluidframework/driver-definitions");
|
|
28
28
|
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
@@ -136,6 +136,10 @@ const defaultCompressionConfig = {
|
|
|
136
136
|
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
137
137
|
};
|
|
138
138
|
const defaultChunkSizeInBytes = 204800;
|
|
139
|
+
/** The default time to wait for pending ops to be processed during summarization */
|
|
140
|
+
exports.defaultPendingOpsWaitTimeoutMs = 1000;
|
|
141
|
+
/** The default time to delay a summarization retry attempt when there are pending ops */
|
|
142
|
+
exports.defaultPendingOpsRetryDelayMs = 1000;
|
|
139
143
|
/**
|
|
140
144
|
* Instead of refreshing from latest because we do not have 100% confidence in the state
|
|
141
145
|
* of the current system, we should close the summarizer and let it recover.
|
|
@@ -201,7 +205,7 @@ exports.makeLegacySendBatchFn = makeLegacySendBatchFn;
|
|
|
201
205
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
202
206
|
* It will define the store level mappings.
|
|
203
207
|
*/
|
|
204
|
-
class ContainerRuntime extends
|
|
208
|
+
class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
205
209
|
/**
|
|
206
210
|
* @internal
|
|
207
211
|
*/
|
|
@@ -454,12 +458,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
454
458
|
});
|
|
455
459
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
456
460
|
this._audience = audience;
|
|
457
|
-
this.summaryStateUpdateMethod = this.mc.config.getString("Fluid.ContainerRuntime.Test.SummaryStateUpdateMethodV2");
|
|
458
461
|
const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
|
|
459
462
|
this.closeSummarizerDelayMs = closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
460
463
|
this.validateSummaryBeforeUpload =
|
|
461
|
-
this.mc.config.getBoolean("Fluid.
|
|
462
|
-
false;
|
|
464
|
+
this.mc.config.getBoolean("Fluid.Summarizer.ValidateSummaryBeforeUpload") ?? false;
|
|
463
465
|
this.summaryCollection = new summary_1.SummaryCollection(this.deltaManager, this.logger);
|
|
464
466
|
this.dirtyContainer =
|
|
465
467
|
this.attachState !== container_definitions_1.AttachState.Attached || this.hasPendingMessages();
|
|
@@ -520,7 +522,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
520
522
|
// we accumulate ops while being in read-only state.
|
|
521
523
|
// once user gets write permissions and we have active connection, flush all pending ops.
|
|
522
524
|
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
523
|
-
(0,
|
|
525
|
+
(0, core_utils_1.assert)(readonly === this.innerDeltaManager.readOnlyInfo.readonly, 0x124 /* "inconsistent readonly property/event state" */);
|
|
524
526
|
// We need to be very careful with when we (re)send pending ops, to ensure that we only send ops
|
|
525
527
|
// when we either never send an op, or attempted to send it but we know for sure it was not
|
|
526
528
|
// sequenced by server and will never be sequenced (i.e. was lost)
|
|
@@ -533,7 +535,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
533
535
|
// can rely on same safety mechanism and resend ops only when we establish new connection.
|
|
534
536
|
// This is applicable for read-only permissions (event is raised before connection is properly registered),
|
|
535
537
|
// but it's an extra requirement for Container.forceReadonly() API
|
|
536
|
-
(0,
|
|
538
|
+
(0, core_utils_1.assert)(!readonly || !this.connected, 0x125 /* "Unsafe to transition to read-only state!" */);
|
|
537
539
|
this.replayPendingStates();
|
|
538
540
|
});
|
|
539
541
|
// logging hardware telemetry
|
|
@@ -557,7 +559,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
557
559
|
disableAttachReorder: this.disableAttachReorder,
|
|
558
560
|
disablePartialFlush,
|
|
559
561
|
idCompressorEnabled: this.idCompressorEnabled,
|
|
560
|
-
summaryStateUpdateMethod: this.summaryStateUpdateMethod,
|
|
561
562
|
closeSummarizerDelayOverride,
|
|
562
563
|
}),
|
|
563
564
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
@@ -567,7 +568,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
567
568
|
(0, batchTracker_1.BindBatchTracker)(this, this.logger);
|
|
568
569
|
this.entryPoint = new core_utils_1.LazyPromise(async () => {
|
|
569
570
|
if (this.isSummarizerClient) {
|
|
570
|
-
(0,
|
|
571
|
+
(0, core_utils_1.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
571
572
|
return this._summarizer;
|
|
572
573
|
}
|
|
573
574
|
return initializeEntryPoint?.(this);
|
|
@@ -652,7 +653,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
652
653
|
if (context.baseSnapshot && blobId) {
|
|
653
654
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
654
655
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
655
|
-
(0,
|
|
656
|
+
(0, core_utils_1.assert)(context.storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
656
657
|
return (0, driver_utils_1.readAndParse)(context.storage, blobId);
|
|
657
658
|
}
|
|
658
659
|
};
|
|
@@ -667,7 +668,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
667
668
|
const blobManagerSnapshot = await blobManager_1.BlobManager.load(context.baseSnapshot?.trees[summary_1.blobsTreeName], async (id) => {
|
|
668
669
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
669
670
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
670
|
-
(0,
|
|
671
|
+
(0, core_utils_1.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
671
672
|
return (0, driver_utils_1.readAndParse)(context.storage, id);
|
|
672
673
|
});
|
|
673
674
|
// Verify summary runtime sequence number matches protocol sequence number.
|
|
@@ -774,7 +775,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
774
775
|
return this._disposed;
|
|
775
776
|
}
|
|
776
777
|
get summarizer() {
|
|
777
|
-
(0,
|
|
778
|
+
(0, core_utils_1.assert)(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
778
779
|
return this._summarizer;
|
|
779
780
|
}
|
|
780
781
|
isSummariesDisabled() {
|
|
@@ -879,7 +880,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
879
880
|
const subRequest = requestParser.createSubRequest(1);
|
|
880
881
|
// We always expect createSubRequest to include a leading slash, but asserting here to protect against
|
|
881
882
|
// unintentionally modifying the url if that changes.
|
|
882
|
-
(0,
|
|
883
|
+
(0, core_utils_1.assert)(subRequest.url.startsWith("/"), 0x126 /* "Expected createSubRequest url to include a leading slash" */);
|
|
883
884
|
return dataStore.request(subRequest);
|
|
884
885
|
}
|
|
885
886
|
return (0, runtime_utils_1.create404Response)(request);
|
|
@@ -938,7 +939,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
938
939
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
939
940
|
this.addMetadataToSummary(summaryTree);
|
|
940
941
|
if (this.idCompressorEnabled) {
|
|
941
|
-
(0,
|
|
942
|
+
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67a /* IdCompressor should be defined if enabled */);
|
|
942
943
|
const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
|
|
943
944
|
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.idCompressorBlobName, idCompressorState);
|
|
944
945
|
}
|
|
@@ -1013,7 +1014,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1013
1014
|
// Save the old state, reset to false, disable event emit
|
|
1014
1015
|
const oldState = this.dirtyContainer;
|
|
1015
1016
|
this.dirtyContainer = false;
|
|
1016
|
-
(0,
|
|
1017
|
+
(0, core_utils_1.assert)(this.emitDirtyDocumentEvent, 0x127 /* "dirty document event not set on replay" */);
|
|
1017
1018
|
this.emitDirtyDocumentEvent = false;
|
|
1018
1019
|
let newState;
|
|
1019
1020
|
try {
|
|
@@ -1047,9 +1048,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1047
1048
|
* ! Note: this format needs to be in-line with what is set in the "ContainerRuntime.submit(...)" method
|
|
1048
1049
|
*/
|
|
1049
1050
|
parseOpContent(serializedContent) {
|
|
1050
|
-
(0,
|
|
1051
|
+
(0, core_utils_1.assert)(serializedContent !== undefined, 0x6d5 /* content must be defined */);
|
|
1051
1052
|
const { type, contents, compatDetails } = JSON.parse(serializedContent);
|
|
1052
|
-
(0,
|
|
1053
|
+
(0, core_utils_1.assert)(type !== undefined, 0x6d6 /* incorrect op content format */);
|
|
1053
1054
|
return { type, contents, compatDetails };
|
|
1054
1055
|
}
|
|
1055
1056
|
async applyStashedOp(op) {
|
|
@@ -1061,7 +1062,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1061
1062
|
case ContainerMessageType.Attach:
|
|
1062
1063
|
return this.dataStores.applyStashedAttachOp(contents);
|
|
1063
1064
|
case ContainerMessageType.IdAllocation:
|
|
1064
|
-
(0,
|
|
1065
|
+
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67b /* IdCompressor should be defined if enabled */);
|
|
1065
1066
|
return this.applyStashedIdAllocationOp(contents);
|
|
1066
1067
|
case ContainerMessageType.Alias:
|
|
1067
1068
|
case ContainerMessageType.BlobAttach:
|
|
@@ -1100,7 +1101,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1100
1101
|
this.setConnectionStateCore(connected, clientId);
|
|
1101
1102
|
}
|
|
1102
1103
|
setConnectionStateCore(connected, clientId) {
|
|
1103
|
-
(0,
|
|
1104
|
+
(0, core_utils_1.assert)(!this.delayConnectClientId, 0x394 /* connect event delay must be cleared before propagating connect event */);
|
|
1104
1105
|
this.verifyNotClosed();
|
|
1105
1106
|
// There might be no change of state due to Container calling this API after loading runtime.
|
|
1106
1107
|
const changeOfState = this._connected !== connected;
|
|
@@ -1118,7 +1119,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1118
1119
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
1119
1120
|
}
|
|
1120
1121
|
else {
|
|
1121
|
-
(0,
|
|
1122
|
+
(0, core_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x3cd /* Connection is possible only if container exists in storage */);
|
|
1122
1123
|
}
|
|
1123
1124
|
// Fail while disconnected
|
|
1124
1125
|
if (reconnection) {
|
|
@@ -1213,7 +1214,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1213
1214
|
this.blobManager.processBlobAttachOp(message, local);
|
|
1214
1215
|
break;
|
|
1215
1216
|
case ContainerMessageType.IdAllocation:
|
|
1216
|
-
(0,
|
|
1217
|
+
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
|
|
1217
1218
|
this.idCompressor.finalizeCreationRange(message.contents);
|
|
1218
1219
|
break;
|
|
1219
1220
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -1311,7 +1312,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1311
1312
|
await this.dataStores.waitIfPendingAlias(id);
|
|
1312
1313
|
const internalId = this.internalId(id);
|
|
1313
1314
|
const context = await this.dataStores.getDataStore(internalId, { wait });
|
|
1314
|
-
(0,
|
|
1315
|
+
(0, core_utils_1.assert)(await context.isRoot(), 0x12b /* "did not get root data store" */);
|
|
1315
1316
|
return context.realize();
|
|
1316
1317
|
}
|
|
1317
1318
|
/**
|
|
@@ -1319,9 +1320,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1319
1320
|
* This method is expected to be called at the end of a batch.
|
|
1320
1321
|
*/
|
|
1321
1322
|
flush() {
|
|
1322
|
-
(0,
|
|
1323
|
+
(0, core_utils_1.assert)(this._orderSequentiallyCalls === 0, 0x24c /* "Cannot call `flush()` from `orderSequentially`'s callback" */);
|
|
1323
1324
|
this.outbox.flush();
|
|
1324
|
-
(0,
|
|
1325
|
+
(0, core_utils_1.assert)(this.outbox.isEmpty, 0x3cf /* reentrancy */);
|
|
1325
1326
|
}
|
|
1326
1327
|
orderSequentially(callback) {
|
|
1327
1328
|
let checkpoint;
|
|
@@ -1481,10 +1482,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1481
1482
|
}
|
|
1482
1483
|
setAttachState(attachState) {
|
|
1483
1484
|
if (attachState === container_definitions_1.AttachState.Attaching) {
|
|
1484
|
-
(0,
|
|
1485
|
+
(0, core_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attaching, 0x12d /* "Container Context should already be in attaching state" */);
|
|
1485
1486
|
}
|
|
1486
1487
|
else {
|
|
1487
|
-
(0,
|
|
1488
|
+
(0, core_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x12e /* "Container Context should already be in attached state" */);
|
|
1488
1489
|
this.emit("attached");
|
|
1489
1490
|
}
|
|
1490
1491
|
if (attachState === container_definitions_1.AttachState.Attached && !this.hasPendingMessages()) {
|
|
@@ -1542,7 +1543,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1542
1543
|
await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC }, telemetryContext);
|
|
1543
1544
|
}
|
|
1544
1545
|
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
1545
|
-
(0,
|
|
1546
|
+
(0, core_utils_1.assert)(summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1546
1547
|
return { stats, summary };
|
|
1547
1548
|
}
|
|
1548
1549
|
finally {
|
|
@@ -1654,7 +1655,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1654
1655
|
case gc_1.GCNodeType.SubDataStore:
|
|
1655
1656
|
return this.dataStores.getDataStorePackagePath(nodePath);
|
|
1656
1657
|
default:
|
|
1657
|
-
(0,
|
|
1658
|
+
(0, core_utils_1.assert)(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
1658
1659
|
}
|
|
1659
1660
|
}
|
|
1660
1661
|
/**
|
|
@@ -1721,7 +1722,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1721
1722
|
all: { summaryNumber },
|
|
1722
1723
|
},
|
|
1723
1724
|
});
|
|
1724
|
-
(0,
|
|
1725
|
+
(0, core_utils_1.assert)(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
|
|
1725
1726
|
let latestSnapshotVersionId;
|
|
1726
1727
|
if (refreshLatestAck) {
|
|
1727
1728
|
const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer((0, telemetry_utils_1.createChildLogger)({
|
|
@@ -1733,6 +1734,40 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1733
1734
|
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
1734
1735
|
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
1735
1736
|
}
|
|
1737
|
+
// If there are pending (unacked ops), the summary will not be eventual consistent and it may even be
|
|
1738
|
+
// incorrect. So, wait for the container to be saved with a timeout. If the container is not saved
|
|
1739
|
+
// within the timeout, check if it should be failed or can continue.
|
|
1740
|
+
if (this.validateSummaryBeforeUpload && this.hasPendingMessages()) {
|
|
1741
|
+
const countBefore = this.pendingMessagesCount;
|
|
1742
|
+
// The timeout for waiting for pending ops can be overridden via configurations.
|
|
1743
|
+
const pendingOpsTimeout = this.mc.config.getNumber("Fluid.Summarizer.waitForPendingOpsTimeoutMs") ??
|
|
1744
|
+
exports.defaultPendingOpsWaitTimeoutMs;
|
|
1745
|
+
await new Promise((resolve, reject) => {
|
|
1746
|
+
const timeoutId = setTimeout(() => resolve(), pendingOpsTimeout);
|
|
1747
|
+
this.once("saved", () => {
|
|
1748
|
+
clearTimeout(timeoutId);
|
|
1749
|
+
resolve();
|
|
1750
|
+
});
|
|
1751
|
+
this.once("dispose", () => {
|
|
1752
|
+
clearTimeout(timeoutId);
|
|
1753
|
+
reject(new Error("Runtime is disposed while summarizing"));
|
|
1754
|
+
});
|
|
1755
|
+
});
|
|
1756
|
+
// Log that there are pending ops while summarizing. This will help us gather data on how often this
|
|
1757
|
+
// happens, whether we attempted to wait for these ops to be acked and what was the result.
|
|
1758
|
+
summaryNumberLogger.sendTelemetryEvent({
|
|
1759
|
+
eventName: "PendingOpsWhileSummarizing",
|
|
1760
|
+
saved: this.hasPendingMessages() ? false : true,
|
|
1761
|
+
timeout: pendingOpsTimeout,
|
|
1762
|
+
countBefore,
|
|
1763
|
+
countAfter: this.pendingMessagesCount,
|
|
1764
|
+
});
|
|
1765
|
+
// There could still be pending ops. Check if summary should fail or continue.
|
|
1766
|
+
const pendingMessagesFailResult = await this.shouldFailSummaryOnPendingOps(summaryNumberLogger, this.deltaManager.lastSequenceNumber, this.deltaManager.minimumSequenceNumber, finalAttempt, true /* beforeSummaryGeneration */);
|
|
1767
|
+
if (pendingMessagesFailResult !== undefined) {
|
|
1768
|
+
return pendingMessagesFailResult;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1736
1771
|
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1737
1772
|
let summaryRefSeqNum;
|
|
1738
1773
|
try {
|
|
@@ -1759,7 +1794,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1759
1794
|
// That said, we rely on submitSystemMessage() that today only works in connected state.
|
|
1760
1795
|
// So if we fail here, it either means that RunWhileConnectedCoordinator does not work correctly,
|
|
1761
1796
|
// OR that design changed and we need to remove this check and fix submitSystemMessage.
|
|
1762
|
-
(0,
|
|
1797
|
+
(0, core_utils_1.assert)(this.connected, 0x258 /* "connected" */);
|
|
1763
1798
|
// Ensure that lastSequenceNumber has not changed after pausing.
|
|
1764
1799
|
// We need the summary op's reference sequence number to match our summary sequence number,
|
|
1765
1800
|
// otherwise we'll get the wrong sequence number stamped on the summary's .protocol attributes.
|
|
@@ -1769,7 +1804,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1769
1804
|
error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
|
|
1770
1805
|
};
|
|
1771
1806
|
}
|
|
1772
|
-
(0,
|
|
1807
|
+
(0, core_utils_1.assert)(summaryRefSeqNum === this.deltaManager.lastMessage?.sequenceNumber, 0x395 /* it's one and the same thing */);
|
|
1773
1808
|
if (lastAck !== this.summaryCollection.latestAck) {
|
|
1774
1809
|
return {
|
|
1775
1810
|
continue: false,
|
|
@@ -1787,7 +1822,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1787
1822
|
error: continueResult.error,
|
|
1788
1823
|
};
|
|
1789
1824
|
}
|
|
1790
|
-
const trace =
|
|
1825
|
+
const trace = client_utils_1.Trace.start();
|
|
1791
1826
|
let summarizeResult;
|
|
1792
1827
|
// If the GC state needs to be reset, we need to force a full tree summary and update the unreferenced
|
|
1793
1828
|
// state of all the nodes.
|
|
@@ -1822,33 +1857,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1822
1857
|
error,
|
|
1823
1858
|
};
|
|
1824
1859
|
}
|
|
1825
|
-
|
|
1826
|
-
if (
|
|
1827
|
-
|
|
1828
|
-
// This is a fallback to make progress in documents where there are consistently pending ops in
|
|
1829
|
-
// the summarizer.
|
|
1830
|
-
if (finalAttempt &&
|
|
1831
|
-
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary")) {
|
|
1832
|
-
const error = telemetry_utils_1.DataProcessingError.create("Pending ops during summarization", "submitSummary", undefined, { pendingMessages: this.pendingMessagesCount });
|
|
1833
|
-
summaryNumberLogger.sendErrorEvent({
|
|
1834
|
-
eventName: "SkipFailingIncorrectSummary",
|
|
1835
|
-
referenceSequenceNumber: summaryRefSeqNum,
|
|
1836
|
-
minimumSequenceNumber,
|
|
1837
|
-
}, error);
|
|
1838
|
-
}
|
|
1839
|
-
else {
|
|
1840
|
-
// Default retry delay is 1 second. This can be overridden via config so that we can adjust it
|
|
1841
|
-
// based on telemetry while we decide on a stable number.
|
|
1842
|
-
const retryDelayMs = this.mc.config.getNumber("Fluid.Summarizer.PendingOpsRetryDelayMs") ??
|
|
1843
|
-
1000;
|
|
1844
|
-
const error = new summary_1.RetriableSummaryError("PendingMessagesInSummary", retryDelayMs / 1000, { count: this.pendingMessagesCount });
|
|
1845
|
-
return {
|
|
1846
|
-
stage: "base",
|
|
1847
|
-
referenceSequenceNumber: summaryRefSeqNum,
|
|
1848
|
-
minimumSequenceNumber,
|
|
1849
|
-
error,
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1860
|
+
const pendingMessagesFailResult = await this.shouldFailSummaryOnPendingOps(summaryNumberLogger, summaryRefSeqNum, minimumSequenceNumber, finalAttempt, false /* beforeSummaryGeneration */);
|
|
1861
|
+
if (pendingMessagesFailResult !== undefined) {
|
|
1862
|
+
return pendingMessagesFailResult;
|
|
1852
1863
|
}
|
|
1853
1864
|
}
|
|
1854
1865
|
const { summary: summaryTree, stats: partialStats } = summarizeResult;
|
|
@@ -1858,7 +1869,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1858
1869
|
// Because handles are unchanged dataStores in the current logic,
|
|
1859
1870
|
// summarized dataStore count is total dataStore count minus handle count
|
|
1860
1871
|
const dataStoreTree = summaryTree.tree[runtime_definitions_1.channelsTreeName];
|
|
1861
|
-
(0,
|
|
1872
|
+
(0, core_utils_1.assert)(dataStoreTree.type === protocol_definitions_1.SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
|
|
1862
1873
|
const handleCount = Object.values(dataStoreTree.tree).filter((value) => value.type === protocol_definitions_1.SummaryType.Handle).length;
|
|
1863
1874
|
const gcSummaryTreeStats = summaryTree.tree[runtime_definitions_1.gcTreeKey]
|
|
1864
1875
|
? (0, runtime_utils_1.calculateStats)(summaryTree.tree[runtime_definitions_1.gcTreeKey])
|
|
@@ -1970,6 +1981,50 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1970
1981
|
}
|
|
1971
1982
|
}
|
|
1972
1983
|
}
|
|
1984
|
+
/**
|
|
1985
|
+
* This helper is called during summarization. If there are pending ops, it will return a failed summarize result
|
|
1986
|
+
* (IBaseSummarizeResult) unless this is the final summarize attempt and SkipFailingIncorrectSummary option is set.
|
|
1987
|
+
* @param logger - The logger to be used for sending telemetry.
|
|
1988
|
+
* @param referenceSequenceNumber - The reference sequence number of the summary attempt.
|
|
1989
|
+
* @param minimumSequenceNumber - The minimum sequence number of the summary attempt.
|
|
1990
|
+
* @param finalAttempt - Whether this is the final summary attempt.
|
|
1991
|
+
* @param beforeSummaryGeneration - Whether this is called before summary generation or after.
|
|
1992
|
+
* @returns failed summarize result (IBaseSummarizeResult) if summary should be failed, undefined otherwise.
|
|
1993
|
+
*/
|
|
1994
|
+
async shouldFailSummaryOnPendingOps(logger, referenceSequenceNumber, minimumSequenceNumber, finalAttempt, beforeSummaryGeneration) {
|
|
1995
|
+
if (!this.hasPendingMessages()) {
|
|
1996
|
+
return;
|
|
1997
|
+
}
|
|
1998
|
+
// If "SkipFailingIncorrectSummary" option is true, don't fail the summary in the last attempt.
|
|
1999
|
+
// This is a fallback to make progress in documents where there are consistently pending ops in
|
|
2000
|
+
// the summarizer.
|
|
2001
|
+
if (finalAttempt &&
|
|
2002
|
+
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary")) {
|
|
2003
|
+
const error = telemetry_utils_1.DataProcessingError.create("Pending ops during summarization", "submitSummary", undefined, { pendingMessages: this.pendingMessagesCount });
|
|
2004
|
+
logger.sendErrorEvent({
|
|
2005
|
+
eventName: "SkipFailingIncorrectSummary",
|
|
2006
|
+
referenceSequenceNumber,
|
|
2007
|
+
minimumSequenceNumber,
|
|
2008
|
+
beforeGenerate: beforeSummaryGeneration,
|
|
2009
|
+
}, error);
|
|
2010
|
+
}
|
|
2011
|
+
else {
|
|
2012
|
+
// The retry delay when there are pending ops can be overridden via config so that we can adjust it
|
|
2013
|
+
// based on telemetry while we decide on a stable number.
|
|
2014
|
+
const retryDelayMs = this.mc.config.getNumber("Fluid.Summarizer.PendingOpsRetryDelayMs") ??
|
|
2015
|
+
exports.defaultPendingOpsRetryDelayMs;
|
|
2016
|
+
const error = new summary_1.RetriableSummaryError("PendingOpsWhileSummarizing", retryDelayMs / 1000, {
|
|
2017
|
+
count: this.pendingMessagesCount,
|
|
2018
|
+
beforeGenerate: beforeSummaryGeneration,
|
|
2019
|
+
});
|
|
2020
|
+
return {
|
|
2021
|
+
stage: "base",
|
|
2022
|
+
referenceSequenceNumber,
|
|
2023
|
+
minimumSequenceNumber,
|
|
2024
|
+
error,
|
|
2025
|
+
};
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
1973
2028
|
get pendingMessagesCount() {
|
|
1974
2029
|
return this.pendingStateManager.pendingMessagesCount + this.outbox.messageCount;
|
|
1975
2030
|
}
|
|
@@ -1978,11 +2033,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1978
2033
|
}
|
|
1979
2034
|
updateDocumentDirtyState(dirty) {
|
|
1980
2035
|
if (this.attachState !== container_definitions_1.AttachState.Attached) {
|
|
1981
|
-
(0,
|
|
2036
|
+
(0, core_utils_1.assert)(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
1982
2037
|
}
|
|
1983
2038
|
else {
|
|
1984
2039
|
// Other way is not true = see this.isContainerMessageDirtyable()
|
|
1985
|
-
(0,
|
|
2040
|
+
(0, core_utils_1.assert)(!dirty || this.hasPendingMessages(), 0x3d3 /* if doc is dirty, there has to be pending ops */);
|
|
1986
2041
|
}
|
|
1987
2042
|
if (this.dirtyContainer === dirty) {
|
|
1988
2043
|
return;
|
|
@@ -2015,7 +2070,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2015
2070
|
let idAllocationBatchMessage;
|
|
2016
2071
|
let idRange;
|
|
2017
2072
|
if (this.idCompressorEnabled) {
|
|
2018
|
-
(0,
|
|
2073
|
+
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67d /* IdCompressor should be defined if enabled */);
|
|
2019
2074
|
idRange = this.idCompressor.takeNextCreationRange();
|
|
2020
2075
|
// Don't include the idRange if there weren't any Ids allocated
|
|
2021
2076
|
idRange = idRange?.ids !== undefined ? idRange : undefined;
|
|
@@ -2042,7 +2097,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2042
2097
|
this.verifyNotClosed();
|
|
2043
2098
|
this.verifyCanSubmitOps();
|
|
2044
2099
|
// There should be no ops in detached container state!
|
|
2045
|
-
(0,
|
|
2100
|
+
(0, core_utils_1.assert)(this.attachState !== container_definitions_1.AttachState.Detached, 0x132 /* "sending ops in detached container" */);
|
|
2046
2101
|
const serializedContent = JSON.stringify(containerRuntimeMessage);
|
|
2047
2102
|
// Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
|
|
2048
2103
|
// container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
|
|
@@ -2142,15 +2197,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2142
2197
|
setTimeout(flush, 0);
|
|
2143
2198
|
break;
|
|
2144
2199
|
default:
|
|
2145
|
-
(0,
|
|
2200
|
+
(0, core_utils_1.assert)(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
|
|
2146
2201
|
break;
|
|
2147
2202
|
}
|
|
2148
2203
|
}
|
|
2149
2204
|
submitSummaryMessage(contents, referenceSequenceNumber) {
|
|
2150
2205
|
this.verifyNotClosed();
|
|
2151
|
-
(0,
|
|
2206
|
+
(0, core_utils_1.assert)(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
|
|
2152
2207
|
// System message should not be sent in the middle of the batch.
|
|
2153
|
-
(0,
|
|
2208
|
+
(0, core_utils_1.assert)(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
2154
2209
|
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
2155
2210
|
return this.submitSummaryFn !== undefined
|
|
2156
2211
|
? this.submitSummaryFn(contents, referenceSequenceNumber)
|
|
@@ -2288,29 +2343,22 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2288
2343
|
/** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
|
|
2289
2344
|
async refreshLatestSummaryAck(options) {
|
|
2290
2345
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
2346
|
+
// proposalHandle is always passed from RunningSummarizer.
|
|
2347
|
+
(0, core_utils_1.assert)(proposalHandle !== undefined, 0x766 /* proposalHandle should be available */);
|
|
2291
2348
|
const readAndParseBlob = async (id) => (0, driver_utils_1.readAndParse)(this.storage, id);
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2349
|
+
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq);
|
|
2350
|
+
/**
|
|
2351
|
+
* When refreshing a summary ack, this check indicates a new ack of a summary that is newer than the
|
|
2352
|
+
* current summary that is tracked, but this summarizer runtime did not produce/track that summary. Thus
|
|
2353
|
+
* it needs to refresh its state. Today refresh is done by fetching the latest snapshot to update the cache
|
|
2354
|
+
* and then close as the current main client is likely to be re-elected as the parent summarizer again.
|
|
2355
|
+
*/
|
|
2356
|
+
if (!result.isSummaryTracked && result.isSummaryNewer) {
|
|
2357
|
+
const fetchResult = await this.fetchSnapshotFromStorage(summaryLogger, {
|
|
2297
2358
|
eventName: "RefreshLatestSummaryAckFetch",
|
|
2298
2359
|
ackHandle,
|
|
2299
2360
|
targetSequenceNumber: summaryRefSeq,
|
|
2300
2361
|
}, readAndParseBlob, null);
|
|
2301
|
-
/**
|
|
2302
|
-
* back-compat - Older loaders and drivers (pre 2.0.0-internal.1.4) don't have fetchSource as a param in the
|
|
2303
|
-
* getVersions API. So, they will not fetch the latest snapshot from network in the previous fetch call. For
|
|
2304
|
-
* these scenarios, fetch the snapshot corresponding to the ack handle to have the same behavior before the
|
|
2305
|
-
* change that started fetching latest snapshot always.
|
|
2306
|
-
*/
|
|
2307
|
-
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
2308
|
-
fetchResult = await this.fetchSnapshotFromStorageAndMaybeClose(summaryLogger, {
|
|
2309
|
-
eventName: "RefreshLatestSummaryAckFetchBackCompat",
|
|
2310
|
-
ackHandle,
|
|
2311
|
-
targetSequenceNumber: summaryRefSeq,
|
|
2312
|
-
}, readAndParseBlob, ackHandle);
|
|
2313
|
-
}
|
|
2314
2362
|
/**
|
|
2315
2363
|
* If the fetched snapshot is older than the one for which the ack was received, close the container.
|
|
2316
2364
|
* This should never happen because an ack should be sent after the latest summary is updated in the server.
|
|
@@ -2330,17 +2378,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2330
2378
|
this.disposeFn(error);
|
|
2331
2379
|
throw error;
|
|
2332
2380
|
}
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
return {
|
|
2337
|
-
snapshotTree: fetchResult.snapshotTree,
|
|
2338
|
-
snapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
2339
|
-
};
|
|
2340
|
-
};
|
|
2341
|
-
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq, fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
2381
|
+
await this.closeStaleSummarizer("RefreshLatestSummaryAckFetch");
|
|
2382
|
+
return;
|
|
2383
|
+
}
|
|
2342
2384
|
// Notify the garbage collector so it can update its latest summary state.
|
|
2343
|
-
await this.garbageCollector.refreshLatestSummary(
|
|
2385
|
+
await this.garbageCollector.refreshLatestSummary(result);
|
|
2344
2386
|
}
|
|
2345
2387
|
/**
|
|
2346
2388
|
* Fetches the latest snapshot from storage and uses it to refresh SummarizerNode's
|
|
@@ -2350,32 +2392,38 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2350
2392
|
*/
|
|
2351
2393
|
async refreshLatestSummaryAckFromServer(summaryLogger) {
|
|
2352
2394
|
const readAndParseBlob = async (id) => (0, driver_utils_1.readAndParse)(this.storage, id);
|
|
2353
|
-
const {
|
|
2395
|
+
const { versionId, latestSnapshotRefSeq } = await this.fetchSnapshotFromStorage(summaryLogger, {
|
|
2354
2396
|
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
2355
2397
|
}, readAndParseBlob, null);
|
|
2356
|
-
|
|
2357
|
-
snapshotTree,
|
|
2358
|
-
snapshotRefSeq: latestSnapshotRefSeq,
|
|
2359
|
-
};
|
|
2360
|
-
const result = await this.summarizerNode.refreshLatestSummary(undefined /* proposalHandle */, latestSnapshotRefSeq, async () => fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
2361
|
-
// Notify the garbage collector so it can update its latest summary state.
|
|
2362
|
-
await this.garbageCollector.refreshLatestSummary(undefined /* proposalHandle */, result, readAndParseBlob);
|
|
2398
|
+
await this.closeStaleSummarizer("RefreshLatestSummaryFromServerFetch");
|
|
2363
2399
|
return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
|
|
2364
2400
|
}
|
|
2401
|
+
async closeStaleSummarizer(codePath) {
|
|
2402
|
+
this.mc.logger.sendTelemetryEvent({
|
|
2403
|
+
eventName: "ClosingSummarizerOnSummaryStale",
|
|
2404
|
+
codePath,
|
|
2405
|
+
message: "Stopping fetch from storage",
|
|
2406
|
+
closeSummarizerDelayMs: this.closeSummarizerDelayMs,
|
|
2407
|
+
}, new telemetry_utils_1.GenericError("Restarting summarizer instead of refreshing"));
|
|
2408
|
+
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2409
|
+
await (0, core_utils_1.delay)(this.closeSummarizerDelayMs);
|
|
2410
|
+
this._summarizer?.stop("latestSummaryStateStale");
|
|
2411
|
+
this.disposeFn();
|
|
2412
|
+
}
|
|
2365
2413
|
/**
|
|
2366
2414
|
* Downloads snapshot from storage with the given versionId or latest if versionId is null.
|
|
2367
2415
|
* By default, it also closes the container after downloading the snapshot. However, this may be
|
|
2368
2416
|
* overridden via options.
|
|
2369
2417
|
*/
|
|
2370
|
-
async
|
|
2371
|
-
|
|
2418
|
+
async fetchSnapshotFromStorage(logger, event, readAndParseBlob, versionId) {
|
|
2419
|
+
return telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2372
2420
|
const stats = {};
|
|
2373
|
-
const trace =
|
|
2421
|
+
const trace = client_utils_1.Trace.start();
|
|
2374
2422
|
const versions = await this.storage.getVersions(versionId, 1, "refreshLatestSummaryAckFromServer", versionId === null ? driver_definitions_1.FetchSource.noCache : undefined);
|
|
2375
|
-
(0,
|
|
2423
|
+
(0, core_utils_1.assert)(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
2376
2424
|
stats.getVersionDuration = trace.trace().duration;
|
|
2377
2425
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
2378
|
-
(0,
|
|
2426
|
+
(0, core_utils_1.assert)(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
|
|
2379
2427
|
stats.getSnapshotDuration = trace.trace().duration;
|
|
2380
2428
|
const latestSnapshotRefSeq = await (0, runtime_utils_1.seqFromTree)(maybeSnapshot, readAndParseBlob);
|
|
2381
2429
|
stats.snapshotRefSeq = latestSnapshotRefSeq;
|
|
@@ -2387,45 +2435,37 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2387
2435
|
latestSnapshotRefSeq,
|
|
2388
2436
|
};
|
|
2389
2437
|
});
|
|
2390
|
-
// We choose to close the summarizer after the snapshot cache is updated to avoid
|
|
2391
|
-
// situations which the main client (which is likely to be re-elected as the leader again)
|
|
2392
|
-
// loads the summarizer from cache.
|
|
2393
|
-
if (this.summaryStateUpdateMethod !== "refreshFromSnapshot") {
|
|
2394
|
-
this.mc.logger.sendTelemetryEvent({
|
|
2395
|
-
...event,
|
|
2396
|
-
eventName: "ClosingSummarizerOnSummaryStale",
|
|
2397
|
-
codePath: event.eventName,
|
|
2398
|
-
message: "Stopping fetch from storage",
|
|
2399
|
-
versionId: versionId != null ? versionId : undefined,
|
|
2400
|
-
closeSummarizerDelayMs: this.closeSummarizerDelayMs,
|
|
2401
|
-
}, new telemetry_utils_1.GenericError("Restarting summarizer instead of refreshing"));
|
|
2402
|
-
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2403
|
-
await (0, common_utils_1.delay)(this.closeSummarizerDelayMs);
|
|
2404
|
-
this._summarizer?.stop("latestSummaryStateStale");
|
|
2405
|
-
this.disposeFn();
|
|
2406
|
-
}
|
|
2407
|
-
return snapshotResults;
|
|
2408
2438
|
}
|
|
2409
2439
|
notifyAttaching() { } // do nothing (deprecated method)
|
|
2410
2440
|
async getPendingLocalState(props) {
|
|
2411
|
-
this.
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
pending
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2441
|
+
return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, {
|
|
2442
|
+
eventName: "getPendingLocalState",
|
|
2443
|
+
notifyImminentClosure: props?.notifyImminentClosure,
|
|
2444
|
+
}, async (event) => {
|
|
2445
|
+
this.verifyNotClosed();
|
|
2446
|
+
const waitBlobsToAttach = props?.notifyImminentClosure;
|
|
2447
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
2448
|
+
throw new telemetry_utils_1.UsageError("can't get state during orderSequentially");
|
|
2449
|
+
}
|
|
2450
|
+
const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(waitBlobsToAttach);
|
|
2451
|
+
const pending = this.pendingStateManager.getLocalState();
|
|
2452
|
+
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
2453
|
+
return; // no pending state to save
|
|
2454
|
+
}
|
|
2455
|
+
// Flush pending batch.
|
|
2456
|
+
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2457
|
+
// to close current batch.
|
|
2458
|
+
this.flush();
|
|
2459
|
+
const pendingState = {
|
|
2460
|
+
pending,
|
|
2461
|
+
pendingAttachmentBlobs,
|
|
2462
|
+
};
|
|
2463
|
+
event.end({
|
|
2464
|
+
attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
|
|
2465
|
+
pendingOpsSize: pending?.pendingStates.length,
|
|
2466
|
+
});
|
|
2467
|
+
return pendingState;
|
|
2468
|
+
});
|
|
2429
2469
|
}
|
|
2430
2470
|
summarizeOnDemand(options) {
|
|
2431
2471
|
if (this.isSummarizerClient) {
|