@fluidframework/container-loader 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.246488

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 (297) hide show
  1. package/.eslintrc.cjs +5 -6
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +48 -0
  4. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  5. package/api-extractor-lint.json +1 -1
  6. package/api-extractor.json +1 -1
  7. package/api-report/container-loader.api.md +2 -2
  8. package/dist/attachment.d.ts +6 -7
  9. package/dist/attachment.d.ts.map +1 -1
  10. package/dist/attachment.js +8 -7
  11. package/dist/attachment.js.map +1 -1
  12. package/dist/audience.d.ts +9 -4
  13. package/dist/audience.d.ts.map +1 -1
  14. package/dist/audience.js +12 -6
  15. package/dist/audience.js.map +1 -1
  16. package/dist/connectionManager.d.ts +3 -3
  17. package/dist/connectionManager.d.ts.map +1 -1
  18. package/dist/connectionManager.js +20 -18
  19. package/dist/connectionManager.js.map +1 -1
  20. package/dist/connectionState.d.ts +1 -0
  21. package/dist/connectionState.d.ts.map +1 -1
  22. package/dist/connectionState.js +1 -0
  23. package/dist/connectionState.js.map +1 -1
  24. package/dist/connectionStateHandler.d.ts +7 -7
  25. package/dist/connectionStateHandler.d.ts.map +1 -1
  26. package/dist/connectionStateHandler.js +32 -32
  27. package/dist/connectionStateHandler.js.map +1 -1
  28. package/dist/container-loader-alpha.d.ts +1 -0
  29. package/dist/container-loader-beta.d.ts +3 -0
  30. package/dist/container-loader-public.d.ts +3 -0
  31. package/dist/container-loader-untrimmed.d.ts +4 -4
  32. package/dist/container.d.ts +11 -22
  33. package/dist/container.d.ts.map +1 -1
  34. package/dist/container.js +101 -194
  35. package/dist/container.js.map +1 -1
  36. package/dist/containerStorageAdapter.d.ts +2 -3
  37. package/dist/containerStorageAdapter.d.ts.map +1 -1
  38. package/dist/containerStorageAdapter.js +4 -10
  39. package/dist/containerStorageAdapter.js.map +1 -1
  40. package/dist/contracts.d.ts +3 -3
  41. package/dist/contracts.d.ts.map +1 -1
  42. package/dist/contracts.js.map +1 -1
  43. package/dist/debugLogger.js.map +1 -1
  44. package/dist/deltaManager.d.ts +5 -5
  45. package/dist/deltaManager.d.ts.map +1 -1
  46. package/dist/deltaManager.js +6 -6
  47. package/dist/deltaManager.js.map +1 -1
  48. package/dist/error.d.ts.map +1 -1
  49. package/dist/error.js.map +1 -1
  50. package/dist/index.d.ts +6 -6
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +11 -11
  53. package/dist/index.js.map +1 -1
  54. package/dist/loader.d.ts +2 -2
  55. package/dist/loader.d.ts.map +1 -1
  56. package/dist/loader.js +13 -17
  57. package/dist/loader.js.map +1 -1
  58. package/dist/location-redirection-utilities/index.d.ts +1 -1
  59. package/dist/location-redirection-utilities/index.d.ts.map +1 -1
  60. package/dist/location-redirection-utilities/index.js +3 -3
  61. package/dist/location-redirection-utilities/index.js.map +1 -1
  62. package/dist/package.json +3 -0
  63. package/dist/packageVersion.d.ts +1 -1
  64. package/dist/packageVersion.js +1 -1
  65. package/dist/packageVersion.js.map +1 -1
  66. package/dist/protocolTreeDocumentStorageService.d.ts +0 -1
  67. package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
  68. package/dist/protocolTreeDocumentStorageService.js +0 -3
  69. package/dist/protocolTreeDocumentStorageService.js.map +1 -1
  70. package/dist/quorum.d.ts.map +1 -1
  71. package/dist/quorum.js +4 -0
  72. package/dist/quorum.js.map +1 -1
  73. package/dist/retriableDocumentStorageService.d.ts +0 -1
  74. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  75. package/dist/retriableDocumentStorageService.js +0 -6
  76. package/dist/retriableDocumentStorageService.js.map +1 -1
  77. package/dist/serializedStateManager.d.ts +44 -0
  78. package/dist/serializedStateManager.d.ts.map +1 -0
  79. package/dist/serializedStateManager.js +149 -0
  80. package/dist/serializedStateManager.js.map +1 -0
  81. package/dist/tsdoc-metadata.json +1 -1
  82. package/dist/utils.d.ts +5 -6
  83. package/dist/utils.d.ts.map +1 -1
  84. package/dist/utils.js +10 -4
  85. package/dist/utils.js.map +1 -1
  86. package/lib/{attachment.d.mts → attachment.d.ts} +11 -8
  87. package/lib/attachment.d.ts.map +1 -0
  88. package/lib/{attachment.mjs → attachment.js} +11 -6
  89. package/lib/attachment.js.map +1 -0
  90. package/lib/{audience.d.mts → audience.d.ts} +14 -5
  91. package/lib/audience.d.ts.map +1 -0
  92. package/lib/{audience.mjs → audience.js} +14 -4
  93. package/lib/audience.js.map +1 -0
  94. package/lib/{catchUpMonitor.d.mts → catchUpMonitor.d.ts} +1 -1
  95. package/lib/catchUpMonitor.d.ts.map +1 -0
  96. package/lib/{catchUpMonitor.mjs → catchUpMonitor.js} +1 -1
  97. package/lib/catchUpMonitor.js.map +1 -0
  98. package/lib/{connectionManager.d.mts → connectionManager.d.ts} +4 -4
  99. package/lib/connectionManager.d.ts.map +1 -0
  100. package/lib/{connectionManager.mjs → connectionManager.js} +9 -7
  101. package/lib/connectionManager.js.map +1 -0
  102. package/lib/{connectionState.d.mts → connectionState.d.ts} +2 -1
  103. package/lib/connectionState.d.ts.map +1 -0
  104. package/lib/{connectionState.mjs → connectionState.js} +2 -1
  105. package/lib/connectionState.js.map +1 -0
  106. package/lib/{connectionStateHandler.d.mts → connectionStateHandler.d.ts} +8 -8
  107. package/lib/connectionStateHandler.d.ts.map +1 -0
  108. package/lib/{connectionStateHandler.mjs → connectionStateHandler.js} +3 -3
  109. package/lib/connectionStateHandler.js.map +1 -0
  110. package/lib/{container-loader-alpha.d.mts → container-loader-alpha.d.ts} +1 -0
  111. package/lib/{container-loader-beta.d.mts → container-loader-beta.d.ts} +3 -0
  112. package/lib/{container-loader-public.d.mts → container-loader-public.d.ts} +3 -0
  113. package/lib/{container-loader-untrimmed.d.mts → container-loader-untrimmed.d.ts} +4 -4
  114. package/lib/{container.d.mts → container.d.ts} +12 -23
  115. package/lib/container.d.ts.map +1 -0
  116. package/lib/{container.mjs → container.js} +55 -148
  117. package/lib/container.js.map +1 -0
  118. package/lib/{containerContext.d.mts → containerContext.d.ts} +1 -1
  119. package/lib/containerContext.d.ts.map +1 -0
  120. package/lib/{containerContext.mjs → containerContext.js} +1 -1
  121. package/lib/containerContext.js.map +1 -0
  122. package/lib/{containerStorageAdapter.d.mts → containerStorageAdapter.d.ts} +3 -4
  123. package/lib/containerStorageAdapter.d.ts.map +1 -0
  124. package/lib/{containerStorageAdapter.mjs → containerStorageAdapter.js} +3 -9
  125. package/lib/containerStorageAdapter.js.map +1 -0
  126. package/lib/{contracts.d.mts → contracts.d.ts} +4 -4
  127. package/lib/contracts.d.ts.map +1 -0
  128. package/lib/{contracts.mjs → contracts.js} +1 -1
  129. package/lib/contracts.js.map +1 -0
  130. package/lib/{debugLogger.d.mts → debugLogger.d.ts} +1 -1
  131. package/lib/debugLogger.d.ts.map +1 -0
  132. package/lib/{debugLogger.mjs → debugLogger.js} +2 -1
  133. package/lib/debugLogger.js.map +1 -0
  134. package/lib/{deltaManager.d.mts → deltaManager.d.ts} +6 -6
  135. package/lib/deltaManager.d.ts.map +1 -0
  136. package/lib/{deltaManager.mjs → deltaManager.js} +4 -4
  137. package/lib/deltaManager.js.map +1 -0
  138. package/lib/{deltaQueue.d.mts → deltaQueue.d.ts} +1 -1
  139. package/lib/deltaQueue.d.ts.map +1 -0
  140. package/lib/{deltaQueue.mjs → deltaQueue.js} +1 -1
  141. package/lib/deltaQueue.js.map +1 -0
  142. package/lib/{disposal.d.mts → disposal.d.ts} +1 -1
  143. package/lib/disposal.d.ts.map +1 -0
  144. package/lib/{disposal.mjs → disposal.js} +1 -1
  145. package/lib/disposal.js.map +1 -0
  146. package/lib/{error.d.mts → error.d.ts} +1 -1
  147. package/lib/error.d.ts.map +1 -0
  148. package/lib/{error.mjs → error.js} +1 -1
  149. package/lib/error.js.map +1 -0
  150. package/lib/{index.d.mts → index.d.ts} +7 -7
  151. package/lib/index.d.ts.map +1 -0
  152. package/lib/index.js +10 -0
  153. package/lib/index.js.map +1 -0
  154. package/lib/{loader.d.mts → loader.d.ts} +3 -3
  155. package/lib/loader.d.ts.map +1 -0
  156. package/lib/{loader.mjs → loader.js} +7 -11
  157. package/lib/loader.js.map +1 -0
  158. package/lib/location-redirection-utilities/{index.mjs → index.d.ts} +2 -2
  159. package/lib/location-redirection-utilities/index.d.ts.map +1 -0
  160. package/lib/location-redirection-utilities/{index.d.mts → index.js} +2 -2
  161. package/lib/location-redirection-utilities/index.js.map +1 -0
  162. package/lib/location-redirection-utilities/{resolveWithLocationRedirection.d.mts → resolveWithLocationRedirection.d.ts} +1 -1
  163. package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
  164. package/lib/location-redirection-utilities/{resolveWithLocationRedirection.mjs → resolveWithLocationRedirection.js} +1 -1
  165. package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
  166. package/lib/{noopHeuristic.d.mts → noopHeuristic.d.ts} +1 -1
  167. package/lib/noopHeuristic.d.ts.map +1 -0
  168. package/lib/{noopHeuristic.mjs → noopHeuristic.js} +1 -1
  169. package/lib/noopHeuristic.js.map +1 -0
  170. package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
  171. package/lib/packageVersion.d.ts.map +1 -0
  172. package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
  173. package/lib/packageVersion.js.map +1 -0
  174. package/lib/{protocol.d.mts → protocol.d.ts} +1 -1
  175. package/lib/protocol.d.ts.map +1 -0
  176. package/lib/{protocol.mjs → protocol.js} +1 -1
  177. package/lib/protocol.js.map +1 -0
  178. package/lib/{protocolTreeDocumentStorageService.d.mts → protocolTreeDocumentStorageService.d.ts} +1 -2
  179. package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -0
  180. package/lib/{protocolTreeDocumentStorageService.mjs → protocolTreeDocumentStorageService.js} +1 -4
  181. package/lib/protocolTreeDocumentStorageService.js.map +1 -0
  182. package/lib/{quorum.d.mts → quorum.d.ts} +5 -1
  183. package/lib/quorum.d.ts.map +1 -0
  184. package/lib/{quorum.mjs → quorum.js} +5 -1
  185. package/lib/quorum.js.map +1 -0
  186. package/lib/{retriableDocumentStorageService.d.mts → retriableDocumentStorageService.d.ts} +1 -2
  187. package/lib/retriableDocumentStorageService.d.ts.map +1 -0
  188. package/lib/{retriableDocumentStorageService.mjs → retriableDocumentStorageService.js} +1 -7
  189. package/lib/retriableDocumentStorageService.js.map +1 -0
  190. package/lib/serializedStateManager.d.ts +44 -0
  191. package/lib/serializedStateManager.d.ts.map +1 -0
  192. package/lib/serializedStateManager.js +145 -0
  193. package/lib/serializedStateManager.js.map +1 -0
  194. package/lib/test/attachment.spec.js +380 -0
  195. package/lib/test/attachment.spec.js.map +1 -0
  196. package/lib/test/catchUpMonitor.spec.js +88 -0
  197. package/lib/test/catchUpMonitor.spec.js.map +1 -0
  198. package/lib/test/connectionManager.spec.js +201 -0
  199. package/lib/test/connectionManager.spec.js.map +1 -0
  200. package/lib/test/connectionStateHandler.spec.js +555 -0
  201. package/lib/test/connectionStateHandler.spec.js.map +1 -0
  202. package/lib/test/container.spec.js +64 -0
  203. package/lib/test/container.spec.js.map +1 -0
  204. package/lib/test/deltaManager.spec.js +405 -0
  205. package/lib/test/deltaManager.spec.js.map +1 -0
  206. package/lib/test/loader.spec.js +212 -0
  207. package/lib/test/loader.spec.js.map +1 -0
  208. package/lib/test/locationRedirectionTests.spec.js +44 -0
  209. package/lib/test/locationRedirectionTests.spec.js.map +1 -0
  210. package/lib/test/serializedStateManager.spec.js +148 -0
  211. package/lib/test/serializedStateManager.spec.js.map +1 -0
  212. package/lib/test/snapshotConversionTest.spec.js +79 -0
  213. package/lib/test/snapshotConversionTest.spec.js.map +1 -0
  214. package/lib/test/types/validateContainerLoaderPrevious.generated.js +38 -0
  215. package/lib/test/types/validateContainerLoaderPrevious.generated.js.map +1 -0
  216. package/lib/test/utils.spec.js +31 -0
  217. package/lib/test/utils.spec.js.map +1 -0
  218. package/lib/{utils.d.mts → utils.d.ts} +6 -7
  219. package/lib/utils.d.ts.map +1 -0
  220. package/lib/{utils.mjs → utils.js} +11 -5
  221. package/lib/utils.js.map +1 -0
  222. package/package.json +56 -62
  223. package/src/attachment.ts +16 -12
  224. package/src/audience.ts +10 -3
  225. package/src/connectionManager.ts +13 -9
  226. package/src/connectionState.ts +1 -0
  227. package/src/connectionStateHandler.ts +8 -7
  228. package/src/container.ts +96 -191
  229. package/src/containerStorageAdapter.ts +6 -14
  230. package/src/contracts.ts +3 -3
  231. package/src/debugLogger.ts +2 -2
  232. package/src/deltaManager.ts +8 -8
  233. package/src/error.ts +2 -2
  234. package/src/index.ts +6 -6
  235. package/src/loader.ts +8 -12
  236. package/src/location-redirection-utilities/index.ts +1 -1
  237. package/src/packageVersion.ts +1 -1
  238. package/src/protocolTreeDocumentStorageService.ts +0 -3
  239. package/src/quorum.ts +1 -0
  240. package/src/retriableDocumentStorageService.ts +0 -7
  241. package/src/serializedStateManager.ts +217 -0
  242. package/src/utils.ts +15 -10
  243. package/tsconfig.cjs.json +7 -0
  244. package/tsconfig.json +2 -5
  245. package/lib/attachment.d.mts.map +0 -1
  246. package/lib/attachment.mjs.map +0 -1
  247. package/lib/audience.d.mts.map +0 -1
  248. package/lib/audience.mjs.map +0 -1
  249. package/lib/catchUpMonitor.d.mts.map +0 -1
  250. package/lib/catchUpMonitor.mjs.map +0 -1
  251. package/lib/connectionManager.d.mts.map +0 -1
  252. package/lib/connectionManager.mjs.map +0 -1
  253. package/lib/connectionState.d.mts.map +0 -1
  254. package/lib/connectionState.mjs.map +0 -1
  255. package/lib/connectionStateHandler.d.mts.map +0 -1
  256. package/lib/connectionStateHandler.mjs.map +0 -1
  257. package/lib/container.d.mts.map +0 -1
  258. package/lib/container.mjs.map +0 -1
  259. package/lib/containerContext.d.mts.map +0 -1
  260. package/lib/containerContext.mjs.map +0 -1
  261. package/lib/containerStorageAdapter.d.mts.map +0 -1
  262. package/lib/containerStorageAdapter.mjs.map +0 -1
  263. package/lib/contracts.d.mts.map +0 -1
  264. package/lib/contracts.mjs.map +0 -1
  265. package/lib/debugLogger.d.mts.map +0 -1
  266. package/lib/debugLogger.mjs.map +0 -1
  267. package/lib/deltaManager.d.mts.map +0 -1
  268. package/lib/deltaManager.mjs.map +0 -1
  269. package/lib/deltaQueue.d.mts.map +0 -1
  270. package/lib/deltaQueue.mjs.map +0 -1
  271. package/lib/disposal.d.mts.map +0 -1
  272. package/lib/disposal.mjs.map +0 -1
  273. package/lib/error.d.mts.map +0 -1
  274. package/lib/error.mjs.map +0 -1
  275. package/lib/index.d.mts.map +0 -1
  276. package/lib/index.mjs +0 -10
  277. package/lib/index.mjs.map +0 -1
  278. package/lib/loader.d.mts.map +0 -1
  279. package/lib/loader.mjs.map +0 -1
  280. package/lib/location-redirection-utilities/index.d.mts.map +0 -1
  281. package/lib/location-redirection-utilities/index.mjs.map +0 -1
  282. package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.mts.map +0 -1
  283. package/lib/location-redirection-utilities/resolveWithLocationRedirection.mjs.map +0 -1
  284. package/lib/noopHeuristic.d.mts.map +0 -1
  285. package/lib/noopHeuristic.mjs.map +0 -1
  286. package/lib/packageVersion.d.mts.map +0 -1
  287. package/lib/packageVersion.mjs.map +0 -1
  288. package/lib/protocol.d.mts.map +0 -1
  289. package/lib/protocol.mjs.map +0 -1
  290. package/lib/protocolTreeDocumentStorageService.d.mts.map +0 -1
  291. package/lib/protocolTreeDocumentStorageService.mjs.map +0 -1
  292. package/lib/quorum.d.mts.map +0 -1
  293. package/lib/quorum.mjs.map +0 -1
  294. package/lib/retriableDocumentStorageService.d.mts.map +0 -1
  295. package/lib/retriableDocumentStorageService.mjs.map +0 -1
  296. package/lib/utils.d.mts.map +0 -1
  297. package/lib/utils.mjs.map +0 -1
