@fluidframework/container-runtime 2.61.0-355054 → 2.61.0-355603
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/api-report/container-runtime.legacy.beta.api.md +2 -1
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts +13 -2
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +41 -24
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +6 -2
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +1 -0
- package/dist/channelCollection.js.map +1 -1
- package/dist/containerCompatibility.d.ts +18 -0
- package/dist/containerCompatibility.d.ts.map +1 -1
- package/dist/containerCompatibility.js +23 -1
- package/dist/containerCompatibility.js.map +1 -1
- package/dist/containerRuntime.d.ts +15 -3
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +74 -51
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +5 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +1 -0
- package/dist/dataStoreContext.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/internal.d.ts +1 -1
- package/legacy.d.ts +1 -1
- package/lib/blobManager/blobManager.d.ts +13 -2
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +41 -24
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +6 -2
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +1 -0
- package/lib/channelCollection.js.map +1 -1
- package/lib/containerCompatibility.d.ts +18 -0
- package/lib/containerCompatibility.d.ts.map +1 -1
- package/lib/containerCompatibility.js +22 -0
- package/lib/containerCompatibility.js.map +1 -1
- package/lib/containerRuntime.d.ts +15 -3
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +25 -2
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +5 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +1 -0
- package/lib/dataStoreContext.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/package.json +20 -20
- package/src/blobManager/blobManager.ts +21 -3
- package/src/channelCollection.ts +9 -1
- package/src/containerCompatibility.ts +56 -0
- package/src/containerRuntime.ts +34 -3
- package/src/dataStoreContext.ts +7 -0
- package/src/packageVersion.ts +1 -1
package/dist/containerRuntime.js
CHANGED
|
@@ -16,7 +16,8 @@ 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
18
|
const internal_8 = require("@fluidframework/runtime-utils/internal");
|
|
19
|
-
const internal_9 = require("@fluidframework/
|
|
19
|
+
const internal_9 = require("@fluidframework/runtime-utils/internal");
|
|
20
|
+
const internal_10 = require("@fluidframework/telemetry-utils/internal");
|
|
20
21
|
const semver_ts_1 = require("semver-ts");
|
|
21
22
|
const uuid_1 = require("uuid");
|
|
22
23
|
const batchTracker_js_1 = require("./batchTracker.js");
|
|
@@ -54,7 +55,7 @@ const throttler_js_1 = require("./throttler.js");
|
|
|
54
55
|
*
|
|
55
56
|
*/
|
|
56
57
|
function getUnknownMessageTypeError(unknownContainerRuntimeMessageType, codePath, sequencedMessage) {
|
|
57
|
-
return
|
|
58
|
+
return internal_10.DataProcessingError.create("Runtime message of unknown type", codePath, sequencedMessage, {
|
|
58
59
|
messageDetails: {
|
|
59
60
|
type: unknownContainerRuntimeMessageType,
|
|
60
61
|
},
|
|
@@ -246,8 +247,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
246
247
|
const backCompatContext = context;
|
|
247
248
|
const passLogger = backCompatContext.taggedLogger ??
|
|
248
249
|
// eslint-disable-next-line import/no-deprecated
|
|
249
|
-
new
|
|
250
|
-
const logger = (0,
|
|
250
|
+
new internal_10.TaggedLoggerAdapter(backCompatContext.logger);
|
|
251
|
+
const logger = (0, internal_10.createChildLogger)({
|
|
251
252
|
logger: passLogger,
|
|
252
253
|
properties: {
|
|
253
254
|
all: {
|
|
@@ -255,14 +256,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
255
256
|
},
|
|
256
257
|
},
|
|
257
258
|
});
|
|
258
|
-
const mc = (0,
|
|
259
|
+
const mc = (0, internal_10.loggerToMonitoringContext)(logger);
|
|
259
260
|
// Some options require a minimum version of the FF runtime to operate, so the default configs will be generated
|
|
260
261
|
// based on the minVersionForCollab.
|
|
261
262
|
// For example, if minVersionForCollab is set to "1.0.0", the default configs will ensure compatibility with FF runtime
|
|
262
263
|
// 1.0.0 or later. If the minVersionForCollab is set to "2.10.0", the default values will be generated to ensure compatibility
|
|
263
264
|
// with FF runtime 2.10.0 or later.
|
|
264
265
|
if (!(0, internal_7.isValidMinVersionForCollab)(minVersionForCollab)) {
|
|
265
|
-
throw new
|
|
266
|
+
throw new internal_10.UsageError(`Invalid minVersionForCollab: ${minVersionForCollab}. It must be an existing FF version (i.e. 2.22.1).`);
|
|
266
267
|
}
|
|
267
268
|
// We also validate that there is not a mismatch between `minVersionForCollab` and runtime options that
|
|
268
269
|
// were manually set.
|
|
@@ -288,6 +289,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
288
289
|
compressionOptions = enableGroupedBatching === false
|
|
289
290
|
? compressionDefinitions_js_1.disabledCompressionConfig
|
|
290
291
|
: defaultConfigs.compressionOptions, createBlobPayloadPending = defaultConfigs.createBlobPayloadPending, } = runtimeOptions;
|
|
292
|
+
// If explicitSchemaControl is off, ensure that options which require explicitSchemaControl are not enabled.
|
|
293
|
+
if (!explicitSchemaControl) {
|
|
294
|
+
const disallowedKeys = Object.keys(runtimeOptions).filter((key) => containerCompatibility_js_1.runtimeOptionKeysThatRequireExplicitSchemaControl.includes(key) && runtimeOptions[key] !== undefined);
|
|
295
|
+
if (disallowedKeys.length > 0) {
|
|
296
|
+
throw new internal_10.UsageError(`explicitSchemaControl must be enabled to use ${disallowedKeys}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
291
299
|
// The logic for enableRuntimeIdCompressor is a bit different. Since `undefined` represents a logical state (off)
|
|
292
300
|
// we need to check it's explicitly set in runtimeOptions. If so, we should use that value even if it's undefined.
|
|
293
301
|
const enableRuntimeIdCompressor = "enableRuntimeIdCompressor" in runtimeOptions
|
|
@@ -330,7 +338,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
330
338
|
// Older runtimes do not understand new schema, and thus could corrupt document if they proceed, thus we are using
|
|
331
339
|
// this poison pill to prevent them from proceeding.
|
|
332
340
|
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
333
|
-
const error = new
|
|
341
|
+
const error = new internal_10.DataCorruptionError(
|
|
334
342
|
// pre-0.58 error message: SummaryMetadataMismatch
|
|
335
343
|
"Summary metadata mismatch", { runtimeVersion: packageVersion_js_1.pkgVersion, runtimeSequenceNumber, protocolSequenceNumber });
|
|
336
344
|
if (loadSequenceNumberVerification === "log") {
|
|
@@ -401,7 +409,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
401
409
|
},
|
|
402
410
|
};
|
|
403
411
|
})();
|
|
404
|
-
const compressorLogger = (0,
|
|
412
|
+
const compressorLogger = (0, internal_10.createSampledLogger)(logger, idCompressorEventSampler);
|
|
405
413
|
const pendingLocalState = context.pendingLocalState;
|
|
406
414
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
407
415
|
return (0, internal_5.deserializeIdCompressor)(pendingLocalState.pendingIdCompressorState, compressorLogger);
|
|
@@ -432,7 +440,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
432
440
|
? minVersionForCollab
|
|
433
441
|
: existingMinVersionForCollab;
|
|
434
442
|
if (compressionLz4 && !enableGroupedBatching) {
|
|
435
|
-
throw new
|
|
443
|
+
throw new internal_10.UsageError("If compression is enabled, op grouping must be enabled too");
|
|
436
444
|
}
|
|
437
445
|
const featureGatesForTelemetry = {};
|
|
438
446
|
// Make sure we've got all the options including internal ones
|
|
@@ -449,7 +457,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
449
457
|
explicitSchemaControl,
|
|
450
458
|
createBlobPayloadPending,
|
|
451
459
|
};
|
|
452
|
-
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], internalRuntimeOptions, containerScope, logger, existing, blobManagerLoadInfo, context.storage, createIdCompressorFn, documentSchemaController, featureGatesForTelemetry, provideEntryPoint, updatedMinVersionForCollab, requestHandler, undefined, // summaryConfiguration
|
|
460
|
+
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], internalRuntimeOptions, containerScope, logger, existing, blobManagerLoadInfo, context.storage, createIdCompressorFn, documentSchemaController, featureGatesForTelemetry, provideEntryPoint, (0, internal_9.semanticVersionToMinimumVersionForCollab)(updatedMinVersionForCollab), requestHandler, undefined, // summaryConfiguration
|
|
453
461
|
recentBatchInfo);
|
|
454
462
|
// Initialize the base state of the runtime before it's returned.
|
|
455
463
|
await runtime.initializeBaseState(context.loader);
|
|
@@ -623,10 +631,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
623
631
|
// eslint-disable-next-line import/no-deprecated
|
|
624
632
|
this.enterStagingMode = () => {
|
|
625
633
|
if (this.stageControls !== undefined) {
|
|
626
|
-
throw new
|
|
634
|
+
throw new internal_10.UsageError("Already in staging mode");
|
|
627
635
|
}
|
|
628
636
|
if (this.attachState === container_definitions_1.AttachState.Detached) {
|
|
629
|
-
throw new
|
|
637
|
+
throw new internal_10.UsageError("Cannot enter staging mode while Detached");
|
|
630
638
|
}
|
|
631
639
|
// Make sure Outbox is empty before entering staging mode,
|
|
632
640
|
// since we mark whole batches as "staged" or not to indicate whether to submit them.
|
|
@@ -644,7 +652,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
644
652
|
this.channelCollection.notifyStagingMode(false);
|
|
645
653
|
}
|
|
646
654
|
catch (error) {
|
|
647
|
-
const normalizedError = (0,
|
|
655
|
+
const normalizedError = (0, internal_10.normalizeError)(error);
|
|
648
656
|
this.closeFn(normalizedError);
|
|
649
657
|
throw normalizedError;
|
|
650
658
|
}
|
|
@@ -702,7 +710,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
702
710
|
// Validate that the Loader is compatible with this Runtime.
|
|
703
711
|
const maybeLoaderCompatDetailsForRuntime = context;
|
|
704
712
|
(0, runtimeLayerCompatState_js_1.validateLoaderCompatibility)(maybeLoaderCompatDetailsForRuntime.ILayerCompatDetails, this.disposeFn);
|
|
705
|
-
this.mc = (0,
|
|
713
|
+
this.mc = (0, internal_10.createChildMonitoringContext)({
|
|
706
714
|
logger: this.baseLogger,
|
|
707
715
|
namespace: "ContainerRuntime",
|
|
708
716
|
properties: {
|
|
@@ -878,7 +886,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
878
886
|
this.offlineEnabled =
|
|
879
887
|
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
|
|
880
888
|
if (this.offlineEnabled && this._flushMode !== internal_6.FlushMode.TurnBased) {
|
|
881
|
-
const error = new
|
|
889
|
+
const error = new internal_10.UsageError("Offline mode is only supported in turn-based mode");
|
|
882
890
|
this.closeFn(error);
|
|
883
891
|
throw error;
|
|
884
892
|
}
|
|
@@ -896,7 +904,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
896
904
|
// This is a runtime enforcement of what's already explicit in the policy's type itself,
|
|
897
905
|
// which dictates the value is either undefined or exactly 5 days in ms.
|
|
898
906
|
// As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
|
|
899
|
-
throw new
|
|
907
|
+
throw new internal_10.UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
|
|
900
908
|
}
|
|
901
909
|
}
|
|
902
910
|
this.garbageCollector = index_js_2.GarbageCollector.create({
|
|
@@ -921,7 +929,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
921
929
|
const summaryReferenceSequenceNumber = baseSnapshot === undefined || metadata?.disableIsolatedChannels === true
|
|
922
930
|
? undefined
|
|
923
931
|
: loadedFromSequenceNumber;
|
|
924
|
-
this.summarizerNode = (0, index_js_4.createRootSummarizerNodeWithGC)((0,
|
|
932
|
+
this.summarizerNode = (0, index_js_4.createRootSummarizerNodeWithGC)((0, internal_10.createChildLogger)({ logger: this.baseLogger, namespace: "SummarizerNode" }),
|
|
925
933
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
926
934
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
927
935
|
// Latest change sequence number, no changes since summary applied yet
|
|
@@ -984,8 +992,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
984
992
|
stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
|
|
985
993
|
createBlobPayloadPending: this.sessionSchema.createBlobPayloadPending === true,
|
|
986
994
|
});
|
|
987
|
-
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0,
|
|
988
|
-
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0,
|
|
995
|
+
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0, internal_10.createChildLogger)({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
|
|
996
|
+
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0, internal_10.createChildLogger)({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
|
|
989
997
|
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(submitFn, this.innerDeltaManager);
|
|
990
998
|
this.skipSafetyFlushDuringProcessStack =
|
|
991
999
|
// Keep the old flag name even though we renamed the class member (it shipped in 2.31.0)
|
|
@@ -1129,7 +1137,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1129
1137
|
async initializeBaseState(loader) {
|
|
1130
1138
|
if (this.sessionSchema.idCompressorMode === "on" ||
|
|
1131
1139
|
(this.sessionSchema.idCompressorMode === "delayed" && this.connected)) {
|
|
1132
|
-
|
|
1140
|
+
internal_10.PerformanceEvent.timedExec(this.mc.logger, { eventName: "CreateIdCompressorOnBoot" }, (event) => {
|
|
1133
1141
|
this._idCompressor = this.createIdCompressorFn();
|
|
1134
1142
|
event.end({
|
|
1135
1143
|
details: {
|
|
@@ -1159,7 +1167,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1159
1167
|
this.summaryConfiguration.initialSummarizerDelayMs,
|
|
1160
1168
|
};
|
|
1161
1169
|
const summaryCollection = new index_js_4.SummaryCollection(this.deltaManager, this.baseLogger);
|
|
1162
|
-
const orderedClientLogger = (0,
|
|
1170
|
+
const orderedClientLogger = (0, internal_10.createChildLogger)({
|
|
1163
1171
|
logger: this.baseLogger,
|
|
1164
1172
|
namespace: "OrderedClientElection",
|
|
1165
1173
|
});
|
|
@@ -1283,7 +1291,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1283
1291
|
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
1284
1292
|
// the file has been overwritten or service lost data.
|
|
1285
1293
|
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
1286
|
-
throw
|
|
1294
|
+
throw internal_10.DataProcessingError.create("Downloaded snapshot older than snapshot we loaded from", "getSnapshotForLoadingGroupId", undefined, {
|
|
1287
1295
|
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
1288
1296
|
snapshotSeqNumber,
|
|
1289
1297
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
@@ -1306,7 +1314,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1306
1314
|
targetSequenceNumber: snapshotSeqNumber, // This is so we reuse some columns in telemetry
|
|
1307
1315
|
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
1308
1316
|
};
|
|
1309
|
-
const event =
|
|
1317
|
+
const event = internal_10.PerformanceEvent.start(this.mc.logger, {
|
|
1310
1318
|
...props,
|
|
1311
1319
|
});
|
|
1312
1320
|
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
@@ -1584,7 +1592,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1584
1592
|
}
|
|
1585
1593
|
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1586
1594
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
1587
|
-
throw new
|
|
1595
|
+
throw new internal_10.LoggingError("GC op not expected to be stashed in summarizer");
|
|
1588
1596
|
}
|
|
1589
1597
|
default: {
|
|
1590
1598
|
const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
|
|
@@ -1596,7 +1604,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1596
1604
|
loadIdCompressor() {
|
|
1597
1605
|
if (this._idCompressor === undefined &&
|
|
1598
1606
|
this.sessionSchema.idCompressorMode !== undefined) {
|
|
1599
|
-
|
|
1607
|
+
internal_10.PerformanceEvent.timedExec(this.mc.logger, { eventName: "CreateIdCompressorOnDelayedLoad" }, (event) => {
|
|
1600
1608
|
this._idCompressor = this.createIdCompressorFn();
|
|
1601
1609
|
// Finalize any ranges we received while the compressor was turned off.
|
|
1602
1610
|
const ops = this.pendingIdCompressorOps;
|
|
@@ -1653,7 +1661,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1653
1661
|
if (reconnection) {
|
|
1654
1662
|
this.consecutiveReconnects++;
|
|
1655
1663
|
if (!this.shouldContinueReconnecting()) {
|
|
1656
|
-
this.closeFn(
|
|
1664
|
+
this.closeFn(internal_10.DataProcessingError.create("Runtime detected too many reconnects with no progress syncing local ops.", "setConnectionState", undefined, {
|
|
1657
1665
|
dataLoss: 1,
|
|
1658
1666
|
attempts: this.consecutiveReconnects,
|
|
1659
1667
|
pendingMessages: this.pendingMessagesCount,
|
|
@@ -1667,7 +1675,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1667
1675
|
this.channelCollection.setConnectionState(canSendOps, clientId);
|
|
1668
1676
|
this.garbageCollector.setConnectionState(canSendOps, clientId);
|
|
1669
1677
|
// Emit "connected" and "disconnected" events based on ability to send ops
|
|
1670
|
-
(0,
|
|
1678
|
+
(0, internal_10.raiseConnectedEvent)(this.mc.logger, this, this.connected /* canSendOps */, clientId);
|
|
1671
1679
|
// Emit "connectedToService" and "disconnectedFromService" events based on service connection status
|
|
1672
1680
|
this.emitServiceConnectionEvents(canSendOpsChanged, canSendOps, clientId);
|
|
1673
1681
|
}
|
|
@@ -1752,7 +1760,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1752
1760
|
const batchStart = inboundResult.batchStart;
|
|
1753
1761
|
const result = this.duplicateBatchDetector?.processInboundBatch(batchStart);
|
|
1754
1762
|
if (result?.duplicate) {
|
|
1755
|
-
const error = new
|
|
1763
|
+
const error = new internal_10.DataCorruptionError("Duplicate batch - The same batch was sequenced twice", { batchId: batchStart.batchId });
|
|
1756
1764
|
this.mc.logger.sendTelemetryEvent({
|
|
1757
1765
|
eventName: "DuplicateBatch",
|
|
1758
1766
|
details: {
|
|
@@ -1761,7 +1769,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1761
1769
|
batchStartCsn: batchStart.batchStartCsn,
|
|
1762
1770
|
size: inboundResult.length,
|
|
1763
1771
|
duplicateBatchSequenceNumber: result.otherSequenceNumber,
|
|
1764
|
-
...(0,
|
|
1772
|
+
...(0, internal_10.extractSafePropertiesFromMessage)(batchStart.keyMessage),
|
|
1765
1773
|
},
|
|
1766
1774
|
}, error);
|
|
1767
1775
|
throw error;
|
|
@@ -2055,7 +2063,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2055
2063
|
(0, internal_2.assert)(!local, 0xba0 /* No recipient found for local signal */);
|
|
2056
2064
|
this.mc.logger.sendTelemetryEvent({
|
|
2057
2065
|
eventName: "SignalAddressNotFound",
|
|
2058
|
-
...(0,
|
|
2066
|
+
...(0, internal_10.tagCodeArtifacts)({
|
|
2059
2067
|
address,
|
|
2060
2068
|
}),
|
|
2061
2069
|
});
|
|
@@ -2075,7 +2083,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2075
2083
|
(0, internal_2.assert)(this.outbox.isEmpty, 0x3cf /* reentrancy */);
|
|
2076
2084
|
}
|
|
2077
2085
|
catch (error) {
|
|
2078
|
-
const error2 = (0,
|
|
2086
|
+
const error2 = (0, internal_10.normalizeError)(error, {
|
|
2079
2087
|
props: {
|
|
2080
2088
|
orderSequentiallyCalls: this.batchRunner.runs,
|
|
2081
2089
|
},
|
|
@@ -2116,15 +2124,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2116
2124
|
stageControls = undefined;
|
|
2117
2125
|
}
|
|
2118
2126
|
catch (error_) {
|
|
2119
|
-
const error2 = (0,
|
|
2120
|
-
return
|
|
2127
|
+
const error2 = (0, internal_10.wrapError)(error_, (message) => {
|
|
2128
|
+
return internal_10.DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
|
|
2121
2129
|
});
|
|
2122
2130
|
this.closeFn(error2);
|
|
2123
2131
|
throw error2;
|
|
2124
2132
|
}
|
|
2125
2133
|
}
|
|
2126
2134
|
else {
|
|
2127
|
-
this.closeFn((0,
|
|
2135
|
+
this.closeFn((0, internal_10.wrapError)(error, (errorMessage) => new internal_10.GenericError(`orderSequentially callback exception: ${errorMessage}`, error, {
|
|
2128
2136
|
orderSequentiallyCalls: this.batchRunner.runs,
|
|
2129
2137
|
})));
|
|
2130
2138
|
}
|
|
@@ -2170,7 +2178,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2170
2178
|
}
|
|
2171
2179
|
const channel = await context.realize();
|
|
2172
2180
|
if (channel.entryPoint === undefined) {
|
|
2173
|
-
throw new
|
|
2181
|
+
throw new internal_10.UsageError("entryPoint must be defined on data store runtime for using getAliasedDataStoreEntryPoint");
|
|
2174
2182
|
}
|
|
2175
2183
|
this.garbageCollector.nodeUpdated({
|
|
2176
2184
|
node: { type: "DataStore", path: `/${internalId}` },
|
|
@@ -2452,7 +2460,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2452
2460
|
if (timestampMs === undefined) {
|
|
2453
2461
|
this.mc.logger.sendTelemetryEvent({
|
|
2454
2462
|
eventName: "NoTimestampInGCOutboundRoute",
|
|
2455
|
-
...(0,
|
|
2463
|
+
...(0, internal_10.tagCodeArtifacts)({
|
|
2456
2464
|
id: toPath,
|
|
2457
2465
|
fromId: fromPath,
|
|
2458
2466
|
}),
|
|
@@ -2475,7 +2483,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2475
2483
|
// use it for all events logged during this summary.
|
|
2476
2484
|
const summaryNumber = this.nextSummaryNumber;
|
|
2477
2485
|
let summaryRefSeqNum;
|
|
2478
|
-
const summaryNumberLogger = (0,
|
|
2486
|
+
const summaryNumberLogger = (0, internal_10.createChildLogger)({
|
|
2479
2487
|
logger: summaryLogger,
|
|
2480
2488
|
properties: {
|
|
2481
2489
|
all: {
|
|
@@ -2486,7 +2494,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2486
2494
|
});
|
|
2487
2495
|
// legacy: assert 0x3d1
|
|
2488
2496
|
if (!this.outbox.isEmpty) {
|
|
2489
|
-
throw
|
|
2497
|
+
throw internal_10.DataProcessingError.create("Can't trigger summary in the middle of a batch", "submitSummary", undefined, {
|
|
2490
2498
|
summaryNumber,
|
|
2491
2499
|
pendingMessages: this.pendingMessagesCount,
|
|
2492
2500
|
outboxLength: this.outbox.messageCount,
|
|
@@ -2623,7 +2631,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2623
2631
|
stage: "base",
|
|
2624
2632
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
2625
2633
|
minimumSequenceNumber,
|
|
2626
|
-
error: (0,
|
|
2634
|
+
error: (0, internal_10.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2627
2635
|
};
|
|
2628
2636
|
}
|
|
2629
2637
|
// Validate that the summary generated by summarizer nodes is correct before uploading.
|
|
@@ -2693,7 +2701,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2693
2701
|
return {
|
|
2694
2702
|
stage: "generate",
|
|
2695
2703
|
...generateSummaryData,
|
|
2696
|
-
error: (0,
|
|
2704
|
+
error: (0, internal_10.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2697
2705
|
};
|
|
2698
2706
|
}
|
|
2699
2707
|
const parent = summaryContext.ackHandle;
|
|
@@ -2725,7 +2733,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2725
2733
|
return {
|
|
2726
2734
|
stage: "upload",
|
|
2727
2735
|
...uploadData,
|
|
2728
|
-
error: (0,
|
|
2736
|
+
error: (0, internal_10.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2729
2737
|
};
|
|
2730
2738
|
}
|
|
2731
2739
|
const submitData = {
|
|
@@ -2741,7 +2749,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2741
2749
|
return {
|
|
2742
2750
|
stage: "upload",
|
|
2743
2751
|
...uploadData,
|
|
2744
|
-
error: (0,
|
|
2752
|
+
error: (0, internal_10.wrapError)(error, (msg) => new index_js_4.RetriableSummaryError(msg)),
|
|
2745
2753
|
};
|
|
2746
2754
|
}
|
|
2747
2755
|
return submitData;
|
|
@@ -2777,7 +2785,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2777
2785
|
// the summarizer.
|
|
2778
2786
|
if (finalAttempt &&
|
|
2779
2787
|
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary")) {
|
|
2780
|
-
const error =
|
|
2788
|
+
const error = internal_10.DataProcessingError.create("Pending ops during summarization", "submitSummary", undefined, { pendingMessages: this.pendingMessagesCount });
|
|
2781
2789
|
logger.sendErrorEvent({
|
|
2782
2790
|
eventName: "SkipFailingIncorrectSummary",
|
|
2783
2791
|
referenceSequenceNumber,
|
|
@@ -2837,6 +2845,21 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2837
2845
|
this.verifyNotClosed();
|
|
2838
2846
|
return this.blobManager.createBlob(blob, signal);
|
|
2839
2847
|
}
|
|
2848
|
+
/**
|
|
2849
|
+
* Lookup the blob storage ID for a given local blob id.
|
|
2850
|
+
* @param localId - The local blob id. Likely coming from a handle.
|
|
2851
|
+
* @returns The storage ID if found and the blob is not pending, undefined otherwise.
|
|
2852
|
+
* @remarks
|
|
2853
|
+
* This method provides access to the BlobManager's storage ID lookup functionality.
|
|
2854
|
+
* For blobs with pending payloads (localId exists but upload hasn't finished), this returns undefined.
|
|
2855
|
+
* Consumers should use the observability APIs on the handle to understand/wait for storage ID availability.
|
|
2856
|
+
*
|
|
2857
|
+
* Warning: the returned blob URL may expire and does not support permalinks.
|
|
2858
|
+
* This API is intended for temporary integration scenarios only.
|
|
2859
|
+
*/
|
|
2860
|
+
lookupTemporaryBlobStorageId(localId) {
|
|
2861
|
+
return this.blobManager.lookupTemporaryBlobStorageId(localId);
|
|
2862
|
+
}
|
|
2840
2863
|
submitIdAllocationOpIfNeeded({ resubmitOutstandingRanges = false, staged, }) {
|
|
2841
2864
|
if (this._idCompressor) {
|
|
2842
2865
|
const idRange = resubmitOutstandingRanges
|
|
@@ -2924,7 +2947,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2924
2947
|
this.scheduleFlush();
|
|
2925
2948
|
}
|
|
2926
2949
|
catch (error) {
|
|
2927
|
-
const dpe =
|
|
2950
|
+
const dpe = internal_10.DataProcessingError.wrapIfUnrecognized(error, "ContainerRuntime.submit", {
|
|
2928
2951
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2929
2952
|
});
|
|
2930
2953
|
this.closeFn(dpe);
|
|
@@ -3169,7 +3192,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3169
3192
|
* happen in scenarios where the snapshot for the ack was lost in storage in scenarios like DB rollback, etc.
|
|
3170
3193
|
*/
|
|
3171
3194
|
async fetchLatestSnapshotAndMaybeClose(targetRefSeq, targetAckHandle, logger) {
|
|
3172
|
-
const fetchedSnapshotRefSeq = await
|
|
3195
|
+
const fetchedSnapshotRefSeq = await internal_10.PerformanceEvent.timedExecAsync(logger, { eventName: "RefreshLatestSummaryAckFetch" }, async (perfEvent) => {
|
|
3173
3196
|
const props = { targetRefSeq, targetAckHandle };
|
|
3174
3197
|
const trace = client_utils_1.Trace.start();
|
|
3175
3198
|
let snapshotTree;
|
|
@@ -3219,20 +3242,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3219
3242
|
getPendingLocalState(props) {
|
|
3220
3243
|
// AB#46464 - Add support for serializing pending state while in staging mode
|
|
3221
3244
|
if (this.inStagingMode) {
|
|
3222
|
-
throw new
|
|
3245
|
+
throw new internal_10.UsageError("getPendingLocalState is not yet supported in staging mode");
|
|
3223
3246
|
}
|
|
3224
3247
|
this.verifyNotClosed();
|
|
3225
3248
|
if (props?.notifyImminentClosure) {
|
|
3226
|
-
throw new
|
|
3249
|
+
throw new internal_10.UsageError("notifyImminentClosure is no longer supported in ContainerRuntime");
|
|
3227
3250
|
}
|
|
3228
3251
|
if (this.batchRunner.running) {
|
|
3229
|
-
throw new
|
|
3252
|
+
throw new internal_10.UsageError("can't get state while manually accumulating a batch");
|
|
3230
3253
|
}
|
|
3231
3254
|
// Flush pending batch.
|
|
3232
3255
|
// getPendingLocalState() is only exposed through Container.getPendingLocalState(), so it's safe
|
|
3233
3256
|
// to close current batch.
|
|
3234
3257
|
this.flush();
|
|
3235
|
-
return
|
|
3258
|
+
return internal_10.PerformanceEvent.timedExec(this.mc.logger, {
|
|
3236
3259
|
eventName: "getPendingLocalState",
|
|
3237
3260
|
}, (event) => {
|
|
3238
3261
|
const pending = this.pendingStateManager.getLocalState(props?.snapshotSequenceNumber);
|
|
@@ -3260,7 +3283,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3260
3283
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3261
3284
|
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
3262
3285
|
// because it is a misuse of the API rather than an expected failure.
|
|
3263
|
-
throw new
|
|
3286
|
+
throw new internal_10.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3264
3287
|
}
|
|
3265
3288
|
else {
|
|
3266
3289
|
return this.summaryManager.summarizeOnDemand(options);
|
|
@@ -3274,7 +3297,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3274
3297
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3275
3298
|
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
3276
3299
|
// because it is a misuse of the API rather than an expected failure.
|
|
3277
|
-
throw new
|
|
3300
|
+
throw new internal_10.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3278
3301
|
}
|
|
3279
3302
|
else {
|
|
3280
3303
|
return this.summaryManager.enqueueSummarize(options);
|