@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.
Files changed (83) hide show
  1. package/dist/blobManager.d.ts +3 -2
  2. package/dist/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager.js +13 -9
  4. package/dist/blobManager.js.map +1 -1
  5. package/dist/connectionTelemetry.d.ts.map +1 -1
  6. package/dist/connectionTelemetry.js +63 -23
  7. package/dist/connectionTelemetry.js.map +1 -1
  8. package/dist/containerRuntime.d.ts +12 -4
  9. package/dist/containerRuntime.d.ts.map +1 -1
  10. package/dist/containerRuntime.js +61 -15
  11. package/dist/containerRuntime.js.map +1 -1
  12. package/dist/opTelemetry.d.ts +22 -0
  13. package/dist/opTelemetry.d.ts.map +1 -0
  14. package/dist/opTelemetry.js +59 -0
  15. package/dist/opTelemetry.js.map +1 -0
  16. package/dist/orderedClientElection.d.ts +57 -6
  17. package/dist/orderedClientElection.d.ts.map +1 -1
  18. package/dist/orderedClientElection.js +140 -25
  19. package/dist/orderedClientElection.js.map +1 -1
  20. package/dist/packageVersion.d.ts +1 -1
  21. package/dist/packageVersion.d.ts.map +1 -1
  22. package/dist/packageVersion.js +1 -1
  23. package/dist/packageVersion.js.map +1 -1
  24. package/dist/summarizerClientElection.d.ts +2 -0
  25. package/dist/summarizerClientElection.d.ts.map +1 -1
  26. package/dist/summarizerClientElection.js +7 -2
  27. package/dist/summarizerClientElection.js.map +1 -1
  28. package/dist/summarizerTypes.d.ts +9 -0
  29. package/dist/summarizerTypes.d.ts.map +1 -1
  30. package/dist/summarizerTypes.js.map +1 -1
  31. package/dist/summaryGenerator.d.ts.map +1 -1
  32. package/dist/summaryGenerator.js +1 -1
  33. package/dist/summaryGenerator.js.map +1 -1
  34. package/dist/summaryManager.d.ts.map +1 -1
  35. package/dist/summaryManager.js +14 -3
  36. package/dist/summaryManager.js.map +1 -1
  37. package/lib/blobManager.d.ts +3 -2
  38. package/lib/blobManager.d.ts.map +1 -1
  39. package/lib/blobManager.js +14 -10
  40. package/lib/blobManager.js.map +1 -1
  41. package/lib/connectionTelemetry.d.ts.map +1 -1
  42. package/lib/connectionTelemetry.js +63 -23
  43. package/lib/connectionTelemetry.js.map +1 -1
  44. package/lib/containerRuntime.d.ts +12 -4
  45. package/lib/containerRuntime.d.ts.map +1 -1
  46. package/lib/containerRuntime.js +62 -16
  47. package/lib/containerRuntime.js.map +1 -1
  48. package/lib/opTelemetry.d.ts +22 -0
  49. package/lib/opTelemetry.d.ts.map +1 -0
  50. package/lib/opTelemetry.js +55 -0
  51. package/lib/opTelemetry.js.map +1 -0
  52. package/lib/orderedClientElection.d.ts +57 -6
  53. package/lib/orderedClientElection.d.ts.map +1 -1
  54. package/lib/orderedClientElection.js +140 -25
  55. package/lib/orderedClientElection.js.map +1 -1
  56. package/lib/packageVersion.d.ts +1 -1
  57. package/lib/packageVersion.d.ts.map +1 -1
  58. package/lib/packageVersion.js +1 -1
  59. package/lib/packageVersion.js.map +1 -1
  60. package/lib/summarizerClientElection.d.ts +2 -0
  61. package/lib/summarizerClientElection.d.ts.map +1 -1
  62. package/lib/summarizerClientElection.js +7 -2
  63. package/lib/summarizerClientElection.js.map +1 -1
  64. package/lib/summarizerTypes.d.ts +9 -0
  65. package/lib/summarizerTypes.d.ts.map +1 -1
  66. package/lib/summarizerTypes.js.map +1 -1
  67. package/lib/summaryGenerator.d.ts.map +1 -1
  68. package/lib/summaryGenerator.js +1 -1
  69. package/lib/summaryGenerator.js.map +1 -1
  70. package/lib/summaryManager.d.ts.map +1 -1
  71. package/lib/summaryManager.js +14 -3
  72. package/lib/summaryManager.js.map +1 -1
  73. package/package.json +47 -15
  74. package/src/blobManager.ts +19 -11
  75. package/src/connectionTelemetry.ts +110 -19
  76. package/src/containerRuntime.ts +85 -19
  77. package/src/opTelemetry.ts +71 -0
  78. package/src/orderedClientElection.ts +154 -25
  79. package/src/packageVersion.ts +1 -1
  80. package/src/summarizerClientElection.ts +7 -2
  81. package/src/summarizerTypes.ts +9 -0
  82. package/src/summaryGenerator.ts +9 -1
  83. package/src/summaryManager.ts +15 -4
@@ -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, endBatch) {
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.sequenceNumber);
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 snapshot = this.blobManager.snapshot();
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 (snapshot.entries.length !== 0) {
885
- const blobsTree = runtime_utils_1.convertToSummaryTree(snapshot, false);
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 summarizeResult = await this.summarizerNode.summarize(fullTree, trackState);
1326
- common_utils_1.assert(summarizeResult.summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
1327
- return Object.assign(Object.assign({}, summarizeResult), { gcStats });
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 { stage: "base", referenceSequenceNumber: summaryRefSeqNum, error: continueResult.error };
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 { stage: "base", referenceSequenceNumber: summaryRefSeqNum, error };
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 summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount, gcStateUpdatedDataStoreCount: (_b = summarizeResult.gcStats) === null || _b === void 0 ? void 0 : _b.updatedDataStoreCount }, partialStats);
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 {