package/src/audience.ts CHANGED
@@ -2,7 +2,8 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { EventEmitter } from "events";
5
+
6
+ import { EventEmitter } from "@fluid-internal/client-utils";
6
7
  import { assert } from "@fluidframework/core-utils";
7
8
  import { IAudienceOwner } from "@fluidframework/container-definitions";
8
9
  import { IClient } from "@fluidframework/protocol-definitions";
@@ -61,14 +62,20 @@ export class Audience extends EventEmitter implements IAudienceOwner {
61
62
  }
62
63
 
63
64
  /**
64
- * Retrieves all the members in the audience
65
+ * Retrieves all the members in the audience.
66
+ *
67
+ * @remarks When the container is disconnected, this will keep returning the audience as it was last seen before the
68
+ * container disconnected.
65
69
  */
66
70
  public getMembers(): Map<string, IClient> {
67
71
  return new Map(this.members);
68
72
  }
69
73
 
70
74
  /**
71
- * Retrieves a specific member of the audience
75
+ * Retrieves a specific member of the audience.
76
+ *
77
+ * @remarks When the container is disconnected, this will keep returning members from the audience as it was last seen
78
+ * before the container disconnected.
72
79
  */
73
80
  public getMember(clientId: string): IClient | undefined {
74
81
  return this.members.get(clientId);
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { IDisposable, ITelemetryProperties, LogLevel } from "@fluidframework/core-interfaces";
6
+ import { IDisposable, ITelemetryBaseProperties, LogLevel } from "@fluidframework/core-interfaces";
7
7
  import { assert } from "@fluidframework/core-utils";
8
8
  import { performance, TypedEventEmitter } from "@fluid-internal/client-utils";
9
9
  import {
@@ -57,10 +57,10 @@ import {
57
57
  IConnectionManagerFactoryArgs,
58
58
  IConnectionDetailsInternal,
59
59
  IConnectionStateChangeReason,
60
- } from "./contracts";
61
- import { DeltaQueue } from "./deltaQueue";
62
- import { SignalType } from "./protocol";
63
- import { isDeltaStreamConnectionForbiddenError } from "./utils";
60
+ } from "./contracts.js";
61
+ import { DeltaQueue } from "./deltaQueue.js";
62
+ import { SignalType } from "./protocol.js";
63
+ import { isDeltaStreamConnectionForbiddenError } from "./utils.js";
64
64
 
65
65
  // We double this value in first try in when we calculate time to wait for in "calculateMaxWaitTime" function.
66
66
  const InitialReconnectDelayInMs = 500;
@@ -229,7 +229,7 @@ export class ConnectionManager implements IConnectionManager {
229
229
 
230
230
  private _connectionVerboseProps: Record<string, string | number> = {};
231
231
 
232
- private _connectionProps: ITelemetryProperties = {};
232
+ private _connectionProps: ITelemetryBaseProperties = {};
233
233
 
234
234
  private _disposed = false;
235
235
 
@@ -290,7 +290,7 @@ export class ConnectionManager implements IConnectionManager {
290
290
  * Returns set of props that can be logged in telemetry that provide some insights / statistics
291
291
  * about current or last connection (if there is no connection at the moment)
292
292
  */
293
- public get connectionProps(): ITelemetryProperties {
293
+ public get connectionProps(): ITelemetryBaseProperties {
294
294
  return this.connection !== undefined
295
295
  ? this._connectionProps
296
296
  : {
@@ -654,8 +654,12 @@ export class ConnectionManager implements IConnectionManager {
654
654
  if (retryDelayFromError !== undefined || globalThis.navigator?.onLine !== false) {
655
655
  delayMs = calculateMaxWaitTime(delayMs, origError);
656
656
  }
657
- // Raise event in case the delay was there.
658
- this.props.reconnectionDelayHandler(delayMs, origError);
657
+
658
+ // Raise event in case the delay was there from the error.
659
+ if (retryDelayFromError !== undefined) {
660
+ this.props.reconnectionDelayHandler(delayMs, origError);
661
+ }
662
+
659
663
  await new Promise<void>((resolve) => {
660
664
  setTimeout(resolve, delayMs);
661
665
  });
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  /**
7
+ * The state of the Container's connection to the service.
7
8
  * @public
8
9
  */
9
10
  export enum ConnectionState {
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryProperties, TelemetryEventCategory } from "@fluidframework/core-interfaces";
6
+ import { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
7
7
  import { assert, Timer } from "@fluidframework/core-utils";
8
8
  import { IDeltaManager } from "@fluidframework/container-definitions";
9
9
  import { ISequencedClient, IClient } from "@fluidframework/protocol-definitions";
@@ -11,12 +11,13 @@ import {
11
11
  ITelemetryLoggerExt,
12
12
  PerformanceEvent,
13
13
  loggerToMonitoringContext,
14
+ type TelemetryEventCategory,
14
15
  } from "@fluidframework/telemetry-utils";
15
16
  import { IAnyDriverError } from "@fluidframework/driver-definitions";
16
- import { CatchUpMonitor, ICatchUpMonitor } from "./catchUpMonitor";
17
- import { ConnectionState } from "./connectionState";
18
- import { IConnectionDetailsInternal, IConnectionStateChangeReason } from "./contracts";
19
- import { IProtocolHandler } from "./protocol";
17
+ import { CatchUpMonitor, ICatchUpMonitor } from "./catchUpMonitor.js";
18
+ import { ConnectionState } from "./connectionState.js";
19
+ import { IConnectionDetailsInternal, IConnectionStateChangeReason } from "./contracts.js";
20
+ import { IProtocolHandler } from "./protocol.js";
20
21
 
21
22
  // Based on recent data, it looks like majority of cases where we get stuck are due to really slow or
22
23
  // timing out ops fetches. So attempt recovery infrequently. Also fetch uses 30 second timeout, so
@@ -43,7 +44,7 @@ export interface IConnectionStateHandlerInputs {
43
44
  logConnectionIssue: (
44
45
  eventName: string,
45
46
  category: TelemetryEventCategory,
46
- details?: ITelemetryProperties,
47
+ details?: ITelemetryBaseProperties,
47
48
  ) => void;
48
49
  /** Callback to note that an old local client ID is still present in the Quorum that should have left and should now be considered invalid */
49
50
  clientShouldHaveLeft: (clientId: string) => void;
@@ -188,7 +189,7 @@ class ConnectionStateHandlerPassThrough
188
189
  public logConnectionIssue(
189
190
  eventName: string,
190
191
  category: TelemetryEventCategory,
191
- details?: ITelemetryProperties,
192
+ details?: ITelemetryBaseProperties,
192
193
  ) {
193
194
  return this.inputs.logConnectionIssue(eventName, category, details);
194
195
  }
package/src/container.ts CHANGED
@@ -4,12 +4,11 @@
4
4
  */
5
5
 
6
6
  import { v4 as uuid } from "uuid";
7
- import { assert, unreachableCase } from "@fluidframework/core-utils";
7
+ import { assert, unreachableCase, isPromiseLike } from "@fluidframework/core-utils";
8
8
  import { TypedEventEmitter, performance } from "@fluid-internal/client-utils";
9
9
  import {
10
10
  IEvent,
11
- ITelemetryProperties,
12
- TelemetryEventCategory,
11
+ ITelemetryBaseProperties,
13
12
  FluidObject,
14
13
  LogLevel,
15
14
  IRequest,
@@ -89,26 +88,23 @@ import {
89
88
  GenericError,
90
89
  UsageError,
91
90
  IFluidErrorBase,
91
+ type TelemetryEventCategory,
92
92
  } from "@fluidframework/telemetry-utils";
93
93
  import structuredClone from "@ungap/structured-clone";
94
- import { Audience } from "./audience";
95
- import { ContainerContext } from "./containerContext";
94
+ import { Audience } from "./audience.js";
95
+ import { ContainerContext } from "./containerContext.js";
96
96
  import {
97
97
  ReconnectMode,
98
98
  IConnectionManagerFactoryArgs,
99
99
  getPackageName,
100
100
  IConnectionDetailsInternal,
101
101
  IConnectionStateChangeReason,
102
- } from "./contracts";
103
- import { DeltaManager, IConnectionArgs } from "./deltaManager";
104
- import { IDetachedBlobStorage, ILoaderOptions, RelativeLoader } from "./loader";
105
- import { pkgVersion } from "./packageVersion";
106
- import {
107
- ContainerStorageAdapter,
108
- getBlobContentsFromTree,
109
- ISerializableBlobContents,
110
- } from "./containerStorageAdapter";
111
- import { IConnectionStateHandler, createConnectionStateHandler } from "./connectionStateHandler";
102
+ } from "./contracts.js";
103
+ import { DeltaManager, IConnectionArgs } from "./deltaManager.js";
104
+ import { IDetachedBlobStorage, ILoaderOptions, RelativeLoader } from "./loader.js";
105
+ import { pkgVersion } from "./packageVersion.js";
106
+ import { ContainerStorageAdapter, ISerializableBlobContents } from "./containerStorageAdapter.js";
107
+ import { IConnectionStateHandler, createConnectionStateHandler } from "./connectionStateHandler.js";
112
108
  import {
113
109
  ISnapshotTreeWithBlobContents,
114
110
  combineAppAndProtocolSummary,
@@ -117,18 +113,19 @@ import {
117
113
  combineSnapshotTreeAndSnapshotBlobs,
118
114
  getDetachedContainerStateFromSerializedContainer,
119
115
  runSingle,
120
- } from "./utils";
121
- import { initQuorumValuesFromCodeDetails } from "./quorum";
122
- import { NoopHeuristic } from "./noopHeuristic";
123
- import { ConnectionManager } from "./connectionManager";
124
- import { ConnectionState } from "./connectionState";
116
+ } from "./utils.js";
117
+ import { initQuorumValuesFromCodeDetails } from "./quorum.js";
118
+ import { NoopHeuristic } from "./noopHeuristic.js";
119
+ import { ConnectionManager } from "./connectionManager.js";
120
+ import { ConnectionState } from "./connectionState.js";
125
121
  import {
126
122
  IProtocolHandler,
127
123
  ProtocolHandler,
128
124
  ProtocolHandlerBuilder,
129
125
  protocolHandlerShouldProcessSignal,
130
- } from "./protocol";
131
- import { AttachProcessProps, AttachmentData, runRetriableAttachProcess } from "./attachment";
126
+ } from "./protocol.js";
127
+ import { AttachProcessProps, AttachmentData, runRetriableAttachProcess } from "./attachment.js";
128
+ import { SerializedStateManager } from "./serializedStateManager.js";
132
129
 
133
130
  const detachedContainerRefSeqNumber = 0;
134
131
 
@@ -318,9 +315,7 @@ export async function waitContainerToCatchUp(container: IContainer) {
318
315
  });
319
316
  }
320
317
 
321
- const getCodeProposal =
322
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
323
- (quorum: IQuorumProposals) => quorum.get("code") ?? quorum.get("code2");
318
+ const getCodeProposal = (quorum: IQuorumProposals) => quorum.get("code") ?? quorum.get("code2");
324
319
 
325
320
  /**
326
321
  * Helper function to report to telemetry cases where operation takes longer than expected (200ms)
@@ -331,7 +326,7 @@ const getCodeProposal =
331
326
  export async function ReportIfTooLong(
332
327
  logger: ITelemetryLoggerExt,
333
328
  eventName: string,
334
- action: () => Promise<ITelemetryProperties>,
329
+ action: () => Promise<ITelemetryBaseProperties>,
335
330
  ) {
336
331
  const event = PerformanceEvent.start(logger, { eventName });
337
332
  const props = await action();
@@ -346,6 +341,7 @@ export async function ReportIfTooLong(
346
341
  * @internal
347
342
  */
348
343
  export interface IPendingContainerState {
344
+ attached: true;
349
345
  pendingRuntimeState: unknown;
350
346
  /**
351
347
  * Snapshot from which container initially loaded.
@@ -372,10 +368,11 @@ export interface IPendingContainerState {
372
368
  * @internal
373
369
  */
374
370
  export interface IPendingDetachedContainerState {
375
- attached: boolean;
371
+ attached: false;
376
372
  baseSnapshot: ISnapshotTree;
377
373
  snapshotBlobs: ISerializableBlobContents;
378
374
  hasAttachmentBlobs: boolean;
375
+ pendingRuntimeState?: unknown;
379
376
  }
380
377
 
381
378
  const summarizerClientType = "summarizer";
@@ -391,7 +388,6 @@ export class Container
391
388
  {
392
389
  /**
393
390
  * Load an existing container.
394
- * @internal
395
391
  */
396
392
  public static async load(
397
393
  loadProps: IContainerLoadProps,
@@ -516,7 +512,6 @@ export class Container
516
512
 
517
513
  /**
518
514
  * Used by the RelativeLoader to spawn a new Container for the same document. Used to create the summarizing client.
519
- * @internal
520
515
  */
521
516
  public readonly clone: (
522
517
  loadProps: IContainerLoadProps,
@@ -592,8 +587,8 @@ export class Container
592
587
  private readonly connectionTransitionTimes: number[] = [];
593
588
  private _loadedFromVersion: IVersion | undefined;
594
589
  private _dirtyContainer = false;
595
- private readonly savedOps: ISequencedDocumentMessage[] = [];
596
590
  private attachmentData: AttachmentData = { state: AttachState.Detached };
591
+ private readonly serializedStateManager: SerializedStateManager;
597
592
  private readonly _containerId: string;
598
593
 
599
594
  private lastVisible: number | undefined;
@@ -676,12 +671,8 @@ export class Container
676
671
  return this._clientId;
677
672
  }
678
673
 
679
- private get offlineLoadEnabled(): boolean {
680
- const enabled =
681
- this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ??
682
- this.options?.enableOfflineLoad === true;
683
- // summarizer will not have any pending state we want to save
684
- return enabled && this.deltaManager.clientDetails.capabilities.interactive;
674
+ private get isInteractiveClient(): boolean {
675
+ return this.deltaManager.clientDetails.capabilities.interactive;
685
676
  }
686
677
 
687
678
  /**
@@ -750,9 +741,6 @@ export class Container
750
741
 
751
742
  private readonly _lifecycleEvents = new TypedEventEmitter<IContainerLifecycleEvents>();
752
743
 
753
- /**
754
- * @internal
755
- */
756
744
  constructor(
757
745
  createProps: IContainerCreateProps,
758
746
  loadProps?: Pick<IContainerLoadProps, "pendingLocalState">,
@@ -825,7 +813,7 @@ export class Container
825
813
 
826
814
  this.client = Container.setupClient(
827
815
  this._containerId,
828
- this.options,
816
+ options.client,
829
817
  this.clientDetailsOverride,
830
818
  );
831
819
 
@@ -902,7 +890,7 @@ export class Container
902
890
  logConnectionIssue: (
903
891
  eventName: string,
904
892
  category: TelemetryEventCategory,
905
- details?: ITelemetryProperties,
893
+ details?: ITelemetryBaseProperties,
906
894
  ) => {
907
895
  const mode = this.connectionMode;
908
896
  // We get here when socket does not receive any ops on "write" connection, including
@@ -968,6 +956,17 @@ export class Container
968
956
  forceEnableSummarizeProtocolTree,
969
957
  );
970
958
 
959
+ const offlineLoadEnabled =
960
+ (this.isInteractiveClient &&
961
+ this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad")) ??
962
+ options.enableOfflineLoad === true;
963
+ this.serializedStateManager = new SerializedStateManager(
964
+ pendingLocalState,
965
+ this.subLogger,
966
+ this.storageAdapter,
967
+ offlineLoadEnabled,
968
+ );
969
+
971
970
  const isDomAvailable =
972
971
  typeof document === "object" &&
973
972
  document !== null &&
@@ -1148,48 +1147,26 @@ export class Container
1148
1147
  }
1149
1148
 
1150
1149
  private async getPendingLocalStateCore(props: IGetPendingLocalStateProps) {
1151
- return PerformanceEvent.timedExecAsync(
1152
- this.mc.logger,
1153
- {
1154
- eventName: "getPendingLocalState",
1155
- notifyImminentClosure: props.notifyImminentClosure,
1156
- savedOpsSize: this.savedOps.length,
1157
- clientId: this.clientId,
1158
- },
1159
- async () => {
1160
- if (!this.offlineLoadEnabled) {
1161
- throw new UsageError(
1162
- "Can't get pending local state unless offline load is enabled",
1163
- );
1164
- }
1165
- if (this.closed || this._disposed) {
1166
- throw new UsageError(
1167
- "Pending state cannot be retried if the container is closed or disposed",
1168
- );
1169
- }
1170
- assert(
1171
- this.attachmentData.state === AttachState.Attached,
1172
- 0x0d1 /* "Container should be attached before close" */,
1173
- );
1174
- assert(
1175
- this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid",
1176
- 0x0d2 /* "resolved url should be valid Fluid url" */,
1177
- );
1178
- assert(this.attachmentData.snapshot !== undefined, 0x5d5 /* no base data */);
1179
- const pendingRuntimeState = await this.runtime.getPendingLocalState(props);
1180
- const pendingState: IPendingContainerState = {
1181
- pendingRuntimeState,
1182
- baseSnapshot: this.attachmentData.snapshot.tree,
1183
- snapshotBlobs: this.attachmentData.snapshot.blobs,
1184
- savedOps: this.savedOps,
1185
- url: this.resolvedUrl.url,
1186
- // no need to save this if there is no pending runtime state
1187
- clientId: pendingRuntimeState !== undefined ? this.clientId : undefined,
1188
- };
1189
-
1190
- return JSON.stringify(pendingState);
1191
- },
1150
+ if (this.closed || this._disposed) {
1151
+ throw new UsageError(
1152
+ "Pending state cannot be retried if the container is closed or disposed",
1153
+ );
1154
+ }
1155
+ assert(
1156
+ this.attachmentData.state === AttachState.Attached,
1157
+ 0x0d1 /* "Container should be attached before close" */,
1158
+ );
1159
+ assert(
1160
+ this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid",
1161
+ 0x0d2 /* "resolved url should be valid Fluid url" */,
1192
1162
  );
1163
+ const pendingState = await this.serializedStateManager.getPendingLocalStateCore(
1164
+ props,
1165
+ this.clientId,
1166
+ this.runtime,
1167
+ this.resolvedUrl,
1168
+ );
1169
+ return pendingState;
1193
1170
  }
1194
1171
 
1195
1172
  public get attachState(): AttachState {
@@ -1197,22 +1174,32 @@ export class Container
1197
1174
  }
1198
1175
 
1199
1176
  public serialize(): string {
1200
- assert(
1201
- this.attachState === AttachState.Detached,
1202
- 0x0d3 /* "Should only be called in detached container" */,
1203
- );
1177
+ if (this.attachmentData.state === AttachState.Attached || this.closed) {
1178
+ throw new UsageError("Container must not be attached or closed.");
1179
+ }
1180
+
1181
+ const attachingData =
1182
+ this.attachmentData.state === AttachState.Attaching ? this.attachmentData : undefined;
1204
1183
 
1205
- const appSummary: ISummaryTree = this.runtime.createSummary();
1206
- const protocolSummary = this.captureProtocolSummary();
1207
- const combinedSummary = combineAppAndProtocolSummary(appSummary, protocolSummary);
1184
+ const combinedSummary =
1185
+ attachingData?.summary ??
1186
+ combineAppAndProtocolSummary(
1187
+ this.runtime.createSummary(),
1188
+ this.captureProtocolSummary(),
1189
+ );
1208
1190
 
1209
1191
  const { tree: snapshot, blobs } =
1210
1192
  getSnapshotTreeAndBlobsFromSerializedContainer(combinedSummary);
1211
1193
 
1194
+ const pendingRuntimeState =
1195
+ attachingData !== undefined ? this.runtime.getPendingLocalState() : undefined;
1196
+ assert(!isPromiseLike(pendingRuntimeState), 0x8e3 /* should not be a promise */);
1197
+
1212
1198
  const detachedContainerState: IPendingDetachedContainerState = {
1213
1199
  attached: false,
1214
1200
  baseSnapshot: snapshot,
1215
1201
  snapshotBlobs: blobs,
1202
+ pendingRuntimeState,
1216
1203
  hasAttachmentBlobs: !!this.detachedBlobStorage && this.detachedBlobStorage.size > 0,
1217
1204
  };
1218
1205
  return JSON.stringify(detachedContainerState);
@@ -1312,7 +1299,7 @@ export class Container
1312
1299
 
1313
1300
  let attachP = runRetriableAttachProcess({
1314
1301
  initialAttachmentData: this.attachmentData,
1315
- offlineLoadEnabled: this.offlineLoadEnabled,
1302
+ offlineLoadEnabled: this.serializedStateManager.offlineLoadEnabled,
1316
1303
  detachedBlobStorage: this.detachedBlobStorage,
1317
1304
  setAttachmentData,
1318
1305
  createAttachmentSummary,
@@ -1328,8 +1315,7 @@ export class Container
1328
1315
  });
1329
1316
  }
1330
1317
 
1331
- await attachP;
1332
-
1318
+ this.serializedStateManager.setSnapshot(await attachP);
1333
1319
  if (!this.closed) {
1334
1320
  this.handleDeltaConnectionArg(
1335
1321
  {
@@ -1521,11 +1507,6 @@ export class Container
1521
1507
  return true;
1522
1508
  }
1523
1509
 
1524
- private async getVersion(version: string | null): Promise<IVersion | undefined> {
1525
- const versions = await this.storageAdapter.getVersions(version, 1);
1526
- return versions[0];
1527
- }
1528
-
1529
1510
  private connectToDeltaStream(args: IConnectionArgs) {
1530
1511
  // All agents need "write" access, including summarizer.
1531
1512
  if (!this._canReconnect || !this.client.details.capabilities.interactive) {
@@ -1598,33 +1579,11 @@ export class Container
1598
1579
 
1599
1580
  timings.phase2 = performance.now();
1600
1581
  // Fetch specified snapshot.
1601
- const { snapshot, versionId } =
1602
- pendingLocalState === undefined
1603
- ? await this.fetchSnapshot(specifiedVersion)
1604
- : { snapshot: pendingLocalState.baseSnapshot, versionId: undefined };
1605
-
1606
- const snapshotTree: ISnapshotTree | undefined = isInstanceOfISnapshot(snapshot)
1607
- ? snapshot.snapshotTree
1608
- : snapshot;
1609
- if (pendingLocalState) {
1610
- this.attachmentData = {
1611
- state: AttachState.Attached,
1612
- snapshot: {
1613
- tree: pendingLocalState.baseSnapshot,
1614
- blobs: pendingLocalState.snapshotBlobs,
1615
- },
1616
- };
1617
- } else {
1618
- assert(snapshotTree !== undefined, 0x237 /* "Snapshot should exist" */);
1619
- if (this.offlineLoadEnabled) {
1620
- const blobs = await getBlobContentsFromTree(snapshotTree, this.storageAdapter);
1621
- this.attachmentData = {
1622
- state: AttachState.Attached,
1623
- snapshot: { tree: snapshotTree, blobs },
1624
- };
1625
- }
1626
- }
1627
-
1582
+ const { snapshotTree, version } = await this.serializedStateManager.fetchSnapshot(
1583
+ specifiedVersion,
1584
+ this.service?.policies?.supportGetSnapshotApi,
1585
+ );
1586
+ this._loadedFromVersion = version;
1628
1587
  const attributes: IDocumentAttributes = await this.getDocumentAttributes(
1629
1588
  this.storageAdapter,
1630
1589
  snapshotTree,
@@ -1727,7 +1686,7 @@ export class Container
1727
1686
  snapshotTree,
1728
1687
  // give runtime a dummy value so it knows we're loading from a stash blob
1729
1688
  pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined,
1730
- isInstanceOfISnapshot(snapshot) ? snapshot : undefined,
1689
+ isInstanceOfISnapshot(snapshotTree) ? snapshotTree : undefined,
1731
1690
  );
1732
1691
 
1733
1692
  // replay saved ops
@@ -1810,7 +1769,7 @@ export class Container
1810
1769
  );
1811
1770
  return {
1812
1771
  sequenceNumber: attributes.sequenceNumber,
1813
- version: versionId,
1772
+ version: version?.id,
1814
1773
  dmLastProcessedSeqNumber: this._deltaManager.lastSequenceNumber,
1815
1774
  dmLastKnownSeqNumber: this._deltaManager.lastKnownSeqNumber,
1816
1775
  };
@@ -1841,10 +1800,10 @@ export class Container
1841
1800
  }
1842
1801
 
1843
1802
  private async rehydrateDetachedFromSnapshot({
1844
- attached,
1845
1803
  baseSnapshot,
1846
1804
  snapshotBlobs,
1847
1805
  hasAttachmentBlobs,
1806
+ pendingRuntimeState,
1848
1807
  }: IPendingDetachedContainerState) {
1849
1808
  if (hasAttachmentBlobs) {
1850
1809
  assert(
@@ -1878,7 +1837,11 @@ export class Container
1878
1837
  );
1879
1838
  const codeDetails = this.getCodeDetailsFromQuorum();
1880
1839
 
1881
- await this.instantiateRuntime(codeDetails, snapshotTreeWithBlobContents);
1840
+ await this.instantiateRuntime(
1841
+ codeDetails,
1842
+ snapshotTreeWithBlobContents,
1843
+ pendingRuntimeState,
1844
+ );
1882
1845
 
1883
1846
  this.setLoaded();
1884
1847
  }
@@ -2022,13 +1985,12 @@ export class Container
2022
1985
 
2023
1986
  private static setupClient(
2024
1987
  containerId: string,
2025
- options?: ILoaderOptions,
1988
+ loaderOptionsClient?: IClient,
2026
1989
  clientDetailsOverride?: IClientDetails,
2027
1990
  ): IClient {
2028
- const loaderOptionsClient = structuredClone(options?.client);
2029
1991
  const client: IClient =
2030
1992
  loaderOptionsClient !== undefined
2031
- ? (loaderOptionsClient as IClient)
1993
+ ? structuredClone(loaderOptionsClient)
2032
1994
  : {
2033
1995
  details: {
2034
1996
  capabilities: { interactive: true },
@@ -2106,10 +2068,10 @@ export class Container
2106
2068
  this.connectionStateHandler.cancelEstablishingConnection(reason);
2107
2069
  });
2108
2070
 
2109
- deltaManager.on("disconnect", (reason: IConnectionStateChangeReason) => {
2071
+ deltaManager.on("disconnect", (text, error) => {
2110
2072
  this.noopHeuristic?.notifyDisconnect();
2111
2073
  if (!this.closed) {
2112
- this.connectionStateHandler.receivedDisconnectEvent(reason);
2074
+ this.connectionStateHandler.receivedDisconnectEvent({ text, error });
2113
2075
  }
2114
2076
  });
2115
2077
 
@@ -2333,9 +2295,6 @@ export class Container
2333
2295
  }
2334
2296
 
2335
2297
  private processRemoteMessage(message: ISequencedDocumentMessage) {
2336
- if (this.offlineLoadEnabled) {
2337
- this.savedOps.push(message);
2338
- }
2339
2298
  const local = this.clientId === message.clientId;
2340
2299
 
2341
2300
  // Allow the protocol handler to process the message
@@ -2343,7 +2302,7 @@ export class Container
2343
2302
 
2344
2303
  // Forward messages to the loaded runtime for processing
2345
2304
  this.runtime.process(message, local);
2346
-
2305
+ this.serializedStateManager.addProcessedOp(message);
2347
2306
  // Inactive (not in quorum or not writers) clients don't take part in the minimum sequence number calculation.
2348
2307
  if (this.activeConnection()) {
2349
2308
  if (this.noopHeuristic === undefined) {
@@ -2396,60 +2355,6 @@ export class Container
2396
2355
  }
2397
2356
  }
2398
2357
 
2399
- /**
2400
- * Get the most recent snapshot, or a specific version.
2401
- * @param specifiedVersion - The specific version of the snapshot to retrieve
2402
- * @returns The snapshot requested, or the latest snapshot if no version was specified, plus version ID
2403
- */
2404
- private async fetchSnapshotTree(
2405
- specifiedVersion: string | undefined,
2406
- ): Promise<{ snapshot?: ISnapshotTree; versionId?: string }> {
2407
- const version = await this.getVersion(specifiedVersion ?? null);
2408
-
2409
- if (version === undefined && specifiedVersion !== undefined) {
2410
- // We should have a defined version to load from if specified version requested
2411
- this.mc.logger.sendErrorEvent({
2412
- eventName: "NoVersionFoundWhenSpecified",
2413
- id: specifiedVersion,
2414
- });
2415
- }
2416
- this._loadedFromVersion = version;
2417
- const snapshot = (await this.storageAdapter.getSnapshotTree(version)) ?? undefined;
2418
-
2419
- if (snapshot === undefined && version !== undefined) {
2420
- this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
2421
- }
2422
- return { snapshot, versionId: version?.id };
2423
- }
2424
-
2425
- private async fetchSnapshot(
2426
- specifiedVersion: string | undefined,
2427
- ): Promise<{ snapshot?: ISnapshot | ISnapshotTree; versionId?: string }> {
2428
- if (
2429
- this.mc.config.getBoolean("Fluid.Container.FetchSnapshotUsingGetSnapshotApi") ===
2430
- true &&
2431
- this.service?.policies?.supportGetSnapshotApi === true
2432
- ) {
2433
- const snapshot = await this.storageAdapter.getSnapshot({
2434
- versionId: specifiedVersion,
2435
- });
2436
- const version: IVersion = {
2437
- id: snapshot.snapshotTree.id ?? "",
2438
- treeId: snapshot.snapshotTree.id ?? "",
2439
- };
2440
- this._loadedFromVersion = version;
2441
-
2442
- if (snapshot === undefined && specifiedVersion !== undefined) {
2443
- this.mc.logger.sendErrorEvent({
2444
- eventName: "getSnapshotTreeFailed",
2445
- id: version.id,
2446
- });
2447
- }
2448
- return { snapshot, versionId: version.id };
2449
- }
2450
- return this.fetchSnapshotTree(specifiedVersion);
2451
- }
2452
-
2453
2358
  private async instantiateRuntime(
2454
2359
  codeDetails: IFluidCodeDetails,
2455
2360
  snapshotTree: ISnapshotTree | undefined,