@fluidframework/container-runtime 1.2.1 → 2.0.0-internal.1.0.0.81601
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 +46 -3
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +98 -79
- 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/opProperties.d.ts +7 -0
- package/dist/opProperties.d.ts.map +1 -0
- package/dist/opProperties.js +19 -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 +46 -3
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +99 -80
- 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/opProperties.d.ts +7 -0
- package/lib/opProperties.d.ts.map +1 -0
- package/lib/opProperties.js +15 -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 +165 -89
- package/src/dataStore.ts +53 -38
- package/src/dataStoreContext.ts +16 -23
- package/src/dataStores.ts +14 -3
- 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/lib/containerRuntime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
2
2
|
import { assert, Trace, TypedEventEmitter, unreachableCase, performance, } from "@fluidframework/common-utils";
|
|
3
|
-
import { ChildLogger, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, loggerToMonitoringContext,
|
|
3
|
+
import { ChildLogger, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, loggerToMonitoringContext, } from "@fluidframework/telemetry-utils";
|
|
4
4
|
import { DriverHeader } from "@fluidframework/driver-definitions";
|
|
5
5
|
import { readAndParse, isUnpackedRuntimeMessage } from "@fluidframework/driver-utils";
|
|
6
6
|
import { DataCorruptionError, DataProcessingError, GenericError, UsageError, extractSafePropertiesFromMessage, } from "@fluidframework/container-utils";
|
|
@@ -29,7 +29,6 @@ import { GarbageCollector, GCNodeType, gcTreeKey, } from "./garbageCollection";
|
|
|
29
29
|
import { channelToDataStore, isDataStoreAliasMessage, } from "./dataStore";
|
|
30
30
|
import { BindBatchTracker } from "./batchTracker";
|
|
31
31
|
import { SerializedSnapshotStorage } from "./serializedSnapshotStorage";
|
|
32
|
-
import { OpTracker } from "./opTelemetry";
|
|
33
32
|
export var ContainerMessageType;
|
|
34
33
|
(function (ContainerMessageType) {
|
|
35
34
|
// An op to be delivered to store
|
|
@@ -47,14 +46,18 @@ export var ContainerMessageType;
|
|
|
47
46
|
})(ContainerMessageType || (ContainerMessageType = {}));
|
|
48
47
|
export const DefaultSummaryConfiguration = {
|
|
49
48
|
state: "enabled",
|
|
50
|
-
idleTime:
|
|
51
|
-
|
|
49
|
+
idleTime: 15 * 1000,
|
|
50
|
+
minIdleTime: 0,
|
|
51
|
+
maxIdleTime: 30 * 1000,
|
|
52
|
+
maxTime: 60 * 1000,
|
|
52
53
|
maxOps: 100,
|
|
53
54
|
minOpsForLastSummaryAttempt: 10,
|
|
54
|
-
maxAckWaitTime:
|
|
55
|
+
maxAckWaitTime: 10 * 60 * 1000,
|
|
55
56
|
maxOpsSinceLastSummary: 7000,
|
|
56
|
-
initialSummarizerDelayMs:
|
|
57
|
+
initialSummarizerDelayMs: 5 * 1000,
|
|
57
58
|
summarizerClientElection: false,
|
|
59
|
+
nonRuntimeOpWeight: 0.1,
|
|
60
|
+
runtimeOpWeight: 1.0,
|
|
58
61
|
};
|
|
59
62
|
/**
|
|
60
63
|
* Accepted header keys for requests coming to the runtime.
|
|
@@ -81,10 +84,6 @@ const maxOpSizeInBytesKey = "Fluid.ContainerRuntime.MaxOpSizeInBytes";
|
|
|
81
84
|
// in order to account for some extra overhead from serialization
|
|
82
85
|
// to not reach the 1MB limits in socket.io and Kafka.
|
|
83
86
|
const defaultMaxOpSizeInBytes = 768000;
|
|
84
|
-
// By default, the size of the contents for the incoming ops is tracked.
|
|
85
|
-
// However, in certain situations, this may incur a performance hit.
|
|
86
|
-
// The feature-gate below can be used to disable this feature.
|
|
87
|
-
const disableOpTrackingKey = "Fluid.ContainerRuntime.DisableOpTracking";
|
|
88
87
|
const defaultFlushMode = FlushMode.TurnBased;
|
|
89
88
|
export var RuntimeMessage;
|
|
90
89
|
(function (RuntimeMessage) {
|
|
@@ -373,7 +372,7 @@ export function getDeviceSpec() {
|
|
|
373
372
|
*/
|
|
374
373
|
export class ContainerRuntime extends TypedEventEmitter {
|
|
375
374
|
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration) {
|
|
376
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
375
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
377
376
|
if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
|
|
378
377
|
super();
|
|
379
378
|
this.context = context;
|
|
@@ -434,6 +433,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
434
433
|
this.chunkMap = new Map(chunks);
|
|
435
434
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
436
435
|
this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
436
|
+
if (this.summaryConfiguration.state === "enabled") {
|
|
437
|
+
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
438
|
+
}
|
|
437
439
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
438
440
|
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
439
441
|
this.summarizerClientElectionEnabled = this.isSummarizerClientElectionEnabled();
|
|
@@ -481,7 +483,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
481
483
|
this.summarizerNode.loadBaseSummaryWithoutDifferential(baseSnapshot);
|
|
482
484
|
}
|
|
483
485
|
this.dataStores = new DataStores(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);
|
|
484
|
-
this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), this
|
|
486
|
+
this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId, localId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId, localId }), (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), this);
|
|
485
487
|
this.scheduleManager = new ScheduleManager(context.deltaManager, this, ChildLogger.create(this.logger, "ScheduleManager"));
|
|
486
488
|
this.deltaSender = this.deltaManager;
|
|
487
489
|
this.pendingStateManager = new PendingStateManager({
|
|
@@ -572,9 +574,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
572
574
|
createContainerRuntimeVersion: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerRuntimeVersion,
|
|
573
575
|
createContainerTimestamp: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerTimestamp,
|
|
574
576
|
};
|
|
575
|
-
//
|
|
576
|
-
//
|
|
577
|
-
loadSummaryNumber = (
|
|
577
|
+
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
578
|
+
// the count is reset to 0.
|
|
579
|
+
loadSummaryNumber = (_h = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _h !== void 0 ? _h : 0;
|
|
578
580
|
}
|
|
579
581
|
else {
|
|
580
582
|
this.createContainerMetadata = {
|
|
@@ -587,7 +589,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
587
589
|
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 }));
|
|
588
590
|
ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
589
591
|
BindBatchTracker(this, this.logger);
|
|
590
|
-
this.opTracker = new OpTracker(this.deltaManager, this.mc.config.getBoolean(disableOpTrackingKey) === true);
|
|
591
592
|
}
|
|
592
593
|
get IContainerRuntime() { return this; }
|
|
593
594
|
get IFluidRouter() { return this; }
|
|
@@ -856,12 +857,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
856
857
|
return this.resolveHandle(requestParser.createSubRequest(1));
|
|
857
858
|
}
|
|
858
859
|
if (id === BlobManager.basePath && requestParser.isLeaf(2)) {
|
|
859
|
-
const
|
|
860
|
-
if (
|
|
860
|
+
const blob = await this.blobManager.getBlob(requestParser.pathParts[1]);
|
|
861
|
+
if (blob) {
|
|
861
862
|
return {
|
|
862
863
|
status: 200,
|
|
863
864
|
mimeType: "fluid/object",
|
|
864
|
-
value:
|
|
865
|
+
value: blob,
|
|
865
866
|
};
|
|
866
867
|
}
|
|
867
868
|
else {
|
|
@@ -884,13 +885,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
884
885
|
}
|
|
885
886
|
internalId(maybeAlias) {
|
|
886
887
|
var _a;
|
|
887
|
-
return (_a = this.dataStores.aliases
|
|
888
|
+
return (_a = this.dataStores.aliases.get(maybeAlias)) !== null && _a !== void 0 ? _a : maybeAlias;
|
|
888
889
|
}
|
|
889
890
|
async getDataStoreFromRequest(id, request) {
|
|
890
891
|
var _a, _b, _c;
|
|
891
892
|
const wait = typeof ((_a = request.headers) === null || _a === void 0 ? void 0 : _a[RuntimeHeaders.wait]) === "boolean"
|
|
892
893
|
? (_b = request.headers) === null || _b === void 0 ? void 0 : _b[RuntimeHeaders.wait]
|
|
893
894
|
: true;
|
|
895
|
+
await this.dataStores.waitIfPendingAlias(id);
|
|
894
896
|
const internalId = this.internalId(id);
|
|
895
897
|
const dataStoreContext = await this.dataStores.getDataStore(internalId, wait);
|
|
896
898
|
/**
|
|
@@ -920,8 +922,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
920
922
|
addMetadataToSummary(summaryTree) {
|
|
921
923
|
var _a;
|
|
922
924
|
const metadata = Object.assign(Object.assign(Object.assign(Object.assign({}, this.createContainerMetadata), {
|
|
923
|
-
// back-compat 0.59.3000: This is renamed to summaryNumber. Can be removed when 0.59.3000 saturates.
|
|
924
|
-
summaryCount: this.nextSummaryNumber,
|
|
925
925
|
// Increment the summary number for the next summary that will be generated.
|
|
926
926
|
summaryNumber: this.nextSummaryNumber++, summaryFormatVersion: 1, disableIsolatedChannels: this.disableIsolatedChannels || undefined }), this.garbageCollector.getMetadata()), {
|
|
927
927
|
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
@@ -936,7 +936,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
936
936
|
const content = JSON.stringify([...this.chunkMap]);
|
|
937
937
|
addBlobToSummary(summaryTree, chunksBlobName, content);
|
|
938
938
|
}
|
|
939
|
-
const dataStoreAliases = this.dataStores.aliases
|
|
939
|
+
const dataStoreAliases = this.dataStores.aliases;
|
|
940
940
|
if (dataStoreAliases.size > 0) {
|
|
941
941
|
addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
942
942
|
}
|
|
@@ -1033,6 +1033,35 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1033
1033
|
}
|
|
1034
1034
|
}
|
|
1035
1035
|
setConnectionState(connected, clientId) {
|
|
1036
|
+
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
1037
|
+
this.delayConnectClientId = undefined;
|
|
1038
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1039
|
+
eventName: "UnsuccessfulConnectedTransition",
|
|
1040
|
+
});
|
|
1041
|
+
// Don't propagate "disconnected" event because we didn't propagate the previous "connected" event
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
// If attachment blobs were added while disconnected, we need to delay
|
|
1045
|
+
// propagation of the "connected" event until we have uploaded them to
|
|
1046
|
+
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
1047
|
+
const connecting = connected && !this._connected && !this.deltaManager.readOnlyInfo.readonly;
|
|
1048
|
+
if (connecting && this.blobManager.hasPendingOfflineUploads) {
|
|
1049
|
+
assert(!this.delayConnectClientId, "Connect event delay must be canceled before subsequent connect event");
|
|
1050
|
+
assert(!!clientId, "Must have clientId when connecting");
|
|
1051
|
+
this.delayConnectClientId = clientId;
|
|
1052
|
+
this.blobManager.onConnected().then(() => {
|
|
1053
|
+
// make sure we didn't reconnect before the promise resolved
|
|
1054
|
+
if (this.delayConnectClientId === clientId && !this.disposed) {
|
|
1055
|
+
this.delayConnectClientId = undefined;
|
|
1056
|
+
this.setConnectionStateCore(connected, clientId);
|
|
1057
|
+
}
|
|
1058
|
+
}, (error) => this.closeFn(error));
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
this.setConnectionStateCore(connected, clientId);
|
|
1062
|
+
}
|
|
1063
|
+
setConnectionStateCore(connected, clientId) {
|
|
1064
|
+
assert(!this.delayConnectClientId, "connect event delay must be cleared before propagating connect event");
|
|
1036
1065
|
this.verifyNotClosed();
|
|
1037
1066
|
// There might be no change of state due to Container calling this API after loading runtime.
|
|
1038
1067
|
const changeOfState = this._connected !== connected;
|
|
@@ -1063,7 +1092,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1063
1092
|
raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
1064
1093
|
}
|
|
1065
1094
|
process(messageArg, local) {
|
|
1066
|
-
var _a
|
|
1095
|
+
var _a;
|
|
1067
1096
|
this.verifyNotClosed();
|
|
1068
1097
|
// If it's not message for runtime, bail out right away.
|
|
1069
1098
|
if (!isUnpackedRuntimeMessage(messageArg)) {
|
|
@@ -1110,8 +1139,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1110
1139
|
this.dataStores.processFluidDataStoreOp(message, local, localOpMetadata);
|
|
1111
1140
|
break;
|
|
1112
1141
|
case ContainerMessageType.BlobAttach:
|
|
1113
|
-
|
|
1114
|
-
this.blobManager.processBlobAttachOp(message.metadata.blobId, local);
|
|
1142
|
+
this.blobManager.processBlobAttachOp(message, local);
|
|
1115
1143
|
break;
|
|
1116
1144
|
default:
|
|
1117
1145
|
}
|
|
@@ -1181,6 +1209,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1181
1209
|
this.dataStores.processSignal(envelope.address, transformed, local);
|
|
1182
1210
|
}
|
|
1183
1211
|
async getRootDataStore(id, wait = true) {
|
|
1212
|
+
return this.getRootDataStoreChannel(id, wait);
|
|
1213
|
+
}
|
|
1214
|
+
async getRootDataStoreChannel(id, wait = true) {
|
|
1215
|
+
await this.dataStores.waitIfPendingAlias(id);
|
|
1184
1216
|
const internalId = this.internalId(id);
|
|
1185
1217
|
const context = await this.dataStores.getDataStore(internalId, wait);
|
|
1186
1218
|
assert(await context.isRoot(), 0x12b /* "did not get root data store" */);
|
|
@@ -1281,14 +1313,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1281
1313
|
*/
|
|
1282
1314
|
async createRootDataStoreLegacy(pkg, rootDataStoreId) {
|
|
1283
1315
|
const fluidDataStore = await this._createDataStore(pkg, true /* isRoot */, rootDataStoreId);
|
|
1284
|
-
|
|
1285
|
-
// older versions, we still have to call bindToContext.
|
|
1286
|
-
if (fluidDataStore.makeVisibleAndAttachGraph !== undefined) {
|
|
1287
|
-
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1288
|
-
}
|
|
1289
|
-
else {
|
|
1290
|
-
fluidDataStore.bindToContext();
|
|
1291
|
-
}
|
|
1316
|
+
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1292
1317
|
return fluidDataStore;
|
|
1293
1318
|
}
|
|
1294
1319
|
/**
|
|
@@ -1315,23 +1340,22 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1315
1340
|
*/
|
|
1316
1341
|
async createAndAliasDataStore(pkg, alias, props) {
|
|
1317
1342
|
const internalId = uuid();
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1343
|
+
try {
|
|
1344
|
+
// A similar call may have been initiated by the same client, so we should try to get
|
|
1345
|
+
// a possible existing aliased datastore first.
|
|
1346
|
+
const existingDataStore = await this.getRootDataStoreChannel(alias, /* wait */ false);
|
|
1347
|
+
return channelToDataStore(existingDataStore, internalId, this, this.dataStores, this.mc.logger, true);
|
|
1348
|
+
}
|
|
1349
|
+
catch (err) {
|
|
1350
|
+
const newChannel = await this._createDataStore(pkg, false /* isRoot */, internalId, props);
|
|
1351
|
+
const newDataStore = channelToDataStore(newChannel, internalId, this, this.dataStores, this.mc.logger);
|
|
1352
|
+
const aliasResult = await newDataStore.trySetAlias(alias);
|
|
1353
|
+
if (aliasResult === "Success") {
|
|
1354
|
+
return newDataStore;
|
|
1355
|
+
}
|
|
1356
|
+
const existingDataStore = await this.getRootDataStoreChannel(alias, /* wait */ false);
|
|
1357
|
+
return channelToDataStore(existingDataStore, internalId, this, this.dataStores, this.mc.logger, true);
|
|
1333
1358
|
}
|
|
1334
|
-
return aliasedDataStore;
|
|
1335
1359
|
}
|
|
1336
1360
|
createDetachedRootDataStore(pkg, rootDataStoreId) {
|
|
1337
1361
|
if (rootDataStoreId.includes("/")) {
|
|
@@ -1351,14 +1375,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1351
1375
|
async _createDataStoreWithPropsLegacy(pkg, props, id = uuid(), isRoot = false) {
|
|
1352
1376
|
const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
|
|
1353
1377
|
if (isRoot) {
|
|
1354
|
-
|
|
1355
|
-
// For older versions, we still have to call bindToContext.
|
|
1356
|
-
if (fluidDataStore.makeVisibleAndAttachGraph !== undefined) {
|
|
1357
|
-
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1358
|
-
}
|
|
1359
|
-
else {
|
|
1360
|
-
fluidDataStore.bindToContext();
|
|
1361
|
-
}
|
|
1378
|
+
fluidDataStore.makeVisibleAndAttachGraph();
|
|
1362
1379
|
this.logger.sendTelemetryEvent({
|
|
1363
1380
|
eventName: "Root datastore with props",
|
|
1364
1381
|
hasProps: props !== undefined,
|
|
@@ -1639,7 +1656,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1639
1656
|
* @param options - options controlling how the summary is generated or submitted
|
|
1640
1657
|
*/
|
|
1641
1658
|
async submitSummary(options) {
|
|
1642
|
-
var _a, _b
|
|
1659
|
+
var _a, _b;
|
|
1643
1660
|
const { fullTree, refreshLatestAck, summaryLogger } = options;
|
|
1644
1661
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1645
1662
|
// use it for all events logged during this summary.
|
|
@@ -1664,17 +1681,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1664
1681
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
1665
1682
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1666
1683
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
1667
|
-
|
|
1668
|
-
// doesn't match the last processed sequence number, log an error.
|
|
1669
|
-
if (summaryRefSeqNum !== ((_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.sequenceNumber)) {
|
|
1670
|
-
summaryNumberLogger.sendErrorEvent({
|
|
1671
|
-
eventName: "LastSequenceMismatch",
|
|
1672
|
-
error: message,
|
|
1673
|
-
});
|
|
1674
|
-
}
|
|
1684
|
+
const lastAck = this.summaryCollection.latestAck;
|
|
1675
1685
|
this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
|
|
1676
1686
|
// Helper function to check whether we should still continue between each async step.
|
|
1677
1687
|
const checkContinue = () => {
|
|
1688
|
+
var _a;
|
|
1678
1689
|
// Do not check for loss of connectivity directly! Instead leave it up to
|
|
1679
1690
|
// RunWhileConnectedCoordinator to control policy in a single place.
|
|
1680
1691
|
// This will allow easier change of design if we chose to. For example, we may chose to allow
|
|
@@ -1698,6 +1709,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1698
1709
|
error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
|
|
1699
1710
|
};
|
|
1700
1711
|
}
|
|
1712
|
+
assert(summaryRefSeqNum === ((_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.sequenceNumber), "it's one and the same thing");
|
|
1713
|
+
if (lastAck !== this.summaryCollection.latestAck) {
|
|
1714
|
+
return {
|
|
1715
|
+
continue: false,
|
|
1716
|
+
// eslint-disable-next-line max-len
|
|
1717
|
+
error: `Last summary changed while summarizing. ${this.summaryCollection.latestAck} !== ${lastAck}`,
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1701
1720
|
return { continue: true };
|
|
1702
1721
|
};
|
|
1703
1722
|
let continueResult = checkContinue();
|
|
@@ -1742,7 +1761,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1742
1761
|
const gcSummaryTreeStats = summaryTree.tree[gcTreeKey]
|
|
1743
1762
|
? calculateStats(summaryTree.tree[gcTreeKey])
|
|
1744
1763
|
: undefined;
|
|
1745
|
-
const summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount, gcStateUpdatedDataStoreCount: (
|
|
1764
|
+
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);
|
|
1746
1765
|
const generateSummaryData = {
|
|
1747
1766
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1748
1767
|
minimumSequenceNumber,
|
|
@@ -1755,11 +1774,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1755
1774
|
if (!continueResult.continue) {
|
|
1756
1775
|
return Object.assign(Object.assign({ stage: "generate" }, generateSummaryData), { error: continueResult.error });
|
|
1757
1776
|
}
|
|
1758
|
-
const lastAck = this.summaryCollection.latestAck;
|
|
1759
1777
|
const summaryContext = lastAck === undefined
|
|
1760
1778
|
? {
|
|
1761
1779
|
proposalHandle: undefined,
|
|
1762
|
-
ackHandle: (
|
|
1780
|
+
ackHandle: (_b = this.context.getLoadedFromVersion()) === null || _b === void 0 ? void 0 : _b.id,
|
|
1763
1781
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1764
1782
|
}
|
|
1765
1783
|
: {
|
|
@@ -1796,7 +1814,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1796
1814
|
}
|
|
1797
1815
|
const submitData = Object.assign(Object.assign({ stage: "submit" }, uploadData), { clientSequenceNumber, submitOpDuration: trace.trace().duration });
|
|
1798
1816
|
this.summarizerNode.completeSummary(handle);
|
|
1799
|
-
this.opTracker.reset();
|
|
1800
1817
|
return submitData;
|
|
1801
1818
|
}
|
|
1802
1819
|
finally {
|
|
@@ -1907,14 +1924,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1907
1924
|
// instead of splitting the content, we will fail by explicitly close the container
|
|
1908
1925
|
this.closeFn(new GenericError("OpTooLarge",
|
|
1909
1926
|
/* error */ undefined, {
|
|
1910
|
-
length:
|
|
1911
|
-
|
|
1912
|
-
tag: TelemetryDataTag.PackageData,
|
|
1913
|
-
},
|
|
1914
|
-
limit: {
|
|
1915
|
-
value: this._maxOpSizeInBytes,
|
|
1916
|
-
tag: TelemetryDataTag.PackageData,
|
|
1917
|
-
},
|
|
1927
|
+
length: serializedContent.length,
|
|
1928
|
+
limit: this._maxOpSizeInBytes,
|
|
1918
1929
|
}));
|
|
1919
1930
|
return -1;
|
|
1920
1931
|
}
|
|
@@ -1989,7 +2000,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1989
2000
|
case ContainerMessageType.ChunkedOp:
|
|
1990
2001
|
throw new Error(`chunkedOp not expected here`);
|
|
1991
2002
|
case ContainerMessageType.BlobAttach:
|
|
1992
|
-
this.
|
|
2003
|
+
this.blobManager.reSubmit(opMetadata);
|
|
1993
2004
|
break;
|
|
1994
2005
|
case ContainerMessageType.Rejoin:
|
|
1995
2006
|
this.submit(type, content);
|
|
@@ -2126,6 +2137,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2126
2137
|
// don't have any more saved ops
|
|
2127
2138
|
await this.pendingStateManager.applyStashedOpsAt();
|
|
2128
2139
|
}
|
|
2140
|
+
validateSummaryHeuristicConfiguration(configuration) {
|
|
2141
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
2142
|
+
for (const prop in configuration) {
|
|
2143
|
+
if (typeof configuration[prop] === "number" && configuration[prop] < 0) {
|
|
2144
|
+
throw new UsageError(`Summary heuristic configuration property "${prop}" cannot be less than 0`);
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2129
2148
|
}
|
|
2130
2149
|
/**
|
|
2131
2150
|
* Wait for a specific sequence number. Promise should resolve when we reach that number,
|