@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.
Files changed (135) hide show
  1. package/dist/blobManager.d.ts +81 -25
  2. package/dist/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager.js +301 -100
  4. package/dist/blobManager.js.map +1 -1
  5. package/dist/containerRuntime.d.ts +65 -11
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +101 -82
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/dataStore.d.ts +1 -1
  10. package/dist/dataStore.d.ts.map +1 -1
  11. package/dist/dataStore.js +32 -26
  12. package/dist/dataStore.js.map +1 -1
  13. package/dist/dataStoreContext.d.ts +3 -4
  14. package/dist/dataStoreContext.d.ts.map +1 -1
  15. package/dist/dataStoreContext.js +16 -23
  16. package/dist/dataStoreContext.js.map +1 -1
  17. package/dist/dataStores.d.ts +5 -2
  18. package/dist/dataStores.d.ts.map +1 -1
  19. package/dist/dataStores.js +11 -3
  20. package/dist/dataStores.js.map +1 -1
  21. package/dist/garbageCollection.d.ts.map +1 -1
  22. package/dist/garbageCollection.js +17 -12
  23. package/dist/garbageCollection.js.map +1 -1
  24. package/dist/opProperties.d.ts +7 -0
  25. package/dist/opProperties.d.ts.map +1 -0
  26. package/dist/opProperties.js +20 -0
  27. package/dist/opProperties.js.map +1 -0
  28. package/dist/packageVersion.d.ts +1 -1
  29. package/dist/packageVersion.d.ts.map +1 -1
  30. package/dist/packageVersion.js +1 -1
  31. package/dist/packageVersion.js.map +1 -1
  32. package/dist/runningSummarizer.d.ts +14 -4
  33. package/dist/runningSummarizer.d.ts.map +1 -1
  34. package/dist/runningSummarizer.js +68 -26
  35. package/dist/runningSummarizer.js.map +1 -1
  36. package/dist/summarizer.d.ts +0 -2
  37. package/dist/summarizer.d.ts.map +1 -1
  38. package/dist/summarizer.js +1 -12
  39. package/dist/summarizer.js.map +1 -1
  40. package/dist/summarizerHeuristics.d.ts +26 -4
  41. package/dist/summarizerHeuristics.d.ts.map +1 -1
  42. package/dist/summarizerHeuristics.js +95 -18
  43. package/dist/summarizerHeuristics.js.map +1 -1
  44. package/dist/summarizerTypes.d.ts +30 -10
  45. package/dist/summarizerTypes.d.ts.map +1 -1
  46. package/dist/summarizerTypes.js.map +1 -1
  47. package/dist/summaryCollection.js +1 -1
  48. package/dist/summaryCollection.js.map +1 -1
  49. package/dist/summaryFormat.d.ts +0 -5
  50. package/dist/summaryFormat.d.ts.map +1 -1
  51. package/dist/summaryFormat.js.map +1 -1
  52. package/dist/summaryGenerator.d.ts +1 -0
  53. package/dist/summaryGenerator.d.ts.map +1 -1
  54. package/dist/summaryGenerator.js +11 -9
  55. package/dist/summaryGenerator.js.map +1 -1
  56. package/lib/blobManager.d.ts +81 -25
  57. package/lib/blobManager.d.ts.map +1 -1
  58. package/lib/blobManager.js +302 -101
  59. package/lib/blobManager.js.map +1 -1
  60. package/lib/containerRuntime.d.ts +65 -11
  61. package/lib/containerRuntime.d.ts.map +1 -1
  62. package/lib/containerRuntime.js +103 -84
  63. package/lib/containerRuntime.js.map +1 -1
  64. package/lib/dataStore.d.ts +1 -1
  65. package/lib/dataStore.d.ts.map +1 -1
  66. package/lib/dataStore.js +32 -26
  67. package/lib/dataStore.js.map +1 -1
  68. package/lib/dataStoreContext.d.ts +3 -4
  69. package/lib/dataStoreContext.d.ts.map +1 -1
  70. package/lib/dataStoreContext.js +17 -24
  71. package/lib/dataStoreContext.js.map +1 -1
  72. package/lib/dataStores.d.ts +5 -2
  73. package/lib/dataStores.d.ts.map +1 -1
  74. package/lib/dataStores.js +11 -3
  75. package/lib/dataStores.js.map +1 -1
  76. package/lib/garbageCollection.d.ts.map +1 -1
  77. package/lib/garbageCollection.js +17 -12
  78. package/lib/garbageCollection.js.map +1 -1
  79. package/lib/opProperties.d.ts +7 -0
  80. package/lib/opProperties.d.ts.map +1 -0
  81. package/lib/opProperties.js +16 -0
  82. package/lib/opProperties.js.map +1 -0
  83. package/lib/packageVersion.d.ts +1 -1
  84. package/lib/packageVersion.d.ts.map +1 -1
  85. package/lib/packageVersion.js +1 -1
  86. package/lib/packageVersion.js.map +1 -1
  87. package/lib/runningSummarizer.d.ts +14 -4
  88. package/lib/runningSummarizer.d.ts.map +1 -1
  89. package/lib/runningSummarizer.js +68 -26
  90. package/lib/runningSummarizer.js.map +1 -1
  91. package/lib/summarizer.d.ts +0 -2
  92. package/lib/summarizer.d.ts.map +1 -1
  93. package/lib/summarizer.js +1 -12
  94. package/lib/summarizer.js.map +1 -1
  95. package/lib/summarizerHeuristics.d.ts +26 -4
  96. package/lib/summarizerHeuristics.d.ts.map +1 -1
  97. package/lib/summarizerHeuristics.js +95 -18
  98. package/lib/summarizerHeuristics.js.map +1 -1
  99. package/lib/summarizerTypes.d.ts +30 -10
  100. package/lib/summarizerTypes.d.ts.map +1 -1
  101. package/lib/summarizerTypes.js.map +1 -1
  102. package/lib/summaryCollection.js +1 -1
  103. package/lib/summaryCollection.js.map +1 -1
  104. package/lib/summaryFormat.d.ts +0 -5
  105. package/lib/summaryFormat.d.ts.map +1 -1
  106. package/lib/summaryFormat.js.map +1 -1
  107. package/lib/summaryGenerator.d.ts +1 -0
  108. package/lib/summaryGenerator.d.ts.map +1 -1
  109. package/lib/summaryGenerator.js +11 -9
  110. package/lib/summaryGenerator.js.map +1 -1
  111. package/package.json +45 -20
  112. package/src/blobManager.ts +360 -119
  113. package/src/containerRuntime.ts +203 -103
  114. package/src/dataStore.ts +53 -38
  115. package/src/dataStoreContext.ts +16 -23
  116. package/src/dataStores.ts +14 -3
  117. package/src/garbageCollection.ts +13 -7
  118. package/src/opProperties.ts +19 -0
  119. package/src/packageVersion.ts +1 -1
  120. package/src/runningSummarizer.ts +75 -22
  121. package/src/summarizer.ts +1 -18
  122. package/src/summarizerHeuristics.ts +133 -19
  123. package/src/summarizerTypes.ts +37 -10
  124. package/src/summaryCollection.ts +1 -1
  125. package/src/summaryFormat.ts +0 -6
  126. package/src/summaryGenerator.ts +40 -22
  127. package/dist/opTelemetry.d.ts +0 -22
  128. package/dist/opTelemetry.d.ts.map +0 -1
  129. package/dist/opTelemetry.js +0 -59
  130. package/dist/opTelemetry.js.map +0 -1
  131. package/lib/opTelemetry.d.ts +0 -22
  132. package/lib/opTelemetry.d.ts.map +0 -1
  133. package/lib/opTelemetry.js +0 -55
  134. package/lib/opTelemetry.js.map +0 -1
  135. package/src/opTelemetry.ts +0 -71
