@fluidframework/container-runtime 0.56.3 → 0.57.0-51086

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 (97) hide show
  1. package/dist/blobManager.d.ts.map +1 -1
  2. package/dist/blobManager.js +9 -1
  3. package/dist/blobManager.js.map +1 -1
  4. package/dist/connectionTelemetry.d.ts.map +1 -1
  5. package/dist/connectionTelemetry.js +6 -6
  6. package/dist/connectionTelemetry.js.map +1 -1
  7. package/dist/containerRuntime.d.ts +65 -24
  8. package/dist/containerRuntime.d.ts.map +1 -1
  9. package/dist/containerRuntime.js +139 -72
  10. package/dist/containerRuntime.js.map +1 -1
  11. package/dist/dataStore.d.ts +62 -0
  12. package/dist/dataStore.d.ts.map +1 -0
  13. package/dist/dataStore.js +135 -0
  14. package/dist/dataStore.js.map +1 -0
  15. package/dist/dataStoreContext.js.map +1 -1
  16. package/dist/dataStores.d.ts +9 -5
  17. package/dist/dataStores.d.ts.map +1 -1
  18. package/dist/dataStores.js +14 -19
  19. package/dist/dataStores.js.map +1 -1
  20. package/dist/garbageCollection.d.ts +47 -21
  21. package/dist/garbageCollection.d.ts.map +1 -1
  22. package/dist/garbageCollection.js +195 -61
  23. package/dist/garbageCollection.js.map +1 -1
  24. package/dist/index.d.ts +3 -2
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +4 -1
  27. package/dist/index.js.map +1 -1
  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 +1 -0
  33. package/dist/runningSummarizer.d.ts.map +1 -1
  34. package/dist/runningSummarizer.js +23 -15
  35. package/dist/runningSummarizer.js.map +1 -1
  36. package/dist/summarizerTypes.d.ts +4 -6
  37. package/dist/summarizerTypes.d.ts.map +1 -1
  38. package/dist/summarizerTypes.js.map +1 -1
  39. package/dist/summaryGenerator.d.ts +2 -1
  40. package/dist/summaryGenerator.d.ts.map +1 -1
  41. package/dist/summaryGenerator.js +46 -29
  42. package/dist/summaryGenerator.js.map +1 -1
  43. package/lib/blobManager.d.ts.map +1 -1
  44. package/lib/blobManager.js +9 -1
  45. package/lib/blobManager.js.map +1 -1
  46. package/lib/connectionTelemetry.d.ts.map +1 -1
  47. package/lib/connectionTelemetry.js +6 -6
  48. package/lib/connectionTelemetry.js.map +1 -1
  49. package/lib/containerRuntime.d.ts +65 -24
  50. package/lib/containerRuntime.d.ts.map +1 -1
  51. package/lib/containerRuntime.js +140 -73
  52. package/lib/containerRuntime.js.map +1 -1
  53. package/lib/dataStore.d.ts +62 -0
  54. package/lib/dataStore.d.ts.map +1 -0
  55. package/lib/dataStore.js +130 -0
  56. package/lib/dataStore.js.map +1 -0
  57. package/lib/dataStoreContext.js.map +1 -1
  58. package/lib/dataStores.d.ts +9 -5
  59. package/lib/dataStores.d.ts.map +1 -1
  60. package/lib/dataStores.js +13 -18
  61. package/lib/dataStores.js.map +1 -1
  62. package/lib/garbageCollection.d.ts +47 -21
  63. package/lib/garbageCollection.d.ts.map +1 -1
  64. package/lib/garbageCollection.js +197 -63
  65. package/lib/garbageCollection.js.map +1 -1
  66. package/lib/index.d.ts +3 -2
  67. package/lib/index.d.ts.map +1 -1
  68. package/lib/index.js +2 -1
  69. package/lib/index.js.map +1 -1
  70. package/lib/packageVersion.d.ts +1 -1
  71. package/lib/packageVersion.d.ts.map +1 -1
  72. package/lib/packageVersion.js +1 -1
  73. package/lib/packageVersion.js.map +1 -1
  74. package/lib/runningSummarizer.d.ts +1 -0
  75. package/lib/runningSummarizer.d.ts.map +1 -1
  76. package/lib/runningSummarizer.js +23 -15
  77. package/lib/runningSummarizer.js.map +1 -1
  78. package/lib/summarizerTypes.d.ts +4 -6
  79. package/lib/summarizerTypes.d.ts.map +1 -1
  80. package/lib/summarizerTypes.js.map +1 -1
  81. package/lib/summaryGenerator.d.ts +2 -1
  82. package/lib/summaryGenerator.d.ts.map +1 -1
  83. package/lib/summaryGenerator.js +46 -29
  84. package/lib/summaryGenerator.js.map +1 -1
  85. package/package.json +13 -13
  86. package/src/blobManager.ts +12 -1
  87. package/src/connectionTelemetry.ts +7 -6
  88. package/src/containerRuntime.ts +220 -93
  89. package/src/dataStore.ts +187 -0
  90. package/src/dataStoreContext.ts +1 -1
  91. package/src/dataStores.ts +18 -38
  92. package/src/garbageCollection.ts +283 -105
  93. package/src/index.ts +3 -1
  94. package/src/packageVersion.ts +1 -1
  95. package/src/runningSummarizer.ts +25 -16
  96. package/src/summarizerTypes.ts +4 -8
  97. package/src/summaryGenerator.ts +71 -23
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.ScheduleManager = exports.unpackRuntimeMessage = exports.isRuntimeMessage = exports.RuntimeMessage = exports.ContainerMessageType = void 0;
7
+ exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.ScheduleManager = exports.unpackRuntimeMessage = exports.isRuntimeMessage = exports.RuntimeMessage = exports.RuntimeHeaders = exports.ContainerMessageType = void 0;
8
8
  const container_definitions_1 = require("@fluidframework/container-definitions");
