@fluidframework/container-runtime 2.0.0-internal.3.0.0 → 2.0.0-internal.3.1.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/.eslintrc.js +19 -19
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +9 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +80 -33
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +11 -9
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +3 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +10 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +140 -72
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +11 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +18 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +66 -15
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -3
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +26 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +103 -18
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +8 -3
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/garbageCollection.d.ts +34 -14
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +188 -93
- package/dist/garbageCollection.js.map +1 -1
- package/dist/garbageCollectionConstants.d.ts +3 -0
- package/dist/garbageCollectionConstants.d.ts.map +1 -1
- package/dist/garbageCollectionConstants.js +6 -1
- package/dist/garbageCollectionConstants.js.map +1 -1
- package/dist/garbageCollectionHelpers.d.ts +26 -0
- package/dist/garbageCollectionHelpers.d.ts.map +1 -0
- package/dist/garbageCollectionHelpers.js +45 -0
- package/dist/garbageCollectionHelpers.js.map +1 -0
- package/dist/gcSweepReadyUsageDetection.d.ts +5 -5
- package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/dist/gcSweepReadyUsageDetection.js +14 -10
- package/dist/gcSweepReadyUsageDetection.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +5 -5
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +19 -12
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +5 -2
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +4 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +19 -17
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js +1 -3
- package/dist/opProperties.js.map +1 -1
- package/dist/orderedClientElection.d.ts.map +1 -1
- package/dist/orderedClientElection.js +10 -4
- package/dist/orderedClientElection.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 +7 -0
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +7 -4
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +34 -21
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +3 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/serializedSnapshotStorage.d.ts +2 -2
- package/dist/serializedSnapshotStorage.d.ts.map +1 -1
- package/dist/serializedSnapshotStorage.js +5 -3
- package/dist/serializedSnapshotStorage.js.map +1 -1
- package/dist/summarizer.d.ts +2 -2
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +37 -17
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerClientElection.d.ts.map +1 -1
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summarizerHandle.d.ts.map +1 -1
- package/dist/summarizerHandle.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +6 -9
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +21 -21
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.d.ts.map +1 -1
- package/dist/summaryCollection.js +18 -8
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryFormat.d.ts +22 -0
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +18 -10
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +34 -15
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +21 -9
- package/dist/summaryManager.js.map +1 -1
- package/dist/throttler.d.ts +2 -2
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -4
- package/dist/throttler.js.map +1 -1
- package/garbageCollection.md +15 -2
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +9 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +82 -35
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +11 -9
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +3 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +10 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +146 -78
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +11 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +18 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +68 -17
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -3
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +26 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +109 -24
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +9 -4
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/garbageCollection.d.ts +34 -14
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +190 -95
- package/lib/garbageCollection.js.map +1 -1
- package/lib/garbageCollectionConstants.d.ts +3 -0
- package/lib/garbageCollectionConstants.d.ts.map +1 -1
- package/lib/garbageCollectionConstants.js +5 -0
- package/lib/garbageCollectionConstants.js.map +1 -1
- package/lib/garbageCollectionHelpers.d.ts +26 -0
- package/lib/garbageCollectionHelpers.d.ts.map +1 -0
- package/lib/garbageCollectionHelpers.js +40 -0
- package/lib/garbageCollectionHelpers.js.map +1 -0
- package/lib/gcSweepReadyUsageDetection.d.ts +5 -5
- package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/lib/gcSweepReadyUsageDetection.js +14 -10
- package/lib/gcSweepReadyUsageDetection.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +5 -5
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +19 -12
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +5 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +5 -2
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +19 -17
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js +1 -3
- package/lib/opProperties.js.map +1 -1
- package/lib/orderedClientElection.d.ts.map +1 -1
- package/lib/orderedClientElection.js +10 -4
- package/lib/orderedClientElection.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 +7 -0
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +7 -4
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +35 -22
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/serializedSnapshotStorage.d.ts +2 -2
- package/lib/serializedSnapshotStorage.d.ts.map +1 -1
- package/lib/serializedSnapshotStorage.js +5 -3
- package/lib/serializedSnapshotStorage.js.map +1 -1
- package/lib/summarizer.d.ts +2 -2
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +37 -17
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerClientElection.d.ts.map +1 -1
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summarizerHandle.d.ts.map +1 -1
- package/lib/summarizerHandle.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +6 -9
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +21 -21
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.d.ts.map +1 -1
- package/lib/summaryCollection.js +18 -8
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryFormat.d.ts +22 -0
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +20 -12
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +34 -15
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +21 -9
- package/lib/summaryManager.js.map +1 -1
- package/lib/throttler.d.ts +2 -2
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +121 -149
- package/prettier.config.cjs +1 -1
- package/src/batchTracker.ts +54 -49
- package/src/blobManager.ts +793 -672
- package/src/connectionTelemetry.ts +280 -249
- package/src/containerHandleContext.ts +27 -29
- package/src/containerRuntime.ts +3168 -2940
- package/src/dataStore.ts +172 -159
- package/src/dataStoreContext.ts +1098 -996
- package/src/dataStoreContexts.ts +178 -161
- package/src/dataStoreRegistry.ts +25 -20
- package/src/dataStores.ts +884 -728
- package/src/deltaScheduler.ts +158 -150
- package/src/garbageCollection.ts +1883 -1692
- package/src/garbageCollectionConstants.ts +6 -0
- package/src/garbageCollectionHelpers.ts +61 -0
- package/src/gcSweepReadyUsageDetection.ts +89 -83
- package/src/index.ts +67 -66
- package/src/opLifecycle/README.md +152 -0
- package/src/opLifecycle/batchManager.ts +145 -141
- package/src/opLifecycle/definitions.ts +29 -29
- package/src/opLifecycle/index.ts +5 -5
- package/src/opLifecycle/opCompressor.ts +54 -53
- package/src/opLifecycle/opDecompressor.ts +100 -81
- package/src/opLifecycle/opSplitter.ts +214 -188
- package/src/opLifecycle/outbox.ts +204 -194
- package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
- package/src/opProperties.ts +11 -9
- package/src/orderedClientElection.ts +489 -457
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +384 -338
- package/src/runWhileConnectedCoordinator.ts +78 -71
- package/src/runningSummarizer.ts +619 -581
- package/src/scheduleManager.ts +299 -269
- package/src/serializedSnapshotStorage.ts +126 -112
- package/src/summarizer.ts +417 -381
- package/src/summarizerClientElection.ts +107 -100
- package/src/summarizerHandle.ts +11 -9
- package/src/summarizerHeuristics.ts +183 -186
- package/src/summarizerTypes.ts +344 -330
- package/src/summaryCollection.ts +378 -349
- package/src/summaryFormat.ts +170 -126
- package/src/summaryGenerator.ts +465 -406
- package/src/summaryManager.ts +377 -348
- package/src/throttler.ts +131 -122
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.js +0 -23
- package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.js +0 -19
- package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
- package/src/garbageCollectionTombstoneUtils.ts +0 -28
package/lib/containerRuntime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
2
|
-
import { assert, Trace, TypedEventEmitter, unreachableCase
|
|
2
|
+
import { assert, Trace, TypedEventEmitter, unreachableCase } from "@fluidframework/common-utils";
|
|
3
3
|
import { ChildLogger, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, loggerToMonitoringContext, wrapError, } from "@fluidframework/telemetry-utils";
|
|
4
4
|
import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
|
|
5
5
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
@@ -13,23 +13,25 @@ import { ContainerFluidHandleContext } from "./containerHandleContext";
|
|
|
13
13
|
import { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
14
14
|
import { Summarizer } from "./summarizer";
|
|
15
15
|
import { SummaryManager } from "./summaryManager";
|
|
16
|
-
import { ReportOpPerfTelemetry
|
|
17
|
-
import { PendingStateManager
|
|
16
|
+
import { ReportOpPerfTelemetry } from "./connectionTelemetry";
|
|
17
|
+
import { PendingStateManager } from "./pendingStateManager";
|
|
18
18
|
import { pkgVersion } from "./packageVersion";
|
|
19
19
|
import { BlobManager } from "./blobManager";
|
|
20
20
|
import { DataStores, getSummaryForDatastores } from "./dataStores";
|
|
21
21
|
import { aliasBlobName, blobsTreeName, chunksBlobName, electedSummarizerBlobName, extractSummaryMetadataMessage, metadataBlobName, wrapSummaryInChannelsTree, } from "./summaryFormat";
|
|
22
22
|
import { SummaryCollection } from "./summaryCollection";
|
|
23
|
-
import { OrderedClientCollection, OrderedClientElection } from "./orderedClientElection";
|
|
23
|
+
import { OrderedClientCollection, OrderedClientElection, } from "./orderedClientElection";
|
|
24
24
|
import { SummarizerClientElection, summarizerClientType } from "./summarizerClientElection";
|
|
25
25
|
import { formExponentialFn, Throttler } from "./throttler";
|
|
26
26
|
import { RunWhileConnectedCoordinator } from "./runWhileConnectedCoordinator";
|
|
27
27
|
import { GarbageCollector, GCNodeType, } from "./garbageCollection";
|
|
28
|
-
import { channelToDataStore, isDataStoreAliasMessage
|
|
28
|
+
import { channelToDataStore, isDataStoreAliasMessage } from "./dataStore";
|
|
29
29
|
import { BindBatchTracker } from "./batchTracker";
|
|
30
|
-
import { SerializedSnapshotStorage } from "./serializedSnapshotStorage";
|
|
30
|
+
import { SerializedSnapshotStorage, } from "./serializedSnapshotStorage";
|
|
31
31
|
import { ScheduleManager } from "./scheduleManager";
|
|
32
32
|
import { OpCompressor, OpDecompressor, Outbox, OpSplitter, RemoteMessageProcessor, } from "./opLifecycle";
|
|
33
|
+
import { shouldAllowGcTombstoneEnforcement } from "./garbageCollectionHelpers";
|
|
34
|
+
import { gcTombstoneGenerationOptionName } from "./garbageCollectionConstants";
|
|
33
35
|
export var ContainerMessageType;
|
|
34
36
|
(function (ContainerMessageType) {
|
|
35
37
|
// An op to be delivered to store
|
|
@@ -134,8 +136,7 @@ export function getDeviceSpec() {
|
|
|
134
136
|
};
|
|
135
137
|
}
|
|
136
138
|
}
|
|
137
|
-
catch (_a) {
|
|
138
|
-
}
|
|
139
|
+
catch (_a) { }
|
|
139
140
|
return {};
|
|
140
141
|
}
|
|
141
142
|
/**
|
|
@@ -147,7 +148,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
147
148
|
* @internal
|
|
148
149
|
*/
|
|
149
150
|
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration) {
|
|
150
|
-
var _a, _b, _c, _d, _e, _f;
|
|
151
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
151
152
|
if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
|
|
152
153
|
super();
|
|
153
154
|
this.context = context;
|
|
@@ -230,28 +231,39 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
230
231
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
231
232
|
this.messageAtLastSummary = metadata === null || metadata === void 0 ? void 0 : metadata.message;
|
|
232
233
|
this._connected = this.context.connected;
|
|
234
|
+
this.gcTombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement((_c = metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix) === null || _c === void 0 ? void 0 : _c.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */);
|
|
233
235
|
this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
234
|
-
|
|
235
|
-
|
|
236
|
+
this.mc.logger.sendTelemetryEvent({
|
|
237
|
+
eventName: "GCFeatureMatrix",
|
|
238
|
+
metadataValue: JSON.stringify(metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix),
|
|
239
|
+
inputs: JSON.stringify({
|
|
240
|
+
gcOptions_gcTombstoneGeneration: this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName],
|
|
241
|
+
}),
|
|
242
|
+
});
|
|
243
|
+
const opSplitter = new OpSplitter(chunks, this.context.submitBatchFn, this.mc.config.getBoolean("Fluid.ContainerRuntime.DisableCompressionChunking") === true
|
|
244
|
+
? Number.POSITIVE_INFINITY
|
|
245
|
+
: runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
|
|
236
246
|
this.remoteMessageProcessor = new RemoteMessageProcessor(opSplitter, new OpDecompressor());
|
|
237
247
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
238
248
|
if (this.summaryConfiguration.state === "enabled") {
|
|
239
249
|
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
240
250
|
}
|
|
241
|
-
this.enableOpReentryCheck =
|
|
242
|
-
|
|
243
|
-
|
|
251
|
+
this.enableOpReentryCheck =
|
|
252
|
+
runtimeOptions.enableOpReentryCheck === true &&
|
|
253
|
+
// Allow for a break-glass config to override the options
|
|
254
|
+
this.mc.config.getBoolean("Fluid.ContainerRuntime.DisableOpReentryCheck") !== true;
|
|
244
255
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
245
256
|
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
246
257
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
247
258
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
248
259
|
this.maxConsecutiveReconnects =
|
|
249
|
-
(
|
|
260
|
+
(_d = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _d !== void 0 ? _d : this.defaultMaxConsecutiveReconnects;
|
|
250
261
|
this._flushMode = runtimeOptions.flushMode;
|
|
251
262
|
const pendingRuntimeState = context.pendingLocalState;
|
|
252
|
-
const baseSnapshot = (
|
|
253
|
-
const maxSnapshotCacheDurationMs = (
|
|
254
|
-
if (maxSnapshotCacheDurationMs !== undefined &&
|
|
263
|
+
const baseSnapshot = (_e = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _e !== void 0 ? _e : context.baseSnapshot;
|
|
264
|
+
const maxSnapshotCacheDurationMs = (_g = (_f = this._storage) === null || _f === void 0 ? void 0 : _f.policies) === null || _g === void 0 ? void 0 : _g.maximumCacheDurationMs;
|
|
265
|
+
if (maxSnapshotCacheDurationMs !== undefined &&
|
|
266
|
+
maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
|
|
255
267
|
// This is a runtime enforcement of what's already explicit in the policy's type itself,
|
|
256
268
|
// which dictates the value is either undefined or exactly 5 days in ms.
|
|
257
269
|
// As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
|
|
@@ -296,12 +308,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
296
308
|
if (baseSnapshot) {
|
|
297
309
|
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
298
310
|
}
|
|
299
|
-
this.dataStores = new DataStores(getSummaryForDatastores(baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getBaseGCDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getBaseGCDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getBaseGCDetails(), (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), new Map(dataStoreAliasMap));
|
|
311
|
+
this.dataStores = new DataStores(getSummaryForDatastores(baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getBaseGCDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getBaseGCDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getBaseGCDetails(), (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
|
|
300
312
|
this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
301
313
|
if (!this.disposed) {
|
|
302
|
-
this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
|
|
314
|
+
this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
|
|
315
|
+
localId,
|
|
316
|
+
blobId,
|
|
317
|
+
});
|
|
303
318
|
}
|
|
304
|
-
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (fromPath, toPath) => this.garbageCollector.addedOutboundReference(fromPath, toPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs, () => this.getCurrentReferenceTimestampMs());
|
|
319
|
+
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (fromPath, toPath) => this.garbageCollector.addedOutboundReference(fromPath, toPath), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs, () => this.getCurrentReferenceTimestampMs());
|
|
305
320
|
this.scheduleManager = new ScheduleManager(context.deltaManager, this, () => this.clientId, ChildLogger.create(this.logger, "ScheduleManager"));
|
|
306
321
|
this.pendingStateManager = new PendingStateManager({
|
|
307
322
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
@@ -312,11 +327,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
312
327
|
rollback: this.rollback.bind(this),
|
|
313
328
|
orderSequentially: this.orderSequentially.bind(this),
|
|
314
329
|
}, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending);
|
|
315
|
-
const compressionOptions = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisableCompression") === true
|
|
316
|
-
{
|
|
330
|
+
const compressionOptions = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisableCompression") === true
|
|
331
|
+
? {
|
|
317
332
|
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
318
|
-
compressionAlgorithm: CompressionAlgorithms.lz4
|
|
319
|
-
}
|
|
333
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
334
|
+
}
|
|
335
|
+
: runtimeOptions.compressionOptions;
|
|
320
336
|
this.outbox = new Outbox({
|
|
321
337
|
shouldSend: () => this.canSendOps(),
|
|
322
338
|
pendingStateManager: this.pendingStateManager,
|
|
@@ -334,8 +350,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
334
350
|
this.remoteMessageProcessor.clearPartialMessagesFor(clientId);
|
|
335
351
|
});
|
|
336
352
|
this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
|
|
337
|
-
this.dirtyContainer =
|
|
338
|
-
|
|
353
|
+
this.dirtyContainer =
|
|
354
|
+
this.context.attachState !== AttachState.Attached ||
|
|
355
|
+
this.pendingStateManager.hasPendingMessages();
|
|
339
356
|
this.context.updateDirtyContainerState(this.dirtyContainer);
|
|
340
357
|
if (this.summariesDisabled) {
|
|
341
358
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
@@ -403,8 +420,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
403
420
|
ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
404
421
|
BindBatchTracker(this, this.logger);
|
|
405
422
|
}
|
|
406
|
-
get IContainerRuntime() {
|
|
407
|
-
|
|
423
|
+
get IContainerRuntime() {
|
|
424
|
+
return this;
|
|
425
|
+
}
|
|
426
|
+
get IFluidRouter() {
|
|
427
|
+
return this;
|
|
428
|
+
}
|
|
408
429
|
/**
|
|
409
430
|
* @deprecated - use loadRuntime instead.
|
|
410
431
|
* Load the stores from a snapshot and returns the runtime.
|
|
@@ -445,7 +466,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
445
466
|
*/
|
|
446
467
|
static async loadRuntime(params) {
|
|
447
468
|
var _a, _b, _c, _d;
|
|
448
|
-
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime } = params;
|
|
469
|
+
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, } = params;
|
|
449
470
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
450
471
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
451
472
|
const backCompatContext = context;
|
|
@@ -457,13 +478,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
457
478
|
});
|
|
458
479
|
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, enableOfflineLoad = false, compressionOptions = {
|
|
459
480
|
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
460
|
-
compressionAlgorithm: CompressionAlgorithms.lz4
|
|
481
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
461
482
|
}, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, chunkSizeInBytes = Number.POSITIVE_INFINITY, enableOpReentryCheck = false, } = runtimeOptions;
|
|
462
483
|
const pendingRuntimeState = context.pendingLocalState;
|
|
463
484
|
const baseSnapshot = (_b = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _b !== void 0 ? _b : context.baseSnapshot;
|
|
464
|
-
const storage = !pendingRuntimeState
|
|
465
|
-
context.storage
|
|
466
|
-
new SerializedSnapshotStorage(() => {
|
|
485
|
+
const storage = !pendingRuntimeState
|
|
486
|
+
? context.storage
|
|
487
|
+
: new SerializedSnapshotStorage(() => {
|
|
488
|
+
return context.storage;
|
|
489
|
+
}, pendingRuntimeState.snapshotBlobs);
|
|
467
490
|
const registry = new FluidDataStoreRegistry(registryEntries);
|
|
468
491
|
const tryFetchBlob = async (blobName) => {
|
|
469
492
|
const blobId = baseSnapshot === null || baseSnapshot === void 0 ? void 0 : baseSnapshot.blobs[blobName];
|
|
@@ -494,7 +517,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
494
517
|
if (!pendingRuntimeState && runtimeSequenceNumber !== undefined) {
|
|
495
518
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
496
519
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
497
|
-
if (loadSequenceNumberVerification !== "bypass" &&
|
|
520
|
+
if (loadSequenceNumberVerification !== "bypass" &&
|
|
521
|
+
runtimeSequenceNumber !== protocolSequenceNumber) {
|
|
498
522
|
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
499
523
|
const error = new DataCorruptionError(
|
|
500
524
|
// pre-0.58 error message: SummaryMetadataMismatch
|
|
@@ -601,7 +625,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
601
625
|
var _a;
|
|
602
626
|
return (_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.electedClientId;
|
|
603
627
|
}
|
|
604
|
-
get disposed() {
|
|
628
|
+
get disposed() {
|
|
629
|
+
return this._disposed;
|
|
630
|
+
}
|
|
605
631
|
get summarizer() {
|
|
606
632
|
assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
607
633
|
return this._summarizer;
|
|
@@ -711,7 +737,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
711
737
|
status: 200,
|
|
712
738
|
mimeType: "fluid/object",
|
|
713
739
|
value: blob,
|
|
714
|
-
}
|
|
740
|
+
}
|
|
741
|
+
: create404Response(request);
|
|
715
742
|
}
|
|
716
743
|
else if (requestParser.pathParts.length > 0) {
|
|
717
744
|
const dataStore = await this.getDataStoreFromRequest(id, request);
|
|
@@ -754,7 +781,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
754
781
|
* This is a workaround to handle scenarios where a data store shared with an external app is deleted
|
|
755
782
|
* and marked as unreferenced by GC. Returning an error will fail to load the data store for the app.
|
|
756
783
|
*/
|
|
757
|
-
if (((_d = request.headers) === null || _d === void 0 ? void 0 : _d[RuntimeHeaders.externalRequest]) &&
|
|
784
|
+
if (((_d = request.headers) === null || _d === void 0 ? void 0 : _d[RuntimeHeaders.externalRequest]) &&
|
|
785
|
+
this.garbageCollector.shouldRunGC) {
|
|
758
786
|
// The data store is referenced if used routes in the base summary has a route to self.
|
|
759
787
|
// Older documents may not have used routes in the summary. They are considered referenced.
|
|
760
788
|
const usedRoutes = (await dataStoreContext.getBaseGCDetails()).usedRoutes;
|
|
@@ -928,7 +956,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
928
956
|
if (reconnection) {
|
|
929
957
|
this.consecutiveReconnects++;
|
|
930
958
|
if (!this.shouldContinueReconnecting()) {
|
|
931
|
-
this.closeFn(DataProcessingError.create("Runtime detected too many reconnects with no progress syncing local ops.
|
|
959
|
+
this.closeFn(DataProcessingError.create("Runtime detected too many reconnects with no progress syncing local ops.", "setConnectionState", undefined, {
|
|
932
960
|
dataLoss: 1,
|
|
933
961
|
attempts: this.consecutiveReconnects,
|
|
934
962
|
pendingMessages: this.pendingStateManager.pendingMessagesCount,
|
|
@@ -1035,7 +1063,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1035
1063
|
if (message.clientId === this.clientId && this.connected) {
|
|
1036
1064
|
// Check to see if the signal was lost.
|
|
1037
1065
|
if (this._perfSignalData.trackingSignalSequenceNumber !== undefined &&
|
|
1038
|
-
envelope.clientSignalSequenceNumber >
|
|
1066
|
+
envelope.clientSignalSequenceNumber >
|
|
1067
|
+
this._perfSignalData.trackingSignalSequenceNumber) {
|
|
1039
1068
|
this._perfSignalData.signalsLost++;
|
|
1040
1069
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
1041
1070
|
this.logger.sendErrorEvent({
|
|
@@ -1046,7 +1075,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1046
1075
|
clientSignalSequenceNumber: envelope.clientSignalSequenceNumber,
|
|
1047
1076
|
});
|
|
1048
1077
|
}
|
|
1049
|
-
else if (envelope.clientSignalSequenceNumber ===
|
|
1078
|
+
else if (envelope.clientSignalSequenceNumber ===
|
|
1079
|
+
this._perfSignalData.trackingSignalSequenceNumber) {
|
|
1050
1080
|
this.sendSignalTelemetryEvent(envelope.clientSignalSequenceNumber);
|
|
1051
1081
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
1052
1082
|
}
|
|
@@ -1133,7 +1163,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1133
1163
|
return this.dataStores.createDetachedDataStoreCore(pkg, false);
|
|
1134
1164
|
}
|
|
1135
1165
|
async _createDataStoreWithProps(pkg, props, id = uuid()) {
|
|
1136
|
-
const fluidDataStore = await this.dataStores
|
|
1166
|
+
const fluidDataStore = await this.dataStores
|
|
1167
|
+
._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
|
|
1168
|
+
.realize();
|
|
1137
1169
|
return channelToDataStore(fluidDataStore, id, this, this.dataStores, this.mc.logger);
|
|
1138
1170
|
}
|
|
1139
1171
|
async _createDataStore(pkg, id = uuid(), props) {
|
|
@@ -1270,7 +1302,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1270
1302
|
}
|
|
1271
1303
|
const telemetryContext = new TelemetryContext();
|
|
1272
1304
|
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
1273
|
-
this.logger.sendTelemetryEvent({
|
|
1305
|
+
this.logger.sendTelemetryEvent({
|
|
1306
|
+
eventName: "SummarizeTelemetry",
|
|
1307
|
+
details: telemetryContext.serialize(),
|
|
1308
|
+
});
|
|
1274
1309
|
assert(summary.type === SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1275
1310
|
return { stats, summary, gcStats };
|
|
1276
1311
|
}
|
|
@@ -1321,6 +1356,18 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1321
1356
|
this.blobManager.updateUnusedRoutes(blobManagerRoutes);
|
|
1322
1357
|
this.dataStores.updateUnusedRoutes(dataStoreRoutes);
|
|
1323
1358
|
}
|
|
1359
|
+
/**
|
|
1360
|
+
* This is called to delete objects from the runtime
|
|
1361
|
+
* @param unusedRoutes - object routes and sub routes that can be deleted
|
|
1362
|
+
* @returns - routes of objects deleted from the runtime
|
|
1363
|
+
*/
|
|
1364
|
+
deleteUnusedNodes(unusedRoutes) {
|
|
1365
|
+
const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
|
|
1366
|
+
const deletedRoutes = [];
|
|
1367
|
+
const deletedDataStoreRoutes = this.dataStores.deleteUnusedNodes(dataStoreRoutes);
|
|
1368
|
+
deletedRoutes.push(...deletedDataStoreRoutes);
|
|
1369
|
+
return deletedRoutes;
|
|
1370
|
+
}
|
|
1324
1371
|
/**
|
|
1325
1372
|
* This is called to update objects that are tombstones.
|
|
1326
1373
|
* @param tombstonedRoutes - Data store and attachment blob routes that are tombstones in this Container.
|
|
@@ -1436,8 +1483,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1436
1483
|
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
1437
1484
|
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
1438
1485
|
}
|
|
1486
|
+
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1439
1487
|
try {
|
|
1440
1488
|
await this.deltaManager.inbound.pause();
|
|
1489
|
+
if (shouldPauseInboundSignal) {
|
|
1490
|
+
await this.deltaManager.inboundSignal.pause();
|
|
1491
|
+
}
|
|
1441
1492
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
1442
1493
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1443
1494
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
@@ -1538,8 +1589,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1538
1589
|
// latestSnapshotVersionId from storage and it does not match with the lastAck ackHandle, then use
|
|
1539
1590
|
// the one fetched from storage as parent as that is the latest.
|
|
1540
1591
|
let summaryContext;
|
|
1541
|
-
if ((lastAck === null || lastAck === void 0 ? void 0 : lastAck.summaryAck.contents.handle) !== latestSnapshotVersionId
|
|
1542
|
-
|
|
1592
|
+
if ((lastAck === null || lastAck === void 0 ? void 0 : lastAck.summaryAck.contents.handle) !== latestSnapshotVersionId &&
|
|
1593
|
+
latestSnapshotVersionId !== undefined) {
|
|
1543
1594
|
summaryContext = {
|
|
1544
1595
|
proposalHandle: undefined,
|
|
1545
1596
|
ackHandle: latestSnapshotVersionId,
|
|
@@ -1596,6 +1647,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1596
1647
|
this.summarizerNode.clearSummary();
|
|
1597
1648
|
// Restart the delta manager
|
|
1598
1649
|
this.deltaManager.inbound.resume();
|
|
1650
|
+
if (shouldPauseInboundSignal) {
|
|
1651
|
+
this.deltaManager.inboundSignal.resume();
|
|
1652
|
+
}
|
|
1599
1653
|
}
|
|
1600
1654
|
}
|
|
1601
1655
|
hasPendingMessages() {
|
|
@@ -1644,7 +1698,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1644
1698
|
const deserializedContent = { type, contents };
|
|
1645
1699
|
const serializedContent = JSON.stringify(deserializedContent);
|
|
1646
1700
|
if (this.deltaManager.readOnlyInfo.readonly) {
|
|
1647
|
-
this.logger.sendTelemetryEvent({
|
|
1701
|
+
this.logger.sendTelemetryEvent({
|
|
1702
|
+
eventName: "SubmitOpInReadonly",
|
|
1703
|
+
connected: this.connected,
|
|
1704
|
+
});
|
|
1648
1705
|
}
|
|
1649
1706
|
const message = {
|
|
1650
1707
|
contents: serializedContent,
|
|
@@ -1674,7 +1731,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1674
1731
|
// issue than sending.
|
|
1675
1732
|
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
1676
1733
|
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
1677
|
-
if (this.currentlyBatching() &&
|
|
1734
|
+
if (this.currentlyBatching() &&
|
|
1735
|
+
type === ContainerMessageType.Attach &&
|
|
1678
1736
|
this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder") !== true) {
|
|
1679
1737
|
this.outbox.submitAttach(message);
|
|
1680
1738
|
}
|
|
@@ -1687,10 +1745,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1687
1745
|
else if (!this.flushMicroTaskExists) {
|
|
1688
1746
|
this.flushMicroTaskExists = true;
|
|
1689
1747
|
// Queue a microtask to detect the end of the turn and force a flush.
|
|
1690
|
-
Promise.resolve()
|
|
1748
|
+
Promise.resolve()
|
|
1749
|
+
.then(() => {
|
|
1691
1750
|
this.flushMicroTaskExists = false;
|
|
1692
1751
|
this.flush();
|
|
1693
|
-
})
|
|
1752
|
+
})
|
|
1753
|
+
.catch((error) => {
|
|
1754
|
+
this.closeFn(error);
|
|
1755
|
+
});
|
|
1694
1756
|
}
|
|
1695
1757
|
}
|
|
1696
1758
|
catch (error) {
|
|
@@ -1804,14 +1866,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1804
1866
|
// The call to fetch the snapshot is very expensive and not always needed.
|
|
1805
1867
|
// It should only be done by the summarizerNode, if required.
|
|
1806
1868
|
// When fetching from storage we will always get the latest version and do not use the ackHandle.
|
|
1807
|
-
const
|
|
1869
|
+
const fetchLatestSnapshot = async () => {
|
|
1808
1870
|
const fetchResult = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1809
|
-
eventName: "
|
|
1871
|
+
eventName: "RefreshLatestSummaryAckFetch",
|
|
1810
1872
|
ackHandle,
|
|
1811
|
-
summaryRefSeq,
|
|
1812
|
-
|
|
1813
|
-
});
|
|
1814
|
-
const latestSnapshotRefSeq = await seqFromTree(fetchResult.snapshotTree, readAndParseBlob);
|
|
1873
|
+
targetSequenceNumber: summaryRefSeq,
|
|
1874
|
+
}, readAndParseBlob);
|
|
1815
1875
|
/**
|
|
1816
1876
|
* If the fetched snapshot is older than the one for which the ack was received, close the container.
|
|
1817
1877
|
* This should never happen because an ack should be sent after the latest summary is updated in the server.
|
|
@@ -1822,29 +1882,26 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1822
1882
|
* such cases, the file will be rolled back along with the ack and we will eventually reach a consistent
|
|
1823
1883
|
* state.
|
|
1824
1884
|
*/
|
|
1825
|
-
if (latestSnapshotRefSeq < summaryRefSeq) {
|
|
1885
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
1826
1886
|
const error = DataProcessingError.create("Fetched snapshot is older than the received ack", "RefreshLatestSummaryAck", undefined /* sequencedMessage */, {
|
|
1827
1887
|
ackHandle,
|
|
1828
1888
|
summaryRefSeq,
|
|
1829
|
-
latestSnapshotRefSeq,
|
|
1889
|
+
latestSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
1830
1890
|
});
|
|
1831
1891
|
this.closeFn(error);
|
|
1832
1892
|
throw error;
|
|
1833
1893
|
}
|
|
1834
|
-
summaryLogger.sendTelemetryEvent({
|
|
1835
|
-
eventName: "LatestSummaryRetrieved",
|
|
1836
|
-
ackHandle,
|
|
1837
|
-
lastSequenceNumber: latestSnapshotRefSeq,
|
|
1838
|
-
targetSequenceNumber: summaryRefSeq,
|
|
1839
|
-
});
|
|
1840
1894
|
// In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
|
|
1841
1895
|
// wait for the delta manager to catch up before refreshing the latest Summary.
|
|
1842
|
-
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryLogger);
|
|
1843
|
-
return
|
|
1896
|
+
await this.waitForDeltaManagerToCatchup(fetchResult.latestSnapshotRefSeq, summaryLogger);
|
|
1897
|
+
return {
|
|
1898
|
+
snapshotTree: fetchResult.snapshotTree,
|
|
1899
|
+
snapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
1900
|
+
};
|
|
1844
1901
|
};
|
|
1845
|
-
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq,
|
|
1902
|
+
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq, fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
1846
1903
|
// Notify the garbage collector so it can update its latest summary state.
|
|
1847
|
-
await this.garbageCollector.refreshLatestSummary(
|
|
1904
|
+
await this.garbageCollector.refreshLatestSummary(proposalHandle, result, readAndParseBlob);
|
|
1848
1905
|
}
|
|
1849
1906
|
/**
|
|
1850
1907
|
* Fetches the latest snapshot from storage and uses it to refresh SummarizerNode's
|
|
@@ -1853,18 +1910,20 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1853
1910
|
* @returns downloaded snapshot's reference sequence number
|
|
1854
1911
|
*/
|
|
1855
1912
|
async refreshLatestSummaryAckFromServer(summaryLogger) {
|
|
1856
|
-
const { snapshotTree, versionId } = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1857
|
-
eventName: "RefreshLatestSummaryGetSnapshot",
|
|
1858
|
-
fetchLatest: true,
|
|
1859
|
-
});
|
|
1860
1913
|
const readAndParseBlob = async (id) => readAndParse(this.storage, id);
|
|
1861
|
-
const latestSnapshotRefSeq = await
|
|
1862
|
-
|
|
1914
|
+
const { snapshotTree, versionId, latestSnapshotRefSeq } = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1915
|
+
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
1916
|
+
}, readAndParseBlob);
|
|
1917
|
+
const fetchLatestSnapshot = {
|
|
1918
|
+
snapshotTree,
|
|
1919
|
+
snapshotRefSeq: latestSnapshotRefSeq,
|
|
1920
|
+
};
|
|
1921
|
+
const result = await this.summarizerNode.refreshLatestSummary(undefined /* proposalHandle */, latestSnapshotRefSeq, async () => fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
1863
1922
|
// Notify the garbage collector so it can update its latest summary state.
|
|
1864
|
-
await this.garbageCollector.refreshLatestSummary(
|
|
1923
|
+
await this.garbageCollector.refreshLatestSummary(undefined /* proposalHandle */, result, readAndParseBlob);
|
|
1865
1924
|
return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
|
|
1866
1925
|
}
|
|
1867
|
-
async fetchLatestSnapshotFromStorage(logger, event) {
|
|
1926
|
+
async fetchLatestSnapshotFromStorage(logger, event, readAndParseBlob) {
|
|
1868
1927
|
return PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
1869
1928
|
const stats = {};
|
|
1870
1929
|
const trace = Trace.start();
|
|
@@ -1874,20 +1933,29 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1874
1933
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
1875
1934
|
assert(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
|
|
1876
1935
|
stats.getSnapshotDuration = trace.trace().duration;
|
|
1936
|
+
const latestSnapshotRefSeq = await seqFromTree(maybeSnapshot, readAndParseBlob);
|
|
1937
|
+
stats.snapshotRefSeq = latestSnapshotRefSeq;
|
|
1938
|
+
stats.snapshotVersion = versions[0].id;
|
|
1877
1939
|
perfEvent.end(stats);
|
|
1878
|
-
return {
|
|
1940
|
+
return {
|
|
1941
|
+
snapshotTree: maybeSnapshot,
|
|
1942
|
+
versionId: versions[0].id,
|
|
1943
|
+
latestSnapshotRefSeq,
|
|
1944
|
+
};
|
|
1879
1945
|
});
|
|
1880
1946
|
}
|
|
1881
1947
|
notifyAttaching(snapshot) {
|
|
1882
1948
|
var _a;
|
|
1883
1949
|
if ((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) {
|
|
1884
|
-
this.baseSnapshotBlobs =
|
|
1950
|
+
this.baseSnapshotBlobs =
|
|
1951
|
+
SerializedSnapshotStorage.serializeTreeWithBlobContents(snapshot);
|
|
1885
1952
|
}
|
|
1886
1953
|
}
|
|
1887
1954
|
async initializeBaseSnapshotBlobs() {
|
|
1888
1955
|
var _a;
|
|
1889
1956
|
if (!((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) ||
|
|
1890
|
-
this.attachState !== AttachState.Attached ||
|
|
1957
|
+
this.attachState !== AttachState.Attached ||
|
|
1958
|
+
this.context.pendingLocalState) {
|
|
1891
1959
|
return;
|
|
1892
1960
|
}
|
|
1893
1961
|
assert(!!this.context.baseSnapshot, 0x2e5 /* "Must have a base snapshot" */);
|