@fluidframework/container-runtime 0.58.2000 → 0.58.3000-61081
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 +3 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +13 -9
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +63 -23
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +12 -4
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +61 -15
- package/dist/containerRuntime.js.map +1 -1
- package/dist/opTelemetry.d.ts +22 -0
- package/dist/opTelemetry.d.ts.map +1 -0
- package/dist/opTelemetry.js +59 -0
- package/dist/opTelemetry.js.map +1 -0
- package/dist/orderedClientElection.d.ts +57 -6
- package/dist/orderedClientElection.d.ts.map +1 -1
- package/dist/orderedClientElection.js +140 -25
- package/dist/orderedClientElection.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/summarizerClientElection.d.ts +2 -0
- package/dist/summarizerClientElection.d.ts.map +1 -1
- package/dist/summarizerClientElection.js +7 -2
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summarizerTypes.d.ts +9 -0
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +1 -1
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +14 -3
- package/dist/summaryManager.js.map +1 -1
- package/lib/blobManager.d.ts +3 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +14 -10
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +63 -23
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +12 -4
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +62 -16
- package/lib/containerRuntime.js.map +1 -1
- package/lib/opTelemetry.d.ts +22 -0
- package/lib/opTelemetry.d.ts.map +1 -0
- package/lib/opTelemetry.js +55 -0
- package/lib/opTelemetry.js.map +1 -0
- package/lib/orderedClientElection.d.ts +57 -6
- package/lib/orderedClientElection.d.ts.map +1 -1
- package/lib/orderedClientElection.js +140 -25
- package/lib/orderedClientElection.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/summarizerClientElection.d.ts +2 -0
- package/lib/summarizerClientElection.d.ts.map +1 -1
- package/lib/summarizerClientElection.js +7 -2
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summarizerTypes.d.ts +9 -0
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +1 -1
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +14 -3
- package/lib/summaryManager.js.map +1 -1
- package/package.json +47 -15
- package/src/blobManager.ts +19 -11
- package/src/connectionTelemetry.ts +110 -19
- package/src/containerRuntime.ts +85 -19
- package/src/opTelemetry.ts +71 -0
- package/src/orderedClientElection.ts +154 -25
- package/src/packageVersion.ts +1 -1
- package/src/summarizerClientElection.ts +7 -2
- package/src/summarizerTypes.ts +9 -0
- package/src/summaryGenerator.ts +9 -1
- package/src/summaryManager.ts +15 -4
package/dist/containerRuntime.js
CHANGED
|
@@ -30,6 +30,7 @@ const runWhileConnectedCoordinator_1 = require("./runWhileConnectedCoordinator")
|
|
|
30
30
|
const garbageCollection_1 = require("./garbageCollection");
|
|
31
31
|
const dataStore_1 = require("./dataStore");
|
|
32
32
|
const batchTracker_1 = require("./batchTracker");
|
|
33
|
+
const opTelemetry_1 = require("./opTelemetry");
|
|
33
34
|
var ContainerMessageType;
|
|
34
35
|
(function (ContainerMessageType) {
|
|
35
36
|
// An op to be delivered to store
|
|
@@ -82,6 +83,11 @@ const maxOpSizeInBytesKey = "Fluid.ContainerRuntime.MaxOpSizeInBytes";
|
|
|
82
83
|
// in order to account for some extra overhead from serialization
|
|
83
84
|
// to not reach the 1MB limits in socket.io and Kafka.
|
|
84
85
|
const defaultMaxOpSizeInBytes = 768000;
|
|
86
|
+
// By default, the size of the contents for the incoming ops is tracked.
|
|
87
|
+
// However, in certain situations, this may incur a performance hit.
|
|
88
|
+
// The feature-gate below can be used to disable this feature.
|
|
89
|
+
const disableOpTrackingKey = "Fluid.ContainerRuntime.DisableOpTracking";
|
|
90
|
+
const defaultFlushMode = runtime_definitions_1.FlushMode.TurnBased;
|
|
85
91
|
var RuntimeMessage;
|
|
86
92
|
(function (RuntimeMessage) {
|
|
87
93
|
RuntimeMessage["FluidDataStoreOp"] = "component";
|
|
@@ -132,6 +138,7 @@ class ScheduleManagerCore {
|
|
|
132
138
|
this.logger = logger;
|
|
133
139
|
this.localPaused = false;
|
|
134
140
|
this.timePaused = 0;
|
|
141
|
+
this.batchCount = 0;
|
|
135
142
|
// Listen for delta manager sends and add batch metadata to messages
|
|
136
143
|
this.deltaManager.on("prepareSend", (messages) => {
|
|
137
144
|
if (messages.length === 0) {
|
|
@@ -198,13 +205,26 @@ class ScheduleManagerCore {
|
|
|
198
205
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
199
206
|
this.deltaManager.inbound.pause();
|
|
200
207
|
}
|
|
201
|
-
resumeQueue(startBatch,
|
|
208
|
+
resumeQueue(startBatch, messageEndBatch) {
|
|
209
|
+
const endBatch = messageEndBatch.sequenceNumber;
|
|
210
|
+
const duration = common_utils_1.performance.now() - this.timePaused;
|
|
211
|
+
this.batchCount++;
|
|
212
|
+
if (this.batchCount % 1000 === 1) {
|
|
213
|
+
this.logger.sendTelemetryEvent({
|
|
214
|
+
eventName: "BatchStats",
|
|
215
|
+
sequenceNumber: endBatch,
|
|
216
|
+
length: endBatch - startBatch + 1,
|
|
217
|
+
msnDistance: endBatch - messageEndBatch.minimumSequenceNumber,
|
|
218
|
+
duration,
|
|
219
|
+
batchCount: this.batchCount,
|
|
220
|
+
interrupted: this.localPaused,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
202
223
|
// Return early if no change in value
|
|
203
224
|
if (!this.localPaused) {
|
|
204
225
|
return;
|
|
205
226
|
}
|
|
206
227
|
this.localPaused = false;
|
|
207
|
-
const duration = common_utils_1.performance.now() - this.timePaused;
|
|
208
228
|
// Random round number - we want to know when batch waiting paused op processing.
|
|
209
229
|
if (duration > connectionTelemetry_1.latencyThreshold) {
|
|
210
230
|
this.logger.sendErrorEvent({
|
|
@@ -265,7 +285,7 @@ class ScheduleManagerCore {
|
|
|
265
285
|
else if (batchMetadata === false) {
|
|
266
286
|
common_utils_1.assert(this.pauseSequenceNumber !== undefined, 0x2a0 /* "batch presence was validated above" */);
|
|
267
287
|
// Batch is complete, we can process it!
|
|
268
|
-
this.resumeQueue(this.pauseSequenceNumber, message
|
|
288
|
+
this.resumeQueue(this.pauseSequenceNumber, message);
|
|
269
289
|
this.pauseSequenceNumber = undefined;
|
|
270
290
|
this.currentBatchClientId = undefined;
|
|
271
291
|
}
|
|
@@ -370,7 +390,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
370
390
|
this._storage = _storage;
|
|
371
391
|
this.defaultMaxConsecutiveReconnects = 15;
|
|
372
392
|
this._orderSequentiallyCalls = 0;
|
|
373
|
-
this._flushMode = runtime_definitions_1.FlushMode.TurnBased;
|
|
374
393
|
this.needsFlush = false;
|
|
375
394
|
this.flushTrigger = false;
|
|
376
395
|
this.paused = false;
|
|
@@ -453,6 +472,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
453
472
|
((_c = runtimeOptions.useDataStoreAliasing) !== null && _c !== void 0 ? _c : false);
|
|
454
473
|
this._maxOpSizeInBytes = ((_d = this.mc.config.getNumber(maxOpSizeInBytesKey)) !== null && _d !== void 0 ? _d : defaultMaxOpSizeInBytes);
|
|
455
474
|
this.maxConsecutiveReconnects = (_e = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _e !== void 0 ? _e : this.defaultMaxConsecutiveReconnects;
|
|
475
|
+
this._flushMode = runtimeOptions.flushMode;
|
|
456
476
|
this.garbageCollector = garbageCollection_1.GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), (nodePath) => this.dataStores.getNodePackagePath(nodePath),
|
|
457
477
|
/**
|
|
458
478
|
* Returns the timestamp of the last message seen by this client. This is used by garbage collector as
|
|
@@ -567,6 +587,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
567
587
|
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryCount: this.summaryCount, 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 }));
|
|
568
588
|
connectionTelemetry_1.ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
569
589
|
batchTracker_1.BindBatchTracker(this, this.logger);
|
|
590
|
+
this.opTracker = new opTelemetry_1.OpTracker(this.deltaManager, this.mc.config.getBoolean(disableOpTrackingKey) === true);
|
|
570
591
|
}
|
|
571
592
|
get IContainerRuntime() { return this; }
|
|
572
593
|
get IFluidRouter() { return this; }
|
|
@@ -589,7 +610,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
589
610
|
runtimeVersion: packageVersion_1.pkgVersion,
|
|
590
611
|
},
|
|
591
612
|
});
|
|
592
|
-
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, } = runtimeOptions;
|
|
613
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, flushMode = defaultFlushMode, } = runtimeOptions;
|
|
593
614
|
// We pack at data store level only. If isolated channels are disabled,
|
|
594
615
|
// then there are no .channel layers, we pack at level 1, otherwise we pack at level 2
|
|
595
616
|
const packingLevel = summaryOptions.disableIsolatedChannels ? 1 : 2;
|
|
@@ -660,6 +681,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
660
681
|
gcOptions,
|
|
661
682
|
loadSequenceNumberVerification,
|
|
662
683
|
useDataStoreAliasing,
|
|
684
|
+
flushMode,
|
|
663
685
|
}, containerScope, logger, loadExisting, blobManagerSnapshot, requestHandler, storage);
|
|
664
686
|
return runtime;
|
|
665
687
|
}
|
|
@@ -878,12 +900,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
878
900
|
const electedSummarizerContent = JSON.stringify((_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.serialize());
|
|
879
901
|
runtime_utils_1.addBlobToSummary(summaryTree, summaryFormat_1.electedSummarizerBlobName, electedSummarizerContent);
|
|
880
902
|
}
|
|
881
|
-
const
|
|
903
|
+
const summary = this.blobManager.summarize();
|
|
882
904
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
883
905
|
// and the blob manager can handle the tree not existing when loading
|
|
884
|
-
if (
|
|
885
|
-
|
|
886
|
-
runtime_utils_1.addTreeToSummary(summaryTree, summaryFormat_1.blobsTreeName, blobsTree);
|
|
906
|
+
if (Object.keys(summary.summary.tree).length > 0) {
|
|
907
|
+
runtime_utils_1.addTreeToSummary(summaryTree, summaryFormat_1.blobsTreeName, summary);
|
|
887
908
|
}
|
|
888
909
|
if (this.garbageCollector.writeDataAtRoot) {
|
|
889
910
|
const gcSummary = this.garbageCollector.summarize();
|
|
@@ -1072,6 +1093,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1072
1093
|
if (mode === this._flushMode) {
|
|
1073
1094
|
return;
|
|
1074
1095
|
}
|
|
1096
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1097
|
+
eventName: "FlushMode Updated",
|
|
1098
|
+
old: this._flushMode,
|
|
1099
|
+
new: mode,
|
|
1100
|
+
});
|
|
1075
1101
|
// Flush any pending batches if switching to immediate
|
|
1076
1102
|
if (mode === runtime_definitions_1.FlushMode.Immediate) {
|
|
1077
1103
|
this.flush();
|
|
@@ -1199,6 +1225,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1199
1225
|
const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
|
|
1200
1226
|
if (isRoot) {
|
|
1201
1227
|
fluidDataStore.bindToContext();
|
|
1228
|
+
this.logger.sendTelemetryEvent({
|
|
1229
|
+
eventName: "Root datastore with props",
|
|
1230
|
+
hasProps: props !== undefined,
|
|
1231
|
+
});
|
|
1202
1232
|
}
|
|
1203
1233
|
return dataStore_1.channelToDataStore(fluidDataStore, id, this, this.dataStores, this.mc.logger);
|
|
1204
1234
|
}
|
|
@@ -1322,9 +1352,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1322
1352
|
if (runGC) {
|
|
1323
1353
|
gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC });
|
|
1324
1354
|
}
|
|
1325
|
-
const
|
|
1326
|
-
common_utils_1.assert(
|
|
1327
|
-
return
|
|
1355
|
+
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState);
|
|
1356
|
+
common_utils_1.assert(summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1357
|
+
return { stats, summary, gcStats };
|
|
1328
1358
|
}
|
|
1329
1359
|
/**
|
|
1330
1360
|
* Implementation of IGarbageCollectionRuntime::updateStateBeforeGC.
|
|
@@ -1399,6 +1429,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1399
1429
|
try {
|
|
1400
1430
|
await this.deltaManager.inbound.pause();
|
|
1401
1431
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
1432
|
+
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1402
1433
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
1403
1434
|
// We should be here is we haven't processed be here. If we are of if the last message's sequence number
|
|
1404
1435
|
// doesn't match the last processed sequence number, log an error.
|
|
@@ -1438,7 +1469,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1438
1469
|
};
|
|
1439
1470
|
let continueResult = checkContinue();
|
|
1440
1471
|
if (!continueResult.continue) {
|
|
1441
|
-
return {
|
|
1472
|
+
return {
|
|
1473
|
+
stage: "base",
|
|
1474
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1475
|
+
minimumSequenceNumber,
|
|
1476
|
+
error: continueResult.error,
|
|
1477
|
+
};
|
|
1442
1478
|
}
|
|
1443
1479
|
// increment summary count
|
|
1444
1480
|
if (this.summaryCount !== undefined) {
|
|
@@ -1461,7 +1497,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1461
1497
|
});
|
|
1462
1498
|
}
|
|
1463
1499
|
catch (error) {
|
|
1464
|
-
return {
|
|
1500
|
+
return {
|
|
1501
|
+
stage: "base",
|
|
1502
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1503
|
+
minimumSequenceNumber,
|
|
1504
|
+
error,
|
|
1505
|
+
};
|
|
1465
1506
|
}
|
|
1466
1507
|
const { summary: summaryTree, stats: partialStats } = summarizeResult;
|
|
1467
1508
|
// Now that we have generated the summary, update the message at last summary to the last message processed.
|
|
@@ -1472,9 +1513,13 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1472
1513
|
const dataStoreTree = this.disableIsolatedChannels ? summaryTree : summaryTree.tree[runtime_definitions_1.channelsTreeName];
|
|
1473
1514
|
common_utils_1.assert(dataStoreTree.type === protocol_definitions_1.SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
|
|
1474
1515
|
const handleCount = Object.values(dataStoreTree.tree).filter((value) => value.type === protocol_definitions_1.SummaryType.Handle).length;
|
|
1475
|
-
const
|
|
1516
|
+
const gcSummaryTreeStats = summaryTree.tree[garbageCollection_1.gcTreeKey]
|
|
1517
|
+
? runtime_utils_1.calculateStats(summaryTree.tree[garbageCollection_1.gcTreeKey])
|
|
1518
|
+
: undefined;
|
|
1519
|
+
const summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount, gcStateUpdatedDataStoreCount: (_b = summarizeResult.gcStats) === null || _b === void 0 ? void 0 : _b.updatedDataStoreCount, gcBlobNodeCount: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.blobNodeCount, gcTotalBlobsSize: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.totalBlobSize, opsSizesSinceLastSummary: this.opTracker.opsSizeAccumulator, nonSystemOpsSinceLastSummary: this.opTracker.nonSystemOpCount }, partialStats);
|
|
1476
1520
|
const generateSummaryData = {
|
|
1477
1521
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1522
|
+
minimumSequenceNumber,
|
|
1478
1523
|
summaryTree,
|
|
1479
1524
|
summaryStats,
|
|
1480
1525
|
generateDuration: trace.trace().duration,
|
|
@@ -1525,6 +1570,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1525
1570
|
}
|
|
1526
1571
|
const submitData = Object.assign(Object.assign({ stage: "submit" }, uploadData), { clientSequenceNumber, submitOpDuration: trace.trace().duration });
|
|
1527
1572
|
this.summarizerNode.completeSummary(handle);
|
|
1573
|
+
this.opTracker.reset();
|
|
1528
1574
|
return submitData;
|
|
1529
1575
|
}
|
|
1530
1576
|
finally {
|