@fluidframework/container-runtime 2.0.0-internal.1.0.0.83139 → 2.0.0-internal.1.0.1

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 (66) hide show
  1. package/dist/batchTracker.js +1 -1
  2. package/dist/batchTracker.js.map +1 -1
  3. package/dist/blobManager.d.ts.map +1 -1
  4. package/dist/blobManager.js +16 -16
  5. package/dist/blobManager.js.map +1 -1
  6. package/dist/containerRuntime.d.ts +1 -38
  7. package/dist/containerRuntime.d.ts.map +1 -1
  8. package/dist/containerRuntime.js +60 -109
  9. package/dist/containerRuntime.js.map +1 -1
  10. package/dist/dataStore.d.ts +1 -1
  11. package/dist/dataStore.d.ts.map +1 -1
  12. package/dist/dataStore.js +2 -3
  13. package/dist/dataStore.js.map +1 -1
  14. package/dist/dataStores.d.ts +1 -1
  15. package/dist/dataStores.d.ts.map +1 -1
  16. package/dist/dataStores.js +2 -2
  17. package/dist/dataStores.js.map +1 -1
  18. package/dist/packageVersion.d.ts +1 -1
  19. package/dist/packageVersion.d.ts.map +1 -1
  20. package/dist/packageVersion.js +1 -1
  21. package/dist/packageVersion.js.map +1 -1
  22. package/dist/runningSummarizer.js +1 -1
  23. package/dist/runningSummarizer.js.map +1 -1
  24. package/dist/summarizer.d.ts.map +1 -1
  25. package/dist/summarizer.js +20 -1
  26. package/dist/summarizer.js.map +1 -1
  27. package/dist/summaryGenerator.js +1 -1
  28. package/dist/summaryGenerator.js.map +1 -1
  29. package/lib/batchTracker.js +1 -1
  30. package/lib/batchTracker.js.map +1 -1
  31. package/lib/blobManager.d.ts.map +1 -1
  32. package/lib/blobManager.js +16 -16
  33. package/lib/blobManager.js.map +1 -1
  34. package/lib/containerRuntime.d.ts +1 -38
  35. package/lib/containerRuntime.d.ts.map +1 -1
  36. package/lib/containerRuntime.js +60 -109
  37. package/lib/containerRuntime.js.map +1 -1
  38. package/lib/dataStore.d.ts +1 -1
  39. package/lib/dataStore.d.ts.map +1 -1
  40. package/lib/dataStore.js +2 -3
  41. package/lib/dataStore.js.map +1 -1
  42. package/lib/dataStores.d.ts +1 -1
  43. package/lib/dataStores.d.ts.map +1 -1
  44. package/lib/dataStores.js +2 -2
  45. package/lib/dataStores.js.map +1 -1
  46. package/lib/packageVersion.d.ts +1 -1
  47. package/lib/packageVersion.d.ts.map +1 -1
  48. package/lib/packageVersion.js +1 -1
  49. package/lib/packageVersion.js.map +1 -1
  50. package/lib/runningSummarizer.js +1 -1
  51. package/lib/runningSummarizer.js.map +1 -1
  52. package/lib/summarizer.d.ts.map +1 -1
  53. package/lib/summarizer.js +22 -3
  54. package/lib/summarizer.js.map +1 -1
  55. package/lib/summaryGenerator.js +1 -1
  56. package/lib/summaryGenerator.js.map +1 -1
  57. package/package.json +27 -18
  58. package/src/batchTracker.ts +1 -1
  59. package/src/blobManager.ts +20 -16
  60. package/src/containerRuntime.ts +84 -164
  61. package/src/dataStore.ts +1 -4
  62. package/src/dataStores.ts +13 -13
  63. package/src/packageVersion.ts +1 -1
  64. package/src/runningSummarizer.ts +1 -1
  65. package/src/summarizer.ts +28 -3
  66. package/src/summaryGenerator.ts +1 -1
@@ -74,7 +74,6 @@ export var RuntimeHeaders;
74
74
  /** True if the request is coming from an IFluidHandle. */
75
75
  RuntimeHeaders["viaHandle"] = "viaHandle";
76
76
  })(RuntimeHeaders || (RuntimeHeaders = {}));
77
- const useDataStoreAliasingKey = "Fluid.ContainerRuntime.UseDataStoreAliasing";
78
77
  const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
79
78
  // Feature gate for the max op size. If the value is negative, chunking is enabled
80
79
  // and all ops over 16k would be chunked. If the value is positive, all ops with