@@ -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: 5000 * 3,
54
- maxTime: 5000 * 12,
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: 6 * 10 * 1000,
58
+ maxAckWaitTime: 10 * 60 * 1000,
58
59
  maxOpsSinceLastSummary: 7000,
59
- initialSummarizerDelayMs: 5000,
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, _j;
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, this.logger);
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
- // back-compat 0.59.3000 - Older document may either write summaryCount or not write it at all. If it does
583
- // not write it, initialize summaryNumber to 0.
584
- loadSummaryNumber = (_j = (_h = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _h !== void 0 ? _h : metadata === null || metadata === void 0 ? void 0 : metadata.summaryCount) !== null && _j !== void 0 ? _j : 0;
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 handle = await this.blobManager.getBlob(requestParser.pathParts[1]);
867
- if (handle) {
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: handle.get(),
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().get(maybeAlias)) !== null && _a !== void 0 ? _a : maybeAlias;
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, _b;
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
- (0, common_utils_1.assert)((_b = message === null || message === void 0 ? void 0 : message.metadata) === null || _b === void 0 ? void 0 : _b.blobId, 0x12a /* "Missing blob id on metadata" */);
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
- // back-compat 0.59.1000 - makeVisibleAndAttachGraph was added in this version to IFluidDataStoreChannel. For
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
- const dataStore = await this._createDataStore(pkg, false /* isRoot */, internalId, props);
1326
- const aliasedDataStore = (0, dataStore_1.channelToDataStore)(dataStore, internalId, this, this.dataStores, this.mc.logger);
1327
- const result = await aliasedDataStore.trySetAlias(alias);
1328
- if (result !== "Success") {
1329
- throw new container_utils_1.GenericError("dataStoreAliasFailure", undefined /* error */, {
1330
- alias: {
1331
- value: alias,
1332
- tag: telemetry_utils_1.TelemetryDataTag.UserData,
1333
- },
1334
- internalId: {
1335
- value: internalId,
1336
- tag: telemetry_utils_1.TelemetryDataTag.PackageData,
1337
- },
1338
- aliasResult: result,
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
- // back-compat 0.59.1000 - makeVisibleAndAttachGraph was added in this version to IFluidDataStoreChannel.
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, _c;
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
- // We should be here is we haven't processed be here. If we are of if the last message's sequence number
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: (_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, summaryNumber }, partialStats);
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: (_c = this.context.getLoadedFromVersion()) === null || _c === void 0 ? void 0 : _c.id,
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
- value: serializedContent.length,
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.submit(type, content, localOpMetadata, opMetadata);
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
  /**