@fluidframework/container-runtime 2.117.0 → 3.0.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 +70 -2
- package/README.md +53 -50
- package/{api-extractor.json → api-extractor/api-extractor-model.json} +1 -1
- package/api-report/container-runtime.legacy.alpha.api.md +3 -1
- package/api-report/container-runtime.legacy.beta.api.md +3 -1
- package/container-runtime.test-files.tar +0 -0
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +5 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager/blobManager.d.ts +1 -1
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +264 -231
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +70 -58
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.js +38 -20
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerCompatibility.d.ts +3 -3
- package/dist/containerCompatibility.d.ts.map +1 -1
- package/dist/containerCompatibility.js +36 -45
- package/dist/containerCompatibility.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +4 -0
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +4 -4
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +346 -223
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +9 -1
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +184 -127
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.js +43 -42
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.js +1 -0
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaManagerProxies.js +5 -0
- package/dist/deltaManagerProxies.js.map +1 -1
- package/dist/deltaScheduler.js +104 -99
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/error.js +2 -1
- package/dist/error.js.map +1 -1
- package/dist/gc/garbageCollection.js +85 -55
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.js +2 -3
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcHelpers.js +12 -13
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js +1 -2
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +8 -3
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.js +12 -5
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +18 -1
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/inboundBatchAggregator.js +122 -117
- package/dist/inboundBatchAggregator.js.map +1 -1
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +3 -3
- package/dist/metadata.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +11 -5
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/duplicateBatchDetector.js +18 -18
- package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +2 -2
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +2 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.js +2 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +10 -6
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +5 -3
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSerialization.d.ts +11 -1
- package/dist/opLifecycle/opSerialization.d.ts.map +1 -1
- package/dist/opLifecycle/opSerialization.js +22 -6
- package/dist/opLifecycle/opSerialization.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +17 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +46 -9
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +17 -13
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +6 -3
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.js +54 -47
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runCounter.js +10 -30
- package/dist/runCounter.js.map +1 -1
- package/dist/runtimeLayerCompatState.d.ts +1 -1
- package/dist/runtimeLayerCompatState.d.ts.map +1 -1
- package/dist/runtimeLayerCompatState.js +31 -11
- package/dist/runtimeLayerCompatState.js.map +1 -1
- package/dist/signalTelemetryProcessing.js +15 -17
- package/dist/signalTelemetryProcessing.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.js +2 -0
- package/dist/storageServiceWithAttachBlobs.js.map +1 -1
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +51 -13
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/orderedClientElection.js +25 -17
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js +18 -7
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +22 -13
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +20 -6
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerUtils.d.ts.map +1 -1
- package/dist/summary/summarizerUtils.js +4 -3
- package/dist/summary/summarizerUtils.js.map +1 -1
- package/dist/summary/summaryCollection.js +23 -11
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js +4 -2
- package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js +65 -46
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.js +15 -6
- package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.js +30 -25
- package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js +9 -0
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.js +3 -5
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +7 -7
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryHelpers.js +5 -5
- package/dist/summary/summaryHelpers.js.map +1 -1
- package/dist/summary/summaryManager.js +66 -54
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -1
- package/dist/throttler.js.map +1 -1
- package/dist/versionMarks/inboundBatch.d.ts +8 -6
- package/dist/versionMarks/inboundBatch.d.ts.map +1 -1
- package/dist/versionMarks/inboundBatch.js +11 -7
- package/dist/versionMarks/inboundBatch.js.map +1 -1
- package/dist/versionMarks/versionMarkResolver.d.ts +30 -23
- package/dist/versionMarks/versionMarkResolver.d.ts.map +1 -1
- package/dist/versionMarks/versionMarkResolver.js +112 -63
- package/dist/versionMarks/versionMarkResolver.js.map +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +5 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +1 -1
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +264 -231
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +65 -53
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.js +36 -18
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerCompatibility.d.ts +3 -3
- package/lib/containerCompatibility.d.ts.map +1 -1
- package/lib/containerCompatibility.js +33 -42
- package/lib/containerCompatibility.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +4 -0
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +4 -4
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +341 -218
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +9 -1
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +182 -125
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.js +43 -42
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.js +1 -0
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/deltaManagerProxies.js +5 -0
- package/lib/deltaManagerProxies.js.map +1 -1
- package/lib/deltaScheduler.js +104 -99
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/error.js +2 -1
- package/lib/error.js.map +1 -1
- package/lib/gc/garbageCollection.js +85 -55
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +8 -3
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.js +12 -5
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +18 -1
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/inboundBatchAggregator.js +122 -117
- package/lib/inboundBatchAggregator.js.map +1 -1
- package/lib/legacy.d.ts +1 -1
- package/lib/legacyAlpha.d.ts +1 -1
- package/lib/metadata.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +8 -2
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/duplicateBatchDetector.js +18 -18
- package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +2 -2
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +2 -2
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.js +3 -2
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +10 -6
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +3 -1
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSerialization.d.ts +11 -1
- package/lib/opLifecycle/opSerialization.d.ts.map +1 -1
- package/lib/opLifecycle/opSerialization.js +16 -0
- package/lib/opLifecycle/opSerialization.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +17 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +44 -7
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +14 -10
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +4 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.js +52 -45
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/runCounter.js +10 -30
- package/lib/runCounter.js.map +1 -1
- package/lib/runtimeLayerCompatState.d.ts +1 -1
- package/lib/runtimeLayerCompatState.d.ts.map +1 -1
- package/lib/runtimeLayerCompatState.js +28 -8
- package/lib/runtimeLayerCompatState.js.map +1 -1
- package/lib/signalTelemetryProcessing.js +15 -17
- package/lib/signalTelemetryProcessing.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.js +2 -0
- package/lib/storageServiceWithAttachBlobs.js.map +1 -1
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +51 -13
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/orderedClientElection.js +25 -17
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js +18 -7
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +22 -13
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +20 -6
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerUtils.d.ts.map +1 -1
- package/lib/summary/summarizerUtils.js +1 -0
- package/lib/summary/summarizerUtils.js.map +1 -1
- package/lib/summary/summaryCollection.js +23 -11
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js +4 -2
- package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js +65 -46
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.js +15 -6
- package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.js +30 -25
- package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js +9 -0
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.js +3 -5
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +66 -54
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -1
- package/lib/throttler.js.map +1 -1
- package/lib/versionMarks/inboundBatch.d.ts +8 -6
- package/lib/versionMarks/inboundBatch.d.ts.map +1 -1
- package/lib/versionMarks/inboundBatch.js +10 -5
- package/lib/versionMarks/inboundBatch.js.map +1 -1
- package/lib/versionMarks/versionMarkResolver.d.ts +30 -23
- package/lib/versionMarks/versionMarkResolver.d.ts.map +1 -1
- package/lib/versionMarks/versionMarkResolver.js +112 -63
- package/lib/versionMarks/versionMarkResolver.js.map +1 -1
- package/package.json +60 -102
- package/src/containerCompatibility.ts +33 -42
- package/src/containerRuntime.ts +15 -12
- package/src/opLifecycle/index.ts +7 -1
- package/src/opLifecycle/opCompressor.ts +2 -2
- package/src/opLifecycle/opSerialization.ts +22 -1
- package/src/opLifecycle/opSplitter.ts +63 -6
- package/src/packageVersion.ts +1 -1
- package/src/runtimeLayerCompatState.ts +28 -21
- package/src/summary/documentSchema.ts +31 -6
- package/src/versionMarks/DEV.md +595 -158
- package/src/versionMarks/inboundBatch.ts +18 -8
- package/src/versionMarks/versionMarkResolver.ts +144 -75
- package/tsconfig.json +1 -1
- package/internal.d.ts +0 -11
- package/legacy/alpha.d.ts +0 -11
- package/legacy.d.ts +0 -11
- /package/api-extractor/{api-extractor.current.json → api-extractor-report.current.json} +0 -0
- /package/api-extractor/{api-extractor.legacy.json → api-extractor-report.legacy.json} +0 -0
package/lib/containerRuntime.js
CHANGED
|
@@ -32,7 +32,7 @@ import { DeltaScheduler } from "./deltaScheduler.js";
|
|
|
32
32
|
import { GCNodeType, GarbageCollector, } from "./gc/index.js";
|
|
33
33
|
import { InboundBatchAggregator } from "./inboundBatchAggregator.js";
|
|
34
34
|
import { ContainerMessageType, } from "./messageTypes.js";
|
|
35
|
-
import { DuplicateBatchDetector, ensureContentsDeserialized, largeBatchThreshold, OpCompressor, OpDecompressor, OpGroupingManager, OpSplitter, Outbox, RemoteMessageProcessor, } from "./opLifecycle/index.js";
|
|
35
|
+
import { DuplicateBatchDetector, ensureContentsDeserialized, largeBatchThreshold, OpCompressor, OpDecompressor, OpGroupingManager, OpSplitter, Outbox, RemoteMessageProcessor, tryGetDeserializedRuntimeOpCopy, } from "./opLifecycle/index.js";
|
|
36
36
|
import { pkgVersion } from "./packageVersion.js";
|
|
37
37
|
import { PendingStateManager, } from "./pendingStateManager.js";
|
|
38
38
|
import { BatchRunCounter, RunCounter } from "./runCounter.js";
|
|
@@ -247,6 +247,17 @@ function canStageMessageOfType(type) {
|
|
|
247
247
|
* @internal
|
|
248
248
|
*/
|
|
249
249
|
export class ContainerRuntime extends TypedEventEmitter {
|
|
250
|
+
registry;
|
|
251
|
+
metadata;
|
|
252
|
+
electedSummarizerData;
|
|
253
|
+
runtimeOptions;
|
|
254
|
+
containerScope;
|
|
255
|
+
_storage;
|
|
256
|
+
createIdCompressorFn;
|
|
257
|
+
documentsSchemaController;
|
|
258
|
+
minVersionForCollab;
|
|
259
|
+
requestHandler;
|
|
260
|
+
summaryConfiguration;
|
|
250
261
|
/**
|
|
251
262
|
* Load the stores from a snapshot and returns the runtime.
|
|
252
263
|
* @param params - An object housing the runtime properties.
|
|
@@ -265,6 +276,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
265
276
|
static async loadRuntime(params) {
|
|
266
277
|
return ContainerRuntime.loadRuntime2(params).then((r) => r.runtime);
|
|
267
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Hack to allow test-utils to detect which version of loadRuntime API to expect.
|
|
281
|
+
* See note in loadRuntime's private remarks.
|
|
282
|
+
*/
|
|
283
|
+
static loadRuntimeAPIVersion = 2;
|
|
268
284
|
/**
|
|
269
285
|
* Load the stores from a snapshot and returns an object containing the runtime.
|
|
270
286
|
* @remarks
|
|
@@ -303,8 +319,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
303
319
|
const mc = loggerToMonitoringContext(logger);
|
|
304
320
|
// Some options require a minimum version of the FF runtime to operate, so the default configs will be generated
|
|
305
321
|
// based on the minVersionForCollab.
|
|
306
|
-
// For example, if minVersionForCollab is set to "
|
|
307
|
-
//
|
|
322
|
+
// For example, if minVersionForCollab is set to "2.0.0", the default configs will ensure compatibility with FF runtime
|
|
323
|
+
// 2.0.0 or later. If the minVersionForCollab is set to "2.10.0", the default values will be generated to ensure compatibility
|
|
308
324
|
// with FF runtime 2.10.0 or later.
|
|
309
325
|
if (!isValidMinVersionForCollab(minVersionForCollab)) {
|
|
310
326
|
throw new UsageError(`Invalid minVersionForCollab: ${minVersionForCollab}. It must be an existing FF version (i.e. 2.22.1).`);
|
|
@@ -515,15 +531,27 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
515
531
|
await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
|
|
516
532
|
return { runtime };
|
|
517
533
|
}
|
|
534
|
+
options;
|
|
535
|
+
_getClientId;
|
|
518
536
|
get clientId() {
|
|
519
537
|
return this._getClientId();
|
|
520
538
|
}
|
|
539
|
+
clientDetails;
|
|
540
|
+
isSummarizerClient;
|
|
521
541
|
get storage() {
|
|
522
542
|
return this._storage;
|
|
523
543
|
}
|
|
524
544
|
get containerRuntime() {
|
|
525
545
|
return this;
|
|
526
546
|
}
|
|
547
|
+
submitSummaryFn;
|
|
548
|
+
submitSignalFn;
|
|
549
|
+
disposeFn;
|
|
550
|
+
/**
|
|
551
|
+
* Initiate closing of the container due to a critical error.
|
|
552
|
+
* @param error - The critical error that caused the container to close.
|
|
553
|
+
*/
|
|
554
|
+
closeFn;
|
|
527
555
|
get flushMode() {
|
|
528
556
|
return this._flushMode;
|
|
529
557
|
}
|
|
@@ -533,9 +561,29 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
533
561
|
get IFluidDataStoreRegistry() {
|
|
534
562
|
return this.registry;
|
|
535
563
|
}
|
|
564
|
+
_getAttachState;
|
|
536
565
|
get attachState() {
|
|
537
566
|
return this._getAttachState();
|
|
538
567
|
}
|
|
568
|
+
/**
|
|
569
|
+
* Whether local op submission is currently disallowed.
|
|
570
|
+
*
|
|
571
|
+
* This is `true` in two distinct situations.
|
|
572
|
+
*
|
|
573
|
+
* First: the delta manager reports a read-only connection (host/service-imposed permission or connection state — the historical meaning of `readOnly`).
|
|
574
|
+
*
|
|
575
|
+
* Second: the `PendingStateManager` is replaying stashed ops (`isApplyingStashedOps`). During this window DDSes must not submit new local ops, as doing so would interleave fresh content ahead of the stashed pending stream and corrupt pending local state. Surfacing it through `isReadOnly()` lets DDSes that consult `readOnly` at realize time self-suppress; see the apply-lifecycle docs on `PendingStateManager` for the full rationale.
|
|
576
|
+
*
|
|
577
|
+
* Note this layers a third meaning ("transiently quiescing for stashed-op replay") onto the `readOnly` predicate, which is broader than its host/connection-permission origin.
|
|
578
|
+
*/
|
|
579
|
+
isReadOnly = () =>
|
|
580
|
+
// `_deltaManager` and `pendingStateManager` are both assigned partway
|
|
581
|
+
// through the constructor; `baseLogger` is built earlier and stamps
|
|
582
|
+
// `isReadOnly` on every error event (e.g. layer-compat failures
|
|
583
|
+
// during construction), so this can be called before either is
|
|
584
|
+
// assigned. Optional chains keep that window safe.
|
|
585
|
+
this._deltaManager?.readOnlyInfo.readonly === true ||
|
|
586
|
+
this.pendingStateManager?.isApplyingStashedOps === true;
|
|
539
587
|
/**
|
|
540
588
|
* Current session schema - defines what options are on & off.
|
|
541
589
|
* It's overlap of document schema (controlled by summary & ops) and options controlling this session.
|
|
@@ -549,6 +597,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
549
597
|
get sessionSchema() {
|
|
550
598
|
return this.documentsSchemaController.sessionSchema.runtime;
|
|
551
599
|
}
|
|
600
|
+
_idCompressor;
|
|
601
|
+
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
602
|
+
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
603
|
+
pendingIdCompressorOps = [];
|
|
604
|
+
// Id Compressor serializes final state (see getPendingLocalState()). As result, it needs to skip all ops that preceeded that state
|
|
605
|
+
// (such ops will be marked by Loader layer as savedOp === true)
|
|
606
|
+
// That said, in "delayed" mode it's possible that Id Compressor was never initialized before getPendingLocalState() is called.
|
|
607
|
+
// In such case we have to process all ops, including those marked with savedOp === true.
|
|
608
|
+
skipSavedCompressorOps;
|
|
552
609
|
/**
|
|
553
610
|
* {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor}
|
|
554
611
|
*/
|
|
@@ -571,6 +628,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
571
628
|
get IFluidHandleContext() {
|
|
572
629
|
return this.handleContext;
|
|
573
630
|
}
|
|
631
|
+
handleContext;
|
|
574
632
|
/**
|
|
575
633
|
* This is a proxy to the delta manager provided by the container context (innerDeltaManager). It restricts certain
|
|
576
634
|
* accesses such as sets "read-only" mode for the summarizer client. This is the default delta manager that should
|
|
@@ -579,6 +637,41 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
579
637
|
get deltaManager() {
|
|
580
638
|
return this._deltaManager;
|
|
581
639
|
}
|
|
640
|
+
_deltaManager;
|
|
641
|
+
/**
|
|
642
|
+
* The delta manager provided by the container context. By default, using the default delta manager (proxy)
|
|
643
|
+
* should be sufficient. This should be used only if necessary. For example, for validating and propagating connected
|
|
644
|
+
* events which requires access to the actual real only info, this is needed.
|
|
645
|
+
*/
|
|
646
|
+
innerDeltaManager;
|
|
647
|
+
// internal logger for ContainerRuntime. Use this.logger for stores, summaries, etc.
|
|
648
|
+
mc;
|
|
649
|
+
summarizerClientElection;
|
|
650
|
+
/**
|
|
651
|
+
* summaryManager will only be created if this client is permitted to spawn a summarizing client
|
|
652
|
+
* It is created only by interactive client, i.e. summarizer client, as well as non-interactive bots
|
|
653
|
+
* do not create it (see SummarizerClientElection.clientDetailsPermitElection() for details)
|
|
654
|
+
*/
|
|
655
|
+
summaryManager;
|
|
656
|
+
summarizerNode;
|
|
657
|
+
maxConsecutiveReconnects;
|
|
658
|
+
batchRunner = new BatchRunCounter();
|
|
659
|
+
_flushMode;
|
|
660
|
+
stagingModeAutoFlushThreshold;
|
|
661
|
+
/**
|
|
662
|
+
* BatchId tracking is needed whenever there's a possibility of a "forked Container",
|
|
663
|
+
* where the same local state is pending in two different running Containers, each of
|
|
664
|
+
* which is trying to ensure it's persisted.
|
|
665
|
+
* "Offline Load" from serialized pending state is one such scenario since two Containers
|
|
666
|
+
* could load from the same serialized pending state.
|
|
667
|
+
*/
|
|
668
|
+
batchIdTrackingEnabled;
|
|
669
|
+
flushScheduled = false;
|
|
670
|
+
canSendOps;
|
|
671
|
+
canSendSignals;
|
|
672
|
+
getConnectionState;
|
|
673
|
+
consecutiveReconnects = 0;
|
|
674
|
+
dataModelChangeRunner = new RunCounter();
|
|
582
675
|
/**
|
|
583
676
|
* Invokes the given callback and expects that no ops are submitted
|
|
584
677
|
* until execution finishes. If an op is submitted, it will be marked as reentrant.
|
|
@@ -601,15 +694,50 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
601
694
|
get summarizerClientId() {
|
|
602
695
|
return this.summarizerClientElection?.electedClientId;
|
|
603
696
|
}
|
|
697
|
+
_disposed = false;
|
|
604
698
|
get disposed() {
|
|
605
699
|
return this._disposed;
|
|
606
700
|
}
|
|
701
|
+
lastEmittedDirty;
|
|
702
|
+
emitDirtyDocumentEvent = true;
|
|
703
|
+
lastEmittedHasStagedChanges;
|
|
704
|
+
useDeltaManagerOpsProxy;
|
|
705
|
+
closeSummarizerDelayMs;
|
|
706
|
+
signalTelemetryManager = new SignalTelemetryManager();
|
|
707
|
+
/**
|
|
708
|
+
* Summarizer is responsible for coordinating when to send generate and send summaries.
|
|
709
|
+
* It is the main entry point for summary work.
|
|
710
|
+
* It is created only by summarizing container (i.e. one with clientType === "summarizer")
|
|
711
|
+
*/
|
|
712
|
+
_summarizer;
|
|
713
|
+
deltaScheduler;
|
|
714
|
+
inboundBatchAggregator;
|
|
715
|
+
blobManager;
|
|
716
|
+
pendingStateManager;
|
|
717
|
+
duplicateBatchDetector;
|
|
718
|
+
versionMarkResolverInternal;
|
|
607
719
|
/**
|
|
608
720
|
* Host-facing version mark resolver.
|
|
609
721
|
*/
|
|
610
722
|
get versionMarkResolver() {
|
|
611
723
|
return this.versionMarkResolverInternal;
|
|
612
724
|
}
|
|
725
|
+
outbox;
|
|
726
|
+
garbageCollector;
|
|
727
|
+
channelCollection;
|
|
728
|
+
remoteMessageProcessor;
|
|
729
|
+
versionMarkInboundBatchId;
|
|
730
|
+
/**
|
|
731
|
+
* The last message processed at the time of the last summary.
|
|
732
|
+
*/
|
|
733
|
+
messageAtLastSummary;
|
|
734
|
+
summariesDisabled;
|
|
735
|
+
createContainerMetadata;
|
|
736
|
+
/**
|
|
737
|
+
* The summary number of the next summary that will be generated for this container. This is incremented every time
|
|
738
|
+
* a summary is generated.
|
|
739
|
+
*/
|
|
740
|
+
nextSummaryNumber;
|
|
613
741
|
/**
|
|
614
742
|
* If false, loading or using a Tombstoned object should merely log, not fail.
|
|
615
743
|
* @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
|
|
@@ -626,6 +754,27 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
626
754
|
get gcThrowOnTombstoneUsage() {
|
|
627
755
|
return false;
|
|
628
756
|
}
|
|
757
|
+
/**
|
|
758
|
+
* GUID to identify a document in telemetry
|
|
759
|
+
* ! Note: should not be used for anything other than telemetry and is not considered a stable GUID
|
|
760
|
+
*/
|
|
761
|
+
telemetryDocumentId;
|
|
762
|
+
/**
|
|
763
|
+
* The id of the version used to initially load this runtime, or undefined if it's newly created.
|
|
764
|
+
*/
|
|
765
|
+
loadedFromVersionId;
|
|
766
|
+
isSnapshotInstanceOfISnapshot;
|
|
767
|
+
/**
|
|
768
|
+
* The summary context of the last acked summary. The properties from this as used when uploading a summary.
|
|
769
|
+
*/
|
|
770
|
+
lastAckedSummaryContext;
|
|
771
|
+
/**
|
|
772
|
+
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
773
|
+
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
774
|
+
*/
|
|
775
|
+
snapshotCacheForLoadingGroupIds = new PromiseCache({
|
|
776
|
+
expiry: { policy: "absolute", durationMs: 60000 },
|
|
777
|
+
});
|
|
629
778
|
/**
|
|
630
779
|
* The compatibility details of the Runtime layer that is exposed to the Loader layer
|
|
631
780
|
* for validating Loader-Runtime compatibility.
|
|
@@ -633,6 +782,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
633
782
|
get ILayerCompatDetails() {
|
|
634
783
|
return runtimeCompatDetailsForLoader;
|
|
635
784
|
}
|
|
785
|
+
extensions = new Map();
|
|
786
|
+
baseLogger;
|
|
636
787
|
/***/
|
|
637
788
|
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope,
|
|
638
789
|
// Create a custom ITelemetryBaseLogger to output telemetry events.
|
|
@@ -656,206 +807,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
656
807
|
this.minVersionForCollab = minVersionForCollab;
|
|
657
808
|
this.requestHandler = requestHandler;
|
|
658
809
|
this.summaryConfiguration = summaryConfiguration;
|
|
659
|
-
/**
|
|
660
|
-
* Whether local op submission is currently disallowed.
|
|
661
|
-
*
|
|
662
|
-
* This is `true` in two distinct situations.
|
|
663
|
-
*
|
|
664
|
-
* First: the delta manager reports a read-only connection (host/service-imposed permission or connection state — the historical meaning of `readOnly`).
|
|
665
|
-
*
|
|
666
|
-
* Second: the `PendingStateManager` is replaying stashed ops (`isApplyingStashedOps`). During this window DDSes must not submit new local ops, as doing so would interleave fresh content ahead of the stashed pending stream and corrupt pending local state. Surfacing it through `isReadOnly()` lets DDSes that consult `readOnly` at realize time self-suppress; see the apply-lifecycle docs on `PendingStateManager` for the full rationale.
|
|
667
|
-
*
|
|
668
|
-
* Note this layers a third meaning ("transiently quiescing for stashed-op replay") onto the `readOnly` predicate, which is broader than its host/connection-permission origin.
|
|
669
|
-
*/
|
|
670
|
-
this.isReadOnly = () =>
|
|
671
|
-
// `_deltaManager` and `pendingStateManager` are both assigned partway
|
|
672
|
-
// through the constructor; `baseLogger` is built earlier and stamps
|
|
673
|
-
// `isReadOnly` on every error event (e.g. layer-compat failures
|
|
674
|
-
// during construction), so this can be called before either is
|
|
675
|
-
// assigned. Optional chains keep that window safe.
|
|
676
|
-
this._deltaManager?.readOnlyInfo.readonly === true ||
|
|
677
|
-
this.pendingStateManager?.isApplyingStashedOps === true;
|
|
678
|
-
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
679
|
-
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
680
|
-
this.pendingIdCompressorOps = [];
|
|
681
|
-
this.batchRunner = new BatchRunCounter();
|
|
682
|
-
this.flushScheduled = false;
|
|
683
|
-
this.consecutiveReconnects = 0;
|
|
684
|
-
this.dataModelChangeRunner = new RunCounter();
|
|
685
|
-
this._disposed = false;
|
|
686
|
-
this.emitDirtyDocumentEvent = true;
|
|
687
|
-
this.signalTelemetryManager = new SignalTelemetryManager();
|
|
688
|
-
/**
|
|
689
|
-
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
690
|
-
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
691
|
-
*/
|
|
692
|
-
this.snapshotCacheForLoadingGroupIds = new PromiseCache({
|
|
693
|
-
expiry: { policy: "absolute", durationMs: 60000 },
|
|
694
|
-
});
|
|
695
|
-
this.extensions = new Map();
|
|
696
|
-
// Boolean payload from the `"readonly"` delta-manager event is intentionally
|
|
697
|
-
// ignored — `isReadOnly()` aggregates delta-manager readonly with the PSM
|
|
698
|
-
// apply window, and that aggregation is the source of truth for fanout.
|
|
699
|
-
// `channelCollection?.` guards against future wiring changes; both callers
|
|
700
|
-
// today (the `"readonly"` listener and `onAfterStashedOpsApplied`) fire
|
|
701
|
-
// after `channelCollection` is assigned.
|
|
702
|
-
this.notifyReadOnlyState = (_readonly) => this.channelCollection?.notifyReadOnlyState(this.isReadOnly());
|
|
703
|
-
/**
|
|
704
|
-
* Enter Staging Mode, such that ops submitted to the ContainerRuntime will not be sent to the ordering service.
|
|
705
|
-
* To exit Staging Mode, call either discardChanges or commitChanges on the Stage Controls returned from this method.
|
|
706
|
-
*
|
|
707
|
-
* @remarks
|
|
708
|
-
* The `stagingModeChanged` event is emitted when staging mode is entered or exited via this method.
|
|
709
|
-
* It is NOT emitted when staging mode is used internally (e.g. by `orderSequentially` for rollback support).
|
|
710
|
-
*
|
|
711
|
-
* @returns Controls for exiting Staging Mode.
|
|
712
|
-
*/
|
|
713
|
-
this.enterStagingMode = () => this.enterStagingModeCore(false);
|
|
714
|
-
/**
|
|
715
|
-
* Internal implementation of enterStagingMode.
|
|
716
|
-
* @param silent - When true, suppresses `stagingModeChanged` event emission.
|
|
717
|
-
* Pass `true` when staging mode is used as an internal implementation detail (e.g. by
|
|
718
|
-
* `orderSequentially` for rollback support) so that external listeners only observe
|
|
719
|
-
* user-initiated staging mode transitions. Pass `false` for all public entry points.
|
|
720
|
-
*/
|
|
721
|
-
this.enterStagingModeCore = (silent) => {
|
|
722
|
-
if (this.stageControls !== undefined) {
|
|
723
|
-
throw new UsageError("Already in staging mode");
|
|
724
|
-
}
|
|
725
|
-
if (this.attachState === AttachState.Detached) {
|
|
726
|
-
throw new UsageError("Cannot enter staging mode while Detached");
|
|
727
|
-
}
|
|
728
|
-
// Make sure Outbox is empty before entering staging mode,
|
|
729
|
-
// since we mark whole batches as "staged" or not to indicate whether to submit them.
|
|
730
|
-
this.flush();
|
|
731
|
-
// Note: `silent` is captured from the enclosing `enterStagingModeCore` call.
|
|
732
|
-
// When `true`, both enter and exit events are suppressed (see orderSequentially).
|
|
733
|
-
const exitStagingMode = (discardOrCommit, exitMethod) => {
|
|
734
|
-
if (this.stageControls !== stageControls) {
|
|
735
|
-
throw new UsageError("Not in staging mode");
|
|
736
|
-
}
|
|
737
|
-
try {
|
|
738
|
-
PerformanceEvent.timedExec(this.mc.logger, {
|
|
739
|
-
eventName: `ExitStagingMode_${exitMethod}`,
|
|
740
|
-
}, (event) => {
|
|
741
|
-
// Final flush of any last staged changes
|
|
742
|
-
// NOTE: We can't use this.flush() here, because orderSequentially uses StagingMode and in the rollback case we'll hit assert 0x24c
|
|
743
|
-
this.outbox.flush();
|
|
744
|
-
this.stageControls = undefined;
|
|
745
|
-
const batchInfos = discardOrCommit();
|
|
746
|
-
event.reportProgress({
|
|
747
|
-
details: {
|
|
748
|
-
autoFlushThreshold: this.stagingModeAutoFlushThreshold,
|
|
749
|
-
batches: batchInfos.length,
|
|
750
|
-
batchesAtOrOverThreshold: batchInfos.filter((b) => b.length >= this.stagingModeAutoFlushThreshold).length,
|
|
751
|
-
},
|
|
752
|
-
});
|
|
753
|
-
this.channelCollection.notifyStagingMode(false);
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
catch (error) {
|
|
757
|
-
const normalizedError = normalizeError(error);
|
|
758
|
-
this.closeFn(normalizedError);
|
|
759
|
-
throw normalizedError;
|
|
760
|
-
}
|
|
761
|
-
if (!silent) {
|
|
762
|
-
this.emit("stagingModeChanged", {
|
|
763
|
-
inStagingMode: false,
|
|
764
|
-
commit: exitMethod === "commit",
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
};
|
|
768
|
-
const stageControls = {
|
|
769
|
-
discardChanges: () => exitStagingMode(() => {
|
|
770
|
-
// Pop all staged batches from the PSM and roll them back in LIFO order
|
|
771
|
-
const batchInfos = this.pendingStateManager.popStagedBatches(({ runtimeOp, localOpMetadata }) => {
|
|
772
|
-
this.rollbackStagedChange(runtimeOp, localOpMetadata);
|
|
773
|
-
});
|
|
774
|
-
this.updateDocumentDirtyState();
|
|
775
|
-
this.updateHasStagedChangesState();
|
|
776
|
-
return batchInfos;
|
|
777
|
-
}, "discard"),
|
|
778
|
-
commitChanges: (options) => {
|
|
779
|
-
const { squash } = { ...defaultStagingCommitOptions, ...options };
|
|
780
|
-
exitStagingMode(() => {
|
|
781
|
-
// Replay all staged batches in typical FIFO order.
|
|
782
|
-
// We'll be out of staging mode so they'll be sent to the service finally.
|
|
783
|
-
const batchInfos = this.pendingStateManager.replayPendingStates({
|
|
784
|
-
committingStagedBatches: true,
|
|
785
|
-
squash,
|
|
786
|
-
});
|
|
787
|
-
this.updateHasStagedChangesState();
|
|
788
|
-
return batchInfos;
|
|
789
|
-
}, "commit");
|
|
790
|
-
},
|
|
791
|
-
};
|
|
792
|
-
this.stageControls = stageControls;
|
|
793
|
-
this.channelCollection.notifyStagingMode(true);
|
|
794
|
-
if (!silent) {
|
|
795
|
-
try {
|
|
796
|
-
this.emit("stagingModeChanged", { inStagingMode: true });
|
|
797
|
-
}
|
|
798
|
-
catch (error) {
|
|
799
|
-
// Don't let a listener error prevent the caller from receiving stage controls.
|
|
800
|
-
this.mc.logger.sendErrorEvent({ eventName: "StagingModeChangedError" }, error);
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
return stageControls;
|
|
804
|
-
};
|
|
805
|
-
this.readAndParseBlob = async (id) => readAndParse(this.storage, id);
|
|
806
|
-
/**
|
|
807
|
-
* ContainerRuntime knows about additional restrictions on when blob sharing can be resumed as compared
|
|
808
|
-
* to BlobManager. In particular, it wants to avoid sharing blobs while in readonly state, and it also
|
|
809
|
-
* wants to avoid sharing blobs before connection completes (otherwise it may cause the sharing to happen
|
|
810
|
-
* before processing shared ops).
|
|
811
|
-
*
|
|
812
|
-
* This method can be called safely before those conditions are met. In the background, it will wait until
|
|
813
|
-
* it is safe before initiating sharing. It will close the container on any error.
|
|
814
|
-
*/
|
|
815
|
-
this.sharePendingBlobs = () => {
|
|
816
|
-
new Promise((resolve) => {
|
|
817
|
-
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
818
|
-
const canStartSharing = () => this.connected && this.deltaManager.readOnlyInfo.readonly !== true;
|
|
819
|
-
if (canStartSharing()) {
|
|
820
|
-
resolve();
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
const checkCanShare = (readonly) => {
|
|
824
|
-
if (canStartSharing()) {
|
|
825
|
-
this.deltaManager.off("readonly", checkCanShare);
|
|
826
|
-
this.off("connected", checkCanShare);
|
|
827
|
-
resolve();
|
|
828
|
-
}
|
|
829
|
-
};
|
|
830
|
-
this.deltaManager.on("readonly", checkCanShare);
|
|
831
|
-
this.on("connected", checkCanShare);
|
|
832
|
-
})
|
|
833
|
-
.then(this.blobManager.sharePendingBlobs)
|
|
834
|
-
// It may not be necessary to close the container on failures - this should just mean there's
|
|
835
|
-
// a handle in the container that is stuck pending, which is a scenario that customers need to
|
|
836
|
-
// handle anyway. Starting with this more aggressive/restrictive behavior to be cautious.
|
|
837
|
-
.catch(this.closeFn);
|
|
838
|
-
};
|
|
839
|
-
// While internal, ContainerRuntime has not been converted to use the new events support.
|
|
840
|
-
// Recreate the required events (new pattern) with injected, wrapper new emitter.
|
|
841
|
-
// It is lazily create to avoid listeners (old events) that ultimately go nowhere.
|
|
842
|
-
this.lazyEventsForExtensions = new Lazy(() => {
|
|
843
|
-
const eventEmitter = createEmitter();
|
|
844
|
-
if (this.getConnectionState) {
|
|
845
|
-
this.on("connectedToService", (clientId, canWrite) => {
|
|
846
|
-
eventEmitter.emit("joined", { clientId, canWrite });
|
|
847
|
-
});
|
|
848
|
-
this.on("disconnectedFromService", () => eventEmitter.emit("disconnected"));
|
|
849
|
-
this.on("operabilityChanged", (canWrite) => eventEmitter.emit("operabilityChanged", canWrite));
|
|
850
|
-
}
|
|
851
|
-
else {
|
|
852
|
-
this.on("connected", (clientId) => {
|
|
853
|
-
eventEmitter.emit("joined", { clientId, canWrite: true });
|
|
854
|
-
});
|
|
855
|
-
this.on("disconnected", () => eventEmitter.emit("disconnected"));
|
|
856
|
-
}
|
|
857
|
-
return eventEmitter;
|
|
858
|
-
});
|
|
859
810
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, signalAudience, pendingLocalState, snapshotWithContents, getConnectionState, } = context;
|
|
860
811
|
this.getConnectionState = getConnectionState;
|
|
861
812
|
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
@@ -1014,6 +965,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1014
965
|
const fetchOps = context.fetchOps;
|
|
1015
966
|
this.versionMarkResolverInternal = new VersionMarkResolver({
|
|
1016
967
|
getCurrentSequenceNumber: () => this.deltaManager.lastSequenceNumber,
|
|
968
|
+
getCurrentTimestamp: () => this.getCurrentReferenceTimestampMs(),
|
|
1017
969
|
getCurrentMinimumSequenceNumber: () => this.deltaManager.minimumSequenceNumber,
|
|
1018
970
|
getCurrentPendingBatchId: () => this.pendingStateManager.getMostRecentPendingBatchId(),
|
|
1019
971
|
logger: createChildLogger({
|
|
@@ -1023,7 +975,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1023
975
|
// Seal the current outbound batch so a just-submitted edit gets a stable batchId in the pending
|
|
1024
976
|
// state before sealAndCaptureVersionMark reads it (a batchId is only assigned when flushed).
|
|
1025
977
|
flushPendingBatch: () => this.flush(),
|
|
1026
|
-
//
|
|
978
|
+
// Keep this optional while a supported older loader may not provide fetchOps. AB#81034 tracks
|
|
979
|
+
// making it required once the Runtime -> Loader compatibility window reaches generation 21.
|
|
1027
980
|
getHistoricalOpReader: fetchOps ? () => ({ fetchMessages: fetchOps }) : undefined,
|
|
1028
981
|
// Unpack scanned historical ops through the same pipeline the live inbound path uses, so a
|
|
1029
982
|
// chunked batch's batchId (only restored after reassembly) is observed by the history scan too.
|
|
@@ -1031,15 +984,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1031
984
|
? () => {
|
|
1032
985
|
// A fresh processor per scan: it holds chunk-reassembly state, so it must not share
|
|
1033
986
|
// the live inbound processor's state. submit/size args are unused on the read path.
|
|
1034
|
-
const scanProcessor = new RemoteMessageProcessor(new OpSplitter([], submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger), new OpDecompressor(this.mc.logger), new OpGroupingManager({ groupedBatchingEnabled: this.groupedBatchingEnabled }, this.mc.logger));
|
|
987
|
+
const scanProcessor = new RemoteMessageProcessor(new OpSplitter([], submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger, { allowInitialPartialChunkStream: true }), new OpDecompressor(this.mc.logger), new OpGroupingManager({ groupedBatchingEnabled: this.groupedBatchingEnabled }, this.mc.logger));
|
|
1035
988
|
return (op) => {
|
|
1036
|
-
//
|
|
1037
|
-
|
|
1038
|
-
if (
|
|
989
|
+
// Only runtime ops carry batches; deserialize a copy so the reader-owned op stays untouched.
|
|
990
|
+
const messageCopy = tryGetDeserializedRuntimeOpCopy(op);
|
|
991
|
+
if (messageCopy === undefined) {
|
|
1039
992
|
return undefined;
|
|
1040
993
|
}
|
|
1041
|
-
const messageCopy = { ...op };
|
|
1042
|
-
ensureContentsDeserialized(messageCopy);
|
|
1043
994
|
return scanProcessor.process(messageCopy, getSingleUseLegacyLogCallback(this.mc.logger, messageCopy.type));
|
|
1044
995
|
};
|
|
1045
996
|
}
|
|
@@ -1263,10 +1214,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1263
1214
|
const clientId = this._getClientId();
|
|
1264
1215
|
return clientId === undefined
|
|
1265
1216
|
? undefined
|
|
1266
|
-
:
|
|
1217
|
+
: {
|
|
1267
1218
|
clientId,
|
|
1268
1219
|
client: audience.getMember(clientId),
|
|
1269
|
-
}
|
|
1220
|
+
};
|
|
1270
1221
|
};
|
|
1271
1222
|
let oldClientId = this.clientId;
|
|
1272
1223
|
this.on("connected", () => {
|
|
@@ -1678,6 +1629,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1678
1629
|
async getEntryPoint() {
|
|
1679
1630
|
return this.entryPoint;
|
|
1680
1631
|
}
|
|
1632
|
+
entryPoint;
|
|
1681
1633
|
internalId(maybeAlias) {
|
|
1682
1634
|
return this.channelCollection.internalId(maybeAlias);
|
|
1683
1635
|
}
|
|
@@ -1896,6 +1848,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1896
1848
|
assert(this.pendingIdCompressorOps.length === 0, 0x976 /* No new ops added */);
|
|
1897
1849
|
}
|
|
1898
1850
|
}
|
|
1851
|
+
// Boolean payload from the `"readonly"` delta-manager event is intentionally
|
|
1852
|
+
// ignored — `isReadOnly()` aggregates delta-manager readonly with the PSM
|
|
1853
|
+
// apply window, and that aggregation is the source of truth for fanout.
|
|
1854
|
+
// `channelCollection?.` guards against future wiring changes; both callers
|
|
1855
|
+
// today (the `"readonly"` listener and `onAfterStashedOpsApplied`) fire
|
|
1856
|
+
// after `channelCollection` is assigned.
|
|
1857
|
+
notifyReadOnlyState = (_readonly) => this.channelCollection?.notifyReadOnlyState(this.isReadOnly());
|
|
1899
1858
|
setConnectionState(canSendOps, clientId) {
|
|
1900
1859
|
this.setConnectionStateToConnectedOrDisconnected(canSendOps, clientId);
|
|
1901
1860
|
}
|
|
@@ -2118,7 +2077,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2118
2077
|
if (this.versionMarkResolverInternal.isTracking) {
|
|
2119
2078
|
const versionMarkUpdate = inboundVersionMarkUpdate(inboundResult, this.versionMarkInboundBatchId);
|
|
2120
2079
|
if (versionMarkUpdate.sequenced !== undefined) {
|
|
2121
|
-
this.versionMarkResolverInternal.processInboundBatch(versionMarkUpdate.sequenced.batchId, versionMarkUpdate.sequenced.sequenceNumber);
|
|
2080
|
+
this.versionMarkResolverInternal.processInboundBatch(versionMarkUpdate.sequenced.batchId, versionMarkUpdate.sequenced.sequenceNumber, versionMarkUpdate.sequenced.timestamp);
|
|
2122
2081
|
}
|
|
2123
2082
|
this.versionMarkInboundBatchId = versionMarkUpdate.carriedBatchId;
|
|
2124
2083
|
}
|
|
@@ -2168,6 +2127,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2168
2127
|
this.resetReconnectCount();
|
|
2169
2128
|
}
|
|
2170
2129
|
}
|
|
2130
|
+
_processedClientSequenceNumber;
|
|
2171
2131
|
/**
|
|
2172
2132
|
* Processes inbound message(s). It calls delta scheduler according to the messages' location in the batch.
|
|
2173
2133
|
* @param messagesWithMetadata - messages to process along with their metadata.
|
|
@@ -2504,6 +2464,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2504
2464
|
}
|
|
2505
2465
|
return result;
|
|
2506
2466
|
}
|
|
2467
|
+
stageControls;
|
|
2507
2468
|
/**
|
|
2508
2469
|
* If true, the ContainerRuntime is not submitting any new ops to the ordering service.
|
|
2509
2470
|
* Ops submitted to the ContainerRuntime while in Staging Mode will be queued in the PendingStateManager,
|
|
@@ -2512,6 +2473,108 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2512
2473
|
get inStagingMode() {
|
|
2513
2474
|
return this.stageControls !== undefined;
|
|
2514
2475
|
}
|
|
2476
|
+
/**
|
|
2477
|
+
* Enter Staging Mode, such that ops submitted to the ContainerRuntime will not be sent to the ordering service.
|
|
2478
|
+
* To exit Staging Mode, call either discardChanges or commitChanges on the Stage Controls returned from this method.
|
|
2479
|
+
*
|
|
2480
|
+
* @remarks
|
|
2481
|
+
* The `stagingModeChanged` event is emitted when staging mode is entered or exited via this method.
|
|
2482
|
+
* It is NOT emitted when staging mode is used internally (e.g. by `orderSequentially` for rollback support).
|
|
2483
|
+
*
|
|
2484
|
+
* @returns Controls for exiting Staging Mode.
|
|
2485
|
+
*/
|
|
2486
|
+
enterStagingMode = () => this.enterStagingModeCore(false);
|
|
2487
|
+
/**
|
|
2488
|
+
* Internal implementation of enterStagingMode.
|
|
2489
|
+
* @param silent - When true, suppresses `stagingModeChanged` event emission.
|
|
2490
|
+
* Pass `true` when staging mode is used as an internal implementation detail (e.g. by
|
|
2491
|
+
* `orderSequentially` for rollback support) so that external listeners only observe
|
|
2492
|
+
* user-initiated staging mode transitions. Pass `false` for all public entry points.
|
|
2493
|
+
*/
|
|
2494
|
+
enterStagingModeCore = (silent) => {
|
|
2495
|
+
if (this.stageControls !== undefined) {
|
|
2496
|
+
throw new UsageError("Already in staging mode");
|
|
2497
|
+
}
|
|
2498
|
+
if (this.attachState === AttachState.Detached) {
|
|
2499
|
+
throw new UsageError("Cannot enter staging mode while Detached");
|
|
2500
|
+
}
|
|
2501
|
+
// Make sure Outbox is empty before entering staging mode,
|
|
2502
|
+
// since we mark whole batches as "staged" or not to indicate whether to submit them.
|
|
2503
|
+
this.flush();
|
|
2504
|
+
// Note: `silent` is captured from the enclosing `enterStagingModeCore` call.
|
|
2505
|
+
// When `true`, both enter and exit events are suppressed (see orderSequentially).
|
|
2506
|
+
const exitStagingMode = (discardOrCommit, exitMethod) => {
|
|
2507
|
+
if (this.stageControls !== stageControls) {
|
|
2508
|
+
throw new UsageError("Not in staging mode");
|
|
2509
|
+
}
|
|
2510
|
+
try {
|
|
2511
|
+
PerformanceEvent.timedExec(this.mc.logger, {
|
|
2512
|
+
eventName: `ExitStagingMode_${exitMethod}`,
|
|
2513
|
+
}, (event) => {
|
|
2514
|
+
// Final flush of any last staged changes
|
|
2515
|
+
// NOTE: We can't use this.flush() here, because orderSequentially uses StagingMode and in the rollback case we'll hit assert 0x24c
|
|
2516
|
+
this.outbox.flush();
|
|
2517
|
+
this.stageControls = undefined;
|
|
2518
|
+
const batchInfos = discardOrCommit();
|
|
2519
|
+
event.reportProgress({
|
|
2520
|
+
details: {
|
|
2521
|
+
autoFlushThreshold: this.stagingModeAutoFlushThreshold,
|
|
2522
|
+
batches: batchInfos.length,
|
|
2523
|
+
batchesAtOrOverThreshold: batchInfos.filter((b) => b.length >= this.stagingModeAutoFlushThreshold).length,
|
|
2524
|
+
},
|
|
2525
|
+
});
|
|
2526
|
+
this.channelCollection.notifyStagingMode(false);
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2529
|
+
catch (error) {
|
|
2530
|
+
const normalizedError = normalizeError(error);
|
|
2531
|
+
this.closeFn(normalizedError);
|
|
2532
|
+
throw normalizedError;
|
|
2533
|
+
}
|
|
2534
|
+
if (!silent) {
|
|
2535
|
+
this.emit("stagingModeChanged", {
|
|
2536
|
+
inStagingMode: false,
|
|
2537
|
+
commit: exitMethod === "commit",
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
};
|
|
2541
|
+
const stageControls = {
|
|
2542
|
+
discardChanges: () => exitStagingMode(() => {
|
|
2543
|
+
// Pop all staged batches from the PSM and roll them back in LIFO order
|
|
2544
|
+
const batchInfos = this.pendingStateManager.popStagedBatches(({ runtimeOp, localOpMetadata }) => {
|
|
2545
|
+
this.rollbackStagedChange(runtimeOp, localOpMetadata);
|
|
2546
|
+
});
|
|
2547
|
+
this.updateDocumentDirtyState();
|
|
2548
|
+
this.updateHasStagedChangesState();
|
|
2549
|
+
return batchInfos;
|
|
2550
|
+
}, "discard"),
|
|
2551
|
+
commitChanges: (options) => {
|
|
2552
|
+
const { squash } = { ...defaultStagingCommitOptions, ...options };
|
|
2553
|
+
exitStagingMode(() => {
|
|
2554
|
+
// Replay all staged batches in typical FIFO order.
|
|
2555
|
+
// We'll be out of staging mode so they'll be sent to the service finally.
|
|
2556
|
+
const batchInfos = this.pendingStateManager.replayPendingStates({
|
|
2557
|
+
committingStagedBatches: true,
|
|
2558
|
+
squash,
|
|
2559
|
+
});
|
|
2560
|
+
this.updateHasStagedChangesState();
|
|
2561
|
+
return batchInfos;
|
|
2562
|
+
}, "commit");
|
|
2563
|
+
},
|
|
2564
|
+
};
|
|
2565
|
+
this.stageControls = stageControls;
|
|
2566
|
+
this.channelCollection.notifyStagingMode(true);
|
|
2567
|
+
if (!silent) {
|
|
2568
|
+
try {
|
|
2569
|
+
this.emit("stagingModeChanged", { inStagingMode: true });
|
|
2570
|
+
}
|
|
2571
|
+
catch (error) {
|
|
2572
|
+
// Don't let a listener error prevent the caller from receiving stage controls.
|
|
2573
|
+
this.mc.logger.sendErrorEvent({ eventName: "StagingModeChangedError" }, error);
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
return stageControls;
|
|
2577
|
+
};
|
|
2515
2578
|
/**
|
|
2516
2579
|
* Returns the aliased data store's entryPoint, given the alias.
|
|
2517
2580
|
* @param alias - The alias for the data store.
|
|
@@ -2558,12 +2621,21 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2558
2621
|
// container runtime's ability to send ops depend on the actual readonly state of the delta manager.
|
|
2559
2622
|
return this.connected && this.innerDeltaManager.readOnlyInfo.readonly !== true;
|
|
2560
2623
|
}
|
|
2624
|
+
_quorum;
|
|
2561
2625
|
getQuorum() {
|
|
2562
2626
|
return this._quorum;
|
|
2563
2627
|
}
|
|
2628
|
+
_audience;
|
|
2564
2629
|
getAudience() {
|
|
2565
2630
|
return this._audience;
|
|
2566
2631
|
}
|
|
2632
|
+
/**
|
|
2633
|
+
* When defined, this {@link @fluidframework/container-definitions#IAudience}
|
|
2634
|
+
* maintains member list using signals only.
|
|
2635
|
+
* Thus "write" members may be known earlier than quorum and avoid noise from
|
|
2636
|
+
* un-summarized quorum history.
|
|
2637
|
+
*/
|
|
2638
|
+
signalAudience;
|
|
2567
2639
|
/**
|
|
2568
2640
|
* Returns true of container is dirty, i.e. there are some pending local changes that
|
|
2569
2641
|
* either were not sent out to delta stream or were not yet acknowledged.
|
|
@@ -2663,6 +2735,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2663
2735
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
2664
2736
|
return summarizeResult.summary;
|
|
2665
2737
|
}
|
|
2738
|
+
getAbsoluteUrl;
|
|
2666
2739
|
/**
|
|
2667
2740
|
* Builds the Summary tree including all the channels and the container state.
|
|
2668
2741
|
*
|
|
@@ -3603,6 +3676,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
3603
3676
|
referenceSequenceNumber: summaryRefSeq,
|
|
3604
3677
|
};
|
|
3605
3678
|
}
|
|
3679
|
+
readAndParseBlob = async (id) => readAndParse(this.storage, id);
|
|
3606
3680
|
/**
|
|
3607
3681
|
* Fetches the latest snapshot from storage. If the fetched snapshot is same or newer than the one for which ack
|
|
3608
3682
|
* was received, close this client. Fetching the snapshot will update the cache for this client so if it's
|
|
@@ -3694,6 +3768,39 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
3694
3768
|
return pendingRuntimeState;
|
|
3695
3769
|
});
|
|
3696
3770
|
}
|
|
3771
|
+
/**
|
|
3772
|
+
* ContainerRuntime knows about additional restrictions on when blob sharing can be resumed as compared
|
|
3773
|
+
* to BlobManager. In particular, it wants to avoid sharing blobs while in readonly state, and it also
|
|
3774
|
+
* wants to avoid sharing blobs before connection completes (otherwise it may cause the sharing to happen
|
|
3775
|
+
* before processing shared ops).
|
|
3776
|
+
*
|
|
3777
|
+
* This method can be called safely before those conditions are met. In the background, it will wait until
|
|
3778
|
+
* it is safe before initiating sharing. It will close the container on any error.
|
|
3779
|
+
*/
|
|
3780
|
+
sharePendingBlobs = () => {
|
|
3781
|
+
new Promise((resolve) => {
|
|
3782
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
3783
|
+
const canStartSharing = () => this.connected && this.deltaManager.readOnlyInfo.readonly !== true;
|
|
3784
|
+
if (canStartSharing()) {
|
|
3785
|
+
resolve();
|
|
3786
|
+
return;
|
|
3787
|
+
}
|
|
3788
|
+
const checkCanShare = (readonly) => {
|
|
3789
|
+
if (canStartSharing()) {
|
|
3790
|
+
this.deltaManager.off("readonly", checkCanShare);
|
|
3791
|
+
this.off("connected", checkCanShare);
|
|
3792
|
+
resolve();
|
|
3793
|
+
}
|
|
3794
|
+
};
|
|
3795
|
+
this.deltaManager.on("readonly", checkCanShare);
|
|
3796
|
+
this.on("connected", checkCanShare);
|
|
3797
|
+
})
|
|
3798
|
+
.then(this.blobManager.sharePendingBlobs)
|
|
3799
|
+
// It may not be necessary to close the container on failures - this should just mean there's
|
|
3800
|
+
// a handle in the container that is stuck pending, which is a scenario that customers need to
|
|
3801
|
+
// handle anyway. Starting with this more aggressive/restrictive behavior to be cautious.
|
|
3802
|
+
.catch(this.closeFn);
|
|
3803
|
+
};
|
|
3697
3804
|
summarizeOnDemand(options) {
|
|
3698
3805
|
if (this._summarizer !== undefined) {
|
|
3699
3806
|
return this._summarizer.summarizeOnDemand(options);
|
|
@@ -3722,6 +3829,26 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
3722
3829
|
return this.summaryManager.enqueueSummarize(options);
|
|
3723
3830
|
}
|
|
3724
3831
|
}
|
|
3832
|
+
// While internal, ContainerRuntime has not been converted to use the new events support.
|
|
3833
|
+
// Recreate the required events (new pattern) with injected, wrapper new emitter.
|
|
3834
|
+
// It is lazily create to avoid listeners (old events) that ultimately go nowhere.
|
|
3835
|
+
lazyEventsForExtensions = new Lazy(() => {
|
|
3836
|
+
const eventEmitter = createEmitter();
|
|
3837
|
+
if (this.getConnectionState) {
|
|
3838
|
+
this.on("connectedToService", (clientId, canWrite) => {
|
|
3839
|
+
eventEmitter.emit("joined", { clientId, canWrite });
|
|
3840
|
+
});
|
|
3841
|
+
this.on("disconnectedFromService", () => eventEmitter.emit("disconnected"));
|
|
3842
|
+
this.on("operabilityChanged", (canWrite) => eventEmitter.emit("operabilityChanged", canWrite));
|
|
3843
|
+
}
|
|
3844
|
+
else {
|
|
3845
|
+
this.on("connected", (clientId) => {
|
|
3846
|
+
eventEmitter.emit("joined", { clientId, canWrite: true });
|
|
3847
|
+
});
|
|
3848
|
+
this.on("disconnected", () => eventEmitter.emit("disconnected"));
|
|
3849
|
+
}
|
|
3850
|
+
return eventEmitter;
|
|
3851
|
+
});
|
|
3725
3852
|
getJoinedStatus() {
|
|
3726
3853
|
const getConnectionState = this.getConnectionState;
|
|
3727
3854
|
if (getConnectionState) {
|
|
@@ -3737,6 +3864,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
3737
3864
|
}
|
|
3738
3865
|
return "disconnected";
|
|
3739
3866
|
}
|
|
3867
|
+
submitExtensionSignal;
|
|
3740
3868
|
acquireExtension(id, factory, ...useContext) {
|
|
3741
3869
|
return this.acquireExtensionInternal(
|
|
3742
3870
|
/* injectionPermitted */ true, id, factory, ...useContext);
|
|
@@ -3815,11 +3943,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
3815
3943
|
return this.sessionSchema.opGroupingEnabled === true;
|
|
3816
3944
|
}
|
|
3817
3945
|
}
|
|
3818
|
-
/**
|
|
3819
|
-
* Hack to allow test-utils to detect which version of loadRuntime API to expect.
|
|
3820
|
-
* See note in loadRuntime's private remarks.
|
|
3821
|
-
*/
|
|
3822
|
-
ContainerRuntime.loadRuntimeAPIVersion = 2;
|
|
3823
3946
|
export function isContainerMessageDirtyable({ type, contents, }) {
|
|
3824
3947
|
// Certain container runtime messages should not mark the container dirty such as the old built-in
|
|
3825
3948
|
// AgentScheduler and Garbage collector messages.
|