@fluidframework/container-runtime 0.58.2002 → 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/lib/containerRuntime.js
CHANGED
|
@@ -6,7 +6,7 @@ import { readAndParse, BlobAggregationStorage } from "@fluidframework/driver-uti
|
|
|
6
6
|
import { DataCorruptionError, GenericError, UsageError, extractSafePropertiesFromMessage, } from "@fluidframework/container-utils";
|
|
7
7
|
import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
|
|
8
8
|
import { FlushMode, channelsTreeName, } from "@fluidframework/runtime-definitions";
|
|
9
|
-
import { addBlobToSummary, addTreeToSummary,
|
|
9
|
+
import { addBlobToSummary, addTreeToSummary, createRootSummarizerNodeWithGC, RequestParser, create404Response, exceptionToResponse, requestFluidObject, responseToException, seqFromTree, calculateStats, } from "@fluidframework/runtime-utils";
|
|
10
10
|
import { v4 as uuid } from "uuid";
|
|
11
11
|
import { ContainerFluidHandleContext } from "./containerHandleContext";
|
|
12
12
|
import { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
@@ -27,6 +27,7 @@ import { RunWhileConnectedCoordinator } from "./runWhileConnectedCoordinator";
|
|
|
27
27
|
import { GarbageCollector, gcTreeKey, } from "./garbageCollection";
|
|
28
28
|
import { channelToDataStore, isDataStoreAliasMessage, } from "./dataStore";
|
|
29
29
|
import { BindBatchTracker } from "./batchTracker";
|
|
30
|
+
import { OpTracker } from "./opTelemetry";
|
|
30
31
|
export var ContainerMessageType;
|
|
31
32
|
(function (ContainerMessageType) {
|
|
32
33
|
// An op to be delivered to store
|
|
@@ -79,6 +80,11 @@ const maxOpSizeInBytesKey = "Fluid.ContainerRuntime.MaxOpSizeInBytes";
|
|
|
79
80
|
// in order to account for some extra overhead from serialization
|
|
80
81
|
// to not reach the 1MB limits in socket.io and Kafka.
|
|
81
82
|
const defaultMaxOpSizeInBytes = 768000;
|
|
83
|
+
// By default, the size of the contents for the incoming ops is tracked.
|
|
84
|
+
// However, in certain situations, this may incur a performance hit.
|
|
85
|
+
// The feature-gate below can be used to disable this feature.
|
|
86
|
+
const disableOpTrackingKey = "Fluid.ContainerRuntime.DisableOpTracking";
|
|
87
|
+
const defaultFlushMode = FlushMode.TurnBased;
|
|
82
88
|
export var RuntimeMessage;
|
|
83
89
|
(function (RuntimeMessage) {
|
|
84
90
|
RuntimeMessage["FluidDataStoreOp"] = "component";
|
|
@@ -127,6 +133,7 @@ class ScheduleManagerCore {
|
|
|
127
133
|
this.logger = logger;
|
|
128
134
|
this.localPaused = false;
|
|
129
135
|
this.timePaused = 0;
|
|
136
|
+
this.batchCount = 0;
|
|
130
137
|
// Listen for delta manager sends and add batch metadata to messages
|
|
131
138
|
this.deltaManager.on("prepareSend", (messages) => {
|
|
132
139
|
if (messages.length === 0) {
|
|
@@ -193,13 +200,26 @@ class ScheduleManagerCore {
|
|
|
193
200
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
194
201
|
this.deltaManager.inbound.pause();
|
|
195
202
|
}
|
|
196
|
-
resumeQueue(startBatch,
|
|
203
|
+
resumeQueue(startBatch, messageEndBatch) {
|
|
204
|
+
const endBatch = messageEndBatch.sequenceNumber;
|
|
205
|
+
const duration = performance.now() - this.timePaused;
|
|
206
|
+
this.batchCount++;
|
|
207
|
+
if (this.batchCount % 1000 === 1) {
|
|
208
|
+
this.logger.sendTelemetryEvent({
|
|
209
|
+
eventName: "BatchStats",
|
|
210
|
+
sequenceNumber: endBatch,
|
|
211
|
+
length: endBatch - startBatch + 1,
|
|
212
|
+
msnDistance: endBatch - messageEndBatch.minimumSequenceNumber,
|
|
213
|
+
duration,
|
|
214
|
+
batchCount: this.batchCount,
|
|
215
|
+
interrupted: this.localPaused,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
197
218
|
// Return early if no change in value
|
|
198
219
|
if (!this.localPaused) {
|
|
199
220
|
return;
|
|
200
221
|
}
|
|
201
222
|
this.localPaused = false;
|
|
202
|
-
const duration = performance.now() - this.timePaused;
|
|
203
223
|
// Random round number - we want to know when batch waiting paused op processing.
|
|
204
224
|
if (duration > latencyThreshold) {
|
|
205
225
|
this.logger.sendErrorEvent({
|
|
@@ -260,7 +280,7 @@ class ScheduleManagerCore {
|
|
|
260
280
|
else if (batchMetadata === false) {
|
|
261
281
|
assert(this.pauseSequenceNumber !== undefined, 0x2a0 /* "batch presence was validated above" */);
|
|
262
282
|
// Batch is complete, we can process it!
|
|
263
|
-
this.resumeQueue(this.pauseSequenceNumber, message
|
|
283
|
+
this.resumeQueue(this.pauseSequenceNumber, message);
|
|
264
284
|
this.pauseSequenceNumber = undefined;
|
|
265
285
|
this.currentBatchClientId = undefined;
|
|
266
286
|
}
|
|
@@ -363,7 +383,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
363
383
|
this._storage = _storage;
|
|
364
384
|
this.defaultMaxConsecutiveReconnects = 15;
|
|
365
385
|
this._orderSequentiallyCalls = 0;
|
|
366
|
-
this._flushMode = FlushMode.TurnBased;
|
|
367
386
|
this.needsFlush = false;
|
|
368
387
|
this.flushTrigger = false;
|
|
369
388
|
this.paused = false;
|
|
@@ -446,6 +465,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
446
465
|
((_c = runtimeOptions.useDataStoreAliasing) !== null && _c !== void 0 ? _c : false);
|
|
447
466
|
this._maxOpSizeInBytes = ((_d = this.mc.config.getNumber(maxOpSizeInBytesKey)) !== null && _d !== void 0 ? _d : defaultMaxOpSizeInBytes);
|
|
448
467
|
this.maxConsecutiveReconnects = (_e = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _e !== void 0 ? _e : this.defaultMaxConsecutiveReconnects;
|
|
468
|
+
this._flushMode = runtimeOptions.flushMode;
|
|
449
469
|
this.garbageCollector = GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), (nodePath) => this.dataStores.getNodePackagePath(nodePath),
|
|
450
470
|
/**
|
|
451
471
|
* Returns the timestamp of the last message seen by this client. This is used by garbage collector as
|
|
@@ -560,6 +580,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
560
580
|
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 }));
|
|
561
581
|
ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
562
582
|
BindBatchTracker(this, this.logger);
|
|
583
|
+
this.opTracker = new OpTracker(this.deltaManager, this.mc.config.getBoolean(disableOpTrackingKey) === true);
|
|
563
584
|
}
|
|
564
585
|
get IContainerRuntime() { return this; }
|
|
565
586
|
get IFluidRouter() { return this; }
|
|
@@ -582,7 +603,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
582
603
|
runtimeVersion: pkgVersion,
|
|
583
604
|
},
|
|
584
605
|
});
|
|
585
|
-
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, } = runtimeOptions;
|
|
606
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, flushMode = defaultFlushMode, } = runtimeOptions;
|
|
586
607
|
// We pack at data store level only. If isolated channels are disabled,
|
|
587
608
|
// then there are no .channel layers, we pack at level 1, otherwise we pack at level 2
|
|
588
609
|
const packingLevel = summaryOptions.disableIsolatedChannels ? 1 : 2;
|
|
@@ -653,6 +674,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
653
674
|
gcOptions,
|
|
654
675
|
loadSequenceNumberVerification,
|
|
655
676
|
useDataStoreAliasing,
|
|
677
|
+
flushMode,
|
|
656
678
|
}, containerScope, logger, loadExisting, blobManagerSnapshot, requestHandler, storage);
|
|
657
679
|
return runtime;
|
|
658
680
|
}
|
|
@@ -871,12 +893,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
871
893
|
const electedSummarizerContent = JSON.stringify((_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.serialize());
|
|
872
894
|
addBlobToSummary(summaryTree, electedSummarizerBlobName, electedSummarizerContent);
|
|
873
895
|
}
|
|
874
|
-
const
|
|
896
|
+
const summary = this.blobManager.summarize();
|
|
875
897
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
876
898
|
// and the blob manager can handle the tree not existing when loading
|
|
877
|
-
if (
|
|
878
|
-
|
|
879
|
-
addTreeToSummary(summaryTree, blobsTreeName, blobsTree);
|
|
899
|
+
if (Object.keys(summary.summary.tree).length > 0) {
|
|
900
|
+
addTreeToSummary(summaryTree, blobsTreeName, summary);
|
|
880
901
|
}
|
|
881
902
|
if (this.garbageCollector.writeDataAtRoot) {
|
|
882
903
|
const gcSummary = this.garbageCollector.summarize();
|
|
@@ -1065,6 +1086,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1065
1086
|
if (mode === this._flushMode) {
|
|
1066
1087
|
return;
|
|
1067
1088
|
}
|
|
1089
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1090
|
+
eventName: "FlushMode Updated",
|
|
1091
|
+
old: this._flushMode,
|
|
1092
|
+
new: mode,
|
|
1093
|
+
});
|
|
1068
1094
|
// Flush any pending batches if switching to immediate
|
|
1069
1095
|
if (mode === FlushMode.Immediate) {
|
|
1070
1096
|
this.flush();
|
|
@@ -1192,6 +1218,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1192
1218
|
const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
|
|
1193
1219
|
if (isRoot) {
|
|
1194
1220
|
fluidDataStore.bindToContext();
|
|
1221
|
+
this.logger.sendTelemetryEvent({
|
|
1222
|
+
eventName: "Root datastore with props",
|
|
1223
|
+
hasProps: props !== undefined,
|
|
1224
|
+
});
|
|
1195
1225
|
}
|
|
1196
1226
|
return channelToDataStore(fluidDataStore, id, this, this.dataStores, this.mc.logger);
|
|
1197
1227
|
}
|
|
@@ -1315,9 +1345,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1315
1345
|
if (runGC) {
|
|
1316
1346
|
gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC });
|
|
1317
1347
|
}
|
|
1318
|
-
const
|
|
1319
|
-
assert(
|
|
1320
|
-
return
|
|
1348
|
+
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState);
|
|
1349
|
+
assert(summary.type === SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1350
|
+
return { stats, summary, gcStats };
|
|
1321
1351
|
}
|
|
1322
1352
|
/**
|
|
1323
1353
|
* Implementation of IGarbageCollectionRuntime::updateStateBeforeGC.
|
|
@@ -1392,6 +1422,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1392
1422
|
try {
|
|
1393
1423
|
await this.deltaManager.inbound.pause();
|
|
1394
1424
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
1425
|
+
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1395
1426
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
1396
1427
|
// We should be here is we haven't processed be here. If we are of if the last message's sequence number
|
|
1397
1428
|
// doesn't match the last processed sequence number, log an error.
|
|
@@ -1431,7 +1462,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1431
1462
|
};
|
|
1432
1463
|
let continueResult = checkContinue();
|
|
1433
1464
|
if (!continueResult.continue) {
|
|
1434
|
-
return {
|
|
1465
|
+
return {
|
|
1466
|
+
stage: "base",
|
|
1467
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1468
|
+
minimumSequenceNumber,
|
|
1469
|
+
error: continueResult.error,
|
|
1470
|
+
};
|
|
1435
1471
|
}
|
|
1436
1472
|
// increment summary count
|
|
1437
1473
|
if (this.summaryCount !== undefined) {
|
|
@@ -1454,7 +1490,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1454
1490
|
});
|
|
1455
1491
|
}
|
|
1456
1492
|
catch (error) {
|
|
1457
|
-
return {
|
|
1493
|
+
return {
|
|
1494
|
+
stage: "base",
|
|
1495
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1496
|
+
minimumSequenceNumber,
|
|
1497
|
+
error,
|
|
1498
|
+
};
|
|
1458
1499
|
}
|
|
1459
1500
|
const { summary: summaryTree, stats: partialStats } = summarizeResult;
|
|
1460
1501
|
// Now that we have generated the summary, update the message at last summary to the last message processed.
|
|
@@ -1465,9 +1506,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1465
1506
|
const dataStoreTree = this.disableIsolatedChannels ? summaryTree : summaryTree.tree[channelsTreeName];
|
|
1466
1507
|
assert(dataStoreTree.type === SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
|
|
1467
1508
|
const handleCount = Object.values(dataStoreTree.tree).filter((value) => value.type === SummaryType.Handle).length;
|
|
1468
|
-
const
|
|
1509
|
+
const gcSummaryTreeStats = summaryTree.tree[gcTreeKey]
|
|
1510
|
+
? calculateStats(summaryTree.tree[gcTreeKey])
|
|
1511
|
+
: undefined;
|
|
1512
|
+
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);
|
|
1469
1513
|
const generateSummaryData = {
|
|
1470
1514
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1515
|
+
minimumSequenceNumber,
|
|
1471
1516
|
summaryTree,
|
|
1472
1517
|
summaryStats,
|
|
1473
1518
|
generateDuration: trace.trace().duration,
|
|
@@ -1518,6 +1563,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1518
1563
|
}
|
|
1519
1564
|
const submitData = Object.assign(Object.assign({ stage: "submit" }, uploadData), { clientSequenceNumber, submitOpDuration: trace.trace().duration });
|
|
1520
1565
|
this.summarizerNode.completeSummary(handle);
|
|
1566
|
+
this.opTracker.reset();
|
|
1521
1567
|
return submitData;
|
|
1522
1568
|
}
|
|
1523
1569
|
finally {
|