@@ -372,7 +371,7 @@ export function getDeviceSpec() {
372
371
  */
373
372
  export class ContainerRuntime extends TypedEventEmitter {
374
373
  constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration) {
375
- var _a, _b, _c, _d, _e, _f, _g, _h;
374
+ var _a, _b, _c, _d, _e, _f;
376
375
  if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
377
376
  super();
378
377
  this.context = context;
@@ -441,15 +440,12 @@ export class ContainerRuntime extends TypedEventEmitter {
441
440
  this.summarizerClientElectionEnabled = this.isSummarizerClientElectionEnabled();
442
441
  this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
443
442
  this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
444
- this._aliasingEnabled =
445
- ((_c = this.mc.config.getBoolean(useDataStoreAliasingKey)) !== null && _c !== void 0 ? _c : false) ||
446
- ((_d = runtimeOptions.useDataStoreAliasing) !== null && _d !== void 0 ? _d : false);
447
- this._maxOpSizeInBytes = ((_e = this.mc.config.getNumber(maxOpSizeInBytesKey)) !== null && _e !== void 0 ? _e : defaultMaxOpSizeInBytes);
443
+ this._maxOpSizeInBytes = ((_c = this.mc.config.getNumber(maxOpSizeInBytesKey)) !== null && _c !== void 0 ? _c : defaultMaxOpSizeInBytes);
448
444
  this.maxConsecutiveReconnects =
449
- (_f = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _f !== void 0 ? _f : this.defaultMaxConsecutiveReconnects;
445
+ (_d = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _d !== void 0 ? _d : this.defaultMaxConsecutiveReconnects;
450
446
  this._flushMode = runtimeOptions.flushMode;
451
447
  const pendingRuntimeState = context.pendingLocalState;
452
- const baseSnapshot = (_g = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _g !== void 0 ? _g : context.baseSnapshot;
448
+ const baseSnapshot = (_e = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _e !== void 0 ? _e : context.baseSnapshot;
453
449
  this.garbageCollector = GarbageCollector.create({
454
450
  runtime: this,
455
451
  gcOptions: this.runtimeOptions.gcOptions,
@@ -576,7 +572,7 @@ export class ContainerRuntime extends TypedEventEmitter {
576
572
  };
577
573
  // summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
578
574
  // the count is reset to 0.
579
- loadSummaryNumber = (_h = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _h !== void 0 ? _h : 0;
575
+ loadSummaryNumber = (_f = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _f !== void 0 ? _f : 0;
580
576
  }
581
577
  else {
582
578
  this.createContainerMetadata = {
@@ -611,7 +607,7 @@ export class ContainerRuntime extends TypedEventEmitter {
611
607
  runtimeVersion: pkgVersion,
612
608
  },
613
609
  });
614
- const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, flushMode = defaultFlushMode, enableOfflineLoad = false, } = runtimeOptions;
610
+ const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, enableOfflineLoad = false, } = runtimeOptions;
615
611
  const pendingRuntimeState = context.pendingLocalState;
616
612
  const baseSnapshot = (_b = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _b !== void 0 ? _b : context.baseSnapshot;
617
613
  const storage = !pendingRuntimeState ?
@@ -664,7 +660,6 @@ export class ContainerRuntime extends TypedEventEmitter {
664
660
  summaryOptions,
665
661
  gcOptions,
666
662
  loadSequenceNumberVerification,
667
- useDataStoreAliasing,
668
663
  flushMode,
669
664
  enableOfflineLoad,
670
665
  }, containerScope, logger, loadExisting, blobManagerSnapshot, storage, requestHandler);
@@ -1046,8 +1041,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1046
1041
  // ensure we don't submit ops referencing a blob that has not been uploaded
1047
1042
  const connecting = connected && !this._connected && !this.deltaManager.readOnlyInfo.readonly;
1048
1043
  if (connecting && this.blobManager.hasPendingOfflineUploads) {
1049
- assert(!this.delayConnectClientId, "Connect event delay must be canceled before subsequent connect event");
1050
- assert(!!clientId, "Must have clientId when connecting");
1044
+ assert(!this.delayConnectClientId, 0x392 /* Connect event delay must be canceled before subsequent connect event */);
1045
+ assert(!!clientId, 0x393 /* Must have clientId when connecting */);
1051
1046
  this.delayConnectClientId = clientId;
1052
1047
  this.blobManager.onConnected().then(() => {
1053
1048
  // make sure we didn't reconnect before the promise resolved
@@ -1061,7 +1056,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1061
1056
  this.setConnectionStateCore(connected, clientId);
1062
1057
  }
1063
1058
  setConnectionStateCore(connected, clientId) {
1064
- assert(!this.delayConnectClientId, "connect event delay must be cleared before propagating connect event");
1059
+ assert(!this.delayConnectClientId, 0x394 /* connect event delay must be cleared before propagating connect event */);
1065
1060
  this.verifyNotClosed();
1066
1061
  // There might be no change of state due to Container calling this API after loading runtime.
1067
1062
  const changeOfState = this._connected !== connected;
@@ -1303,59 +1298,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1303
1298
  }
1304
1299
  async createDataStore(pkg) {
1305
1300
  const internalId = uuid();
1306
- return channelToDataStore(await this._createDataStore(pkg, false /* isRoot */, internalId), internalId, this, this.dataStores, this.mc.logger);
1307
- }
1308
- /**
1309
- * Creates a root datastore directly with a user generated id and attaches it to storage.
1310
- * It is vulnerable to name collisions and should not be used.
1311
- *
1312
- * This method will be removed. See #6465.
1313
- */
1314
- async createRootDataStoreLegacy(pkg, rootDataStoreId) {
1315
- const fluidDataStore = await this._createDataStore(pkg, true /* isRoot */, rootDataStoreId);
1316
- fluidDataStore.makeVisibleAndAttachGraph();
1317
- return fluidDataStore;
1318
- }
1319
- /**
1320
- * @deprecated - will be removed in an upcoming release. See #9660.
1321
- */
1322
- async createRootDataStore(pkg, rootDataStoreId) {
1323
- if (rootDataStoreId.includes("/")) {
1324
- throw new UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
1325
- }
1326
- return this._aliasingEnabled === true ?
1327
- this.createAndAliasDataStore(pkg, rootDataStoreId) :
1328
- this.createRootDataStoreLegacy(pkg, rootDataStoreId);
1329
- }
1330
- /**
1331
- * Creates a data store then attempts to alias it.
1332
- * If aliasing fails, it will raise an exception.
1333
- *
1334
- * This method will be removed. See #6465.
1335
- *
1336
- * @param pkg - Package name of the data store
1337
- * @param alias - Alias to be assigned to the data store
1338
- * @param props - Properties for the data store
1339
- * @returns - An aliased data store which can can be found / loaded by alias.
1340
- */
1341
- async createAndAliasDataStore(pkg, alias, props) {
1342
- const internalId = uuid();
1343
- try {
1344
- // A similar call may have been initiated by the same client, so we should try to get
1345
- // a possible existing aliased datastore first.
1346
- const existingDataStore = await this.getRootDataStoreChannel(alias, /* wait */ false);
1347
- return channelToDataStore(existingDataStore, internalId, this, this.dataStores, this.mc.logger, true);
1348
- }
1349
- catch (err) {
1350
- const newChannel = await this._createDataStore(pkg, false /* isRoot */, internalId, props);
1351
- const newDataStore = channelToDataStore(newChannel, internalId, this, this.dataStores, this.mc.logger);
1352
- const aliasResult = await newDataStore.trySetAlias(alias);
1353
- if (aliasResult === "Success") {
1354
- return newDataStore;
1355
- }
1356
- const existingDataStore = await this.getRootDataStoreChannel(alias, /* wait */ false);
1357
- return channelToDataStore(existingDataStore, internalId, this, this.dataStores, this.mc.logger, true);
1358
- }
1301
+ return channelToDataStore(await this._createDataStore(pkg, internalId), internalId, this, this.dataStores, this.mc.logger);
1359
1302
  }
1360
1303
  createDetachedRootDataStore(pkg, rootDataStoreId) {
1361
1304
  if (rootDataStoreId.includes("/")) {
@@ -1366,31 +1309,13 @@ export class ContainerRuntime extends TypedEventEmitter {
1366
1309
  createDetachedDataStore(pkg) {
1367
1310
  return this.dataStores.createDetachedDataStoreCore(pkg, false);
1368
1311
  }
1369
- /**
1370
- * Creates a possibly root datastore directly with a possibly user generated id and attaches it to storage.
1371
- * It is vulnerable to name collisions if both aforementioned conditions are true, and should not be used.
1372
- *
1373
- * This method will be removed. See #6465.
1374
- */
1375
- async _createDataStoreWithPropsLegacy(pkg, props, id = uuid(), isRoot = false) {
1376
- const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
1377
- if (isRoot) {
1378
- fluidDataStore.makeVisibleAndAttachGraph();
1379
- this.logger.sendTelemetryEvent({
1380
- eventName: "Root datastore with props",
1381
- hasProps: props !== undefined,
1382
- });
1383
- }
1312
+ async _createDataStoreWithProps(pkg, props, id = uuid()) {
1313
+ const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props).realize();
1384
1314
  return channelToDataStore(fluidDataStore, id, this, this.dataStores, this.mc.logger);
1385
1315
  }
1386
- async _createDataStoreWithProps(pkg, props, id = uuid(), isRoot = false) {
1387
- return this._aliasingEnabled === true && isRoot ?
1388
- this.createAndAliasDataStore(pkg, id, props) :
1389
- this._createDataStoreWithPropsLegacy(pkg, props, id, isRoot);
1390
- }
1391
- async _createDataStore(pkg, isRoot, id = uuid(), props) {
1316
+ async _createDataStore(pkg, id = uuid(), props) {
1392
1317
  return this.dataStores
1393
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props)
1318
+ ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
1394
1319
  .realize();
1395
1320
  }
1396
1321
  canSendOps() {
@@ -1664,16 +1589,19 @@ export class ContainerRuntime extends TypedEventEmitter {
1664
1589
  const summaryNumberLogger = ChildLogger.create(summaryLogger, undefined, {
1665
1590
  all: { summaryNumber },
1666
1591
  });
1592
+ let latestSnapshotVersionId;
1667
1593
  if (refreshLatestAck) {
1668
- const latestSummaryRefSeq = await this.refreshLatestSummaryAckFromServer(ChildLogger.create(summaryNumberLogger, undefined, { all: { safeSummary: true } }));
1669
- if (latestSummaryRefSeq > this.deltaManager.lastSequenceNumber) {
1594
+ const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer(ChildLogger.create(summaryNumberLogger, undefined, { all: { safeSummary: true } }));
1595
+ const latestSnapshotRefSeq = latestSnapshotInfo.latestSnapshotRefSeq;
1596
+ latestSnapshotVersionId = latestSnapshotInfo.latestSnapshotVersionId;
1597
+ if (latestSnapshotRefSeq > this.deltaManager.lastSequenceNumber) {
1670
1598
  // We need to catch up to the latest summary's reference sequence number before pausing.
1671
1599
  await PerformanceEvent.timedExecAsync(summaryNumberLogger, {
1672
1600
  eventName: "WaitingForSeq",
1673
1601
  lastSequenceNumber: this.deltaManager.lastSequenceNumber,
1674
- targetSequenceNumber: latestSummaryRefSeq,
1602
+ targetSequenceNumber: latestSnapshotRefSeq,
1675
1603
  lastKnownSeqNumber: this.deltaManager.lastKnownSeqNumber,
1676
- }, async () => waitForSeq(this.deltaManager, latestSummaryRefSeq), { start: true, end: true, cancel: "error" });
1604
+ }, async () => waitForSeq(this.deltaManager, latestSnapshotRefSeq), { start: true, end: true, cancel: "error" });
1677
1605
  }
1678
1606
  }
1679
1607
  try {
@@ -1709,7 +1637,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1709
1637
  error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
1710
1638
  };
1711
1639
  }
1712
- assert(summaryRefSeqNum === ((_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.sequenceNumber), "it's one and the same thing");
1640
+ assert(summaryRefSeqNum === ((_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.sequenceNumber), 0x395 /* it's one and the same thing */);
1713
1641
  if (lastAck !== this.summaryCollection.latestAck) {
1714
1642
  return {
1715
1643
  continue: false,
@@ -1774,17 +1702,34 @@ export class ContainerRuntime extends TypedEventEmitter {
1774
1702
  if (!continueResult.continue) {
1775
1703
  return Object.assign(Object.assign({ stage: "generate" }, generateSummaryData), { error: continueResult.error });
1776
1704
  }
1777
- const summaryContext = lastAck === undefined
1778
- ? {
1705
+ // It may happen that the lastAck it not correct due to missing summaryAck in case of single commit
1706
+ // summary. So if the previous summarizer closes just after submitting the summary and before
1707
+ // submitting the summaryOp then we can't rely on summaryAck. So in case we have
1708
+ // latestSnapshotVersionId from storage and it does not match with the lastAck ackHandle, then use
1709
+ // the one fetched from storage as parent as that is the latest.
1710
+ let summaryContext;
1711
+ if ((lastAck === null || lastAck === void 0 ? void 0 : lastAck.summaryAck.contents.handle) !== latestSnapshotVersionId
1712
+ && latestSnapshotVersionId !== undefined) {
1713
+ summaryContext = {
1714
+ proposalHandle: undefined,
1715
+ ackHandle: latestSnapshotVersionId,
1716
+ referenceSequenceNumber: summaryRefSeqNum,
1717
+ };
1718
+ }
1719
+ else if (lastAck === undefined) {
1720
+ summaryContext = {
1779
1721
  proposalHandle: undefined,
1780
1722
  ackHandle: (_b = this.context.getLoadedFromVersion()) === null || _b === void 0 ? void 0 : _b.id,
1781
1723
  referenceSequenceNumber: summaryRefSeqNum,
1782
- }
1783
- : {
1724
+ };
1725
+ }
1726
+ else {
1727
+ summaryContext = {
1784
1728
  proposalHandle: lastAck.summaryOp.contents.handle,
1785
1729
  ackHandle: lastAck.summaryAck.contents.handle,
1786
1730
  referenceSequenceNumber: summaryRefSeqNum,
1787
1731
  };
1732
+ }
1788
1733
  let handle;
1789
1734
  try {
1790
1735
  handle = await this.storage.uploadSummaryWithContext(summarizeResult.summary, summaryContext);
@@ -2023,12 +1968,18 @@ export class ContainerRuntime extends TypedEventEmitter {
2023
1968
  /** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
2024
1969
  async refreshLatestSummaryAck(proposalHandle, ackHandle, summaryRefSeq, summaryLogger) {
2025
1970
  const readAndParseBlob = async (id) => readAndParse(this.storage, id);
2026
- const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq, async () => this.fetchSnapshotFromStorage(ackHandle, summaryLogger, {
2027
- eventName: "RefreshLatestSummaryGetSnapshot",
2028
- ackHandle,
2029
- summaryRefSeq,
2030
- fetchLatest: false,
2031
- }), readAndParseBlob, summaryLogger);
1971
+ // The call to fetch the snapshot is very expensive and not always needed.
1972
+ // It should only be done by the summarizerNode, if required.
1973
+ const snapshotTreeFetcher = async () => {
1974
+ const fetchResult = await this.fetchSnapshotFromStorage(ackHandle, summaryLogger, {
1975
+ eventName: "RefreshLatestSummaryGetSnapshot",
1976
+ ackHandle,
1977
+ summaryRefSeq,
1978
+ fetchLatest: false,
1979
+ });
1980
+ return fetchResult.snapshotTree;
1981
+ };
1982
+ const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq, snapshotTreeFetcher, readAndParseBlob, summaryLogger);
2032
1983
  // Notify the garbage collector so it can update its latest summary state.
2033
1984
  await this.garbageCollector.latestSummaryStateRefreshed(result, readAndParseBlob);
2034
1985
  }
@@ -2039,16 +1990,16 @@ export class ContainerRuntime extends TypedEventEmitter {
2039
1990
  * @returns downloaded snapshot's reference sequence number
2040
1991
  */
2041
1992
  async refreshLatestSummaryAckFromServer(summaryLogger) {
2042
- const snapshot = await this.fetchSnapshotFromStorage(null, summaryLogger, {
1993
+ const { snapshotTree, versionId } = await this.fetchSnapshotFromStorage(null, summaryLogger, {
2043
1994
  eventName: "RefreshLatestSummaryGetSnapshot",
2044
1995
  fetchLatest: true,
2045
1996
  }, FetchSource.noCache);
2046
1997
  const readAndParseBlob = async (id) => readAndParse(this.storage, id);
2047
- const snapshotRefSeq = await seqFromTree(snapshot, readAndParseBlob);
2048
- const result = await this.summarizerNode.refreshLatestSummary(undefined, snapshotRefSeq, async () => snapshot, readAndParseBlob, summaryLogger);
1998
+ const latestSnapshotRefSeq = await seqFromTree(snapshotTree, readAndParseBlob);
1999
+ const result = await this.summarizerNode.refreshLatestSummary(undefined, latestSnapshotRefSeq, async () => snapshotTree, readAndParseBlob, summaryLogger);
2049
2000
  // Notify the garbage collector so it can update its latest summary state.
2050
2001
  await this.garbageCollector.latestSummaryStateRefreshed(result, readAndParseBlob);
2051
- return snapshotRefSeq;
2002
+ return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
2052
2003
  }
2053
2004
  async fetchSnapshotFromStorage(versionId, logger, event, fetchSource) {
2054
2005
  return PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
@@ -2061,7 +2012,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2061
2012
  assert(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
2062
2013
  stats.getSnapshotDuration = trace.trace().duration;
2063
2014
  perfEvent.end(stats);
2064
- return maybeSnapshot;
2015
+ return { snapshotTree: maybeSnapshot, versionId: versions[0].id };
2065
2016
  });
2066
2017
  }
2067
2018
  notifyAttaching(snapshot) {