@fluidframework/container-runtime 2.62.0-356644 → 2.62.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.cjs +4 -72
- package/CHANGELOG.md +4 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +10 -7
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
- package/dist/channelCollection.js +2 -2
- package/dist/channelCollection.js.map +1 -1
- package/dist/containerRuntime.d.ts +1 -2
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +93 -96
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +2 -2
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/deltaScheduler.js +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +3 -1
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.js +3 -1
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +4 -3
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/inboundBatchAggregator.js +1 -1
- package/dist/inboundBatchAggregator.js.map +1 -1
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +2 -1
- package/dist/metadata.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +2 -2
- package/dist/opLifecycle/opGroupingManager.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.map +1 -1
- package/dist/pendingStateManager.js +8 -3
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js +3 -2
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.js +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +10 -7
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
- package/lib/channelCollection.js +2 -2
- package/lib/channelCollection.js.map +1 -1
- package/lib/containerRuntime.d.ts +1 -2
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +22 -25
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +2 -2
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/deltaScheduler.js +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +3 -1
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.js +3 -1
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +4 -3
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/inboundBatchAggregator.js +1 -1
- package/lib/inboundBatchAggregator.js.map +1 -1
- package/lib/metadata.d.ts.map +1 -1
- package/lib/metadata.js +2 -1
- package/lib/metadata.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +2 -2
- package/lib/opLifecycle/opGroupingManager.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.map +1 -1
- package/lib/pendingStateManager.js +8 -3
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js +3 -2
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.js +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/package.json +18 -18
- package/src/blobManager/blobManager.ts +12 -7
- package/src/blobManager/blobManagerSnapSum.ts +1 -1
- package/src/channelCollection.ts +3 -3
- package/src/containerRuntime.ts +58 -65
- package/src/dataStoreContext.ts +3 -3
- package/src/deltaScheduler.ts +1 -1
- package/src/gc/garbageCollection.ts +5 -2
- package/src/gc/gcConfigs.ts +3 -3
- package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
- package/src/gc/gcTelemetry.ts +4 -5
- package/src/inboundBatchAggregator.ts +1 -1
- package/src/metadata.ts +2 -1
- package/src/opLifecycle/opGroupingManager.ts +2 -2
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +11 -5
- package/src/summary/summaryDelayLoadedModule/runningSummarizer.ts +3 -2
- package/src/summary/summaryDelayLoadedModule/summarizer.ts +1 -1
- package/src/summary/summaryDelayLoadedModule/summaryGenerator.ts +1 -1
package/dist/containerRuntime.js
CHANGED
|
@@ -15,9 +15,7 @@ const internal_4 = require("@fluidframework/driver-utils/internal");
|
|
|
15
15
|
const internal_5 = require("@fluidframework/id-compressor/internal");
|
|
16
16
|
const internal_6 = require("@fluidframework/runtime-definitions/internal");
|
|
17
17
|
const internal_7 = require("@fluidframework/runtime-utils/internal");
|
|
18
|
-
const internal_8 = require("@fluidframework/
|
|
19
|
-
const internal_9 = require("@fluidframework/runtime-utils/internal");
|
|
20
|
-
const internal_10 = require("@fluidframework/telemetry-utils/internal");
|
|
18
|
+
const internal_8 = require("@fluidframework/telemetry-utils/internal");
|
|
21
19
|
const semver_ts_1 = require("semver-ts");
|
|
22
20
|
const uuid_1 = require("uuid");
|
|
23
21
|
const batchTracker_js_1 = require("./batchTracker.js");
|
|
@@ -40,6 +38,7 @@ const pendingStateManager_js_1 = require("./pendingStateManager.js");
|
|
|
40
38
|
const runCounter_js_1 = require("./runCounter.js");
|
|
41
39
|
const runtimeLayerCompatState_js_1 = require("./runtimeLayerCompatState.js");
|
|
42
40
|
const signalTelemetryProcessing_js_1 = require("./signalTelemetryProcessing.js");
|
|
41
|
+
// These types are imported as types here because they are present in summaryDelayLoadedModule, which is loaded dynamically when required.
|
|
43
42
|
const index_js_4 = require("./summary/index.js");
|
|
44
43
|
const throttler_js_1 = require("./throttler.js");
|
|
45
44
|
/**
|
|
@@ -55,7 +54,7 @@ const throttler_js_1 = require("./throttler.js");
|
|
|
55
54
|
*
|
|
56
55
|
*/
|
|
57
56
|
function getUnknownMessageTypeError(unknownContainerRuntimeMessageType, codePath, sequencedMessage) {
|
|
58
|
-
return
|
|
57
|
+
return internal_8.DataProcessingError.create("Runtime message of unknown type", codePath, sequencedMessage, {
|
|
59
58
|
messageDetails: {
|
|
60
59
|
type: unknownContainerRuntimeMessageType,
|
|
61
60
|
},
|
|
@@ -165,7 +164,7 @@ exports.makeLegacySendBatchFn = makeLegacySendBatchFn;
|
|
|
165
164
|
* Please see addMetadataToSummary() as well
|
|
166
165
|
*/
|
|
167
166
|
function lastMessageFromMetadata(metadata) {
|
|
168
|
-
return metadata?.documentSchema?.runtime?.explicitSchemaControl
|
|
167
|
+
return metadata?.documentSchema?.runtime?.explicitSchemaControl === true
|
|
169
168
|
? metadata?.lastMessage
|
|
170
169
|
: metadata?.message;
|
|
171
170
|
}
|
|
@@ -247,8 +246,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
247
246
|
const backCompatContext = context;
|
|
248
247
|
const passLogger = backCompatContext.taggedLogger ??
|
|
249
248
|
// eslint-disable-next-line import/no-deprecated
|
|
250
|
-
new
|
|
251
|
-
const logger = (0,
|
|
249
|
+
new internal_8.TaggedLoggerAdapter(backCompatContext.logger);
|
|
250
|
+
const logger = (0, internal_8.createChildLogger)({
|
|
252
251
|
logger: passLogger,
|
|
253
252
|
properties: {
|
|
254
253
|
all: {
|
|
@@ -256,14 +255,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
256
255
|
},
|
|
257
256
|
},
|
|
258
257
|
});
|
|
259
|
-
const mc = (0,
|
|
258
|
+
const mc = (0, internal_8.loggerToMonitoringContext)(logger);
|
|
260
259
|
// Some options require a minimum version of the FF runtime to operate, so the default configs will be generated
|
|
261
260
|
// based on the minVersionForCollab.
|
|
262
261
|
// For example, if minVersionForCollab is set to "1.0.0", the default configs will ensure compatibility with FF runtime
|
|
263
262
|
// 1.0.0 or later. If the minVersionForCollab is set to "2.10.0", the default values will be generated to ensure compatibility
|
|
264
263
|
// with FF runtime 2.10.0 or later.
|
|
265
264
|
if (!(0, internal_7.isValidMinVersionForCollab)(minVersionForCollab)) {
|
|
266
|
-
throw new
|
|
265
|
+
throw new internal_8.UsageError(`Invalid minVersionForCollab: ${minVersionForCollab}. It must be an existing FF version (i.e. 2.22.1).`);
|
|
267
266
|
}
|
|
268
267
|
// We also validate that there is not a mismatch between `minVersionForCollab` and runtime options that
|
|
269
268
|
// were manually set.
|
|
@@ -293,7 +292,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
293
292
|
if (!explicitSchemaControl) {
|
|
294
293
|
const disallowedKeys = Object.keys(runtimeOptions).filter((key) => containerCompatibility_js_1.runtimeOptionKeysThatRequireExplicitSchemaControl.includes(key) && runtimeOptions[key] !== undefined);
|
|
295
294
|
if (disallowedKeys.length > 0) {
|
|
296
|
-
throw new
|
|
295
|
+
throw new internal_8.UsageError(`explicitSchemaControl must be enabled to use ${disallowedKeys}`);
|
|
297
296
|
}
|
|
298
297
|
}
|
|
299
298
|
// The logic for enableRuntimeIdCompressor is a bit different. Since `undefined` represents a logical state (off)
|
|
@@ -304,7 +303,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
304
303
|
const registry = new dataStoreRegistry_js_1.FluidDataStoreRegistry(registryEntries);
|
|
305
304
|
const tryFetchBlob = async (blobName) => {
|
|
306
305
|
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
307
|
-
if (context.baseSnapshot && blobId) {
|
|
306
|
+
if (context.baseSnapshot !== undefined && blobId !== undefined) {
|
|
308
307
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
309
308
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
310
309
|
(0, internal_2.assert)(context.storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
@@ -326,7 +325,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
326
325
|
const runtimeSequenceNumber = messageAtLastSummary?.sequenceNumber;
|
|
327
326
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
328
327
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
329
|
-
if (
|
|
328
|
+
if (context.pendingLocalState === undefined && runtimeSequenceNumber !== undefined) {
|
|
330
329
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
331
330
|
// eslint-disable-next-line unicorn/no-lonely-if -- Separate if statements make flow easier to parse
|
|
332
331
|
if (loadSequenceNumberVerification !== "bypass" &&
|
|
@@ -338,7 +337,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
338
337
|
// Older runtimes do not understand new schema, and thus could corrupt document if they proceed, thus we are using
|
|
339
338
|
// this poison pill to prevent them from proceeding.
|
|
340
339
|
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
341
|
-
const error = new
|
|
340
|
+
const error = new internal_8.DataCorruptionError(
|
|
342
341
|
// pre-0.58 error message: SummaryMetadataMismatch
|
|
343
342
|
"Summary metadata mismatch", { runtimeVersion: packageVersion_js_1.pkgVersion, runtimeSequenceNumber, protocolSequenceNumber });
|
|
344
343
|
if (loadSequenceNumberVerification === "log") {
|
|
@@ -409,7 +408,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
409
408
|
},
|
|
410
409
|
};
|
|
411
410
|
})();
|
|
412
|
-
const compressorLogger = (0,
|
|
411
|
+
const compressorLogger = (0, internal_8.createSampledLogger)(logger, idCompressorEventSampler);
|
|
413
412
|
const pendingLocalState = context.pendingLocalState;
|
|
414
413
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
415
414
|
return (0, internal_5.deserializeIdCompressor)(pendingLocalState.pendingIdCompressorState, compressorLogger);
|
|
@@ -440,7 +439,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
440
439
|
? minVersionForCollab
|
|
441
440
|
: existingMinVersionForCollab;
|
|
442
441
|
if (compressionLz4 && !enableGroupedBatching) {
|
|
443
|
-
throw new
|
|
442
|
+
throw new internal_8.UsageError("If compression is enabled, op grouping must be enabled too");
|
|
444
443
|
}
|
|
445
444
|
const featureGatesForTelemetry = {};
|
|
446
445
|
// Make sure we've got all the options including internal ones
|
|
@@ -457,7 +456,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
457
456
|
explicitSchemaControl,
|
|
458
457
|
createBlobPayloadPending,
|
|
459
458
|
};
|
|
460
|
-
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], internalRuntimeOptions, containerScope, logger, existing, blobManagerLoadInfo, context.storage, createIdCompressorFn, documentSchemaController, featureGatesForTelemetry, provideEntryPoint, (0,
|
|
459
|
+
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], internalRuntimeOptions, containerScope, logger, existing, blobManagerLoadInfo, context.storage, createIdCompressorFn, documentSchemaController, featureGatesForTelemetry, provideEntryPoint, (0, internal_7.semanticVersionToMinimumVersionForCollab)(updatedMinVersionForCollab), requestHandler, undefined, // summaryConfiguration
|
|
461
460
|
recentBatchInfo);
|
|
462
461
|
// Initialize the base state of the runtime before it's returned.
|
|
463
462
|
await runtime.initializeBaseState(context.loader);
|
|
@@ -631,10 +630,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
631
630
|
// eslint-disable-next-line import/no-deprecated
|
|
632
631
|
this.enterStagingMode = () => {
|
|
633
632
|
if (this.stageControls !== undefined) {
|
|
634
|
-
throw new
|
|
633
|
+
throw new internal_8.UsageError("Already in staging mode");
|
|
635
634
|
}
|
|
636
635
|
if (this.attachState === container_definitions_1.AttachState.Detached) {
|
|
637
|
-
throw new
|
|
636
|
+
throw new internal_8.UsageError("Cannot enter staging mode while Detached");
|
|
638
637
|
}
|
|
639
638
|
// Make sure Outbox is empty before entering staging mode,
|
|
640
639
|
// since we mark whole batches as "staged" or not to indicate whether to submit them.
|
|
@@ -652,7 +651,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
652
651
|
this.channelCollection.notifyStagingMode(false);
|
|
653
652
|
}
|
|
654
653
|
catch (error) {
|
|
655
|
-
const normalizedError = (0,
|
|
654
|
+
const normalizedError = (0, internal_8.normalizeError)(error);
|
|
656
655
|
this.closeFn(normalizedError);
|
|
657
656
|
throw normalizedError;
|
|
658
657
|
}
|
|
@@ -707,10 +706,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
707
706
|
this.getConnectionState = getConnectionState;
|
|
708
707
|
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
709
708
|
this.disposeFn = disposeFn ?? closeFn;
|
|
709
|
+
this.isSnapshotInstanceOfISnapshot = snapshotWithContents !== undefined;
|
|
710
710
|
// Validate that the Loader is compatible with this Runtime.
|
|
711
711
|
const maybeLoaderCompatDetailsForRuntime = context;
|
|
712
712
|
(0, runtimeLayerCompatState_js_1.validateLoaderCompatibility)(maybeLoaderCompatDetailsForRuntime.ILayerCompatDetails, this.disposeFn);
|
|
713
|
-
this.mc = (0,
|
|
713
|
+
this.mc = (0, internal_8.createChildMonitoringContext)({
|
|
714
714
|
logger: this.baseLogger,
|
|
715
715
|
namespace: "ContainerRuntime",
|
|
716
716
|
properties: {
|
|
@@ -744,7 +744,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
744
744
|
submitSignalFn(envelope, targetClientId);
|
|
745
745
|
};
|
|
746
746
|
this.submitSignalFn = (envelope, targetClientId) => {
|
|
747
|
-
if (envelope.address?.startsWith("/")) {
|
|
747
|
+
if (envelope.address?.startsWith("/") === true) {
|
|
748
748
|
throw new Error("General path based addressing is not implemented");
|
|
749
749
|
}
|
|
750
750
|
sequenceAndSubmitSignal(envelope, targetClientId);
|
|
@@ -886,7 +886,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
886
886
|
this.offlineEnabled =
|
|
887
887
|
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
|
|
888
888
|
if (this.offlineEnabled && this._flushMode !== internal_6.FlushMode.TurnBased) {
|
|
889
|
-
const error = new
|
|
889
|
+
const error = new internal_8.UsageError("Offline mode is only supported in turn-based mode");
|
|
890
890
|
this.closeFn(error);
|
|
891
891
|
throw error;
|
|
892
892
|
}
|
|
@@ -904,7 +904,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
904
904
|
// This is a runtime enforcement of what's already explicit in the policy's type itself,
|
|
905
905
|
// which dictates the value is either undefined or exactly 5 days in ms.
|
|
906
906
|
// As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
|
|
907
|
-
throw new
|
|
907
|
+
throw new internal_8.UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
|
|
908
908
|
}
|
|
909
909
|
}
|
|
910
910
|
this.garbageCollector = index_js_2.GarbageCollector.create({
|
|
@@ -929,7 +929,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
929
929
|
const summaryReferenceSequenceNumber = baseSnapshot === undefined || metadata?.disableIsolatedChannels === true
|
|
930
930
|
? undefined
|
|
931
931
|
: loadedFromSequenceNumber;
|
|
932
|
-
this.summarizerNode = (0, index_js_4.createRootSummarizerNodeWithGC)((0,
|
|
932
|
+
this.summarizerNode = (0, index_js_4.createRootSummarizerNodeWithGC)((0, internal_8.createChildLogger)({ logger: this.baseLogger, namespace: "SummarizerNode" }),
|
|
933
933
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
934
934
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
935
935
|
// Latest change sequence number, no changes since summary applied yet
|
|
@@ -945,9 +945,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
945
945
|
// Function to get the GC details from the base snapshot we loaded from.
|
|
946
946
|
async () => this.garbageCollector.getBaseGCDetails());
|
|
947
947
|
const parentContext = (0, channelCollection_js_1.wrapContext)(this);
|
|
948
|
-
if (snapshotWithContents !== undefined) {
|
|
949
|
-
this.isSnapshotInstanceOfISnapshot = true;
|
|
950
|
-
}
|
|
951
948
|
// Due to a mismatch between different layers in terms of
|
|
952
949
|
// what is the interface of passing signals, we need the
|
|
953
950
|
// downstream stores to wrap the signal.
|
|
@@ -992,8 +989,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
992
989
|
stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
|
|
993
990
|
createBlobPayloadPending: this.sessionSchema.createBlobPayloadPending === true,
|
|
994
991
|
});
|
|
995
|
-
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0,
|
|
996
|
-
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0,
|
|
992
|
+
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0, internal_8.createChildLogger)({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
|
|
993
|
+
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0, internal_8.createChildLogger)({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
|
|
997
994
|
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(submitFn, this.innerDeltaManager);
|
|
998
995
|
this.skipSafetyFlushDuringProcessStack =
|
|
999
996
|
// Keep the old flag name even though we renamed the class member (it shipped in 2.31.0)
|
|
@@ -1137,7 +1134,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1137
1134
|
async initializeBaseState(loader) {
|
|
1138
1135
|
if (this.sessionSchema.idCompressorMode === "on" ||
|
|
1139
1136
|
(this.sessionSchema.idCompressorMode === "delayed" && this.connected)) {
|
|
1140
|
-
|
|
1137
|
+
internal_8.PerformanceEvent.timedExec(this.mc.logger, { eventName: "CreateIdCompressorOnBoot" }, (event) => {
|
|
1141
1138
|
this._idCompressor = this.createIdCompressorFn();
|
|
1142
1139
|
event.end({
|
|
1143
1140
|
details: {
|
|
@@ -1167,7 +1164,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1167
1164
|
this.summaryConfiguration.initialSummarizerDelayMs,
|
|
1168
1165
|
};
|
|
1169
1166
|
const summaryCollection = new index_js_4.SummaryCollection(this.deltaManager, this.baseLogger);
|
|
1170
|
-
const orderedClientLogger = (0,
|
|
1167
|
+
const orderedClientLogger = (0, internal_8.createChildLogger)({
|
|
1171
1168
|
logger: this.baseLogger,
|
|
1172
1169
|
namespace: "OrderedClientElection",
|
|
1173
1170
|
});
|
|
@@ -1291,7 +1288,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1291
1288
|
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
1292
1289
|
// the file has been overwritten or service lost data.
|
|
1293
1290
|
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
1294
|
-
throw
|
|
1291
|
+
throw internal_8.DataProcessingError.create("Downloaded snapshot older than snapshot we loaded from", "getSnapshotForLoadingGroupId", undefined, {
|
|
1295
1292
|
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
1296
1293
|
snapshotSeqNumber,
|
|
1297
1294
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
@@ -1314,7 +1311,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1314
1311
|
targetSequenceNumber: snapshotSeqNumber, // This is so we reuse some columns in telemetry
|
|
1315
1312
|
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
1316
1313
|
};
|
|
1317
|
-
const event =
|
|
1314
|
+
const event = internal_8.PerformanceEvent.start(this.mc.logger, {
|
|
1318
1315
|
...props,
|
|
1319
1316
|
});
|
|
1320
1317
|
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
@@ -1359,7 +1356,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1359
1356
|
// @ts-expect-error expected to be used by LTS Loaders and Containers
|
|
1360
1357
|
async request(request) {
|
|
1361
1358
|
try {
|
|
1362
|
-
const parser =
|
|
1359
|
+
const parser = internal_7.RequestParser.create(request);
|
|
1363
1360
|
const id = parser.pathParts[0];
|
|
1364
1361
|
if (id === index_js_4.summarizerRequestUrl && parser.pathParts.length === 1) {
|
|
1365
1362
|
if (this._summarizer !== undefined) {
|
|
@@ -1369,16 +1366,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1369
1366
|
value: this._summarizer,
|
|
1370
1367
|
};
|
|
1371
1368
|
}
|
|
1372
|
-
return (0,
|
|
1369
|
+
return (0, internal_7.create404Response)(request);
|
|
1373
1370
|
}
|
|
1374
1371
|
if (this.requestHandler !== undefined) {
|
|
1375
1372
|
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
1376
1373
|
return this.requestHandler(parser, this);
|
|
1377
1374
|
}
|
|
1378
|
-
return (0,
|
|
1375
|
+
return (0, internal_7.create404Response)(request);
|
|
1379
1376
|
}
|
|
1380
1377
|
catch (error) {
|
|
1381
|
-
return (0,
|
|
1378
|
+
return (0, internal_7.exceptionToResponse)(error);
|
|
1382
1379
|
}
|
|
1383
1380
|
}
|
|
1384
1381
|
/**
|
|
@@ -1387,7 +1384,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1387
1384
|
*/
|
|
1388
1385
|
async resolveHandle(request) {
|
|
1389
1386
|
try {
|
|
1390
|
-
const requestParser =
|
|
1387
|
+
const requestParser = internal_7.RequestParser.create(request);
|
|
1391
1388
|
const id = requestParser.pathParts[0];
|
|
1392
1389
|
if (id === "_channels") {
|
|
1393
1390
|
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
@@ -1395,10 +1392,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1395
1392
|
}
|
|
1396
1393
|
if (id === index_js_1.blobManagerBasePath && requestParser.isLeaf(2)) {
|
|
1397
1394
|
const localId = requestParser.pathParts[1];
|
|
1398
|
-
const payloadPending = requestParser.headers?.[
|
|
1395
|
+
const payloadPending = requestParser.headers?.[internal_7.RuntimeHeaders.payloadPending] === true;
|
|
1399
1396
|
if (!this.blobManager.hasBlob(localId) &&
|
|
1400
|
-
requestParser.headers?.[
|
|
1401
|
-
return (0,
|
|
1397
|
+
requestParser.headers?.[internal_7.RuntimeHeaders.wait] === false) {
|
|
1398
|
+
return (0, internal_7.create404Response)(request);
|
|
1402
1399
|
}
|
|
1403
1400
|
const blob = await this.blobManager.getBlob(localId, payloadPending);
|
|
1404
1401
|
return {
|
|
@@ -1410,10 +1407,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1410
1407
|
else if (requestParser.pathParts.length > 0) {
|
|
1411
1408
|
return await this.channelCollection.request(request);
|
|
1412
1409
|
}
|
|
1413
|
-
return (0,
|
|
1410
|
+
return (0, internal_7.create404Response)(request);
|
|
1414
1411
|
}
|
|
1415
1412
|
catch (error) {
|
|
1416
|
-
return (0,
|
|
1413
|
+
return (0, internal_7.exceptionToResponse)(error);
|
|
1417
1414
|
}
|
|
1418
1415
|
}
|
|
1419
1416
|
/**
|
|
@@ -1435,7 +1432,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1435
1432
|
this.messageAtLastSummary;
|
|
1436
1433
|
const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
|
|
1437
1434
|
// Is document schema explicit control on?
|
|
1438
|
-
const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
|
|
1435
|
+
const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl === true;
|
|
1439
1436
|
const metadata = {
|
|
1440
1437
|
...this.createContainerMetadata,
|
|
1441
1438
|
// Increment the summary number for the next summary that will be generated.
|
|
@@ -1445,7 +1442,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1445
1442
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1446
1443
|
// If explicit document schema control is not on, use legacy way to supply last message (using 'message' property).
|
|
1447
1444
|
// Otherwise use new 'lastMessage' property, but also put content into the 'message' property that cases old
|
|
1448
|
-
// runtimes (that
|
|
1445
|
+
// runtimes (that preceded document schema control capabilities) to close container on load due to mismatch in
|
|
1449
1446
|
// last message's sequence number.
|
|
1450
1447
|
// See also lastMessageFromMetadata()
|
|
1451
1448
|
message: explicitSchemaControl
|
|
@@ -1454,39 +1451,39 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1454
1451
|
lastMessage: explicitSchemaControl ? message : undefined,
|
|
1455
1452
|
documentSchema,
|
|
1456
1453
|
};
|
|
1457
|
-
(0,
|
|
1454
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_4.metadataBlobName, JSON.stringify(metadata));
|
|
1458
1455
|
}
|
|
1459
1456
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
1460
1457
|
this.addMetadataToSummary(summaryTree);
|
|
1461
1458
|
if (this._idCompressor) {
|
|
1462
1459
|
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
1463
|
-
(0,
|
|
1460
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_4.idCompressorBlobName, idCompressorState);
|
|
1464
1461
|
}
|
|
1465
1462
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
1466
1463
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
1467
|
-
(0,
|
|
1464
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_4.chunksBlobName, content);
|
|
1468
1465
|
}
|
|
1469
1466
|
const recentBatchInfo = this.duplicateBatchDetector?.getRecentBatchInfoForSummary(telemetryContext);
|
|
1470
1467
|
if (recentBatchInfo !== undefined) {
|
|
1471
|
-
(0,
|
|
1468
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_4.recentBatchInfoBlobName, JSON.stringify(recentBatchInfo));
|
|
1472
1469
|
}
|
|
1473
1470
|
const dataStoreAliases = this.channelCollection.aliases;
|
|
1474
1471
|
if (dataStoreAliases.size > 0) {
|
|
1475
|
-
(0,
|
|
1472
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_4.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
1476
1473
|
}
|
|
1477
1474
|
if (this.summarizerClientElection) {
|
|
1478
1475
|
const electedSummarizerContent = JSON.stringify(this.summarizerClientElection?.serialize());
|
|
1479
|
-
(0,
|
|
1476
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_4.electedSummarizerBlobName, electedSummarizerContent);
|
|
1480
1477
|
}
|
|
1481
1478
|
const blobManagerSummary = this.blobManager.summarize();
|
|
1482
1479
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
1483
1480
|
// and the blob manager can handle the tree not existing when loading
|
|
1484
1481
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
1485
|
-
(0,
|
|
1482
|
+
(0, internal_7.addSummarizeResultToSummary)(summaryTree, index_js_1.blobsTreeName, blobManagerSummary);
|
|
1486
1483
|
}
|
|
1487
1484
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
1488
1485
|
if (gcSummary !== undefined) {
|
|
1489
|
-
(0,
|
|
1486
|
+
(0, internal_7.addSummarizeResultToSummary)(summaryTree, internal_6.gcTreeKey, gcSummary);
|
|
1490
1487
|
}
|
|
1491
1488
|
}
|
|
1492
1489
|
// Track how many times the container tries to reconnect with pending messages.
|
|
@@ -1592,7 +1589,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1592
1589
|
}
|
|
1593
1590
|
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1594
1591
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
1595
|
-
throw new
|
|
1592
|
+
throw new internal_8.LoggingError("GC op not expected to be stashed in summarizer");
|
|
1596
1593
|
}
|
|
1597
1594
|
default: {
|
|
1598
1595
|
const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
|
|
@@ -1604,7 +1601,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1604
1601
|
loadIdCompressor() {
|
|
1605
1602
|
if (this._idCompressor === undefined &&
|
|
1606
1603
|
this.sessionSchema.idCompressorMode !== undefined) {
|
|
1607
|
-
|
|
1604
|
+
internal_8.PerformanceEvent.timedExec(this.mc.logger, { eventName: "CreateIdCompressorOnDelayedLoad" }, (event) => {
|
|
1608
1605
|
this._idCompressor = this.createIdCompressorFn();
|
|
1609
1606
|
// Finalize any ranges we received while the compressor was turned off.
|
|
1610
1607
|
const ops = this.pendingIdCompressorOps;
|
|
@@ -1661,7 +1658,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1661
1658
|
if (reconnection) {
|
|
1662
1659
|
this.consecutiveReconnects++;
|
|
1663
1660
|
if (!this.shouldContinueReconnecting()) {
|
|
1664
|
-
this.closeFn(
|
|
1661
|
+
this.closeFn(internal_8.DataProcessingError.create("Runtime detected too many reconnects with no progress syncing local ops.", "setConnectionState", undefined, {
|
|
1665
1662
|
dataLoss: 1,
|
|
1666
1663
|
attempts: this.consecutiveReconnects,
|
|
1667
1664
|
pendingMessages: this.pendingMessagesCount,
|
|
@@ -1675,7 +1672,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1675
1672
|
this.channelCollection.setConnectionState(canSendOps, clientId);
|
|
1676
1673
|
this.garbageCollector.setConnectionState(canSendOps, clientId);
|
|
1677
1674
|
// Emit "connected" and "disconnected" events based on ability to send ops
|
|
1678
|
-
(0,
|
|
1675
|
+
(0, internal_8.raiseConnectedEvent)(this.mc.logger, this, this.connected /* canSendOps */, clientId);
|
|
1679
1676
|
// Emit "connectedToService" and "disconnectedFromService" events based on service connection status
|
|
1680
1677
|
this.emitServiceConnectionEvents(canSendOpsChanged, canSendOps, clientId);
|
|
1681
1678
|
}
|
|
@@ -1759,8 +1756,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1759
1756
|
if ("batchStart" in inboundResult) {
|
|
1760
1757
|
const batchStart = inboundResult.batchStart;
|
|
1761
1758
|
const result = this.duplicateBatchDetector?.processInboundBatch(batchStart);
|
|
1762
|
-
if (result?.duplicate) {
|
|
1763
|
-
const error = new
|
|
1759
|
+
if (result?.duplicate === true) {
|
|
1760
|
+
const error = new internal_8.DataCorruptionError("Duplicate batch - The same batch was sequenced twice", { batchId: batchStart.batchId });
|
|
1764
1761
|
this.mc.logger.sendTelemetryEvent({
|
|
1765
1762
|
eventName: "DuplicateBatch",
|
|
1766
1763
|
details: {
|
|
@@ -1769,7 +1766,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1769
1766
|
batchStartCsn: batchStart.batchStartCsn,
|
|
1770
1767
|
size: inboundResult.length,
|
|
1771
1768
|
duplicateBatchSequenceNumber: result.otherSequenceNumber,
|
|
1772
|
-
...(0,
|
|
1769
|
+
...(0, internal_8.extractSafePropertiesFromMessage)(batchStart.keyMessage),
|
|
1773
1770
|
},
|
|
1774
1771
|
}, error);
|
|
1775
1772
|
throw error;
|
|
@@ -2063,7 +2060,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2063
2060
|
(0, internal_2.assert)(!local, 0xba0 /* No recipient found for local signal */);
|
|
2064
2061
|
this.mc.logger.sendTelemetryEvent({
|
|
2065
2062
|
eventName: "SignalAddressNotFound",
|
|
2066
|
-
...(0,
|
|
2063
|
+
...(0, internal_8.tagCodeArtifacts)({
|
|
2067
2064
|
address,
|
|
2068
2065
|
}),
|
|
2069
2066
|
});
|
|
@@ -2083,7 +2080,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2083
2080
|
(0, internal_2.assert)(this.outbox.isEmpty, 0x3cf /* reentrancy */);
|
|
2084
2081
|
}
|
|
2085
2082
|
catch (error) {
|
|
2086
|
-
const error2 = (0,
|
|
2083
|
+
const error2 = (0, internal_8.normalizeError)(error, {
|
|
2087
2084
|
props: {
|
|
2088
2085
|
orderSequentiallyCalls: this.batchRunner.runs,
|
|
2089
2086
|
},
|
|
@@ -2099,7 +2096,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2099
2096
|
let checkpoint;
|
|
2100
2097
|
// eslint-disable-next-line import/no-deprecated
|
|
2101
2098
|
let stageControls;
|
|
2102
|
-
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.EnableRollback")) {
|
|
2099
|
+
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.EnableRollback") === true) {
|
|
2103
2100
|
if (!this.batchRunner.running && !this.inStagingMode) {
|
|
2104
2101
|
stageControls = this.enterStagingMode();
|
|
2105
2102
|
}
|
|
@@ -2124,15 +2121,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2124
2121
|
stageControls = undefined;
|
|
2125
2122
|
}
|
|
2126
2123
|
catch (error_) {
|
|
2127
|
-
const error2 = (0,
|
|
2128
|
-
return
|
|
2124
|
+
const error2 = (0, internal_8.wrapError)(error_, (message) => {
|
|
2125
|
+
return internal_8.DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
|
|
2129
2126
|
});
|
|
2130
2127
|
this.closeFn(error2);
|
|
2131
2128
|
throw error2;
|
|
2132
2129
|
}
|
|
2133
2130
|
}
|
|
2134
2131
|
else {
|
|
2135
|
-
this.closeFn((0,
|
|
2132
|
+
this.closeFn((0, internal_8.wrapError)(error, (errorMessage) => new internal_8.GenericError(`orderSequentially callback exception: ${errorMessage}`, error, {
|
|
2136
2133
|
orderSequentiallyCalls: this.batchRunner.runs,
|
|
2137
2134
|
})));
|
|
2138
2135
|
}
|
|
@@ -2178,7 +2175,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2178
2175
|
}
|
|
2179
2176
|
const channel = await context.realize();
|
|
2180
2177
|
if (channel.entryPoint === undefined) {
|
|
2181
|
-
throw new
|
|
2178
|
+
throw new internal_8.UsageError("entryPoint must be defined on data store runtime for using getAliasedDataStoreEntryPoint");
|
|
2182
2179
|
}
|
|
2183
2180
|
this.garbageCollector.nodeUpdated({
|
|
2184
2181
|
node: { type: "DataStore", path: `/${internalId}` },
|
|
@@ -2198,7 +2195,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2198
2195
|
shouldSendOps() {
|
|
2199
2196
|
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
2200
2197
|
// container runtime's ability to send ops depend on the actual readonly state of the delta manager.
|
|
2201
|
-
return this.connected &&
|
|
2198
|
+
return this.connected && this.innerDeltaManager.readOnlyInfo.readonly !== true;
|
|
2202
2199
|
}
|
|
2203
2200
|
getQuorum() {
|
|
2204
2201
|
return this._quorum;
|
|
@@ -2300,7 +2297,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2300
2297
|
async summarize(options) {
|
|
2301
2298
|
this.verifyNotClosed();
|
|
2302
2299
|
const { fullTree = false, trackState = true, summaryLogger = this.mc.logger, runGC = this.garbageCollector.shouldRunGC, runSweep, fullGC, } = options;
|
|
2303
|
-
const telemetryContext = new
|
|
2300
|
+
const telemetryContext = new internal_7.TelemetryContext();
|
|
2304
2301
|
// Add the options that are used to generate this summary to the telemetry context.
|
|
2305
2302
|
telemetryContext.setMultiple("fluid_Summarize", "Options", {
|
|
2306
2303
|
fullTree,
|
|
@@ -2333,7 +2330,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2333
2330
|
* @see IGarbageCollectionRuntime.getGCData
|
|
2334
2331
|
*/
|
|
2335
2332
|
async getGCData(fullGC) {
|
|
2336
|
-
const builder = new
|
|
2333
|
+
const builder = new internal_7.GCDataBuilder();
|
|
2337
2334
|
const dsGCData = await this.summarizerNode.getGCData(fullGC);
|
|
2338
2335
|
builder.addNodes(dsGCData.gcNodes);
|
|
2339
2336
|
const blobsGCData = this.blobManager.getGCData(fullGC);
|
|
@@ -2460,7 +2457,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2460
2457
|
if (timestampMs === undefined) {
|
|
2461
2458
|
this.mc.logger.sendTelemetryEvent({
|
|
2462
2459
|
eventName: "NoTimestampInGCOutboundRoute",
|
|
2463
|
-
...(0,
|
|
2460
|
+
...(0, internal_8.tagCodeArtifacts)({
|
|
2464
2461
|
id: toPath,
|
|
2465
2462
|
fromId: fromPath,
|
|
2466
2463
|
}),
|
|
@@ -2483,7 +2480,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2483
2480
|
// use it for all events logged during this summary.
|
|
2484
2481
|
const summaryNumber = this.nextSummaryNumber;
|
|
2485
2482
|
let summaryRefSeqNum;
|
|
2486
|
-
const summaryNumberLogger = (0,
|
|
2483
|
+
const summaryNumberLogger = (0, internal_8.createChildLogger)({
|
|
2487
2484
|
logger: summaryLogger,
|
|
2488
2485
|
properties: {
|
|
2489
2486
|
all: {
|
|
@@ -2494,7 +2491,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2494
2491
|
});
|
|
2495
2492
|
// legacy: assert 0x3d1
|
|
2496
2493
|
if (!this.outbox.isEmpty) {
|
|
2497
|
-
throw
|
|
2494
|
+
throw internal_8.DataProcessingError.create("Can't trigger summary in the middle of a batch", "submitSummary", undefined, {
|
|
2498
2495
|
summaryNumber,
|
|
2499
2496
|
pendingMessages: this.pendingMessagesCount,
|
|
2500
2497
|
outboxLength: this.outbox.messageCount,
|
|
@@ -2631,7 +2628,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2631
2628
|
stage: "base",
|
|
2632
2629
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
2633
2630
|
minimumSequenceNumber,
|
|
2634
|
-
error: (0,
|
|
2631
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2635
2632
|
};
|
|
2636
2633
|
}
|
|
2637
2634
|
// Validate that the summary generated by summarizer nodes is correct before uploading.
|
|
@@ -2659,11 +2656,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2659
2656
|
// Because handles are unchanged dataStores in the current logic,
|
|
2660
2657
|
// summarized dataStore count is total dataStore count minus handle count
|
|
2661
2658
|
const dataStoreTree = summaryTree.tree[internal_6.channelsTreeName];
|
|
2662
|
-
(0, internal_2.assert)(dataStoreTree
|
|
2659
|
+
(0, internal_2.assert)(dataStoreTree?.type === driver_definitions_1.SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
|
|
2663
2660
|
const handleCount = Object.values(dataStoreTree.tree).filter((value) => value.type === driver_definitions_1.SummaryType.Handle).length;
|
|
2664
|
-
const gcSummaryTreeStats = summaryTree.tree[internal_6.gcTreeKey]
|
|
2665
|
-
?
|
|
2666
|
-
:
|
|
2661
|
+
const gcSummaryTreeStats = summaryTree.tree[internal_6.gcTreeKey] === undefined
|
|
2662
|
+
? undefined
|
|
2663
|
+
: (0, internal_7.calculateStats)(summaryTree.tree[internal_6.gcTreeKey]);
|
|
2667
2664
|
const summaryStats = {
|
|
2668
2665
|
dataStoreCount: this.channelCollection.size,
|
|
2669
2666
|
summarizedDataStoreCount: this.channelCollection.size - handleCount,
|
|
@@ -2701,7 +2698,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2701
2698
|
return {
|
|
2702
2699
|
stage: "generate",
|
|
2703
2700
|
...generateSummaryData,
|
|
2704
|
-
error: (0,
|
|
2701
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2705
2702
|
};
|
|
2706
2703
|
}
|
|
2707
2704
|
const parent = summaryContext.ackHandle;
|
|
@@ -2710,7 +2707,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2710
2707
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
2711
2708
|
head: parent,
|
|
2712
2709
|
message,
|
|
2713
|
-
parents: parent ? [
|
|
2710
|
+
parents: parent === undefined ? [] : [parent],
|
|
2714
2711
|
};
|
|
2715
2712
|
const uploadData = {
|
|
2716
2713
|
...generateSummaryData,
|
|
@@ -2733,7 +2730,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2733
2730
|
return {
|
|
2734
2731
|
stage: "upload",
|
|
2735
2732
|
...uploadData,
|
|
2736
|
-
error: (0,
|
|
2733
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2737
2734
|
};
|
|
2738
2735
|
}
|
|
2739
2736
|
const submitData = {
|
|
@@ -2749,7 +2746,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2749
2746
|
return {
|
|
2750
2747
|
stage: "upload",
|
|
2751
2748
|
...uploadData,
|
|
2752
|
-
error: (0,
|
|
2749
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2753
2750
|
};
|
|
2754
2751
|
}
|
|
2755
2752
|
return submitData;
|
|
@@ -2784,8 +2781,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2784
2781
|
// This is a fallback to make progress in documents where there are consistently pending ops in
|
|
2785
2782
|
// the summarizer.
|
|
2786
2783
|
if (finalAttempt &&
|
|
2787
|
-
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary")) {
|
|
2788
|
-
const error =
|
|
2784
|
+
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary") === true) {
|
|
2785
|
+
const error = internal_8.DataProcessingError.create("Pending ops during summarization", "submitSummary", undefined, { pendingMessages: this.pendingMessagesCount });
|
|
2789
2786
|
logger.sendErrorEvent({
|
|
2790
2787
|
eventName: "SkipFailingIncorrectSummary",
|
|
2791
2788
|
referenceSequenceNumber,
|
|
@@ -2888,7 +2885,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2888
2885
|
containerRuntimeMessage.type === messageTypes_js_1.ContainerMessageType.BlobAttach, 0x93f /* metadata */);
|
|
2889
2886
|
// Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
|
|
2890
2887
|
// container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
|
|
2891
|
-
if (this.innerDeltaManager.readOnlyInfo.readonly) {
|
|
2888
|
+
if (this.innerDeltaManager.readOnlyInfo.readonly === true) {
|
|
2892
2889
|
this.mc.logger.sendTelemetryEvent({
|
|
2893
2890
|
eventName: "SubmitOpInReadonly",
|
|
2894
2891
|
connected: this.connected,
|
|
@@ -2947,7 +2944,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2947
2944
|
this.scheduleFlush();
|
|
2948
2945
|
}
|
|
2949
2946
|
catch (error) {
|
|
2950
|
-
const dpe =
|
|
2947
|
+
const dpe = internal_8.DataProcessingError.wrapIfUnrecognized(error, "ContainerRuntime.submit", {
|
|
2951
2948
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2952
2949
|
});
|
|
2953
2950
|
this.closeFn(dpe);
|
|
@@ -3192,7 +3189,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3192
3189
|
* happen in scenarios where the snapshot for the ack was lost in storage in scenarios like DB rollback, etc.
|
|
3193
3190
|
*/
|
|
3194
3191
|
async fetchLatestSnapshotAndMaybeClose(targetRefSeq, targetAckHandle, logger) {
|
|
3195
|
-
const fetchedSnapshotRefSeq = await
|
|
3192
|
+
const fetchedSnapshotRefSeq = await internal_8.PerformanceEvent.timedExecAsync(logger, { eventName: "RefreshLatestSummaryAckFetch" }, async (perfEvent) => {
|
|
3196
3193
|
const props = { targetRefSeq, targetAckHandle };
|
|
3197
3194
|
const trace = client_utils_1.Trace.start();
|
|
3198
3195
|
let snapshotTree;
|
|
@@ -3217,13 +3214,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3217
3214
|
const versions = await this.storage.getVersions(
|
|
3218
3215
|
// eslint-disable-next-line unicorn/no-null
|
|
3219
3216
|
null, 1, scenarioName, internal_3.FetchSource.noCache);
|
|
3220
|
-
(0, internal_2.assert)(
|
|
3217
|
+
(0, internal_2.assert)(versions[0] !== undefined, 0x137 /* "Failed to get version from storage" */);
|
|
3221
3218
|
snapshotTree = await this.storage.getSnapshotTree(versions[0]);
|
|
3222
3219
|
(0, internal_2.assert)(!!snapshotTree, 0x138 /* "Failed to get snapshot from storage" */);
|
|
3223
3220
|
props.snapshotVersion = versions[0].id;
|
|
3224
3221
|
}
|
|
3225
3222
|
props.getSnapshotDuration = trace.trace().duration;
|
|
3226
|
-
const snapshotRefSeq = await (0,
|
|
3223
|
+
const snapshotRefSeq = await (0, internal_7.seqFromTree)(snapshotTree, this.readAndParseBlob);
|
|
3227
3224
|
props.snapshotRefSeq = snapshotRefSeq;
|
|
3228
3225
|
props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
|
|
3229
3226
|
perfEvent.end({ details: props });
|
|
@@ -3242,20 +3239,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3242
3239
|
getPendingLocalState(props) {
|
|
3243
3240
|
// AB#46464 - Add support for serializing pending state while in staging mode
|
|
3244
3241
|
if (this.inStagingMode) {
|
|
3245
|
-
throw new
|
|
3242
|
+
throw new internal_8.UsageError("getPendingLocalState is not yet supported in staging mode");
|
|
3246
3243
|
}
|
|
3247
3244
|
this.verifyNotClosed();
|
|
3248
|
-
if (props?.notifyImminentClosure) {
|
|
3249
|
-
throw new
|
|
3245
|
+
if (props?.notifyImminentClosure === true) {
|
|
3246
|
+
throw new internal_8.UsageError("notifyImminentClosure is no longer supported in ContainerRuntime");
|
|
3250
3247
|
}
|
|
3251
3248
|
if (this.batchRunner.running) {
|
|
3252
|
-
throw new
|
|
3249
|
+
throw new internal_8.UsageError("can't get state while manually accumulating a batch");
|
|
3253
3250
|
}
|
|
3254
3251
|
// Flush pending batch.
|
|
3255
3252
|
// getPendingLocalState() is only exposed through Container.getPendingLocalState(), so it's safe
|
|
3256
3253
|
// to close current batch.
|
|
3257
3254
|
this.flush();
|
|
3258
|
-
return
|
|
3255
|
+
return internal_8.PerformanceEvent.timedExec(this.mc.logger, {
|
|
3259
3256
|
eventName: "getPendingLocalState",
|
|
3260
3257
|
}, (event) => {
|
|
3261
3258
|
const pending = this.pendingStateManager.getLocalState(props?.snapshotSequenceNumber);
|
|
@@ -3283,7 +3280,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3283
3280
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3284
3281
|
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
3285
3282
|
// because it is a misuse of the API rather than an expected failure.
|
|
3286
|
-
throw new
|
|
3283
|
+
throw new internal_8.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3287
3284
|
}
|
|
3288
3285
|
else {
|
|
3289
3286
|
return this.summaryManager.summarizeOnDemand(options);
|
|
@@ -3297,7 +3294,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3297
3294
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3298
3295
|
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
3299
3296
|
// because it is a misuse of the API rather than an expected failure.
|
|
3300
|
-
throw new
|
|
3297
|
+
throw new internal_8.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3301
3298
|
}
|
|
3302
3299
|
else {
|
|
3303
3300
|
return this.summaryManager.enqueueSummarize(options);
|