@fluidframework/container-runtime 1.2.2 → 2.0.0-internal.1.0.0.82159
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/dist/blobManager.d.ts +81 -25
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +301 -100
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +65 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +101 -82
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +32 -26
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +3 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +16 -23
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +5 -2
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +11 -3
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +17 -12
- package/dist/garbageCollection.js.map +1 -1
- package/dist/opProperties.d.ts +7 -0
- package/dist/opProperties.d.ts.map +1 -0
- package/dist/opProperties.js +20 -0
- package/dist/opProperties.js.map +1 -0
- 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/runningSummarizer.d.ts +14 -4
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +68 -26
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizer.d.ts +0 -2
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +1 -12
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts +26 -4
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +95 -18
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +30 -10
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.js +1 -1
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryFormat.d.ts +0 -5
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts +1 -0
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +11 -9
- package/dist/summaryGenerator.js.map +1 -1
- package/lib/blobManager.d.ts +81 -25
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +302 -101
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +65 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +103 -84
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +32 -26
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +3 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +17 -24
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +5 -2
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +11 -3
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +17 -12
- package/lib/garbageCollection.js.map +1 -1
- package/lib/opProperties.d.ts +7 -0
- package/lib/opProperties.d.ts.map +1 -0
- package/lib/opProperties.js +16 -0
- package/lib/opProperties.js.map +1 -0
- 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/runningSummarizer.d.ts +14 -4
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +68 -26
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizer.d.ts +0 -2
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +1 -12
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts +26 -4
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +95 -18
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +30 -10
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.js +1 -1
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryFormat.d.ts +0 -5
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts +1 -0
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +11 -9
- package/lib/summaryGenerator.js.map +1 -1
- package/package.json +45 -20
- package/src/blobManager.ts +360 -119
- package/src/containerRuntime.ts +203 -103
- package/src/dataStore.ts +53 -38
- package/src/dataStoreContext.ts +16 -23
- package/src/dataStores.ts +14 -3
- package/src/garbageCollection.ts +13 -7
- package/src/opProperties.ts +19 -0
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +75 -22
- package/src/summarizer.ts +1 -18
- package/src/summarizerHeuristics.ts +133 -19
- package/src/summarizerTypes.ts +37 -10
- package/src/summaryCollection.ts +1 -1
- package/src/summaryFormat.ts +0 -6
- package/src/summaryGenerator.ts +40 -22
- package/dist/opTelemetry.d.ts +0 -22
- package/dist/opTelemetry.d.ts.map +0 -1
- package/dist/opTelemetry.js +0 -59
- package/dist/opTelemetry.js.map +0 -1
- package/lib/opTelemetry.d.ts +0 -22
- package/lib/opTelemetry.d.ts.map +0 -1
- package/lib/opTelemetry.js +0 -55
- package/lib/opTelemetry.js.map +0 -1
- package/src/opTelemetry.ts +0 -71
package/dist/containerRuntime.js
CHANGED
|
@@ -32,7 +32,6 @@ const garbageCollection_1 = require("./garbageCollection");
|
|
|
32
32
|
const dataStore_1 = require("./dataStore");
|
|
33
33
|
const batchTracker_1 = require("./batchTracker");
|
|
34
34
|
const serializedSnapshotStorage_1 = require("./serializedSnapshotStorage");
|
|
35
|
-
const opTelemetry_1 = require("./opTelemetry");
|
|
36
35
|
var ContainerMessageType;
|
|
37
36
|
(function (ContainerMessageType) {
|
|
38
37
|
// An op to be delivered to store
|
|
@@ -50,14 +49,18 @@ var ContainerMessageType;
|
|
|
50
49
|
})(ContainerMessageType = exports.ContainerMessageType || (exports.ContainerMessageType = {}));
|
|
51
50
|
exports.DefaultSummaryConfiguration = {
|
|
52
51
|
state: "enabled",
|
|
53
|
-
idleTime:
|
|
54
|
-
|
|
52
|
+
idleTime: 15 * 1000,
|
|
53
|
+
minIdleTime: 0,
|
|
54
|
+
maxIdleTime: 30 * 1000,
|
|
55
|
+
maxTime: 60 * 1000,
|
|
55
56
|
maxOps: 100,
|
|
56
57
|
minOpsForLastSummaryAttempt: 10,
|
|
57
|
-
maxAckWaitTime:
|
|
58
|
+
maxAckWaitTime: 10 * 60 * 1000,
|
|
58
59
|
maxOpsSinceLastSummary: 7000,
|
|
59
|
-
initialSummarizerDelayMs:
|
|
60
|
+
initialSummarizerDelayMs: 5 * 1000,
|
|
60
61
|
summarizerClientElection: false,
|
|
62
|
+
nonRuntimeOpWeight: 0.1,
|
|
63
|
+
runtimeOpWeight: 1.0,
|
|
61
64
|
};
|
|
62
65
|
/**
|
|
63
66
|
* Accepted header keys for requests coming to the runtime.
|
|
@@ -84,10 +87,6 @@ const maxOpSizeInBytesKey = "Fluid.ContainerRuntime.MaxOpSizeInBytes";
|
|
|
84
87
|
// in order to account for some extra overhead from serialization
|
|
85
88
|
// to not reach the 1MB limits in socket.io and Kafka.
|
|
86
89
|
const defaultMaxOpSizeInBytes = 768000;
|
|
87
|
-
// By default, the size of the contents for the incoming ops is tracked.
|
|
88
|
-
// However, in certain situations, this may incur a performance hit.
|
|
89
|
-
// The feature-gate below can be used to disable this feature.
|
|
90
|
-
const disableOpTrackingKey = "Fluid.ContainerRuntime.DisableOpTracking";
|
|
91
90
|
const defaultFlushMode = runtime_definitions_1.FlushMode.TurnBased;
|
|
92
91
|
var RuntimeMessage;
|
|
93
92
|
(function (RuntimeMessage) {
|
|
@@ -380,7 +379,7 @@ exports.getDeviceSpec = getDeviceSpec;
|
|
|
380
379
|
*/
|
|
381
380
|
class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
382
381
|
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration) {
|
|
383
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
382
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
384
383
|
if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, exports.DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
|
|
385
384
|
super();
|
|
386
385
|
this.context = context;
|
|
@@ -441,6 +440,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
441
440
|
this.chunkMap = new Map(chunks);
|
|
442
441
|
this.handleContext = new containerHandleContext_1.ContainerFluidHandleContext("", this);
|
|
443
442
|
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
443
|
+
if (this.summaryConfiguration.state === "enabled") {
|
|
444
|
+
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
445
|
+
}
|
|
444
446
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
445
447
|
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
446
448
|
this.summarizerClientElectionEnabled = this.isSummarizerClientElectionEnabled();
|
|
@@ -488,7 +490,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
488
490
|
this.summarizerNode.loadBaseSummaryWithoutDifferential(baseSnapshot);
|
|
489
491
|
}
|
|
490
492
|
this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getBaseGCDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getBaseGCDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getBaseGCDetails(), (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), new Map(dataStoreAliasMap), this.garbageCollector.writeDataAtRoot);
|
|
491
|
-
this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), this
|
|
493
|
+
this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId, localId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId, localId }), (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), this);
|
|
492
494
|
this.scheduleManager = new ScheduleManager(context.deltaManager, this, telemetry_utils_1.ChildLogger.create(this.logger, "ScheduleManager"));
|
|
493
495
|
this.deltaSender = this.deltaManager;
|
|
494
496
|
this.pendingStateManager = new pendingStateManager_1.PendingStateManager({
|
|
@@ -579,9 +581,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
579
581
|
createContainerRuntimeVersion: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerRuntimeVersion,
|
|
580
582
|
createContainerTimestamp: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerTimestamp,
|
|
581
583
|
};
|
|
582
|
-
//
|
|
583
|
-
//
|
|
584
|
-
loadSummaryNumber = (
|
|
584
|
+
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
585
|
+
// the count is reset to 0.
|
|
586
|
+
loadSummaryNumber = (_h = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _h !== void 0 ? _h : 0;
|
|
585
587
|
}
|
|
586
588
|
else {
|
|
587
589
|
this.createContainerMetadata = {
|
|
@@ -594,7 +596,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
594
596
|
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, summaryFormatVersion: metadata === null || metadata === void 0 ? void 0 : metadata.summaryFormatVersion, disableIsolatedChannels: metadata === null || metadata === void 0 ? void 0 : metadata.disableIsolatedChannels, gcVersion: metadata === null || metadata === void 0 ? void 0 : metadata.gcFeature }));
|
|
595
597
|
(0, connectionTelemetry_1.ReportOpPerfTelemetry)(this.context.clientId, this.deltaManager, this.logger);
|
|
596
598
|
(0, batchTracker_1.BindBatchTracker)(this, this.logger);
|
|
597
|
-
this.opTracker = new opTelemetry_1.OpTracker(this.deltaManager, this.mc.config.getBoolean(disableOpTrackingKey) === true);
|
|
598
599
|
}
|
|
599
600
|
get IContainerRuntime() { return this; }
|
|
600
601
|
get IFluidRouter() { return this; }
|
|
@@ -863,12 +864,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
863
864
|
return this.resolveHandle(requestParser.createSubRequest(1));
|
|
864
865
|
}
|
|
865
866
|
if (id === blobManager_1.BlobManager.basePath && requestParser.isLeaf(2)) {
|
|
866
|
-
const
|
|
867
|
-
if (
|
|
867
|
+
const blob = await this.blobManager.getBlob(requestParser.pathParts[1]);
|
|
868
|
+
if (blob) {
|
|
868
869
|
return {
|
|
869
870
|
status: 200,
|
|
870
871
|
mimeType: "fluid/object",
|
|
871
|
-
value:
|
|
872
|
+
value: blob,
|
|
872
873
|
};
|
|
873
874
|
}
|
|
874
875
|
else {
|
|
@@ -891,13 +892,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
891
892
|
}
|
|
892
893
|
internalId(maybeAlias) {
|
|
893
894
|
var _a;
|
|
894
|
-
return (_a = this.dataStores.aliases
|
|
895
|
+
return (_a = this.dataStores.aliases.get(maybeAlias)) !== null && _a !== void 0 ? _a : maybeAlias;
|
|
895
896
|
}
|
|
896
897
|
async getDataStoreFromRequest(id, request) {
|
|
897
898
|
var _a, _b, _c;
|
|
898
899
|
const wait = typeof ((_a = request.headers) === null || _a === void 0 ? void 0 : _a[RuntimeHeaders.wait]) === "boolean"
|
|
899
900
|
? (_b = request.headers) === null || _b === void 0 ? void 0 : _b[RuntimeHeaders.wait]
|
|
900
901
|
: true;
|
|
902
|
+
await this.dataStores.waitIfPendingAlias(id);
|
|
901
903
|
const internalId = this.internalId(id);
|
|
902
904
|
const dataStoreContext = await this.dataStores.getDataStore(internalId, wait);
|
|
903
905
|
/**
|
|
@@ -927,8 +929,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
927
929
|
addMetadataToSummary(summaryTree) {
|
|
928
930
|
var _a;
|
|
929
931
|
const metadata = Object.assign(Object.assign(Object.assign(Object.assign({}, this.createContainerMetadata), {
|
|
930
|
-
// back-compat 0.59.3000: This is renamed to summaryNumber. Can be removed when 0.59.3000 saturates.
|
|
931
|
-
summaryCount: this.nextSummaryNumber,
|
|
932
932
|
// Increment the summary number for the next summary that will be generated.
|
|
933
933
|
summaryNumber: this.nextSummaryNumber++, summaryFormatVersion: 1, disableIsolatedChannels: this.disableIsolatedChannels || undefined }), this.garbageCollector.getMetadata()), {
|
|
934
934
|
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
@@ -943,7 +943,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
943
943
|
const content = JSON.stringify([...this.chunkMap]);
|
|
944
944
|
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summaryFormat_1.chunksBlobName, content);
|
|
945
945
|
}
|
|
946
|
-
const dataStoreAliases = this.dataStores.aliases
|
|
946
|
+
const dataStoreAliases = this.dataStores.aliases;
|
|
947
947
|
if (dataStoreAliases.size > 0) {
|
|
948
948
|
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summaryFormat_1.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
949
949
|
}
|
|
@@ -1040,6 +1040,35 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1040
1040
|
}
|
|
1041
1041
|
}
|
|
1042
1042
|
setConnectionState(connected, clientId) {
|
|
1043
|
+
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
1044
|
+
this.delayConnectClientId = undefined;
|
|
1045
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1046
|
+
eventName: "UnsuccessfulConnectedTransition",
|
|
1047
|
+
});
|
|
1048
|
+
// Don't propagate "disconnected" event because we didn't propagate the previous "connected" event
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
// If attachment blobs were added while disconnected, we need to delay
|
|
1052
|
+
// propagation of the "connected" event until we have uploaded them to
|
|
1053
|
+
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
1054
|
+
const connecting = connected && !this._connected && !this.deltaManager.readOnlyInfo.readonly;
|
|
1055
|
+
if (connecting && this.blobManager.hasPendingOfflineUploads) {
|
|
1056
|
+
(0, common_utils_1.assert)(!this.delayConnectClientId, "Connect event delay must be canceled before subsequent connect event");
|
|
1057
|
+
(0, common_utils_1.assert)(!!clientId, "Must have clientId when connecting");
|
|
1058
|
+
this.delayConnectClientId = clientId;
|
|
1059
|
+
this.blobManager.onConnected().then(() => {
|
|
1060
|
+
// make sure we didn't reconnect before the promise resolved
|
|
1061
|
+
if (this.delayConnectClientId === clientId && !this.disposed) {
|
|
1062
|
+
this.delayConnectClientId = undefined;
|
|
1063
|
+
this.setConnectionStateCore(connected, clientId);
|
|
1064
|
+
}
|
|
1065
|
+
}, (error) => this.closeFn(error));
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
this.setConnectionStateCore(connected, clientId);
|
|
1069
|
+
}
|
|
1070
|
+
setConnectionStateCore(connected, clientId) {
|
|
1071
|
+
(0, common_utils_1.assert)(!this.delayConnectClientId, "connect event delay must be cleared before propagating connect event");
|
|
1043
1072
|
this.verifyNotClosed();
|
|
1044
1073
|
// There might be no change of state due to Container calling this API after loading runtime.
|
|
1045
1074
|
const changeOfState = this._connected !== connected;
|
|
@@ -1070,7 +1099,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1070
1099
|
(0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, connected, clientId);
|
|
1071
1100
|
}
|
|
1072
1101
|
process(messageArg, local) {
|
|
1073
|
-
var _a
|
|
1102
|
+
var _a;
|
|
1074
1103
|
this.verifyNotClosed();
|
|
1075
1104
|
// If it's not message for runtime, bail out right away.
|
|
1076
1105
|
if (!(0, driver_utils_1.isUnpackedRuntimeMessage)(messageArg)) {
|
|
@@ -1117,8 +1146,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1117
1146
|
this.dataStores.processFluidDataStoreOp(message, local, localOpMetadata);
|
|
1118
1147
|
break;
|
|
1119
1148
|
case ContainerMessageType.BlobAttach:
|
|
1120
|
-
|
|
1121
|
-
this.blobManager.processBlobAttachOp(message.metadata.blobId, local);
|
|
1149
|
+
this.blobManager.processBlobAttachOp(message, local);
|
|
1122
1150
|
break;
|
|
1123
1151
|
default:
|
|
1124
1152
|
}
|
|
@@ -1188,6 +1216,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1188
1216
|
this.dataStores.processSignal(envelope.address, transformed, local);
|
|
1189
1217
|
}
|
|
1190
1218
|
async getRootDataStore(id, wait = true) {
|
|
1219
|
+
return this.getRootDataStoreChannel(id, wait);
|
|
1220
|
+
}
|
|
1221
|
+
async getRootDataStoreChannel(id, wait = true) {
|
|
1222
|
+
await this.dataStores.waitIfPendingAlias(id);
|
|
1191
1223
|
const internalId = this.internalId(id);
|
|
1192
1224
|
const context = await this.dataStores.getDataStore(internalId, wait);
|
|
1193
1225
|
(0, common_utils_1.assert)(await context.isRoot(), 0x12b /* "did not get root data store" */);
|
|
@@ -1288,14 +1320,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1288
1320
|
*/
|
|
1289
1321
|
async createRootDataStoreLegacy(pkg, rootDataStoreId) {
|
|
1290
1322
|
const fluidDataStore = await this._createDataStore(pkg, true /* isRoot */, rootDataStoreId);
|
|
1291
|
-
|
|
1292
|
-
// older versions, we still have to call bindToContext.
|
|
1293
|
-
if (fluidDataStore.makeVisibleAndAttachGraph !== undefined) {
|
|
1294
|
-
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1295
|
-
}
|
|
1296
|
-
else {
|
|
1297
|
-
fluidDataStore.bindToContext();
|
|
1298
|
-
}
|
|
1323
|
+
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1299
1324
|
return fluidDataStore;
|
|
1300
1325
|
}
|
|
1301
1326
|
/**
|
|
@@ -1322,23 +1347,22 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1322
1347
|
*/
|
|
1323
1348
|
async createAndAliasDataStore(pkg, alias, props) {
|
|
1324
1349
|
const internalId = (0, uuid_1.v4)();
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1350
|
+
try {
|
|
1351
|
+
// A similar call may have been initiated by the same client, so we should try to get
|
|
1352
|
+
// a possible existing aliased datastore first.
|
|
1353
|
+
const existingDataStore = await this.getRootDataStoreChannel(alias, /* wait */ false);
|
|
1354
|
+
return (0, dataStore_1.channelToDataStore)(existingDataStore, internalId, this, this.dataStores, this.mc.logger, true);
|
|
1355
|
+
}
|
|
1356
|
+
catch (err) {
|
|
1357
|
+
const newChannel = await this._createDataStore(pkg, false /* isRoot */, internalId, props);
|
|
1358
|
+
const newDataStore = (0, dataStore_1.channelToDataStore)(newChannel, internalId, this, this.dataStores, this.mc.logger);
|
|
1359
|
+
const aliasResult = await newDataStore.trySetAlias(alias);
|
|
1360
|
+
if (aliasResult === "Success") {
|
|
1361
|
+
return newDataStore;
|
|
1362
|
+
}
|
|
1363
|
+
const existingDataStore = await this.getRootDataStoreChannel(alias, /* wait */ false);
|
|
1364
|
+
return (0, dataStore_1.channelToDataStore)(existingDataStore, internalId, this, this.dataStores, this.mc.logger, true);
|
|
1340
1365
|
}
|
|
1341
|
-
return aliasedDataStore;
|
|
1342
1366
|
}
|
|
1343
1367
|
createDetachedRootDataStore(pkg, rootDataStoreId) {
|
|
1344
1368
|
if (rootDataStoreId.includes("/")) {
|
|
@@ -1358,14 +1382,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1358
1382
|
async _createDataStoreWithPropsLegacy(pkg, props, id = (0, uuid_1.v4)(), isRoot = false) {
|
|
1359
1383
|
const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
|
|
1360
1384
|
if (isRoot) {
|
|
1361
|
-
|
|
1362
|
-
// For older versions, we still have to call bindToContext.
|
|
1363
|
-
if (fluidDataStore.makeVisibleAndAttachGraph !== undefined) {
|
|
1364
|
-
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1365
|
-
}
|
|
1366
|
-
else {
|
|
1367
|
-
fluidDataStore.bindToContext();
|
|
1368
|
-
}
|
|
1385
|
+
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1369
1386
|
this.logger.sendTelemetryEvent({
|
|
1370
1387
|
eventName: "Root datastore with props",
|
|
1371
1388
|
hasProps: props !== undefined,
|
|
@@ -1646,7 +1663,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1646
1663
|
* @param options - options controlling how the summary is generated or submitted
|
|
1647
1664
|
*/
|
|
1648
1665
|
async submitSummary(options) {
|
|
1649
|
-
var _a, _b
|
|
1666
|
+
var _a, _b;
|
|
1650
1667
|
const { fullTree, refreshLatestAck, summaryLogger } = options;
|
|
1651
1668
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1652
1669
|
// use it for all events logged during this summary.
|
|
@@ -1671,17 +1688,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1671
1688
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
1672
1689
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1673
1690
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
1674
|
-
|
|
1675
|
-
// doesn't match the last processed sequence number, log an error.
|
|
1676
|
-
if (summaryRefSeqNum !== ((_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.sequenceNumber)) {
|
|
1677
|
-
summaryNumberLogger.sendErrorEvent({
|
|
1678
|
-
eventName: "LastSequenceMismatch",
|
|
1679
|
-
error: message,
|
|
1680
|
-
});
|
|
1681
|
-
}
|
|
1691
|
+
const lastAck = this.summaryCollection.latestAck;
|
|
1682
1692
|
this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
|
|
1683
1693
|
// Helper function to check whether we should still continue between each async step.
|
|
1684
1694
|
const checkContinue = () => {
|
|
1695
|
+
var _a;
|
|
1685
1696
|
// Do not check for loss of connectivity directly! Instead leave it up to
|
|
1686
1697
|
// RunWhileConnectedCoordinator to control policy in a single place.
|
|
1687
1698
|
// This will allow easier change of design if we chose to. For example, we may chose to allow
|
|
@@ -1705,6 +1716,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1705
1716
|
error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
|
|
1706
1717
|
};
|
|
1707
1718
|
}
|
|
1719
|
+
(0, common_utils_1.assert)(summaryRefSeqNum === ((_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.sequenceNumber), "it's one and the same thing");
|
|
1720
|
+
if (lastAck !== this.summaryCollection.latestAck) {
|
|
1721
|
+
return {
|
|
1722
|
+
continue: false,
|
|
1723
|
+
// eslint-disable-next-line max-len
|
|
1724
|
+
error: `Last summary changed while summarizing. ${this.summaryCollection.latestAck} !== ${lastAck}`,
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1708
1727
|
return { continue: true };
|
|
1709
1728
|
};
|
|
1710
1729
|
let continueResult = checkContinue();
|
|
@@ -1749,7 +1768,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1749
1768
|
const gcSummaryTreeStats = summaryTree.tree[garbageCollection_1.gcTreeKey]
|
|
1750
1769
|
? (0, runtime_utils_1.calculateStats)(summaryTree.tree[garbageCollection_1.gcTreeKey])
|
|
1751
1770
|
: undefined;
|
|
1752
|
-
const summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount, gcStateUpdatedDataStoreCount: (
|
|
1771
|
+
const summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount, gcStateUpdatedDataStoreCount: (_a = summarizeResult.gcStats) === null || _a === void 0 ? void 0 : _a.updatedDataStoreCount, gcBlobNodeCount: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.blobNodeCount, gcTotalBlobsSize: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.totalBlobSize, summaryNumber }, partialStats);
|
|
1753
1772
|
const generateSummaryData = {
|
|
1754
1773
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1755
1774
|
minimumSequenceNumber,
|
|
@@ -1762,11 +1781,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1762
1781
|
if (!continueResult.continue) {
|
|
1763
1782
|
return Object.assign(Object.assign({ stage: "generate" }, generateSummaryData), { error: continueResult.error });
|
|
1764
1783
|
}
|
|
1765
|
-
const lastAck = this.summaryCollection.latestAck;
|
|
1766
1784
|
const summaryContext = lastAck === undefined
|
|
1767
1785
|
? {
|
|
1768
1786
|
proposalHandle: undefined,
|
|
1769
|
-
ackHandle: (
|
|
1787
|
+
ackHandle: (_b = this.context.getLoadedFromVersion()) === null || _b === void 0 ? void 0 : _b.id,
|
|
1770
1788
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1771
1789
|
}
|
|
1772
1790
|
: {
|
|
@@ -1803,7 +1821,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1803
1821
|
}
|
|
1804
1822
|
const submitData = Object.assign(Object.assign({ stage: "submit" }, uploadData), { clientSequenceNumber, submitOpDuration: trace.trace().duration });
|
|
1805
1823
|
this.summarizerNode.completeSummary(handle);
|
|
1806
|
-
this.opTracker.reset();
|
|
1807
1824
|
return submitData;
|
|
1808
1825
|
}
|
|
1809
1826
|
finally {
|
|
@@ -1914,14 +1931,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1914
1931
|
// instead of splitting the content, we will fail by explicitly close the container
|
|
1915
1932
|
this.closeFn(new container_utils_1.GenericError("OpTooLarge",
|
|
1916
1933
|
/* error */ undefined, {
|
|
1917
|
-
length:
|
|
1918
|
-
|
|
1919
|
-
tag: telemetry_utils_1.TelemetryDataTag.PackageData,
|
|
1920
|
-
},
|
|
1921
|
-
limit: {
|
|
1922
|
-
value: this._maxOpSizeInBytes,
|
|
1923
|
-
tag: telemetry_utils_1.TelemetryDataTag.PackageData,
|
|
1924
|
-
},
|
|
1934
|
+
length: serializedContent.length,
|
|
1935
|
+
limit: this._maxOpSizeInBytes,
|
|
1925
1936
|
}));
|
|
1926
1937
|
return -1;
|
|
1927
1938
|
}
|
|
@@ -1996,7 +2007,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1996
2007
|
case ContainerMessageType.ChunkedOp:
|
|
1997
2008
|
throw new Error(`chunkedOp not expected here`);
|
|
1998
2009
|
case ContainerMessageType.BlobAttach:
|
|
1999
|
-
this.
|
|
2010
|
+
this.blobManager.reSubmit(opMetadata);
|
|
2000
2011
|
break;
|
|
2001
2012
|
case ContainerMessageType.Rejoin:
|
|
2002
2013
|
this.submit(type, content);
|
|
@@ -2038,7 +2049,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2038
2049
|
const snapshot = await this.fetchSnapshotFromStorage(null, summaryLogger, {
|
|
2039
2050
|
eventName: "RefreshLatestSummaryGetSnapshot",
|
|
2040
2051
|
fetchLatest: true,
|
|
2041
|
-
});
|
|
2052
|
+
}, driver_definitions_1.FetchSource.noCache);
|
|
2042
2053
|
const readAndParseBlob = async (id) => (0, driver_utils_1.readAndParse)(this.storage, id);
|
|
2043
2054
|
const snapshotRefSeq = await (0, runtime_utils_1.seqFromTree)(snapshot, readAndParseBlob);
|
|
2044
2055
|
const result = await this.summarizerNode.refreshLatestSummary(undefined, snapshotRefSeq, async () => snapshot, readAndParseBlob, summaryLogger);
|
|
@@ -2046,11 +2057,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2046
2057
|
await this.garbageCollector.latestSummaryStateRefreshed(result, readAndParseBlob);
|
|
2047
2058
|
return snapshotRefSeq;
|
|
2048
2059
|
}
|
|
2049
|
-
async fetchSnapshotFromStorage(versionId, logger, event) {
|
|
2060
|
+
async fetchSnapshotFromStorage(versionId, logger, event, fetchSource) {
|
|
2050
2061
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2051
2062
|
const stats = {};
|
|
2052
2063
|
const trace = common_utils_1.Trace.start();
|
|
2053
|
-
const versions = await this.storage.getVersions(versionId, 1);
|
|
2064
|
+
const versions = await this.storage.getVersions(versionId, 1, "refreshLatestSummaryAckFromServer", fetchSource);
|
|
2054
2065
|
(0, common_utils_1.assert)(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
2055
2066
|
stats.getVersionDuration = trace.trace().duration;
|
|
2056
2067
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
@@ -2133,6 +2144,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2133
2144
|
// don't have any more saved ops
|
|
2134
2145
|
await this.pendingStateManager.applyStashedOpsAt();
|
|
2135
2146
|
}
|
|
2147
|
+
validateSummaryHeuristicConfiguration(configuration) {
|
|
2148
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
2149
|
+
for (const prop in configuration) {
|
|
2150
|
+
if (typeof configuration[prop] === "number" && configuration[prop] < 0) {
|
|
2151
|
+
throw new container_utils_1.UsageError(`Summary heuristic configuration property "${prop}" cannot be less than 0`);
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2136
2155
|
}
|
|
2137
2156
|
exports.ContainerRuntime = ContainerRuntime;
|
|
2138
2157
|
/**
|