@fluidframework/container-runtime 2.0.0-internal.6.1.0 → 2.0.0-internal.6.2.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 +35 -0
- package/README.md +4 -3
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +4 -20
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +47 -125
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +82 -14
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +236 -138
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +1 -2
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +4 -5
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +1 -2
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.js +2 -2
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +4 -5
- package/dist/dataStores.js.map +1 -1
- package/dist/error.d.ts +14 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +21 -0
- package/dist/error.js.map +1 -0
- package/dist/gc/garbageCollection.d.ts +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +23 -5
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +5 -3
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +2 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +2 -0
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.d.ts +8 -30
- package/dist/id-compressor/appendOnlySortedMap.d.ts.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.js +25 -67
- package/dist/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/finalSpace.d.ts +29 -0
- package/dist/id-compressor/finalSpace.d.ts.map +1 -0
- package/dist/id-compressor/finalSpace.js +62 -0
- package/dist/id-compressor/finalSpace.js.map +1 -0
- package/dist/id-compressor/idCompressor.d.ts +25 -250
- package/dist/id-compressor/idCompressor.d.ts.map +1 -1
- package/dist/id-compressor/idCompressor.js +385 -1149
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/identifiers.d.ts +32 -0
- package/dist/id-compressor/identifiers.d.ts.map +1 -0
- package/dist/id-compressor/identifiers.js +15 -0
- package/dist/id-compressor/identifiers.js.map +1 -0
- package/dist/id-compressor/index.d.ts +5 -6
- package/dist/id-compressor/index.d.ts.map +1 -1
- package/dist/id-compressor/index.js +20 -26
- package/dist/id-compressor/index.js.map +1 -1
- package/dist/id-compressor/persistanceUtilities.d.ts +22 -0
- package/dist/id-compressor/persistanceUtilities.d.ts.map +1 -0
- package/dist/id-compressor/persistanceUtilities.js +43 -0
- package/dist/id-compressor/persistanceUtilities.js.map +1 -0
- package/dist/id-compressor/sessionSpaceNormalizer.d.ts +46 -0
- package/dist/id-compressor/sessionSpaceNormalizer.d.ts.map +1 -0
- package/dist/id-compressor/sessionSpaceNormalizer.js +80 -0
- package/dist/id-compressor/sessionSpaceNormalizer.js.map +1 -0
- package/dist/id-compressor/sessions.d.ts +115 -0
- package/dist/id-compressor/sessions.d.ts.map +1 -0
- package/dist/id-compressor/sessions.js +305 -0
- package/dist/id-compressor/sessions.js.map +1 -0
- package/dist/id-compressor/utilities.d.ts +49 -0
- package/dist/id-compressor/utilities.d.ts.map +1 -0
- package/dist/id-compressor/utilities.js +166 -0
- package/dist/id-compressor/utilities.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +1 -2
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +2 -3
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +1 -0
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +10 -11
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +11 -5
- package/dist/opLifecycle/remoteMessageProcessor.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 +12 -5
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +24 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +4 -5
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/index.d.ts +2 -2
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +2 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +1 -2
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +2 -3
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +27 -4
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +237 -66
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +6 -5
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +70 -67
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +38 -25
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +1 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +9 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +42 -38
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +7 -6
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +22 -15
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.js +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +4 -20
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +46 -124
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +82 -14
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +223 -123
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +1 -2
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +1 -2
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +1 -2
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.js +1 -1
- package/lib/dataStoreRegistry.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/error.d.ts +14 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +17 -0
- package/lib/error.js.map +1 -0
- package/lib/gc/garbageCollection.d.ts +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +22 -4
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +3 -1
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +2 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +2 -0
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.d.ts +8 -30
- package/lib/id-compressor/appendOnlySortedMap.d.ts.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.js +24 -65
- package/lib/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/finalSpace.d.ts +29 -0
- package/lib/id-compressor/finalSpace.d.ts.map +1 -0
- package/lib/id-compressor/finalSpace.js +58 -0
- package/lib/id-compressor/finalSpace.js.map +1 -0
- package/lib/id-compressor/idCompressor.d.ts +25 -250
- package/lib/id-compressor/idCompressor.d.ts.map +1 -1
- package/lib/id-compressor/idCompressor.js +381 -1139
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/identifiers.d.ts +32 -0
- package/lib/id-compressor/identifiers.d.ts.map +1 -0
- package/lib/id-compressor/identifiers.js +11 -0
- package/lib/id-compressor/identifiers.js.map +1 -0
- package/lib/id-compressor/index.d.ts +5 -6
- package/lib/id-compressor/index.d.ts.map +1 -1
- package/lib/id-compressor/index.js +5 -6
- package/lib/id-compressor/index.js.map +1 -1
- package/lib/id-compressor/persistanceUtilities.d.ts +22 -0
- package/lib/id-compressor/persistanceUtilities.d.ts.map +1 -0
- package/lib/id-compressor/persistanceUtilities.js +34 -0
- package/lib/id-compressor/persistanceUtilities.js.map +1 -0
- package/lib/id-compressor/sessionSpaceNormalizer.d.ts +46 -0
- package/lib/id-compressor/sessionSpaceNormalizer.d.ts.map +1 -0
- package/lib/id-compressor/sessionSpaceNormalizer.js +76 -0
- package/lib/id-compressor/sessionSpaceNormalizer.js.map +1 -0
- package/lib/id-compressor/sessions.d.ts +115 -0
- package/lib/id-compressor/sessions.d.ts.map +1 -0
- package/lib/id-compressor/sessions.js +290 -0
- package/lib/id-compressor/sessions.js.map +1 -0
- package/lib/id-compressor/utilities.d.ts +49 -0
- package/lib/id-compressor/utilities.d.ts.map +1 -0
- package/lib/id-compressor/utilities.js +148 -0
- package/lib/id-compressor/utilities.js.map +1 -0
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +1 -2
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +1 -2
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +1 -0
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +6 -7
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +12 -6
- package/lib/opLifecycle/remoteMessageProcessor.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 +12 -5
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +21 -7
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +1 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/index.d.ts +2 -2
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js +1 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +1 -2
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +1 -2
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +27 -4
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +237 -66
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +6 -5
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +68 -65
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +38 -25
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +1 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +9 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +43 -39
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +7 -6
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +23 -16
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +27 -24
- package/src/batchTracker.ts +1 -1
- package/src/blobManager.ts +57 -146
- package/src/containerRuntime.ts +331 -158
- package/src/dataStore.ts +1 -2
- package/src/dataStoreContext.ts +3 -6
- package/src/dataStoreContexts.ts +1 -2
- package/src/dataStoreRegistry.ts +1 -1
- package/src/dataStores.ts +3 -5
- package/src/error.ts +18 -0
- package/src/gc/garbageCollection.ts +38 -5
- package/src/gc/gcConfigs.ts +4 -2
- package/src/gc/gcDefinitions.ts +2 -0
- package/src/gc/gcTelemetry.ts +2 -0
- package/src/id-compressor/appendOnlySortedMap.ts +25 -86
- package/src/id-compressor/finalSpace.ts +67 -0
- package/src/id-compressor/idCompressor.ts +455 -1681
- package/src/id-compressor/identifiers.ts +42 -0
- package/src/id-compressor/index.ts +11 -20
- package/src/id-compressor/persistanceUtilities.ts +58 -0
- package/src/id-compressor/sessionSpaceNormalizer.ts +83 -0
- package/src/id-compressor/sessions.ts +405 -0
- package/src/id-compressor/utilities.ts +187 -0
- package/src/index.ts +7 -1
- package/src/opLifecycle/opCompressor.ts +1 -2
- package/src/opLifecycle/opSplitter.ts +4 -4
- package/src/opLifecycle/outbox.ts +13 -10
- package/src/opLifecycle/remoteMessageProcessor.ts +19 -6
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +49 -27
- package/src/scheduleManager.ts +5 -4
- package/src/summary/index.ts +3 -1
- package/src/summary/orderedClientElection.ts +6 -4
- package/src/summary/runningSummarizer.ts +276 -95
- package/src/summary/summarizer.ts +22 -12
- package/src/summary/summarizerClientElection.ts +1 -1
- package/src/summary/summarizerTypes.ts +40 -25
- package/src/summary/summaryCollection.ts +1 -2
- package/src/summary/summaryGenerator.ts +49 -52
- package/src/summary/summaryManager.ts +33 -11
- package/dist/id-compressor/idRange.d.ts +0 -11
- package/dist/id-compressor/idRange.d.ts.map +0 -1
- package/dist/id-compressor/idRange.js +0 -29
- package/dist/id-compressor/idRange.js.map +0 -1
- package/dist/id-compressor/numericUuid.d.ts +0 -59
- package/dist/id-compressor/numericUuid.d.ts.map +0 -1
- package/dist/id-compressor/numericUuid.js +0 -325
- package/dist/id-compressor/numericUuid.js.map +0 -1
- package/dist/id-compressor/sessionIdNormalizer.d.ts +0 -138
- package/dist/id-compressor/sessionIdNormalizer.d.ts.map +0 -1
- package/dist/id-compressor/sessionIdNormalizer.js +0 -483
- package/dist/id-compressor/sessionIdNormalizer.js.map +0 -1
- package/dist/id-compressor/utils.d.ts +0 -57
- package/dist/id-compressor/utils.d.ts.map +0 -1
- package/dist/id-compressor/utils.js +0 -90
- package/dist/id-compressor/utils.js.map +0 -1
- package/dist/id-compressor/uuidUtilities.d.ts +0 -28
- package/dist/id-compressor/uuidUtilities.d.ts.map +0 -1
- package/dist/id-compressor/uuidUtilities.js +0 -104
- package/dist/id-compressor/uuidUtilities.js.map +0 -1
- package/lib/id-compressor/idRange.d.ts +0 -11
- package/lib/id-compressor/idRange.d.ts.map +0 -1
- package/lib/id-compressor/idRange.js +0 -25
- package/lib/id-compressor/idRange.js.map +0 -1
- package/lib/id-compressor/numericUuid.d.ts +0 -59
- package/lib/id-compressor/numericUuid.d.ts.map +0 -1
- package/lib/id-compressor/numericUuid.js +0 -315
- package/lib/id-compressor/numericUuid.js.map +0 -1
- package/lib/id-compressor/sessionIdNormalizer.d.ts +0 -138
- package/lib/id-compressor/sessionIdNormalizer.d.ts.map +0 -1
- package/lib/id-compressor/sessionIdNormalizer.js +0 -479
- package/lib/id-compressor/sessionIdNormalizer.js.map +0 -1
- package/lib/id-compressor/utils.d.ts +0 -57
- package/lib/id-compressor/utils.d.ts.map +0 -1
- package/lib/id-compressor/utils.js +0 -79
- package/lib/id-compressor/utils.js.map +0 -1
- package/lib/id-compressor/uuidUtilities.d.ts +0 -28
- package/lib/id-compressor/uuidUtilities.d.ts.map +0 -1
- package/lib/id-compressor/uuidUtilities.js +0 -96
- package/lib/id-compressor/uuidUtilities.js.map +0 -1
- package/src/id-compressor/idRange.ts +0 -35
- package/src/id-compressor/numericUuid.ts +0 -383
- package/src/id-compressor/sessionIdNormalizer.ts +0 -609
- package/src/id-compressor/utils.ts +0 -114
- package/src/id-compressor/uuidUtilities.ts +0 -120
package/lib/containerRuntime.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
2
|
-
import { assert, delay, Trace, TypedEventEmitter
|
|
2
|
+
import { assert, delay, Trace, TypedEventEmitter } from "@fluidframework/common-utils";
|
|
3
3
|
import { LazyPromise } from "@fluidframework/core-utils";
|
|
4
|
-
import { createChildLogger,
|
|
4
|
+
import { createChildLogger, createChildMonitoringContext, DataCorruptionError, DataProcessingError, GenericError, raiseConnectedEvent, PerformanceEvent,
|
|
5
|
+
// eslint-disable-next-line import/no-deprecated
|
|
6
|
+
TaggedLoggerAdapter, wrapError, UsageError, } from "@fluidframework/telemetry-utils";
|
|
5
7
|
import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
|
|
6
8
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
7
|
-
import { DataCorruptionError, DataProcessingError, GenericError, UsageError, } from "@fluidframework/container-utils";
|
|
8
9
|
import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
|
|
9
10
|
import { FlushMode, FlushModeExperimental, gcTreeKey, channelsTreeName, } from "@fluidframework/runtime-definitions";
|
|
10
11
|
import { addBlobToSummary, addSummarizeResultToSummary, addTreeToSummary, RequestParser, create404Response, exceptionToResponse, GCDataBuilder, requestFluidObject, seqFromTree, calculateStats, TelemetryContext, } from "@fluidframework/runtime-utils";
|
|
@@ -45,6 +46,18 @@ export var ContainerMessageType;
|
|
|
45
46
|
*/
|
|
46
47
|
ContainerMessageType["IdAllocation"] = "idAllocation";
|
|
47
48
|
})(ContainerMessageType || (ContainerMessageType = {}));
|
|
49
|
+
/**
|
|
50
|
+
* Utility to implement compat behaviors given an unknown message type
|
|
51
|
+
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
52
|
+
*
|
|
53
|
+
* @param _unknownContainerRuntimeMessageType - Typed as never, to ensure all known types have been
|
|
54
|
+
* handled before calling this function (e.g. in a switch statement).
|
|
55
|
+
* @param compatBehavior - Typed redundantly with CompatModeBehavior to ensure handling is added when updating that type
|
|
56
|
+
*/
|
|
57
|
+
function compatBehaviorAllowsMessageType(_unknownContainerRuntimeMessageType, compatBehavior) {
|
|
58
|
+
// undefined defaults to same behavior as "FailToProcess"
|
|
59
|
+
return compatBehavior === "Ignore";
|
|
60
|
+
}
|
|
48
61
|
export const DefaultSummaryConfiguration = {
|
|
49
62
|
state: "enabled",
|
|
50
63
|
minIdleTime: 0,
|
|
@@ -71,8 +84,12 @@ export var RuntimeHeaders;
|
|
|
71
84
|
})(RuntimeHeaders || (RuntimeHeaders = {}));
|
|
72
85
|
/** True if a tombstoned object should be returned without erroring */
|
|
73
86
|
export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
87
|
+
/** [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring */
|
|
88
|
+
export const AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
|
|
74
89
|
/** Tombstone error responses will have this header set to true */
|
|
75
90
|
export const TombstoneResponseHeaderKey = "isTombstoned";
|
|
91
|
+
/** Inactive error responses will have this header set to true */
|
|
92
|
+
export const InactiveResponseHeaderKey = "isInactive";
|
|
76
93
|
/** Default values for Runtime Headers */
|
|
77
94
|
export const defaultRuntimeHeaderData = {
|
|
78
95
|
wait: true,
|
|
@@ -200,34 +217,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
200
217
|
signalTimestamp: 0,
|
|
201
218
|
trackingSignalSequenceNumber: undefined,
|
|
202
219
|
};
|
|
203
|
-
this.summarizeOnDemand = (...args) => {
|
|
204
|
-
if (this.isSummarizerClient) {
|
|
205
|
-
return this.summarizer.summarizeOnDemand(...args);
|
|
206
|
-
}
|
|
207
|
-
else if (this.summaryManager !== undefined) {
|
|
208
|
-
return this.summaryManager.summarizeOnDemand(...args);
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
212
|
-
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
213
|
-
// because it is a misuse of the API rather than an expected failure.
|
|
214
|
-
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
this.enqueueSummarize = (...args) => {
|
|
218
|
-
if (this.isSummarizerClient) {
|
|
219
|
-
return this.summarizer.enqueueSummarize(...args);
|
|
220
|
-
}
|
|
221
|
-
else if (this.summaryManager !== undefined) {
|
|
222
|
-
return this.summaryManager.enqueueSummarize(...args);
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
226
|
-
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
227
|
-
// because it is a misuse of the API rather than an expected failure.
|
|
228
|
-
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
220
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
|
|
232
221
|
this.innerDeltaManager = deltaManager;
|
|
233
222
|
this.deltaManager = new DeltaManagerSummarizerProxy(this.innerDeltaManager);
|
|
@@ -450,8 +439,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
450
439
|
false;
|
|
451
440
|
this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
|
|
452
441
|
this.dirtyContainer =
|
|
453
|
-
this.attachState !== AttachState.Attached ||
|
|
454
|
-
this.pendingStateManager.hasPendingMessages();
|
|
442
|
+
this.attachState !== AttachState.Attached || this.hasPendingMessages();
|
|
455
443
|
context.updateDirtyContainerState(this.dirtyContainer);
|
|
456
444
|
if (this.summariesDisabled) {
|
|
457
445
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
@@ -499,6 +487,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
499
487
|
formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
|
|
500
488
|
initialDelayMs: this.initialSummarizerDelayMs,
|
|
501
489
|
}, this.heuristicsDisabled);
|
|
490
|
+
this.summaryManager.on("summarize", (eventProps) => {
|
|
491
|
+
this.emit("summarize", eventProps);
|
|
492
|
+
});
|
|
502
493
|
this.summaryManager.start();
|
|
503
494
|
}
|
|
504
495
|
}
|
|
@@ -607,11 +598,21 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
607
598
|
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
608
599
|
*/
|
|
609
600
|
static async loadRuntime(params) {
|
|
610
|
-
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime,
|
|
601
|
+
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, } = params;
|
|
602
|
+
const initializeEntryPoint = params.initializeEntryPoint ??
|
|
603
|
+
(async (containerRuntime) => ({
|
|
604
|
+
get IFluidRouter() {
|
|
605
|
+
return this;
|
|
606
|
+
},
|
|
607
|
+
async request(req) {
|
|
608
|
+
return containerRuntime.request(req);
|
|
609
|
+
},
|
|
610
|
+
}));
|
|
611
611
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
612
612
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
613
613
|
const backCompatContext = context;
|
|
614
614
|
const passLogger = backCompatContext.taggedLogger ??
|
|
615
|
+
// eslint-disable-next-line import/no-deprecated
|
|
615
616
|
new TaggedLoggerAdapter(backCompatContext.logger);
|
|
616
617
|
const logger = createChildLogger({
|
|
617
618
|
logger: passLogger,
|
|
@@ -673,7 +674,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
673
674
|
idCompressor =
|
|
674
675
|
serializedIdCompressor !== undefined
|
|
675
676
|
? IdCompressor.deserialize(serializedIdCompressor, createSessionId())
|
|
676
|
-
:
|
|
677
|
+
: IdCompressor.create(logger);
|
|
677
678
|
}
|
|
678
679
|
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
679
680
|
summaryOptions,
|
|
@@ -688,6 +689,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
688
689
|
enableGroupedBatching,
|
|
689
690
|
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, idCompressor, requestHandler, undefined, // summaryConfiguration
|
|
690
691
|
initializeEntryPoint);
|
|
692
|
+
await runtime.blobManager.processStashedChanges();
|
|
691
693
|
// It's possible to have ops with a reference sequence number of 0. Op sequence numbers start
|
|
692
694
|
// at 1, so we won't see a replayed saved op with a sequence number of 0.
|
|
693
695
|
await runtime.pendingStateManager.applyStashedOpsAt(0);
|
|
@@ -704,6 +706,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
704
706
|
/** @deprecated - The functionality is no longer exposed publicly */
|
|
705
707
|
get reSubmitFn() {
|
|
706
708
|
return (type, contents, localOpMetadata, opMetadata) => this.reSubmitCore({ type, contents }, localOpMetadata, opMetadata);
|
|
709
|
+
// Note: compatDetails is not included in this deprecated API
|
|
707
710
|
}
|
|
708
711
|
get flushMode() {
|
|
709
712
|
return this._flushMode;
|
|
@@ -854,7 +857,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
854
857
|
// We always expect createSubRequest to include a leading slash, but asserting here to protect against
|
|
855
858
|
// unintentionally modifying the url if that changes.
|
|
856
859
|
assert(subRequest.url.startsWith("/"), 0x126 /* "Expected createSubRequest url to include a leading slash" */);
|
|
857
|
-
return dataStore.
|
|
860
|
+
return dataStore.request(subRequest);
|
|
858
861
|
}
|
|
859
862
|
return create404Response(request);
|
|
860
863
|
}
|
|
@@ -962,7 +965,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
962
965
|
this.mc.logger.sendTelemetryEvent({
|
|
963
966
|
eventName: "ReconnectsWithNoProgress",
|
|
964
967
|
attempts: this.consecutiveReconnects,
|
|
965
|
-
pendingMessages: this.
|
|
968
|
+
pendingMessages: this.pendingMessagesCount,
|
|
966
969
|
});
|
|
967
970
|
}
|
|
968
971
|
return this.consecutiveReconnects < this.maxConsecutiveReconnects;
|
|
@@ -1022,13 +1025,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1022
1025
|
*/
|
|
1023
1026
|
parseOpContent(serializedContent) {
|
|
1024
1027
|
assert(serializedContent !== undefined, 0x6d5 /* content must be defined */);
|
|
1025
|
-
const { type, contents } = JSON.parse(serializedContent);
|
|
1028
|
+
const { type, contents, compatDetails } = JSON.parse(serializedContent);
|
|
1026
1029
|
assert(type !== undefined, 0x6d6 /* incorrect op content format */);
|
|
1027
|
-
return { type, contents };
|
|
1030
|
+
return { type, contents, compatDetails };
|
|
1028
1031
|
}
|
|
1029
1032
|
async applyStashedOp(op) {
|
|
1030
1033
|
// Need to parse from string for back-compat
|
|
1031
|
-
const { type, contents } = this.parseOpContent(op);
|
|
1034
|
+
const { type, contents, compatDetails } = this.parseOpContent(op);
|
|
1032
1035
|
switch (type) {
|
|
1033
1036
|
case ContainerMessageType.FluidDataStoreOp:
|
|
1034
1037
|
return this.dataStores.applyStashedOp(contents);
|
|
@@ -1044,8 +1047,22 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1044
1047
|
throw new Error("chunkedOp not expected here");
|
|
1045
1048
|
case ContainerMessageType.Rejoin:
|
|
1046
1049
|
throw new Error("rejoin not expected here");
|
|
1047
|
-
default:
|
|
1048
|
-
|
|
1050
|
+
default: {
|
|
1051
|
+
// This should be extremely rare for stashed ops.
|
|
1052
|
+
// It would require a newer runtime stashing ops and then an older one applying them,
|
|
1053
|
+
// e.g. if an app rolled back its container version
|
|
1054
|
+
const compatBehavior = compatDetails?.behavior;
|
|
1055
|
+
if (!compatBehaviorAllowsMessageType(type, compatBehavior)) {
|
|
1056
|
+
const error = DataProcessingError.create("Stashed runtime message of unknown type", "applyStashedOp", undefined /* sequencedMessage */, {
|
|
1057
|
+
messageDetails: JSON.stringify({
|
|
1058
|
+
type,
|
|
1059
|
+
compatBehavior,
|
|
1060
|
+
}),
|
|
1061
|
+
});
|
|
1062
|
+
this.closeFn(error);
|
|
1063
|
+
throw error;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1049
1066
|
}
|
|
1050
1067
|
}
|
|
1051
1068
|
setConnectionState(connected, clientId) {
|
|
@@ -1057,24 +1074,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1057
1074
|
// Don't propagate "disconnected" event because we didn't propagate the previous "connected" event
|
|
1058
1075
|
return;
|
|
1059
1076
|
}
|
|
1060
|
-
// If attachment blobs were added while disconnected, we need to delay
|
|
1061
|
-
// propagation of the "connected" event until we have uploaded them to
|
|
1062
|
-
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
1063
|
-
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
1064
|
-
const connecting = connected && !this._connected && !this.innerDeltaManager.readOnlyInfo.readonly;
|
|
1065
|
-
if (connecting && this.blobManager.hasPendingOfflineUploads) {
|
|
1066
|
-
assert(!this.delayConnectClientId, 0x392 /* Connect event delay must be canceled before subsequent connect event */);
|
|
1067
|
-
assert(!!clientId, 0x393 /* Must have clientId when connecting */);
|
|
1068
|
-
this.delayConnectClientId = clientId;
|
|
1069
|
-
this.blobManager.onConnected().then(() => {
|
|
1070
|
-
// make sure we didn't reconnect before the promise resolved
|
|
1071
|
-
if (this.delayConnectClientId === clientId && !this.disposed) {
|
|
1072
|
-
this.delayConnectClientId = undefined;
|
|
1073
|
-
this.setConnectionStateCore(connected, clientId);
|
|
1074
|
-
}
|
|
1075
|
-
}, (error) => this.closeFn(error));
|
|
1076
|
-
return;
|
|
1077
|
-
}
|
|
1078
1077
|
this.setConnectionStateCore(connected, clientId);
|
|
1079
1078
|
}
|
|
1080
1079
|
setConnectionStateCore(connected, clientId) {
|
|
@@ -1105,7 +1104,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1105
1104
|
this.closeFn(DataProcessingError.create("Runtime detected too many reconnects with no progress syncing local ops.", "setConnectionState", undefined, {
|
|
1106
1105
|
dataLoss: 1,
|
|
1107
1106
|
attempts: this.consecutiveReconnects,
|
|
1108
|
-
pendingMessages: this.
|
|
1107
|
+
pendingMessages: this.pendingMessagesCount,
|
|
1109
1108
|
}));
|
|
1110
1109
|
return;
|
|
1111
1110
|
}
|
|
@@ -1122,23 +1121,23 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1122
1121
|
}
|
|
1123
1122
|
process(messageArg, local) {
|
|
1124
1123
|
this.verifyNotClosed();
|
|
1125
|
-
// Whether or not the message
|
|
1124
|
+
// Whether or not the message appears to be a runtime message from an up-to-date client.
|
|
1126
1125
|
// It may be a legacy runtime message (ie already unpacked and ContainerMessageType)
|
|
1127
1126
|
// or something different, like a system message.
|
|
1128
|
-
const
|
|
1127
|
+
const modernRuntimeMessage = messageArg.type === MessageType.Operation;
|
|
1129
1128
|
// Do shallow copy of message, as the processing flow will modify it.
|
|
1130
1129
|
const messageCopy = { ...messageArg };
|
|
1131
1130
|
for (const message of this.remoteMessageProcessor.process(messageCopy)) {
|
|
1132
|
-
this.processCore(message, local,
|
|
1131
|
+
this.processCore(message, local, modernRuntimeMessage);
|
|
1133
1132
|
}
|
|
1134
1133
|
}
|
|
1135
1134
|
/**
|
|
1136
1135
|
* Direct the message to the correct subsystem for processing, and implement other side effects
|
|
1137
1136
|
* @param message - The unpacked message. Likely a ContainerRuntimeMessage, but could also be a system op
|
|
1138
1137
|
* @param local - Did this client send the op?
|
|
1139
|
-
* @param
|
|
1138
|
+
* @param modernRuntimeMessage - Does this appear like a current ContainerRuntimeMessage?
|
|
1140
1139
|
*/
|
|
1141
|
-
processCore(message, local,
|
|
1140
|
+
processCore(message, local, modernRuntimeMessage) {
|
|
1142
1141
|
// Surround the actual processing of the operation with messages to the schedule manager indicating
|
|
1143
1142
|
// the beginning and end. This allows it to emit appropriate events and/or pause the processing of new
|
|
1144
1143
|
// messages once a batch has been fully processed.
|
|
@@ -1146,7 +1145,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1146
1145
|
this._processedClientSequenceNumber = message.clientSequenceNumber;
|
|
1147
1146
|
try {
|
|
1148
1147
|
let localOpMetadata;
|
|
1149
|
-
if (local &&
|
|
1148
|
+
if (local && modernRuntimeMessage && message.type !== ContainerMessageType.ChunkedOp) {
|
|
1150
1149
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(message);
|
|
1151
1150
|
}
|
|
1152
1151
|
// If there are no more pending messages after processing a local message,
|
|
@@ -1154,43 +1153,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1154
1153
|
if (!this.hasPendingMessages()) {
|
|
1155
1154
|
this.updateDocumentDirtyState(false);
|
|
1156
1155
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
case ContainerMessageType.Attach:
|
|
1160
|
-
this.dataStores.processAttachMessage(message, local);
|
|
1161
|
-
break;
|
|
1162
|
-
case ContainerMessageType.Alias:
|
|
1163
|
-
this.processAliasMessage(message, localOpMetadata, local);
|
|
1164
|
-
break;
|
|
1165
|
-
case ContainerMessageType.FluidDataStoreOp:
|
|
1166
|
-
this.dataStores.processFluidDataStoreOp(message, local, localOpMetadata);
|
|
1167
|
-
break;
|
|
1168
|
-
case ContainerMessageType.BlobAttach:
|
|
1169
|
-
this.blobManager.processBlobAttachOp(message, local);
|
|
1170
|
-
break;
|
|
1171
|
-
case ContainerMessageType.IdAllocation:
|
|
1172
|
-
assert(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
|
|
1173
|
-
this.idCompressor.finalizeCreationRange(message.contents);
|
|
1174
|
-
break;
|
|
1175
|
-
case ContainerMessageType.ChunkedOp:
|
|
1176
|
-
case ContainerMessageType.Rejoin:
|
|
1177
|
-
break;
|
|
1178
|
-
default:
|
|
1179
|
-
if (runtimeMessage) {
|
|
1180
|
-
const error = DataProcessingError.create(
|
|
1181
|
-
// Former assert 0x3ce
|
|
1182
|
-
"Runtime message of unknown type", "OpProcessing", message, {
|
|
1183
|
-
local,
|
|
1184
|
-
type: message.type,
|
|
1185
|
-
contentType: typeof message.contents,
|
|
1186
|
-
batch: message.metadata?.batch,
|
|
1187
|
-
compression: message.compression,
|
|
1188
|
-
});
|
|
1189
|
-
this.closeFn(error);
|
|
1190
|
-
throw error;
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
this.emit("op", message, runtimeMessage);
|
|
1156
|
+
this.validateAndProcessRuntimeMessage(message, localOpMetadata, local, modernRuntimeMessage);
|
|
1157
|
+
this.emit("op", message, modernRuntimeMessage);
|
|
1194
1158
|
this.scheduleManager.afterOpProcessing(undefined, message);
|
|
1195
1159
|
if (local) {
|
|
1196
1160
|
// If we have processed a local op, this means that the container is
|
|
@@ -1204,8 +1168,59 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1204
1168
|
throw e;
|
|
1205
1169
|
}
|
|
1206
1170
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1171
|
+
/**
|
|
1172
|
+
* Assuming the given message is also a ContainerRuntimeMessage,
|
|
1173
|
+
* checks its type and dispatches the message to the appropriate handler in the runtime.
|
|
1174
|
+
* Throws a DataProcessingError if the message doesn't conform to the ContainerRuntimeMessage type.
|
|
1175
|
+
*/
|
|
1176
|
+
validateAndProcessRuntimeMessage(message, localOpMetadata, local, expectRuntimeMessageType) {
|
|
1177
|
+
// Optimistically extract ContainerRuntimeMessage-specific props from the message
|
|
1178
|
+
const { type: maybeContainerMessageType, compatDetails } = message;
|
|
1179
|
+
switch (maybeContainerMessageType) {
|
|
1180
|
+
case ContainerMessageType.Attach:
|
|
1181
|
+
this.dataStores.processAttachMessage(message, local);
|
|
1182
|
+
break;
|
|
1183
|
+
case ContainerMessageType.Alias:
|
|
1184
|
+
this.dataStores.processAliasMessage(message, localOpMetadata, local);
|
|
1185
|
+
break;
|
|
1186
|
+
case ContainerMessageType.FluidDataStoreOp:
|
|
1187
|
+
this.dataStores.processFluidDataStoreOp(message, local, localOpMetadata);
|
|
1188
|
+
break;
|
|
1189
|
+
case ContainerMessageType.BlobAttach:
|
|
1190
|
+
this.blobManager.processBlobAttachOp(message, local);
|
|
1191
|
+
break;
|
|
1192
|
+
case ContainerMessageType.IdAllocation:
|
|
1193
|
+
assert(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
|
|
1194
|
+
this.idCompressor.finalizeCreationRange(message.contents);
|
|
1195
|
+
break;
|
|
1196
|
+
case ContainerMessageType.ChunkedOp:
|
|
1197
|
+
case ContainerMessageType.Rejoin:
|
|
1198
|
+
break;
|
|
1199
|
+
default: {
|
|
1200
|
+
// If we didn't necessarily expect a runtime message type, then no worries - just return
|
|
1201
|
+
// e.g. this case applies to system ops, or legacy ops that would have fallen into the above cases anyway.
|
|
1202
|
+
if (!expectRuntimeMessageType) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
const compatBehavior = compatDetails?.behavior;
|
|
1206
|
+
if (!compatBehaviorAllowsMessageType(maybeContainerMessageType, compatBehavior)) {
|
|
1207
|
+
const error = DataProcessingError.create(
|
|
1208
|
+
// Former assert 0x3ce
|
|
1209
|
+
"Runtime message of unknown type", "OpProcessing", message, {
|
|
1210
|
+
local,
|
|
1211
|
+
messageDetails: JSON.stringify({
|
|
1212
|
+
type: message.type,
|
|
1213
|
+
contentType: typeof message.contents,
|
|
1214
|
+
compatBehavior,
|
|
1215
|
+
batch: message.metadata?.batch,
|
|
1216
|
+
compression: message.compression,
|
|
1217
|
+
}),
|
|
1218
|
+
});
|
|
1219
|
+
this.closeFn(error);
|
|
1220
|
+
throw error;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1209
1224
|
}
|
|
1210
1225
|
/**
|
|
1211
1226
|
* Emits the Signal event and update the perf signal data.
|
|
@@ -1673,7 +1688,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1673
1688
|
* @param options - options controlling how the summary is generated or submitted
|
|
1674
1689
|
*/
|
|
1675
1690
|
async submitSummary(options) {
|
|
1676
|
-
const { fullTree = false, refreshLatestAck, summaryLogger } = options;
|
|
1691
|
+
const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger } = options;
|
|
1677
1692
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1678
1693
|
// use it for all events logged during this summary.
|
|
1679
1694
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -1770,9 +1785,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1770
1785
|
error,
|
|
1771
1786
|
};
|
|
1772
1787
|
}
|
|
1773
|
-
// If validateSummaryBeforeUpload is true, validate that the summary generated
|
|
1774
|
-
// correct before this summary is uploaded.
|
|
1788
|
+
// If validateSummaryBeforeUpload is true, validate that the summary generated is correct before uploading.
|
|
1775
1789
|
if (this.validateSummaryBeforeUpload) {
|
|
1790
|
+
// Validate that the summaries generated by summarize nodes is correct.
|
|
1776
1791
|
const validateResult = this.summarizerNode.validateSummary();
|
|
1777
1792
|
if (!validateResult.success) {
|
|
1778
1793
|
const { success, ...loggingProps } = validateResult;
|
|
@@ -1784,6 +1799,34 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1784
1799
|
error,
|
|
1785
1800
|
};
|
|
1786
1801
|
}
|
|
1802
|
+
// If there are pending messages, the summary has more data than at the summaryRefSeqNum.
|
|
1803
|
+
if (this.hasPendingMessages()) {
|
|
1804
|
+
// If "SkipFailingIncorrectSummary" option is true, don't fail the summary in the last attempt.
|
|
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
|
+
}
|
|
1829
|
+
}
|
|
1787
1830
|
}
|
|
1788
1831
|
const { summary: summaryTree, stats: partialStats } = summarizeResult;
|
|
1789
1832
|
// Now that we have generated the summary, update the message at last summary to the last message processed.
|
|
@@ -1904,8 +1947,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1904
1947
|
}
|
|
1905
1948
|
}
|
|
1906
1949
|
}
|
|
1950
|
+
get pendingMessagesCount() {
|
|
1951
|
+
return this.pendingStateManager.pendingMessagesCount + this.outbox.messageCount;
|
|
1952
|
+
}
|
|
1907
1953
|
hasPendingMessages() {
|
|
1908
|
-
return this.
|
|
1954
|
+
return this.pendingMessagesCount !== 0;
|
|
1909
1955
|
}
|
|
1910
1956
|
updateDocumentDirtyState(dirty) {
|
|
1911
1957
|
if (this.attachState !== AttachState.Attached) {
|
|
@@ -1949,7 +1995,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1949
1995
|
assert(this.idCompressor !== undefined, 0x67d /* IdCompressor should be defined if enabled */);
|
|
1950
1996
|
idRange = this.idCompressor.takeNextCreationRange();
|
|
1951
1997
|
// Don't include the idRange if there weren't any Ids allocated
|
|
1952
|
-
idRange = idRange?.ids
|
|
1998
|
+
idRange = idRange?.ids !== undefined ? idRange : undefined;
|
|
1953
1999
|
}
|
|
1954
2000
|
if (idRange !== undefined) {
|
|
1955
2001
|
const idAllocationMessage = {
|
|
@@ -2168,8 +2214,27 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2168
2214
|
case ContainerMessageType.Rejoin:
|
|
2169
2215
|
this.submit(message);
|
|
2170
2216
|
break;
|
|
2171
|
-
default:
|
|
2172
|
-
|
|
2217
|
+
default: {
|
|
2218
|
+
// This case should be very rare - it would imply an op was stashed from a
|
|
2219
|
+
// future version of runtime code and now is being applied on an older version
|
|
2220
|
+
const compatBehavior = message.compatDetails?.behavior;
|
|
2221
|
+
if (compatBehaviorAllowsMessageType(message.type, compatBehavior)) {
|
|
2222
|
+
this.logger.sendTelemetryEvent({
|
|
2223
|
+
eventName: "resubmitUnrecognizedMessageTypeAllowed",
|
|
2224
|
+
messageDetails: { type: message.type, compatBehavior },
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
else {
|
|
2228
|
+
const error = DataProcessingError.create("Resubmitting runtime message of unknown type", "reSubmitCore", undefined /* sequencedMessage */, {
|
|
2229
|
+
messageDetails: JSON.stringify({
|
|
2230
|
+
type: message.type,
|
|
2231
|
+
compatBehavior,
|
|
2232
|
+
}),
|
|
2233
|
+
});
|
|
2234
|
+
this.closeFn(error);
|
|
2235
|
+
throw error;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2173
2238
|
}
|
|
2174
2239
|
}
|
|
2175
2240
|
rollback(content, localOpMetadata) {
|
|
@@ -2182,6 +2247,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2182
2247
|
this.dataStores.rollbackDataStoreOp(contents, localOpMetadata);
|
|
2183
2248
|
break;
|
|
2184
2249
|
default:
|
|
2250
|
+
// Don't check message.compatDetails because this is for rolling back a local op so the type will be known
|
|
2185
2251
|
throw new Error(`Can't rollback ${type}`);
|
|
2186
2252
|
}
|
|
2187
2253
|
}
|
|
@@ -2204,11 +2270,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2204
2270
|
// It should only be done by the summarizerNode, if required.
|
|
2205
2271
|
// When fetching from storage we will always get the latest version and do not use the ackHandle.
|
|
2206
2272
|
const fetchLatestSnapshot = async () => {
|
|
2207
|
-
let fetchResult = await this.
|
|
2273
|
+
let fetchResult = await this.fetchSnapshotFromStorageAndMaybeClose(summaryLogger, {
|
|
2208
2274
|
eventName: "RefreshLatestSummaryAckFetch",
|
|
2209
2275
|
ackHandle,
|
|
2210
2276
|
targetSequenceNumber: summaryRefSeq,
|
|
2211
|
-
}, readAndParseBlob);
|
|
2277
|
+
}, readAndParseBlob, null);
|
|
2212
2278
|
/**
|
|
2213
2279
|
* back-compat - Older loaders and drivers (pre 2.0.0-internal.1.4) don't have fetchSource as a param in the
|
|
2214
2280
|
* getVersions API. So, they will not fetch the latest snapshot from network in the previous fetch call. For
|
|
@@ -2216,7 +2282,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2216
2282
|
* change that started fetching latest snapshot always.
|
|
2217
2283
|
*/
|
|
2218
2284
|
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
2219
|
-
fetchResult = await this.
|
|
2285
|
+
fetchResult = await this.fetchSnapshotFromStorageAndMaybeClose(summaryLogger, {
|
|
2220
2286
|
eventName: "RefreshLatestSummaryAckFetchBackCompat",
|
|
2221
2287
|
ackHandle,
|
|
2222
2288
|
targetSequenceNumber: summaryRefSeq,
|
|
@@ -2261,9 +2327,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2261
2327
|
*/
|
|
2262
2328
|
async refreshLatestSummaryAckFromServer(summaryLogger) {
|
|
2263
2329
|
const readAndParseBlob = async (id) => readAndParse(this.storage, id);
|
|
2264
|
-
const { snapshotTree, versionId, latestSnapshotRefSeq } = await this.
|
|
2330
|
+
const { snapshotTree, versionId, latestSnapshotRefSeq } = await this.fetchSnapshotFromStorageAndMaybeClose(summaryLogger, {
|
|
2265
2331
|
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
2266
|
-
}, readAndParseBlob);
|
|
2332
|
+
}, readAndParseBlob, null);
|
|
2267
2333
|
const fetchLatestSnapshot = {
|
|
2268
2334
|
snapshotTree,
|
|
2269
2335
|
snapshotRefSeq: latestSnapshotRefSeq,
|
|
@@ -2273,10 +2339,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2273
2339
|
await this.garbageCollector.refreshLatestSummary(undefined /* proposalHandle */, result, readAndParseBlob);
|
|
2274
2340
|
return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
|
|
2275
2341
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2342
|
+
/**
|
|
2343
|
+
* Downloads snapshot from storage with the given versionId or latest if versionId is null.
|
|
2344
|
+
* By default, it also closes the container after downloading the snapshot. However, this may be
|
|
2345
|
+
* overridden via options.
|
|
2346
|
+
*/
|
|
2347
|
+
async fetchSnapshotFromStorageAndMaybeClose(logger, event, readAndParseBlob, versionId) {
|
|
2280
2348
|
const snapshotResults = await PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2281
2349
|
const stats = {};
|
|
2282
2350
|
const trace = Trace.start();
|
|
@@ -2323,14 +2391,46 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2323
2391
|
throw new UsageError("can't get state during orderSequentially");
|
|
2324
2392
|
}
|
|
2325
2393
|
const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(waitBlobsToAttach);
|
|
2394
|
+
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
2395
|
+
return; // no pending state to save
|
|
2396
|
+
}
|
|
2326
2397
|
// Flush pending batch.
|
|
2327
2398
|
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2328
2399
|
// to close current batch.
|
|
2329
2400
|
this.flush();
|
|
2330
|
-
|
|
2401
|
+
const pendingState = {
|
|
2331
2402
|
pending: this.pendingStateManager.getLocalState(),
|
|
2332
2403
|
pendingAttachmentBlobs,
|
|
2333
2404
|
};
|
|
2405
|
+
return pendingState;
|
|
2406
|
+
}
|
|
2407
|
+
summarizeOnDemand(options) {
|
|
2408
|
+
if (this.isSummarizerClient) {
|
|
2409
|
+
return this.summarizer.summarizeOnDemand(options);
|
|
2410
|
+
}
|
|
2411
|
+
else if (this.summaryManager !== undefined) {
|
|
2412
|
+
return this.summaryManager.summarizeOnDemand(options);
|
|
2413
|
+
}
|
|
2414
|
+
else {
|
|
2415
|
+
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
2416
|
+
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
2417
|
+
// because it is a misuse of the API rather than an expected failure.
|
|
2418
|
+
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
enqueueSummarize(options) {
|
|
2422
|
+
if (this.isSummarizerClient) {
|
|
2423
|
+
return this.summarizer.enqueueSummarize(options);
|
|
2424
|
+
}
|
|
2425
|
+
else if (this.summaryManager !== undefined) {
|
|
2426
|
+
return this.summaryManager.enqueueSummarize(options);
|
|
2427
|
+
}
|
|
2428
|
+
else {
|
|
2429
|
+
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
2430
|
+
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
2431
|
+
// because it is a misuse of the API rather than an expected failure.
|
|
2432
|
+
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
2433
|
+
}
|
|
2334
2434
|
}
|
|
2335
2435
|
/**
|
|
2336
2436
|
* * Forms a function that will request a Summarizer.
|