@fluidframework/container-runtime 2.113.1 → 2.115.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 +8 -0
- package/api-extractor/api-extractor-lint-legacyAlpha.cjs.json +5 -0
- package/api-extractor/api-extractor-lint-legacyAlpha.esm.json +5 -0
- package/api-extractor/api-extractor.legacy.json +5 -1
- package/api-report/container-runtime.legacy.alpha.api.md +453 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/containerRuntime.d.ts +7 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +100 -43
- package/dist/containerRuntime.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +1 -1
- package/dist/legacyAlpha.d.ts +76 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +7 -0
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +15 -0
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/public.d.ts +1 -1
- package/dist/runtimeLayerCompatState.d.ts +2 -2
- package/dist/versionMarks/inboundBatch.d.ts +36 -0
- package/dist/versionMarks/inboundBatch.d.ts.map +1 -0
- package/dist/versionMarks/inboundBatch.js +50 -0
- package/dist/versionMarks/inboundBatch.js.map +1 -0
- package/dist/versionMarks/index.d.ts +7 -0
- package/dist/versionMarks/index.d.ts.map +1 -0
- package/dist/versionMarks/index.js +12 -0
- package/dist/versionMarks/index.js.map +1 -0
- package/dist/versionMarks/versionMarkResolver.d.ts +162 -0
- package/dist/versionMarks/versionMarkResolver.d.ts.map +1 -0
- package/dist/versionMarks/versionMarkResolver.js +198 -0
- package/dist/versionMarks/versionMarkResolver.js.map +1 -0
- package/internal.d.ts +1 -1
- package/legacy/alpha.d.ts +11 -0
- package/legacy.d.ts +1 -1
- package/lib/containerRuntime.d.ts +7 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +57 -0
- package/lib/containerRuntime.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +1 -1
- package/lib/legacyAlpha.d.ts +76 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +7 -0
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +15 -0
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/runtimeLayerCompatState.d.ts +2 -2
- package/lib/versionMarks/inboundBatch.d.ts +36 -0
- package/lib/versionMarks/inboundBatch.d.ts.map +1 -0
- package/lib/versionMarks/inboundBatch.js +46 -0
- package/lib/versionMarks/inboundBatch.js.map +1 -0
- package/lib/versionMarks/index.d.ts +7 -0
- package/lib/versionMarks/index.d.ts.map +1 -0
- package/lib/versionMarks/index.js +7 -0
- package/lib/versionMarks/index.js.map +1 -0
- package/lib/versionMarks/versionMarkResolver.d.ts +162 -0
- package/lib/versionMarks/versionMarkResolver.d.ts.map +1 -0
- package/lib/versionMarks/versionMarkResolver.js +194 -0
- package/lib/versionMarks/versionMarkResolver.js.map +1 -0
- package/package.json +35 -23
- package/src/containerRuntime.ts +87 -0
- package/src/index.ts +5 -0
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +18 -0
- package/src/versionMarks/DEV.md +329 -0
- package/src/versionMarks/inboundBatch.ts +70 -0
- package/src/versionMarks/index.ts +13 -0
- package/src/versionMarks/versionMarkResolver.ts +341 -0
package/dist/containerRuntime.js
CHANGED
|
@@ -39,8 +39,9 @@ const pendingStateManager_js_1 = require("./pendingStateManager.js");
|
|
|
39
39
|
const runCounter_js_1 = require("./runCounter.js");
|
|
40
40
|
const runtimeLayerCompatState_js_1 = require("./runtimeLayerCompatState.js");
|
|
41
41
|
const signalTelemetryProcessing_js_1 = require("./signalTelemetryProcessing.js");
|
|
42
|
+
const index_js_4 = require("./versionMarks/index.js");
|
|
42
43
|
// These types are imported as types here because they are present in summaryDelayLoadedModule, which is loaded dynamically when required.
|
|
43
|
-
const
|
|
44
|
+
const index_js_5 = require("./summary/index.js");
|
|
44
45
|
const throttler_js_1 = require("./throttler.js");
|
|
45
46
|
/**
|
|
46
47
|
* ContainerRuntime's compatibility details that is exposed to Container Extensions.
|
|
@@ -345,12 +346,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
345
346
|
}
|
|
346
347
|
};
|
|
347
348
|
const [chunks, recentBatchInfo, metadata, electedSummarizerData, aliases, serializedIdCompressor,] = await Promise.all([
|
|
348
|
-
tryFetchBlob(
|
|
349
|
-
tryFetchBlob(
|
|
350
|
-
tryFetchBlob(
|
|
351
|
-
tryFetchBlob(
|
|
352
|
-
tryFetchBlob(
|
|
353
|
-
tryFetchBlob(
|
|
349
|
+
tryFetchBlob(index_js_5.chunksBlobName),
|
|
350
|
+
tryFetchBlob(index_js_5.recentBatchInfoBlobName),
|
|
351
|
+
tryFetchBlob(index_js_5.metadataBlobName),
|
|
352
|
+
tryFetchBlob(index_js_5.electedSummarizerBlobName),
|
|
353
|
+
tryFetchBlob(index_js_5.aliasBlobName),
|
|
354
|
+
tryFetchBlob(index_js_5.idCompressorBlobName),
|
|
354
355
|
]);
|
|
355
356
|
// read snapshot blobs needed for BlobManager to load
|
|
356
357
|
const blobManagerLoadInfo = await (0, index_js_1.loadBlobManagerLoadInfo)(context);
|
|
@@ -456,7 +457,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
456
457
|
};
|
|
457
458
|
const compressionLz4 = compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY &&
|
|
458
459
|
compressionOptions.compressionAlgorithm === "lz4";
|
|
459
|
-
const documentSchemaController = new
|
|
460
|
+
const documentSchemaController = new index_js_5.DocumentsSchemaController(existing, protocolSequenceNumber, metadata?.documentSchema, {
|
|
460
461
|
explicitSchemaControl,
|
|
461
462
|
compressionLz4,
|
|
462
463
|
idCompressorMode,
|
|
@@ -592,6 +593,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
592
593
|
get disposed() {
|
|
593
594
|
return this._disposed;
|
|
594
595
|
}
|
|
596
|
+
/**
|
|
597
|
+
* Host-facing version mark resolver.
|
|
598
|
+
*/
|
|
599
|
+
get versionMarkResolver() {
|
|
600
|
+
return this.versionMarkResolverInternal;
|
|
601
|
+
}
|
|
595
602
|
/**
|
|
596
603
|
* If false, loading or using a Tombstoned object should merely log, not fail.
|
|
597
604
|
* @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
|
|
@@ -622,7 +629,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
622
629
|
// // eslint-disable-next-line unicorn/no-object-as-default-parameter
|
|
623
630
|
summaryConfiguration = {
|
|
624
631
|
// the defaults
|
|
625
|
-
...
|
|
632
|
+
...index_js_5.DefaultSummaryConfiguration,
|
|
626
633
|
// the runtime configuration overrides
|
|
627
634
|
...runtimeOptions.summaryOptions?.summaryConfigOverrides,
|
|
628
635
|
}, recentBatchInfo) {
|
|
@@ -902,7 +909,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
902
909
|
// Values are generally expected to be set from the runtime side.
|
|
903
910
|
this.options = options ?? {};
|
|
904
911
|
this.clientDetails = clientDetails;
|
|
905
|
-
this.isSummarizerClient = this.clientDetails.type ===
|
|
912
|
+
this.isSummarizerClient = this.clientDetails.type === index_js_5.summarizerClientType;
|
|
906
913
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
907
914
|
this._getClientId = () => context.clientId;
|
|
908
915
|
this._getAttachState = () => context.attachState;
|
|
@@ -991,6 +998,42 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
991
998
|
this.notifyReadOnlyState();
|
|
992
999
|
},
|
|
993
1000
|
});
|
|
1001
|
+
// fetchOps is an internal-only capability the loader injects (IContainerContextInternal), not part
|
|
1002
|
+
// of the public IContainerContext contract, so narrow to read it.
|
|
1003
|
+
const fetchOps = context.fetchOps;
|
|
1004
|
+
this.versionMarkResolverInternal = new index_js_4.VersionMarkResolver({
|
|
1005
|
+
getCurrentSequenceNumber: () => this.deltaManager.lastSequenceNumber,
|
|
1006
|
+
getCurrentMinimumSequenceNumber: () => this.deltaManager.minimumSequenceNumber,
|
|
1007
|
+
getCurrentPendingBatchId: () => this.pendingStateManager.getMostRecentPendingBatchId(),
|
|
1008
|
+
logger: (0, internal_8.createChildLogger)({
|
|
1009
|
+
logger: this.baseLogger,
|
|
1010
|
+
namespace: "VersionMarkResolver",
|
|
1011
|
+
}),
|
|
1012
|
+
// Seal the current outbound batch so a just-submitted edit gets a stable batchId in the pending
|
|
1013
|
+
// state before sealAndCaptureVersionMark reads it (a batchId is only assigned when flushed).
|
|
1014
|
+
flushPendingBatch: () => this.flush(),
|
|
1015
|
+
// Wire the container-provided op reader (if any) so resolution can read historical ops.
|
|
1016
|
+
getHistoricalOpReader: fetchOps ? () => ({ fetchMessages: fetchOps }) : undefined,
|
|
1017
|
+
// Unpack scanned historical ops through the same pipeline the live inbound path uses, so a
|
|
1018
|
+
// chunked batch's batchId (only restored after reassembly) is observed by the history scan too.
|
|
1019
|
+
createHistoricalOpUnpacker: fetchOps
|
|
1020
|
+
? () => {
|
|
1021
|
+
// A fresh processor per scan: it holds chunk-reassembly state, so it must not share
|
|
1022
|
+
// the live inbound processor's state. submit/size args are unused on the read path.
|
|
1023
|
+
const scanProcessor = new index_js_3.RemoteMessageProcessor(new index_js_3.OpSplitter([], submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger), new index_js_3.OpDecompressor(this.mc.logger), new index_js_3.OpGroupingManager({ groupedBatchingEnabled: this.groupedBatchingEnabled }, this.mc.logger));
|
|
1024
|
+
return (op) => {
|
|
1025
|
+
// Mirror the live path: only modern runtime-envelope ops (type Operation, with a
|
|
1026
|
+
// client id) carry batches; skip system/server ops.
|
|
1027
|
+
if (op.type !== internal_3.MessageType.Operation || typeof op.clientId !== "string") {
|
|
1028
|
+
return undefined;
|
|
1029
|
+
}
|
|
1030
|
+
const messageCopy = { ...op };
|
|
1031
|
+
(0, index_js_3.ensureContentsDeserialized)(messageCopy);
|
|
1032
|
+
return scanProcessor.process(messageCopy, (0, exports.getSingleUseLegacyLogCallback)(this.mc.logger, messageCopy.type));
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
: undefined,
|
|
1036
|
+
});
|
|
994
1037
|
let outerDeltaManager = this.innerDeltaManager;
|
|
995
1038
|
this.useDeltaManagerOpsProxy =
|
|
996
1039
|
this.mc.config.getBoolean("Fluid.ContainerRuntime.DeltaManagerOpsProxy") === true;
|
|
@@ -1009,10 +1052,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1009
1052
|
: new deltaManagerProxies_js_1.BaseDeltaManagerProxy(outerDeltaManager);
|
|
1010
1053
|
this.handleContext = new containerHandleContext_js_1.ContainerFluidHandleContext("", this);
|
|
1011
1054
|
if (this.summaryConfiguration.state === "enabled") {
|
|
1012
|
-
(0,
|
|
1055
|
+
(0, index_js_5.validateSummaryHeuristicConfiguration)(this.summaryConfiguration);
|
|
1013
1056
|
}
|
|
1014
1057
|
this.summariesDisabled =
|
|
1015
|
-
(0,
|
|
1058
|
+
(0, index_js_5.isSummariesDisabled)(this.summaryConfiguration) ||
|
|
1016
1059
|
this.mc.config.getBoolean("Fluid.ContainerRuntime.Test.DisableSummaries") === true;
|
|
1017
1060
|
this.maxConsecutiveReconnects =
|
|
1018
1061
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ?? defaultMaxConsecutiveReconnects;
|
|
@@ -1096,7 +1139,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1096
1139
|
const summaryReferenceSequenceNumber = baseSnapshot === undefined || metadata?.disableIsolatedChannels === true
|
|
1097
1140
|
? undefined
|
|
1098
1141
|
: loadedFromSequenceNumber;
|
|
1099
|
-
this.summarizerNode = (0,
|
|
1142
|
+
this.summarizerNode = (0, index_js_5.createRootSummarizerNodeWithGC)((0, internal_8.createChildLogger)({ logger: this.baseLogger, namespace: "SummarizerNode" }),
|
|
1100
1143
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
1101
1144
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
1102
1145
|
// Latest change sequence number, no changes since summary applied yet
|
|
@@ -1337,7 +1380,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1337
1380
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
1338
1381
|
return;
|
|
1339
1382
|
}
|
|
1340
|
-
const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = (0,
|
|
1383
|
+
const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = (0, index_js_5.isSummariesDisabled)(this.summaryConfiguration)
|
|
1341
1384
|
? {}
|
|
1342
1385
|
: {
|
|
1343
1386
|
...this.summaryConfiguration,
|
|
@@ -1347,8 +1390,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1347
1390
|
this.runtimeOptions.summaryOptions.initialSummarizerDelayMs ??
|
|
1348
1391
|
this.summaryConfiguration.initialSummarizerDelayMs,
|
|
1349
1392
|
};
|
|
1350
|
-
const summaryCollection = new
|
|
1351
|
-
const onRequestMode = (0,
|
|
1393
|
+
const summaryCollection = new index_js_5.SummaryCollection(this.deltaManager, this.baseLogger);
|
|
1394
|
+
const onRequestMode = (0, index_js_5.isSummaryOnRequest)(this.summaryConfiguration);
|
|
1352
1395
|
if (this.isSummarizerClient) {
|
|
1353
1396
|
// We want to dynamically import any thing inside summaryDelayLoadedModule module only when we are the summarizer client,
|
|
1354
1397
|
// so that all non summarizer clients don't have to load the code inside this module.
|
|
@@ -1370,16 +1413,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1370
1413
|
() => this.innerDeltaManager.active));
|
|
1371
1414
|
}
|
|
1372
1415
|
else if (!onRequestMode &&
|
|
1373
|
-
|
|
1416
|
+
index_js_5.SummarizerClientElection.clientDetailsPermitElection(this.clientDetails)) {
|
|
1374
1417
|
// Only create a SummaryManager and SummarizerClientElection
|
|
1375
1418
|
// if summaries are enabled and we are not the summarizer client.
|
|
1376
1419
|
const orderedClientLogger = (0, internal_8.createChildLogger)({
|
|
1377
1420
|
logger: this.baseLogger,
|
|
1378
1421
|
namespace: "OrderedClientElection",
|
|
1379
1422
|
});
|
|
1380
|
-
const orderedClientCollection = new
|
|
1381
|
-
const orderedClientElectionForSummarizer = new
|
|
1382
|
-
this.summarizerClientElection = new
|
|
1423
|
+
const orderedClientCollection = new index_js_5.OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
|
|
1424
|
+
const orderedClientElectionForSummarizer = new index_js_5.OrderedClientElection(orderedClientLogger, orderedClientCollection, this.electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, index_js_5.SummarizerClientElection.isClientEligible, this.mc.config.getBoolean("Fluid.ContainerRuntime.OrderedClientElection.EnablePerformanceEvents"));
|
|
1425
|
+
this.summarizerClientElection = new index_js_5.SummarizerClientElection(orderedClientLogger, summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary);
|
|
1383
1426
|
const defaultAction = () => {
|
|
1384
1427
|
if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
|
|
1385
1428
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -1402,8 +1445,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1402
1445
|
};
|
|
1403
1446
|
summaryCollection.on("default", defaultAction);
|
|
1404
1447
|
// Create the SummaryManager and mark the initial state
|
|
1405
|
-
this.summaryManager = new
|
|
1406
|
-
summaryCollection, this.baseLogger, (0,
|
|
1448
|
+
this.summaryManager = new index_js_5.SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
1449
|
+
summaryCollection, this.baseLogger, (0, index_js_5.formCreateSummarizerFn)(loader), new throttler_js_1.Throttler(60 * 1000, // 60 sec delay window
|
|
1407
1450
|
30 * 1000, // 30 sec max delay
|
|
1408
1451
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
1409
1452
|
(0, throttler_js_1.formExponentialFn)({ coefficient: 20, initialDelay: 0 })), {
|
|
@@ -1484,7 +1527,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1484
1527
|
}),
|
|
1485
1528
|
});
|
|
1486
1529
|
// Find the snapshotTree inside the returned snapshot based on the path as given in the request.
|
|
1487
|
-
const hasIsolatedChannels = (0,
|
|
1530
|
+
const hasIsolatedChannels = (0, index_js_5.rootHasIsolatedChannels)(this.metadata);
|
|
1488
1531
|
const snapshotTreeForPath = this.getSnapshotTreeForPath(snapshot.snapshotTree, pathParts, hasIsolatedChannels);
|
|
1489
1532
|
(0, internal_2.assert)(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
|
|
1490
1533
|
const snapshotSeqNumber = snapshot.sequenceNumber;
|
|
@@ -1563,7 +1606,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1563
1606
|
try {
|
|
1564
1607
|
const parser = internal_7.RequestParser.create(request);
|
|
1565
1608
|
const id = parser.pathParts[0];
|
|
1566
|
-
if (id ===
|
|
1609
|
+
if (id === index_js_5.summarizerRequestUrl && parser.pathParts.length === 1) {
|
|
1567
1610
|
if (this._summarizer !== undefined) {
|
|
1568
1611
|
return {
|
|
1569
1612
|
status: 200,
|
|
@@ -1633,7 +1676,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1633
1676
|
addMetadataToSummary(summaryTree) {
|
|
1634
1677
|
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
1635
1678
|
// last summary.
|
|
1636
|
-
const message = (0,
|
|
1679
|
+
const message = (0, index_js_5.extractSummaryMetadataMessage)(this.deltaManager.lastMessage) ??
|
|
1637
1680
|
this.messageAtLastSummary;
|
|
1638
1681
|
const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
|
|
1639
1682
|
// Is document schema explicit control on?
|
|
@@ -1656,29 +1699,29 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1656
1699
|
lastMessage: explicitSchemaControl ? message : undefined,
|
|
1657
1700
|
documentSchema,
|
|
1658
1701
|
};
|
|
1659
|
-
(0, internal_7.addBlobToSummary)(summaryTree,
|
|
1702
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_5.metadataBlobName, JSON.stringify(metadata));
|
|
1660
1703
|
}
|
|
1661
1704
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
1662
1705
|
this.addMetadataToSummary(summaryTree);
|
|
1663
1706
|
if (this._idCompressor) {
|
|
1664
1707
|
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
1665
|
-
(0, internal_7.addBlobToSummary)(summaryTree,
|
|
1708
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_5.idCompressorBlobName, idCompressorState);
|
|
1666
1709
|
}
|
|
1667
1710
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
1668
1711
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
1669
|
-
(0, internal_7.addBlobToSummary)(summaryTree,
|
|
1712
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_5.chunksBlobName, content);
|
|
1670
1713
|
}
|
|
1671
1714
|
const recentBatchInfo = this.duplicateBatchDetector?.getRecentBatchInfoForSummary(telemetryContext);
|
|
1672
1715
|
if (recentBatchInfo !== undefined) {
|
|
1673
|
-
(0, internal_7.addBlobToSummary)(summaryTree,
|
|
1716
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_5.recentBatchInfoBlobName, JSON.stringify(recentBatchInfo));
|
|
1674
1717
|
}
|
|
1675
1718
|
const dataStoreAliases = this.channelCollection.aliases;
|
|
1676
1719
|
if (dataStoreAliases.size > 0) {
|
|
1677
|
-
(0, internal_7.addBlobToSummary)(summaryTree,
|
|
1720
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_5.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
1678
1721
|
}
|
|
1679
1722
|
if (this.summarizerClientElection) {
|
|
1680
1723
|
const electedSummarizerContent = JSON.stringify(this.summarizerClientElection?.serialize());
|
|
1681
|
-
(0, internal_7.addBlobToSummary)(summaryTree,
|
|
1724
|
+
(0, internal_7.addBlobToSummary)(summaryTree, index_js_5.electedSummarizerBlobName, electedSummarizerContent);
|
|
1682
1725
|
}
|
|
1683
1726
|
const blobManagerSummary = this.blobManager.summarize();
|
|
1684
1727
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
@@ -2054,6 +2097,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2054
2097
|
// or to check to ensure the *remote* messages don't match the batchId of a pending local batch.
|
|
2055
2098
|
// This latter case would indicate that the container has forked - two copies are trying to persist the same local changes.
|
|
2056
2099
|
let messagesWithPendingState = this.pendingStateManager.processInboundMessages(inboundResult, local);
|
|
2100
|
+
// Record the version-mark point for a completed batch (its last op's sequence number), carrying
|
|
2101
|
+
// the batch id across a piecemeal batch's messages. This runs only AFTER processInboundMessages
|
|
2102
|
+
// has validated the batch: that call throws (fork detection / pending-content mismatch) for a
|
|
2103
|
+
// batch that must be rejected. processInboundBatch synchronously notifies listeners, which an
|
|
2104
|
+
// app uses to promote a mark in an external store - an irreversible side effect - so it must not
|
|
2105
|
+
// fire for a batch validation is about to reject. Gated on isTracking so a container that never
|
|
2106
|
+
// uses version marks does no per-batch work here (mirrors #22497's DuplicateBatchDetector gating).
|
|
2107
|
+
if (this.versionMarkResolverInternal.isTracking) {
|
|
2108
|
+
const versionMarkUpdate = (0, index_js_4.inboundVersionMarkUpdate)(inboundResult, this.versionMarkInboundBatchId);
|
|
2109
|
+
if (versionMarkUpdate.sequenced !== undefined) {
|
|
2110
|
+
this.versionMarkResolverInternal.processInboundBatch(versionMarkUpdate.sequenced.batchId, versionMarkUpdate.sequenced.sequenceNumber);
|
|
2111
|
+
}
|
|
2112
|
+
this.versionMarkInboundBatchId = versionMarkUpdate.carriedBatchId;
|
|
2113
|
+
}
|
|
2057
2114
|
if (inboundResult.type !== "fullBatch") {
|
|
2058
2115
|
(0, internal_2.assert)(messagesWithPendingState.length === 1, 0xa3d /* Partial batch should have exactly one message */);
|
|
2059
2116
|
}
|
|
@@ -2591,7 +2648,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2591
2648
|
}
|
|
2592
2649
|
const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
|
|
2593
2650
|
// Wrap data store summaries in .channels subtree.
|
|
2594
|
-
(0,
|
|
2651
|
+
(0, index_js_5.wrapSummaryInChannelsTree)(summarizeResult);
|
|
2595
2652
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
2596
2653
|
return summarizeResult.summary;
|
|
2597
2654
|
}
|
|
@@ -2604,7 +2661,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2604
2661
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
2605
2662
|
const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
|
|
2606
2663
|
// Wrap data store summaries in .channels subtree.
|
|
2607
|
-
(0,
|
|
2664
|
+
(0, index_js_5.wrapSummaryInChannelsTree)(summarizeResult);
|
|
2608
2665
|
const pathPartsForChildren = [internal_6.channelsTreeName];
|
|
2609
2666
|
this.loadIdCompressor();
|
|
2610
2667
|
this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
|
|
@@ -2888,7 +2945,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2888
2945
|
stage: "base",
|
|
2889
2946
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
2890
2947
|
minimumSequenceNumber,
|
|
2891
|
-
error: new
|
|
2948
|
+
error: new index_js_5.RetriableSummaryError(`Summarizer node state inconsistent with summarizer state.`),
|
|
2892
2949
|
};
|
|
2893
2950
|
}
|
|
2894
2951
|
}
|
|
@@ -2932,7 +2989,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2932
2989
|
stage: "base",
|
|
2933
2990
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
2934
2991
|
minimumSequenceNumber,
|
|
2935
|
-
error: new
|
|
2992
|
+
error: new index_js_5.RetriableSummaryError(continueResult.error),
|
|
2936
2993
|
};
|
|
2937
2994
|
}
|
|
2938
2995
|
const trace = client_utils_1.Trace.start();
|
|
@@ -2951,14 +3008,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2951
3008
|
stage: "base",
|
|
2952
3009
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
2953
3010
|
minimumSequenceNumber,
|
|
2954
|
-
error: (0, internal_8.wrapError)(error, (msg) => new
|
|
3011
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_5.RetriableSummaryError(msg)),
|
|
2955
3012
|
};
|
|
2956
3013
|
}
|
|
2957
3014
|
// Validate that the summary generated by summarizer nodes is correct before uploading.
|
|
2958
3015
|
const validateResult = this.summarizerNode.validateSummary();
|
|
2959
3016
|
if (!validateResult.success) {
|
|
2960
3017
|
const { success, ...loggingProps } = validateResult;
|
|
2961
|
-
const error = new
|
|
3018
|
+
const error = new index_js_5.RetriableSummaryError(validateResult.reason, validateResult.retryAfterSeconds, { ...loggingProps });
|
|
2962
3019
|
return {
|
|
2963
3020
|
stage: "base",
|
|
2964
3021
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
@@ -3005,7 +3062,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3005
3062
|
return {
|
|
3006
3063
|
stage: "generate",
|
|
3007
3064
|
...generateSummaryData,
|
|
3008
|
-
error: new
|
|
3065
|
+
error: new index_js_5.RetriableSummaryError(continueResult.error),
|
|
3009
3066
|
};
|
|
3010
3067
|
}
|
|
3011
3068
|
const summaryContext = {
|
|
@@ -3021,7 +3078,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3021
3078
|
return {
|
|
3022
3079
|
stage: "generate",
|
|
3023
3080
|
...generateSummaryData,
|
|
3024
|
-
error: (0, internal_8.wrapError)(error, (msg) => new
|
|
3081
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_5.RetriableSummaryError(msg)),
|
|
3025
3082
|
};
|
|
3026
3083
|
}
|
|
3027
3084
|
const parent = summaryContext.ackHandle;
|
|
@@ -3042,7 +3099,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3042
3099
|
return {
|
|
3043
3100
|
stage: "upload",
|
|
3044
3101
|
...uploadData,
|
|
3045
|
-
error: new
|
|
3102
|
+
error: new index_js_5.RetriableSummaryError(continueResult.error),
|
|
3046
3103
|
};
|
|
3047
3104
|
}
|
|
3048
3105
|
let clientSequenceNumber;
|
|
@@ -3053,7 +3110,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3053
3110
|
return {
|
|
3054
3111
|
stage: "upload",
|
|
3055
3112
|
...uploadData,
|
|
3056
|
-
error: (0, internal_8.wrapError)(error, (msg) => new
|
|
3113
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_5.RetriableSummaryError(msg)),
|
|
3057
3114
|
};
|
|
3058
3115
|
}
|
|
3059
3116
|
const submitData = {
|
|
@@ -3069,7 +3126,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3069
3126
|
return {
|
|
3070
3127
|
stage: "upload",
|
|
3071
3128
|
...uploadData,
|
|
3072
|
-
error: (0, internal_8.wrapError)(error, (msg) => new
|
|
3129
|
+
error: (0, internal_8.wrapError)(error, (msg) => new index_js_5.RetriableSummaryError(msg)),
|
|
3073
3130
|
};
|
|
3074
3131
|
}
|
|
3075
3132
|
return submitData;
|
|
@@ -3117,7 +3174,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3117
3174
|
// based on telemetry while we decide on a stable number.
|
|
3118
3175
|
const retryDelayMs = this.mc.config.getNumber("Fluid.Summarizer.PendingOpsRetryDelayMs") ??
|
|
3119
3176
|
exports.defaultPendingOpsRetryDelayMs;
|
|
3120
|
-
const error = new
|
|
3177
|
+
const error = new index_js_5.RetriableSummaryError("PendingOpsWhileSummarizing", retryDelayMs / 1000, {
|
|
3121
3178
|
count: this.pendingMessagesCount,
|
|
3122
3179
|
beforeGenerate: beforeSummaryGeneration,
|
|
3123
3180
|
});
|