9
9
  const common_utils_1 = require("@fluidframework/common-utils");
10
10
  const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
@@ -32,6 +32,7 @@ const summarizerClientElection_1 = require("./summarizerClientElection");
32
32
  const throttler_1 = require("./throttler");
33
33
  const runWhileConnectedCoordinator_1 = require("./runWhileConnectedCoordinator");
34
34
  const garbageCollection_1 = require("./garbageCollection");
35
+ const dataStore_1 = require("./dataStore");
35
36
  var ContainerMessageType;
36
37
  (function (ContainerMessageType) {
37
38
  // An op to be delivered to store
@@ -59,9 +60,24 @@ const DefaultSummaryConfiguration = {
59
60
  // the min of the two will be chosen
60
61
  maxAckWaitTime: 120000,
61
62
  };
62
- ;
63
+ /**
64
+ * Accepted header keys for requests coming to the runtime.
65
+ */
66
+ var RuntimeHeaders;
67
+ (function (RuntimeHeaders) {
68
+ /** True to wait for a data store to be created and loaded before returning it. */
69
+ RuntimeHeaders["wait"] = "wait";
70
+ /**
71
+ * True if the request is from an external app. Used for GC to handle scenarios where a data store
72
+ * is deleted and requested via an external app.
73
+ */
74
+ RuntimeHeaders["externalRequest"] = "externalRequest";
75
+ /** True if the request is coming from an IFluidHandle. */
76
+ RuntimeHeaders["viaHandle"] = "viaHandle";
77
+ })(RuntimeHeaders = exports.RuntimeHeaders || (exports.RuntimeHeaders = {}));
63
78
  // Local storage key to set the default flush mode to TurnBased
64
79
  const turnBasedFlushModeKey = "Fluid.ContainerRuntime.FlushModeTurnBased";
80
+ const useDataStoreAliasingKey = "Fluid.ContainerRuntime.UseDataStoreAliasing";
65
81
  var RuntimeMessage;
66
82
  (function (RuntimeMessage) {
67
83
  RuntimeMessage["FluidDataStoreOp"] = "component";
@@ -339,7 +355,7 @@ exports.getDeviceSpec = getDeviceSpec;
339
355
  */
340
356
  class ContainerRuntime extends common_utils_1.TypedEventEmitter {
341
357
  constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, requestHandler, _storage) {
342
- var _a, _b, _c, _d, _e;
358
+ var _a, _b, _c, _d, _e, _f, _g, _h;
343
359
  super();
344
360
  this.context = context;
345
361
  this.registry = registry;
@@ -353,7 +369,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
353
369
  this.flushTrigger = false;
354
370
  this.paused = false;
355
371
  this._disposed = false;
356
- this.dirtyContainer = false;
357
372
  this.emitDirtyDocumentEvent = true;
358
373
  this.summarizerWarning = (warning) => this.mc.logger.sendTelemetryEvent({ eventName: "summarizerWarning" }, warning);
359
374
  /**
@@ -429,6 +444,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
429
444
  this.mc = telemetry_utils_1.loggerToMonitoringContext(telemetry_utils_1.ChildLogger.create(this.logger, "ContainerRuntime"));
430
445
  this._flushMode =
431
446
  ((_b = this.mc.config.getBoolean(turnBasedFlushModeKey)) !== null && _b !== void 0 ? _b : false) ? runtime_definitions_1.FlushMode.TurnBased : runtime_definitions_1.FlushMode.Immediate;
447
+ this._aliasingEnabled =
448
+ ((_c = this.mc.config.getBoolean(useDataStoreAliasingKey)) !== null && _c !== void 0 ? _c : false) ||
449
+ ((_d = runtimeOptions.useDataStoreAliasing) !== null && _d !== void 0 ? _d : false);
432
450
  /**
433
451
  * Function that return the current server timestamp. This is used by the garbage collector to set the
434
452
  * time when a node becomes unreferenced.
@@ -442,7 +460,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
442
460
  const timestamp = client === null || client === void 0 ? void 0 : client.timestamp;
443
461
  return (_c = (_b = (_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : timestamp) !== null && _c !== void 0 ? _c : Date.now();
444
462
  };
445
- this.garbageCollector = garbageCollection_1.GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), getCurrentTimestamp, this.closeFn, context.baseSnapshot, async (id) => driver_utils_1.readAndParse(this.storage, id), this.mc.logger, existing, metadata);
463
+ this.garbageCollector = garbageCollection_1.GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), (nodePath) => this.dataStores.getNodePackagePath(nodePath), getCurrentTimestamp, this.closeFn, context.baseSnapshot, async (id) => driver_utils_1.readAndParse(this.storage, id), this.mc.logger, existing, metadata);
446
464
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
447
465
  this.summarizerNode = runtime_utils_1.createRootSummarizerNodeWithGC(telemetry_utils_1.ChildLogger.create(this.logger, "SummarizerNode"),
448
466
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
@@ -463,7 +481,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
463
481
  if (this.context.baseSnapshot) {
464
482
  this.summarizerNode.loadBaseSummaryWithoutDifferential(this.context.baseSnapshot);
465
483
  }
466
- this.dataStores = new dataStores_1.DataStores(dataStores_1.getSummaryForDatastores(context.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.getDataStoreBaseGCDetails(), (id) => this.garbageCollector.nodeChanged(id), new Map(dataStoreAliasMap), this.garbageCollector.writeDataAtRoot);
484
+ this.dataStores = new dataStores_1.DataStores(dataStores_1.getSummaryForDatastores(context.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.getDataStoreBaseGCDetails(), (dataStorePath, packagePath) => this.garbageCollector.nodeUpdated(dataStorePath, "Changed", packagePath), new Map(dataStoreAliasMap), this.garbageCollector.writeDataAtRoot);
467
485
  this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), this, this.logger);
468
486
  this.scheduleManager = new ScheduleManager(context.deltaManager, this, telemetry_utils_1.ChildLogger.create(this.logger, "ScheduleManager"));
469
487
  this.deltaSender = this.deltaManager;
@@ -472,6 +490,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
472
490
  this.clearPartialChunks(clientId);
473
491
  });
474
492
  this.summaryCollection = new summaryCollection_1.SummaryCollection(this.deltaManager, this.logger);
493
+ const { attachState, pendingLocalState } = this.context;
494
+ this.dirtyContainer = attachState !== container_definitions_1.AttachState.Attached
495
+ || ((_e = pendingLocalState) === null || _e === void 0 ? void 0 : _e.pendingStates.length) > 0;
496
+ this.context.updateDirtyContainerState(this.dirtyContainer);
475
497
  // Map the deprecated generateSummaries flag to disableSummaries.
476
498
  if (this.runtimeOptions.summaryOptions.generateSummaries === false) {
477
499
  this.runtimeOptions.summaryOptions.disableSummaries = true;
@@ -483,8 +505,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
483
505
  const orderedClientLogger = telemetry_utils_1.ChildLogger.create(this.logger, "OrderedClientElection");
484
506
  const orderedClientCollection = new orderedClientElection_1.OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
485
507
  const orderedClientElectionForSummarizer = new orderedClientElection_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, summarizerClientElection_1.SummarizerClientElection.isClientEligible);
486
- const summarizerClientElectionEnabled = (_c = this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) !== null && _c !== void 0 ? _c : ((_d = this.runtimeOptions.summaryOptions) === null || _d === void 0 ? void 0 : _d.summarizerClientElection) === true;
487
- const maxOpsSinceLastSummary = (_e = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary) !== null && _e !== void 0 ? _e : 7000;
508
+ const summarizerClientElectionEnabled = (_f = this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) !== null && _f !== void 0 ? _f : ((_g = this.runtimeOptions.summaryOptions) === null || _g === void 0 ? void 0 : _g.summarizerClientElection) === true;
509
+ const maxOpsSinceLastSummary = (_h = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary) !== null && _h !== void 0 ? _h : 7000;
488
510
  this.summarizerClientElection = new summarizerClientElection_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary, summarizerClientElectionEnabled);
489
511
  if (this.context.clientDetails.type === summarizerClientElection_1.summarizerClientType) {
490
512
  this._summarizer = new summarizer_1.Summarizer("/_summarizer", this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => runWhileConnectedCoordinator_1.RunWhileConnectedCoordinator.create(runtime));
@@ -568,7 +590,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
568
590
  runtimeVersion: packageVersion_1.pkgVersion,
569
591
  },
570
592
  });
571
- const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", } = runtimeOptions;
593
+ const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, } = runtimeOptions;
572
594
  // We pack at data store level only. If isolated channels are disabled,
573
595
  // then there are no .channel layers, we pack at level 1, otherwise we pack at level 2
574
596
  const packingLevel = summaryOptions.disableIsolatedChannels ? 1 : 2;
@@ -636,6 +658,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
636
658
  summaryOptions,
637
659
  gcOptions,
638
660
  loadSequenceNumberVerification,
661
+ useDataStoreAliasing,
639
662
  }, containerScope, logger, loadExisting, blobManagerSnapshot, requestHandler, storage);
640
663
  return runtime;
641
664
  }
@@ -775,7 +798,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
775
798
  * @param request - Request made to the handler.
776
799
  */
777
800
  async resolveHandle(request) {
778
- var _a, _b;
779
801
  try {
780
802
  const requestParser = runtime_utils_1.RequestParser.create(request);
781
803
  const id = requestParser.pathParts[0];
@@ -796,18 +818,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
796
818
  }
797
819
  }
798
820
  else if (requestParser.pathParts.length > 0) {
799
- /**
800
- * If GC should run and this an external app request with "externalRequest" header, we need to return
801
- * an error if the data store being requested is marked as unreferenced as per the data store's initial
802
- * summary.
803
- *
804
- * This is a workaround to handle scenarios where a data store shared with an external app is deleted
805
- * and marked as unreferenced by GC. Returning an error will fail to load the data store for the app.
806
- */
807
- const wait = typeof ((_a = request.headers) === null || _a === void 0 ? void 0 : _a.wait) === "boolean" ? request.headers.wait : undefined;
808
- const dataStore = ((_b = request.headers) === null || _b === void 0 ? void 0 : _b.externalRequest) && this.garbageCollector.shouldRunGC
809
- ? await this.getDataStoreIfInitiallyReferenced(id, wait)
810
- : await this.getDataStore(id, wait);
821
+ const dataStore = await this.getDataStoreFromRequest(id, request);
811
822
  const subRequest = requestParser.createSubRequest(1);
812
823
  // We always expect createSubRequest to include a leading slash, but asserting here to protect against
813
824
  // unintentionally modifying the url if that changes.
@@ -820,6 +831,33 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
820
831
  return runtime_utils_1.exceptionToResponse(error);
821
832
  }
822
833
  }
834
+ async getDataStoreFromRequest(id, request) {
835
+ var _a, _b, _c;
836
+ const wait = typeof ((_a = request.headers) === null || _a === void 0 ? void 0 : _a[RuntimeHeaders.wait]) === "boolean"
837
+ ? (_b = request.headers) === null || _b === void 0 ? void 0 : _b[RuntimeHeaders.wait] : true;
838
+ const dataStoreContext = await this.dataStores.getDataStore(id, wait);
839
+ /**
840
+ * If GC should run and this an external app request with "externalRequest" header, we need to return
841
+ * an error if the data store being requested is marked as unreferenced as per the data store's base
842
+ * GC data.
843
+ *
844
+ * This is a workaround to handle scenarios where a data store shared with an external app is deleted
845
+ * and marked as unreferenced by GC. Returning an error will fail to load the data store for the app.
846
+ */
847
+ if (((_c = request.headers) === null || _c === void 0 ? void 0 : _c[RuntimeHeaders.externalRequest]) && this.garbageCollector.shouldRunGC) {
848
+ // The data store is referenced if used routes in the base summary has a route to self.
849
+ // Older documents may not have used routes in the summary. They are considered referenced.
850
+ const usedRoutes = (await dataStoreContext.getBaseGCDetails()).usedRoutes;
851
+ if (!(usedRoutes === undefined || usedRoutes.includes("") || usedRoutes.includes("/"))) {
852
+ throw runtime_utils_1.responseToException(runtime_utils_1.create404Response(request), request);
853
+ }
854
+ }
855
+ const dataStoreChannel = await dataStoreContext.realize();
856
+ // Let the garbage collector know that a data store was requested / loaded. Realize the data store first so
857
+ // that the package path is available.
858
+ this.garbageCollector.nodeUpdated(`/${id}`, "Loaded", dataStoreContext.packagePath, request === null || request === void 0 ? void 0 : request.headers);
859
+ return dataStoreChannel;
860
+ }
823
861
  formMetadata() {
824
862
  var _a;
825
863
  return Object.assign(Object.assign({}, this.createContainerMetadata), { summaryCount: this.summaryCount, summaryFormatVersion: 1, disableIsolatedChannels: this.disableIsolatedChannels || undefined, gcFeature: this.garbageCollector.gcSummaryFeatureVersion,
@@ -827,40 +865,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
827
865
  // the base summary we loaded from. So, use the message from its metadata blob.
828
866
  message: (_a = summaryFormat_1.extractSummaryMetadataMessage(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.baseSummaryMessage, sessionExpiryTimeoutMs: this.garbageCollector.sessionExpiryTimeoutMs });
829
867
  }
830
- /**
831
- * Retrieves the runtime for a data store if it's referenced as per the initially summary that it is loaded with.
832
- * This is a workaround to handle scenarios where a data store shared with an external app is deleted and marked
833
- * as unreferenced by GC.
834
- * @param id - Id supplied during creating the data store.
835
- * @param wait - True if you want to wait for it.
836
- * @returns the data store runtime if the data store exists and is initially referenced; undefined otherwise.
837
- */
838
- async getDataStoreIfInitiallyReferenced(id, wait = true) {
839
- const dataStoreContext = await this.dataStores.getDataStore(id, wait);
840
- // The data store is referenced if used routes in the initial summary has a route to self.
841
- // Older documents may not have used routes in the summary. They are considered referenced.
842
- const usedRoutes = (await dataStoreContext.getBaseGCDetails()).usedRoutes;
843
- if (usedRoutes === undefined || usedRoutes.includes("") || usedRoutes.includes("/")) {
844
- return dataStoreContext.realize();
845
- }
846
- // The data store is unreferenced. Throw a 404 response exception.
847
- const request = { url: id };
848
- throw runtime_utils_1.responseToException(runtime_utils_1.create404Response(request), request);
849
- }
850
- /**
851
- * Notifies this object to take the snapshot of the container.
852
- * @deprecated - Use summarize to get summary of the container runtime.
853
- */
854
- async snapshot() {
855
- const summaryResult = await this.summarize({
856
- summaryLogger: this.logger,
857
- fullTree: true,
858
- trackState: false,
859
- runGC: this.garbageCollector.shouldRunGC,
860
- fullGC: true,
861
- });
862
- return runtime_utils_1.convertSummaryTreeToITree(summaryResult.summary);
863
- }
864
868
  addContainerStateToSummary(summaryTree) {
865
869
  var _a;
866
870
  runtime_utils_1.addBlobToSummary(summaryTree, summaryFormat_1.metadataBlobName, JSON.stringify(this.formMetadata()));
@@ -1022,9 +1026,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1022
1026
  common_utils_1.assert(await context.isRoot(), 0x12b /* "did not get root data store" */);
1023
1027
  return context.realize();
1024
1028
  }
1025
- async getDataStore(id, wait = true) {
1026
- return (await this.dataStores.getDataStore(id, wait)).realize();
1027
- }
1028
1029
  setFlushMode(mode) {
1029
1030
  if (mode === this._flushMode) {
1030
1031
  return;
@@ -1089,28 +1090,84 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1089
1090
  }
1090
1091
  }
1091
1092
  async createDataStore(pkg) {
1092
- return this._createDataStore(pkg, false /* isRoot */);
1093
+ const internalId = uuid_1.v4();
1094
+ return dataStore_1.channelToDataStore(await this._createDataStore(pkg, false /* isRoot */, internalId), internalId, this, this.dataStores, this.mc.logger);
1093
1095
  }
1094
- async createRootDataStore(pkg, rootDataStoreId) {
1096
+ /**
1097
+ * Creates a root datastore directly with a user generated id and attaches it to storage.
1098
+ * It is vulnerable to name collisions and should not be used.
1099
+ *
1100
+ * This method will be removed. See #6465.
1101
+ */
1102
+ async createRootDataStoreLegacy(pkg, rootDataStoreId) {
1095
1103
  const fluidDataStore = await this._createDataStore(pkg, true /* isRoot */, rootDataStoreId);
1096
1104
  fluidDataStore.bindToContext();
1097
1105
  return fluidDataStore;
1098
1106
  }
1107
+ async createRootDataStore(pkg, rootDataStoreId) {
1108
+ return this._aliasingEnabled === true ?
1109
+ this.createAndAliasDataStore(pkg, rootDataStoreId) :
1110
+ this.createRootDataStoreLegacy(pkg, rootDataStoreId);
1111
+ }
1112
+ /**
1113
+ * Creates a data store then attempts to alias it.
1114
+ * If aliasing fails, it will raise an exception.
1115
+ *
1116
+ * This method will be removed. See #6465.
1117
+ *
1118
+ * @param pkg - Package name of the data store
1119
+ * @param alias - Alias to be assigned to the data store
1120
+ * @param props - Properties for the data store
1121
+ * @returns - An aliased data store which can can be found / loaded by alias.
1122
+ */
1123
+ async createAndAliasDataStore(pkg, alias, props) {
1124
+ const internalId = uuid_1.v4();
1125
+ const dataStore = await this._createDataStore(pkg, false /* isRoot */, internalId, props);
1126
+ const aliasedDataStore = dataStore_1.channelToDataStore(dataStore, internalId, this, this.dataStores, this.mc.logger);
1127
+ const result = await aliasedDataStore.trySetAlias(alias);
1128
+ if (result !== dataStore_1.AliasResult.Success) {
1129
+ throw new container_utils_1.GenericError("dataStoreAliasFailure", undefined /* error */, {
1130
+ alias: {
1131
+ value: alias,
1132
+ tag: telemetry_utils_1.TelemetryDataTag.UserData,
1133
+ },
1134
+ internalId: {
1135
+ value: internalId,
1136
+ tag: telemetry_utils_1.TelemetryDataTag.PackageData,
1137
+ },
1138
+ aliasResult: result,
1139
+ });
1140
+ }
1141
+ return aliasedDataStore;
1142
+ }
1099
1143
  createDetachedRootDataStore(pkg, rootDataStoreId) {
1100
1144
  return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
1101
1145
  }
1102
1146
  createDetachedDataStore(pkg) {
1103
1147
  return this.dataStores.createDetachedDataStoreCore(pkg, false);
1104
1148
  }
1105
- async _createDataStoreWithProps(pkg, props, id = uuid_1.v4(), isRoot = false) {
1149
+ /**
1150
+ * Creates a possibly root datastore directly with a possibly user generated id and attaches it to storage.
1151
+ * It is vulnerable to name collisions if both aforementioned conditions are true, and should not be used.
1152
+ *
1153
+ * This method will be removed. See #6465.
1154
+ */
1155
+ async _createDataStoreWithPropsLegacy(pkg, props, id = uuid_1.v4(), isRoot = false) {
1106
1156
  const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
1107
1157
  if (isRoot) {
1108
1158
  fluidDataStore.bindToContext();
1109
1159
  }
1110
1160
  return fluidDataStore;
1111
1161
  }
1112
- async _createDataStore(pkg, isRoot, id = uuid_1.v4()) {
1113
- return this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot).realize();
1162
+ async _createDataStoreWithProps(pkg, props, id = uuid_1.v4(), isRoot = false) {
1163
+ return this._aliasingEnabled === true && isRoot ?
1164
+ this.createAndAliasDataStore(pkg, id, props) :
1165
+ this._createDataStoreWithPropsLegacy(pkg, props, id, isRoot);
1166
+ }
1167
+ async _createDataStore(pkg, isRoot, id = uuid_1.v4(), props) {
1168
+ return this.dataStores
1169
+ ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props)
1170
+ .realize();
1114
1171
  }
1115
1172
  canSendOps() {
1116
1173
  return this.connected && !this.deltaManager.readOnlyInfo.readonly;
@@ -1168,6 +1225,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1168
1225
  common_utils_1.assert(this.attachState === container_definitions_1.AttachState.Attached, 0x12e /* "Container Context should already be in attached state" */);
1169
1226
  this.emit("attached");
1170
1227
  }
1228
+ if (attachState === container_definitions_1.AttachState.Attached && !this.pendingStateManager.hasPendingMessages()) {
1229
+ this.updateDocumentDirtyState(false);
1230
+ }
1171
1231
  this.dataStores.setAttachState(attachState);
1172
1232
  }
1173
1233
  /**
@@ -1214,13 +1274,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1214
1274
  */
1215
1275
  async summarize(options) {
1216
1276
  this.verifyNotClosed();
1217
- const { summaryLogger, fullTree = false, trackState = true, runGC = true, runSweep, fullGC } = options;
1277
+ const { fullTree = false, trackState = true, summaryLogger = this.logger, runGC = this.garbageCollector.shouldRunGC, runSweep, fullGC, } = options;
1278
+ let gcStats;
1218
1279
  if (runGC) {
1219
- await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC });
1280
+ gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC });
1220
1281
  }
1221
1282
  const summarizeResult = await this.summarizerNode.summarize(fullTree, trackState);
1222
1283
  common_utils_1.assert(summarizeResult.summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
1223
- return summarizeResult;
1284
+ return Object.assign(Object.assign({}, summarizeResult), { gcStats });
1224
1285
  }
1225
1286
  /**
1226
1287
  * Implementation of IGarbageCollectionRuntime::updateStateBeforeGC.
@@ -1245,7 +1306,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1245
1306
  * @param usedRoutes - The routes that are used in all nodes in this Container.
1246
1307
  * @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes
1247
1308
  * unreferenced as part of this GC run, this should be used to update the time when it happens.
1248
- * @returns the statistics of the used state of the data stores.
1249
1309
  */
1250
1310
  updateUsedRoutes(usedRoutes, gcTimestamp) {
1251
1311
  // Update our summarizer node's used routes. Updating used routes in summarizer node before
@@ -1279,7 +1339,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1279
1339
  * @param options - options controlling how the summary is generated or submitted
1280
1340
  */
1281
1341
  async submitSummary(options) {
1282
- var _a;
1342
+ var _a, _b;
1283
1343
  const { fullTree, refreshLatestAck, summaryLogger } = options;
1284
1344
  if (refreshLatestAck) {
1285
1345
  const latestSummaryRefSeq = await this.refreshLatestSummaryAckFromServer(telemetry_utils_1.ChildLogger.create(summaryLogger, undefined, { all: { safeSummary: true } }));
@@ -1343,9 +1403,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1343
1403
  const forcedFullTree = this.garbageCollector.summaryStateNeedsReset;
1344
1404
  try {
1345
1405
  summarizeResult = await this.summarize({
1346
- summaryLogger,
1347
1406
  fullTree: fullTree || forcedFullTree,
1348
1407
  trackState: true,
1408
+ summaryLogger,
1349
1409
  runGC: this.garbageCollector.shouldRunGC,
1350
1410
  });
1351
1411
  }
@@ -1359,7 +1419,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1359
1419
  const dataStoreTree = this.disableIsolatedChannels ? summaryTree : summaryTree.tree[runtime_definitions_1.channelsTreeName];
1360
1420
  common_utils_1.assert(dataStoreTree.type === protocol_definitions_1.SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
1361
1421
  const handleCount = Object.values(dataStoreTree.tree).filter((value) => value.type === protocol_definitions_1.SummaryType.Handle).length;
1362
- const summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount }, partialStats);
1422
+ 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 }, partialStats);
1363
1423
  const generateSummaryData = {
1364
1424
  referenceSequenceNumber: summaryRefSeqNum,
1365
1425
  summaryTree,
@@ -1375,7 +1435,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1375
1435
  const summaryContext = lastAck === undefined
1376
1436
  ? {
1377
1437
  proposalHandle: undefined,
1378
- ackHandle: (_a = this.context.getLoadedFromVersion()) === null || _a === void 0 ? void 0 : _a.id,
1438
+ ackHandle: (_b = this.context.getLoadedFromVersion()) === null || _b === void 0 ? void 0 : _b.id,
1379
1439
  referenceSequenceNumber: summaryRefSeqNum,
1380
1440
  }
1381
1441
  : {
@@ -1470,6 +1530,13 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
1470
1530
  };
1471
1531
  this.submit(ContainerMessageType.FluidDataStoreOp, envelope, localOpMetadata);
1472
1532
  }
1533
+ submitDataStoreAliasOp(contents, localOpMetadata) {
1534
+ const aliasMessage = contents;
1535
+ if (!dataStore_1.isDataStoreAliasMessage(aliasMessage)) {
1536
+ throw new container_utils_1.UsageError("malformedDataStoreAliasMessage");
1537
+ }
1538
+ this.submit(ContainerMessageType.Alias, contents, localOpMetadata);
1539
+ }
1473
1540
  async uploadBlob(blob) {
1474
1541
  this.verifyNotClosed();
1475
1542
  return this.blobManager.createBlob(blob);