@fluidframework/container-runtime 2.33.0-333010 → 2.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/api-report/container-runtime.legacy.alpha.api.md +71 -67
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts +7 -4
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +38 -12
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +4 -0
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +24 -0
- package/dist/channelCollection.js.map +1 -1
- package/dist/compatUtils.d.ts +74 -0
- package/dist/compatUtils.d.ts.map +1 -0
- package/dist/compatUtils.js +151 -0
- package/dist/compatUtils.js.map +1 -0
- package/dist/compressionDefinitions.d.ts +39 -0
- package/dist/compressionDefinitions.d.ts.map +1 -0
- package/dist/compressionDefinitions.js +30 -0
- package/dist/compressionDefinitions.js.map +1 -0
- package/dist/containerRuntime.d.ts +78 -52
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +141 -54
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +3 -0
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +122 -66
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/deltaManagerProxies.d.ts +55 -12
- package/dist/deltaManagerProxies.d.ts.map +1 -1
- package/dist/deltaManagerProxies.js +63 -55
- package/dist/deltaManagerProxies.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +2 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +1 -0
- package/dist/opLifecycle/batchManager.d.ts +1 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +4 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +35 -4
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.js +2 -2
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +3 -3
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +2 -2
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +1 -2
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSerialization.d.ts +3 -1
- package/dist/opLifecycle/opSerialization.d.ts.map +1 -1
- package/dist/opLifecycle/opSerialization.js +4 -2
- package/dist/opLifecycle/opSerialization.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +6 -3
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +46 -20
- package/dist/opLifecycle/outbox.js.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.d.ts +36 -7
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +83 -16
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runtimeLayerCompatState.d.ts.map +1 -1
- package/dist/runtimeLayerCompatState.js +1 -1
- package/dist/runtimeLayerCompatState.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +1 -0
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +2 -0
- package/dist/summary/documentSchema.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +7 -4
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +38 -12
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +4 -0
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +24 -0
- package/lib/channelCollection.js.map +1 -1
- package/lib/compatUtils.d.ts +74 -0
- package/lib/compatUtils.d.ts.map +1 -0
- package/lib/compatUtils.js +142 -0
- package/lib/compatUtils.js.map +1 -0
- package/lib/compressionDefinitions.d.ts +39 -0
- package/lib/compressionDefinitions.d.ts.map +1 -0
- package/lib/compressionDefinitions.js +27 -0
- package/lib/compressionDefinitions.js.map +1 -0
- package/lib/containerRuntime.d.ts +78 -52
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +143 -56
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +3 -0
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +57 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/deltaManagerProxies.d.ts +55 -12
- package/lib/deltaManagerProxies.d.ts.map +1 -1
- package/lib/deltaManagerProxies.js +63 -55
- package/lib/deltaManagerProxies.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +2 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/index.d.ts +4 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +1 -0
- package/lib/opLifecycle/batchManager.d.ts +1 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +4 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +35 -4
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.js +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +1 -1
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +2 -2
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +1 -2
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSerialization.d.ts +3 -1
- package/lib/opLifecycle/opSerialization.d.ts.map +1 -1
- package/lib/opLifecycle/opSerialization.js +4 -2
- package/lib/opLifecycle/opSerialization.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +6 -3
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +46 -20
- package/lib/opLifecycle/outbox.js.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.d.ts +36 -7
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +84 -17
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runtimeLayerCompatState.d.ts.map +1 -1
- package/lib/runtimeLayerCompatState.js +2 -2
- package/lib/runtimeLayerCompatState.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +1 -0
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +2 -0
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +21 -20
- package/src/blobManager/blobManager.ts +48 -15
- package/src/channelCollection.ts +27 -0
- package/src/compatUtils.ts +211 -0
- package/src/compressionDefinitions.ts +47 -0
- package/src/containerRuntime.ts +259 -108
- package/src/dataStoreContext.ts +82 -2
- package/src/deltaManagerProxies.ts +132 -70
- package/src/gc/gcDefinitions.ts +2 -0
- package/src/index.ts +5 -3
- package/src/opLifecycle/batchManager.ts +5 -4
- package/src/opLifecycle/definitions.ts +34 -4
- package/src/opLifecycle/index.ts +1 -0
- package/src/opLifecycle/opCompressor.ts +1 -1
- package/src/opLifecycle/opDecompressor.ts +1 -1
- package/src/opLifecycle/opGroupingManager.ts +7 -5
- package/src/opLifecycle/opSerialization.ts +6 -2
- package/src/opLifecycle/outbox.ts +65 -30
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +135 -21
- package/src/runtimeLayerCompatState.ts +5 -2
- package/src/summary/documentSchema.ts +3 -0
package/dist/containerRuntime.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.createNewSignalEnvelope = exports.ContainerRuntime = exports.loadContainerRuntime = exports.getSingleUseLegacyLogCallback = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isUnpackedRuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.
|
|
7
|
+
exports.createNewSignalEnvelope = exports.ContainerRuntime = exports.loadContainerRuntime = exports.getSingleUseLegacyLogCallback = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isUnpackedRuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.DeletedResponseHeaderKey = void 0;
|
|
8
8
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
9
9
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
10
10
|
const internal_1 = require("@fluidframework/container-definitions/internal");
|
|
@@ -19,6 +19,8 @@ const uuid_1 = require("uuid");
|
|
|
19
19
|
const batchTracker_js_1 = require("./batchTracker.js");
|
|
20
20
|
const index_js_1 = require("./blobManager/index.js");
|
|
21
21
|
const channelCollection_js_1 = require("./channelCollection.js");
|
|
22
|
+
const compatUtils_js_1 = require("./compatUtils.js");
|
|
23
|
+
const compressionDefinitions_js_1 = require("./compressionDefinitions.js");
|
|
22
24
|
const connectionTelemetry_js_1 = require("./connectionTelemetry.js");
|
|
23
25
|
const containerHandleContext_js_1 = require("./containerHandleContext.js");
|
|
24
26
|
const dataStore_js_1 = require("./dataStore.js");
|
|
@@ -83,35 +85,12 @@ exports.defaultRuntimeHeaderData = {
|
|
|
83
85
|
viaHandle: false,
|
|
84
86
|
allowTombstone: false,
|
|
85
87
|
};
|
|
86
|
-
/**
|
|
87
|
-
* Available compression algorithms for op compression.
|
|
88
|
-
* @legacy
|
|
89
|
-
* @alpha
|
|
90
|
-
*/
|
|
91
|
-
var CompressionAlgorithms;
|
|
92
|
-
(function (CompressionAlgorithms) {
|
|
93
|
-
CompressionAlgorithms["lz4"] = "lz4";
|
|
94
|
-
})(CompressionAlgorithms || (exports.CompressionAlgorithms = CompressionAlgorithms = {}));
|
|
95
|
-
/**
|
|
96
|
-
* @legacy
|
|
97
|
-
* @alpha
|
|
98
|
-
*/
|
|
99
|
-
exports.disabledCompressionConfig = {
|
|
100
|
-
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
101
|
-
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
102
|
-
};
|
|
103
88
|
const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
|
|
104
|
-
const defaultFlushMode = internal_5.FlushMode.TurnBased;
|
|
105
89
|
// The actual limit is 1Mb (socket.io and Kafka limits)
|
|
106
90
|
// We can't estimate it fully, as we
|
|
107
91
|
// - do not know what properties relay service will add
|
|
108
92
|
// - we do not stringify final op, thus we do not know how much escaping will be added.
|
|
109
93
|
const defaultMaxBatchSizeInBytes = 700 * 1024;
|
|
110
|
-
const defaultCompressionConfig = {
|
|
111
|
-
// Batches with content size exceeding this value will be compressed
|
|
112
|
-
minimumBatchSizeInBytes: 614400,
|
|
113
|
-
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
114
|
-
};
|
|
115
94
|
const defaultChunkSizeInBytes = 204800;
|
|
116
95
|
/**
|
|
117
96
|
* The default time to wait for pending ops to be processed during summarization
|
|
@@ -255,9 +234,42 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
255
234
|
},
|
|
256
235
|
});
|
|
257
236
|
const mc = (0, internal_7.loggerToMonitoringContext)(logger);
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
237
|
+
// Some options require a minimum version of the FF runtime to operate, so the default configs will be generated
|
|
238
|
+
// based on the compatibility mode.
|
|
239
|
+
// For example, if compatibility mode is set to "1.0.0", the default configs will ensure compatibility with FF runtime
|
|
240
|
+
// 1.0.0 or later. If the compatibility mode is set to "2.10.0", the default values will be generated to ensure compatibility
|
|
241
|
+
// with FF runtime 2.10.0 or later.
|
|
242
|
+
// TODO: We will add in a way for users to pass in compatibilityVersion in a follow up PR.
|
|
243
|
+
const compatibilityVersion = compatUtils_js_1.defaultCompatibilityVersion;
|
|
244
|
+
if (!(0, compatUtils_js_1.isValidCompatVersion)(compatibilityVersion)) {
|
|
245
|
+
throw new internal_7.UsageError(`Invalid compatibility version: ${compatibilityVersion}. It must be an existing FF version (i.e. 2.22.1).`);
|
|
246
|
+
}
|
|
247
|
+
const defaultVersionDependentConfigs = (0, compatUtils_js_1.getCompatibilityVersionDefaults)(compatibilityVersion);
|
|
248
|
+
// The following are the default values for the options that do not affect the DocumentSchema.
|
|
249
|
+
const defaultConfigsNonVersionDependent = {
|
|
250
|
+
summaryOptions: {},
|
|
251
|
+
loadSequenceNumberVerification: "close",
|
|
252
|
+
maxBatchSizeInBytes: defaultMaxBatchSizeInBytes,
|
|
253
|
+
chunkSizeInBytes: defaultChunkSizeInBytes,
|
|
254
|
+
};
|
|
255
|
+
const defaultConfigs = {
|
|
256
|
+
...defaultVersionDependentConfigs,
|
|
257
|
+
...defaultConfigsNonVersionDependent,
|
|
258
|
+
};
|
|
259
|
+
// Here we set each option to its corresponding default config value if it's not provided in runtimeOptions.
|
|
260
|
+
// Note: We cannot do a simple object merge of defaultConfigs/runtimeOptions because in most cases we don't want
|
|
261
|
+
// a option that is undefined in runtimeOptions to override the default value (except for idCompressor, see below).
|
|
262
|
+
const { summaryOptions = defaultConfigs.summaryOptions, gcOptions = defaultConfigs.gcOptions, loadSequenceNumberVerification = defaultConfigs.loadSequenceNumberVerification, maxBatchSizeInBytes = defaultConfigs.maxBatchSizeInBytes, chunkSizeInBytes = defaultConfigs.chunkSizeInBytes, explicitSchemaControl = defaultConfigs.explicitSchemaControl, enableGroupedBatching = defaultConfigs.enableGroupedBatching, flushMode = defaultConfigs.flushMode,
|
|
263
|
+
// If batching is disabled then we should disable compression as well. If batching is disabled and compression
|
|
264
|
+
// is enabled via runtimeOptions, we will throw an error later.
|
|
265
|
+
compressionOptions = enableGroupedBatching === false
|
|
266
|
+
? compressionDefinitions_js_1.disabledCompressionConfig
|
|
267
|
+
: defaultConfigs.compressionOptions, createBlobPayloadPending = defaultConfigs.createBlobPayloadPending, } = runtimeOptions;
|
|
268
|
+
// The logic for enableRuntimeIdCompressor is a bit different. Since `undefined` represents a logical state (off)
|
|
269
|
+
// we need to check it's explicitly set in runtimeOptions. If so, we should use that value even if it's undefined.
|
|
270
|
+
const enableRuntimeIdCompressor = "enableRuntimeIdCompressor" in runtimeOptions
|
|
271
|
+
? runtimeOptions.enableRuntimeIdCompressor
|
|
272
|
+
: defaultConfigs.enableRuntimeIdCompressor;
|
|
261
273
|
const registry = new dataStoreRegistry_js_1.FluidDataStoreRegistry(registryEntries);
|
|
262
274
|
const tryFetchBlob = async (blobName) => {
|
|
263
275
|
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
@@ -386,6 +398,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
386
398
|
compressionLz4,
|
|
387
399
|
idCompressorMode,
|
|
388
400
|
opGroupingEnabled: enableGroupedBatching,
|
|
401
|
+
createBlobPayloadPending,
|
|
389
402
|
disallowedVersions: [],
|
|
390
403
|
}, (schema) => {
|
|
391
404
|
runtime.onSchemaChange(schema);
|
|
@@ -403,10 +416,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
403
416
|
compressionOptions,
|
|
404
417
|
maxBatchSizeInBytes,
|
|
405
418
|
chunkSizeInBytes,
|
|
406
|
-
|
|
407
|
-
enableRuntimeIdCompressor: enableRuntimeIdCompressor,
|
|
419
|
+
enableRuntimeIdCompressor,
|
|
408
420
|
enableGroupedBatching,
|
|
409
421
|
explicitSchemaControl,
|
|
422
|
+
createBlobPayloadPending,
|
|
410
423
|
};
|
|
411
424
|
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], internalRuntimeOptions, containerScope, logger, existing, blobManagerLoadInfo, context.storage, createIdCompressorFn, documentSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler, undefined, // summaryConfiguration
|
|
412
425
|
recentBatchInfo);
|
|
@@ -556,6 +569,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
556
569
|
this.requestHandler = requestHandler;
|
|
557
570
|
this.summaryConfiguration = summaryConfiguration;
|
|
558
571
|
this.imminentClosure = false;
|
|
572
|
+
this.isReadOnly = () => this.deltaManager.readOnlyInfo.readonly === true;
|
|
559
573
|
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
560
574
|
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
561
575
|
this.pendingIdCompressorOps = [];
|
|
@@ -573,6 +587,51 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
573
587
|
this.snapshotCacheForLoadingGroupIds = new internal_2.PromiseCache({
|
|
574
588
|
expiry: { policy: "absolute", durationMs: 60000 },
|
|
575
589
|
});
|
|
590
|
+
this.notifyReadOnlyState = (readonly) => this.channelCollection.notifyReadOnlyState(readonly);
|
|
591
|
+
/**
|
|
592
|
+
* Enter Staging Mode, such that ops submitted to the ContainerRuntime will not be sent to the ordering service.
|
|
593
|
+
* To exit Staging Mode, call either discardChanges or commitChanges on the Stage Controls returned from this method.
|
|
594
|
+
*
|
|
595
|
+
* @returns StageControlsExperimental - Controls for exiting Staging Mode.
|
|
596
|
+
*/
|
|
597
|
+
// eslint-disable-next-line import/no-deprecated
|
|
598
|
+
this.enterStagingMode = () => {
|
|
599
|
+
if (this.stageControls !== undefined) {
|
|
600
|
+
throw new Error("already in staging mode");
|
|
601
|
+
}
|
|
602
|
+
// Make sure all BatchManagers are empty before entering staging mode,
|
|
603
|
+
// since we mark whole batches as "staged" or not to indicate whether to submit them.
|
|
604
|
+
this.outbox.flush();
|
|
605
|
+
const exitStagingMode = (discardOrCommit) => () => {
|
|
606
|
+
// Final flush of any last staged changes
|
|
607
|
+
this.outbox.flush(undefined, true /* staged */);
|
|
608
|
+
this.stageControls = undefined;
|
|
609
|
+
discardOrCommit();
|
|
610
|
+
};
|
|
611
|
+
const stageControls = {
|
|
612
|
+
discardChanges: exitStagingMode(() => {
|
|
613
|
+
// Pop all staged batches from the PSM and roll them back in LIFO order
|
|
614
|
+
this.pendingStateManager.popStagedBatches(({ runtimeOp, localOpMetadata }) => {
|
|
615
|
+
(0, internal_2.assert)(runtimeOp !== undefined, 0xb82 /* Staged batches expected to have runtimeOp defined */);
|
|
616
|
+
this.rollback(runtimeOp, localOpMetadata);
|
|
617
|
+
});
|
|
618
|
+
if (this.attachState === container_definitions_1.AttachState.Attached) {
|
|
619
|
+
this.updateDocumentDirtyState(this.pendingMessagesCount !== 0);
|
|
620
|
+
}
|
|
621
|
+
}),
|
|
622
|
+
commitChanges: exitStagingMode(() => {
|
|
623
|
+
// All staged changes are in the PSM, so just replay them (ignore pre-staging batches)
|
|
624
|
+
// FUTURE: Have this do squash-rebase instead of resubmitting all intermediate changes
|
|
625
|
+
if (this.connected) {
|
|
626
|
+
this.pendingStateManager.replayPendingStates(true /* onlyStagedBatched */);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
this.pendingStateManager.clearStagingFlags();
|
|
630
|
+
}
|
|
631
|
+
}),
|
|
632
|
+
};
|
|
633
|
+
return (this.stageControls = stageControls);
|
|
634
|
+
};
|
|
576
635
|
this.readAndParseBlob = async (id) => (0, internal_4.readAndParse)(this.storage, id);
|
|
577
636
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, pendingLocalState, supportedFeatures, snapshotWithContents, } = context;
|
|
578
637
|
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
@@ -592,7 +651,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
592
651
|
minimumBatchSizeInBytes: this.sessionSchema.compressionLz4
|
|
593
652
|
? runtimeOptions.compressionOptions.minimumBatchSizeInBytes
|
|
594
653
|
: Number.POSITIVE_INFINITY,
|
|
595
|
-
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
654
|
+
compressionAlgorithm: compressionDefinitions_js_1.CompressionAlgorithms.lz4,
|
|
596
655
|
};
|
|
597
656
|
(0, internal_2.assert)((0, internal_1.isIDeltaManagerFull)(deltaManager), 0xa80 /* Invalid delta manager */);
|
|
598
657
|
this.innerDeltaManager = deltaManager;
|
|
@@ -692,19 +751,22 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
692
751
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
693
752
|
isAttached: () => this.attachState !== container_definitions_1.AttachState.Detached,
|
|
694
753
|
}, pendingRuntimeState?.pending, this.baseLogger);
|
|
695
|
-
let outerDeltaManager;
|
|
754
|
+
let outerDeltaManager = this.innerDeltaManager;
|
|
696
755
|
this.useDeltaManagerOpsProxy =
|
|
697
756
|
this.mc.config.getBoolean("Fluid.ContainerRuntime.DeltaManagerOpsProxy") === true;
|
|
698
757
|
// The summarizerDeltaManager Proxy is used to lie to the summarizer to convince it is in the right state as a summarizer client.
|
|
699
|
-
|
|
700
|
-
outerDeltaManager = summarizerDeltaManagerProxy;
|
|
758
|
+
outerDeltaManager = deltaManagerProxies_js_1.DeltaManagerSummarizerProxy.wrapIfSummarizer(outerDeltaManager);
|
|
701
759
|
// The DeltaManagerPendingOpsProxy is used to control the minimum sequence number
|
|
702
760
|
// It allows us to lie to the layers below so that they can maintain enough local state for rebasing ops.
|
|
703
761
|
if (this.useDeltaManagerOpsProxy) {
|
|
704
|
-
const pendingOpsDeltaManagerProxy = new deltaManagerProxies_js_1.DeltaManagerPendingOpsProxy(
|
|
762
|
+
const pendingOpsDeltaManagerProxy = new deltaManagerProxies_js_1.DeltaManagerPendingOpsProxy(outerDeltaManager, this.pendingStateManager);
|
|
705
763
|
outerDeltaManager = pendingOpsDeltaManagerProxy;
|
|
706
764
|
}
|
|
707
|
-
|
|
765
|
+
// always wrap the exposed delta manager in at least on layer of proxying
|
|
766
|
+
this._deltaManager =
|
|
767
|
+
outerDeltaManager instanceof deltaManagerProxies_js_1.BaseDeltaManagerProxy
|
|
768
|
+
? outerDeltaManager
|
|
769
|
+
: new deltaManagerProxies_js_1.BaseDeltaManagerProxy(outerDeltaManager);
|
|
708
770
|
this.handleContext = new containerHandleContext_js_1.ContainerFluidHandleContext("", this);
|
|
709
771
|
if (this.summaryConfiguration.state === "enabled") {
|
|
710
772
|
(0, index_js_4.validateSummaryHeuristicConfiguration)(this.summaryConfiguration);
|
|
@@ -815,6 +877,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
815
877
|
...props,
|
|
816
878
|
timestampMs: props.timestampMs ?? this.getCurrentReferenceTimestampMs(),
|
|
817
879
|
}), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap), async (runtime) => provideEntryPoint);
|
|
880
|
+
this._deltaManager.on("readonly", this.notifyReadOnlyState);
|
|
818
881
|
this.blobManager = new index_js_1.BlobManager({
|
|
819
882
|
routeContext: this.handleContext,
|
|
820
883
|
blobManagerLoadInfo,
|
|
@@ -835,6 +898,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
835
898
|
isBlobDeleted: (blobPath) => this.garbageCollector.isNodeDeleted(blobPath),
|
|
836
899
|
runtime: this,
|
|
837
900
|
stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
|
|
901
|
+
createBlobPayloadPending: this.sessionSchema.createBlobPayloadPending === true,
|
|
838
902
|
});
|
|
839
903
|
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0, internal_7.createChildLogger)({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
|
|
840
904
|
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0, internal_7.createChildLogger)({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
|
|
@@ -1086,6 +1150,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1086
1150
|
this.pendingStateManager.dispose();
|
|
1087
1151
|
this.inboundBatchAggregator.dispose();
|
|
1088
1152
|
this.deltaScheduler.dispose();
|
|
1153
|
+
this._deltaManager.dispose();
|
|
1089
1154
|
this.emit("dispose");
|
|
1090
1155
|
this.removeAllListeners();
|
|
1091
1156
|
}
|
|
@@ -1231,7 +1296,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1231
1296
|
return this.resolveHandle(requestParser.createSubRequest(1));
|
|
1232
1297
|
}
|
|
1233
1298
|
if (id === index_js_1.blobManagerBasePath && requestParser.isLeaf(2)) {
|
|
1234
|
-
const
|
|
1299
|
+
const localId = requestParser.pathParts[1];
|
|
1300
|
+
const payloadPending = requestParser.headers?.[internal_6.RuntimeHeaders.payloadPending] === true;
|
|
1301
|
+
if (!this.blobManager.hasBlob(localId) &&
|
|
1302
|
+
requestParser.headers?.[internal_6.RuntimeHeaders.wait] === false) {
|
|
1303
|
+
return (0, internal_6.create404Response)(request);
|
|
1304
|
+
}
|
|
1305
|
+
const blob = await this.blobManager.getBlob(localId, payloadPending);
|
|
1235
1306
|
return {
|
|
1236
1307
|
status: 200,
|
|
1237
1308
|
mimeType: "fluid/object",
|
|
@@ -1871,11 +1942,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1871
1942
|
*
|
|
1872
1943
|
* @param resubmittingBatchId - If defined, indicates this is a resubmission of a batch
|
|
1873
1944
|
* with the given Batch ID, which must be preserved
|
|
1945
|
+
* @param resubmittingStagedBatch - If defined, indicates this is a resubmission of a batch that is staged,
|
|
1946
|
+
* meaning it should not be sent to the ordering service yet.
|
|
1874
1947
|
*/
|
|
1875
|
-
flush(resubmittingBatchId) {
|
|
1948
|
+
flush(resubmittingBatchId, resubmittingStagedBatch) {
|
|
1876
1949
|
try {
|
|
1877
1950
|
(0, internal_2.assert)(!this.batchRunner.running, 0x24c /* "Cannot call `flush()` while manually accumulating a batch (e.g. under orderSequentially) */);
|
|
1878
|
-
this.outbox.flush(resubmittingBatchId);
|
|
1951
|
+
this.outbox.flush(resubmittingBatchId, resubmittingStagedBatch);
|
|
1879
1952
|
(0, internal_2.assert)(this.outbox.isEmpty, 0x3cf /* reentrancy */);
|
|
1880
1953
|
}
|
|
1881
1954
|
catch (error) {
|
|
@@ -1894,7 +1967,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1894
1967
|
orderSequentially(callback) {
|
|
1895
1968
|
let checkpoint;
|
|
1896
1969
|
const checkpointDirtyState = this.dirtyContainer;
|
|
1970
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1971
|
+
let stageControls;
|
|
1897
1972
|
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.EnableRollback")) {
|
|
1973
|
+
if (!this.batchRunner.running && !this.inStagingMode) {
|
|
1974
|
+
stageControls = this.enterStagingMode();
|
|
1975
|
+
}
|
|
1898
1976
|
// Note: we are not touching any batches other than mainBatch here, for two reasons:
|
|
1899
1977
|
// 1. It would not help, as other batches are flushed independently from main batch.
|
|
1900
1978
|
// 2. There is no way to undo process of data store creation, blob creation, ID compressor ops, or other things tracked by other batches.
|
|
@@ -1908,11 +1986,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1908
1986
|
if (checkpoint) {
|
|
1909
1987
|
// This will throw and close the container if rollback fails
|
|
1910
1988
|
try {
|
|
1911
|
-
checkpoint.rollback((message) => this.rollback(message.
|
|
1989
|
+
checkpoint.rollback((message) => this.rollback(message.runtimeOp, message.localOpMetadata));
|
|
1912
1990
|
// reset the dirty state after rollback to what it was before to keep it consistent
|
|
1913
1991
|
if (this.dirtyContainer !== checkpointDirtyState) {
|
|
1914
1992
|
this.updateDocumentDirtyState(checkpointDirtyState);
|
|
1915
1993
|
}
|
|
1994
|
+
stageControls?.discardChanges();
|
|
1995
|
+
stageControls = undefined;
|
|
1916
1996
|
}
|
|
1917
1997
|
catch (error_) {
|
|
1918
1998
|
const error2 = (0, internal_7.wrapError)(error_, (message) => {
|
|
@@ -1930,12 +2010,21 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1930
2010
|
throw error; // throw the original error for the consumer of the runtime
|
|
1931
2011
|
}
|
|
1932
2012
|
});
|
|
2013
|
+
stageControls?.commitChanges();
|
|
1933
2014
|
// We don't flush on TurnBased since we expect all messages in the same JS turn to be part of the same batch
|
|
1934
2015
|
if (this.flushMode !== internal_5.FlushMode.TurnBased && !this.batchRunner.running) {
|
|
1935
2016
|
this.flush();
|
|
1936
2017
|
}
|
|
1937
2018
|
return result;
|
|
1938
2019
|
}
|
|
2020
|
+
/**
|
|
2021
|
+
* If true, the ContainerRuntime is not submitting any new ops to the ordering service.
|
|
2022
|
+
* Ops submitted to the ContainerRuntime while in Staging Mode will be queued in the PendingStateManager,
|
|
2023
|
+
* either to be discarded or committed later (via the Stage Controls returned from enterStagingMode).
|
|
2024
|
+
*/
|
|
2025
|
+
get inStagingMode() {
|
|
2026
|
+
return this.stageControls !== undefined;
|
|
2027
|
+
}
|
|
1939
2028
|
/**
|
|
1940
2029
|
* Returns the aliased data store's entryPoint, given the alias.
|
|
1941
2030
|
* @param alias - The alias for the data store.
|
|
@@ -2668,8 +2757,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2668
2757
|
contents: idRange,
|
|
2669
2758
|
};
|
|
2670
2759
|
const idAllocationBatchMessage = {
|
|
2671
|
-
|
|
2760
|
+
runtimeOp: idAllocationMessage,
|
|
2672
2761
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2762
|
+
// Note: For now, we will never stage ID Allocation messages.
|
|
2763
|
+
// They won't contain personal info and no harm in extra allocations in case of discarding the staged changes
|
|
2764
|
+
staged: false,
|
|
2673
2765
|
};
|
|
2674
2766
|
this.outbox.submitIdAllocation(idAllocationBatchMessage);
|
|
2675
2767
|
}
|
|
@@ -2711,17 +2803,19 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2711
2803
|
contents: schemaChangeMessage,
|
|
2712
2804
|
};
|
|
2713
2805
|
this.outbox.submit({
|
|
2714
|
-
|
|
2806
|
+
runtimeOp: msg,
|
|
2715
2807
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2808
|
+
staged: this.inStagingMode,
|
|
2716
2809
|
});
|
|
2717
2810
|
}
|
|
2718
2811
|
const message = {
|
|
2719
2812
|
// This will encode any handles present in this op before serializing to string
|
|
2720
2813
|
// Note: handles may already have been encoded by the DDS layer, but encoding handles is idempotent so there's no problem.
|
|
2721
|
-
|
|
2814
|
+
runtimeOp: containerRuntimeMessage,
|
|
2722
2815
|
metadata,
|
|
2723
2816
|
localOpMetadata,
|
|
2724
2817
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2818
|
+
staged: this.inStagingMode,
|
|
2725
2819
|
};
|
|
2726
2820
|
if (type === messageTypes_js_1.ContainerMessageType.BlobAttach) {
|
|
2727
2821
|
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
@@ -2805,7 +2899,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2805
2899
|
* @remarks - If the "Offline Load" feature is enabled, the batchId is included in the resubmitted messages,
|
|
2806
2900
|
* for correlation to detect container forking.
|
|
2807
2901
|
*/
|
|
2808
|
-
reSubmitBatch(batch, batchId) {
|
|
2902
|
+
reSubmitBatch(batch, batchId, staged) {
|
|
2809
2903
|
this.batchRunner.run(() => {
|
|
2810
2904
|
for (const message of batch) {
|
|
2811
2905
|
this.reSubmit(message);
|
|
@@ -2813,14 +2907,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2813
2907
|
});
|
|
2814
2908
|
// Only include Batch ID if "Offline Load" feature is enabled
|
|
2815
2909
|
// It's only needed to identify batches across container forks arising from misuse of offline load.
|
|
2816
|
-
this.flush(this.offlineEnabled ? batchId : undefined);
|
|
2910
|
+
this.flush(this.offlineEnabled ? batchId : undefined, staged);
|
|
2817
2911
|
}
|
|
2818
2912
|
reSubmit(message) {
|
|
2819
|
-
|
|
2820
|
-
// Note that roundtripping handles through string like this means this parsed contents
|
|
2821
|
-
// contains RemoteFluidObjectHandles, not the original handle.
|
|
2822
|
-
const containerRuntimeMessage = this.parseLocalOpContent(message.content);
|
|
2823
|
-
this.reSubmitCore(containerRuntimeMessage, message.localOpMetadata, message.opMetadata);
|
|
2913
|
+
this.reSubmitCore(message.runtimeOp, message.localOpMetadata, message.opMetadata);
|
|
2824
2914
|
}
|
|
2825
2915
|
/**
|
|
2826
2916
|
* Finds the right store and asks it to resubmit the message. This typically happens when we
|
|
@@ -2875,11 +2965,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2875
2965
|
}
|
|
2876
2966
|
}
|
|
2877
2967
|
}
|
|
2878
|
-
rollback(
|
|
2879
|
-
|
|
2880
|
-
// Note that roundtripping handles through string like this means this parsed contents
|
|
2881
|
-
// contains RemoteFluidObjectHandles, not the original handle.
|
|
2882
|
-
const { type, contents } = this.parseLocalOpContent(content);
|
|
2968
|
+
rollback(runtimeOp, localOpMetadata) {
|
|
2969
|
+
const { type, contents } = runtimeOp;
|
|
2883
2970
|
switch (type) {
|
|
2884
2971
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp: {
|
|
2885
2972
|
// For operations, call rollbackDataStoreOp which will find the right store
|