@fluidframework/container-loader 2.0.0-rc.1.0.4 → 2.0.0-rc.2.0.0

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 (298) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +5 -6
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +48 -0
  4. package/README.md +3 -3
  5. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  6. package/api-extractor-lint.json +1 -1
  7. package/api-extractor.json +1 -1
  8. package/api-report/container-loader.api.md +2 -2
  9. package/dist/attachment.d.ts +115 -0
  10. package/dist/attachment.d.ts.map +1 -0
  11. package/dist/attachment.js +83 -0
  12. package/dist/attachment.js.map +1 -0
  13. package/dist/audience.d.ts +9 -4
  14. package/dist/audience.d.ts.map +1 -1
  15. package/dist/audience.js +10 -4
  16. package/dist/audience.js.map +1 -1
  17. package/dist/connectionManager.d.ts +3 -3
  18. package/dist/connectionManager.d.ts.map +1 -1
  19. package/dist/connectionManager.js +17 -18
  20. package/dist/connectionManager.js.map +1 -1
  21. package/dist/connectionState.d.ts +1 -0
  22. package/dist/connectionState.d.ts.map +1 -1
  23. package/dist/connectionState.js +1 -0
  24. package/dist/connectionState.js.map +1 -1
  25. package/dist/connectionStateHandler.d.ts +7 -7
  26. package/dist/connectionStateHandler.d.ts.map +1 -1
  27. package/dist/connectionStateHandler.js +32 -32
  28. package/dist/connectionStateHandler.js.map +1 -1
  29. package/dist/container-loader-alpha.d.ts +2 -1
  30. package/dist/container-loader-beta.d.ts +3 -0
  31. package/dist/container-loader-public.d.ts +3 -0
  32. package/dist/container-loader-untrimmed.d.ts +5 -5
  33. package/dist/container.d.ts +29 -27
  34. package/dist/container.d.ts.map +1 -1
  35. package/dist/container.js +219 -284
  36. package/dist/container.js.map +1 -1
  37. package/dist/containerContext.d.ts +3 -2
  38. package/dist/containerContext.d.ts.map +1 -1
  39. package/dist/containerContext.js +2 -1
  40. package/dist/containerContext.js.map +1 -1
  41. package/dist/containerStorageAdapter.d.ts +5 -6
  42. package/dist/containerStorageAdapter.d.ts.map +1 -1
  43. package/dist/containerStorageAdapter.js +14 -21
  44. package/dist/containerStorageAdapter.js.map +1 -1
  45. package/dist/contracts.d.ts +3 -3
  46. package/dist/contracts.d.ts.map +1 -1
  47. package/dist/contracts.js.map +1 -1
  48. package/dist/debugLogger.js.map +1 -1
  49. package/dist/deltaManager.d.ts +5 -5
  50. package/dist/deltaManager.d.ts.map +1 -1
  51. package/dist/deltaManager.js +6 -6
  52. package/dist/deltaManager.js.map +1 -1
  53. package/dist/error.d.ts.map +1 -1
  54. package/dist/error.js.map +1 -1
  55. package/dist/index.d.ts +6 -6
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +11 -11
  58. package/dist/index.js.map +1 -1
  59. package/dist/loader.d.ts +3 -3
  60. package/dist/loader.d.ts.map +1 -1
  61. package/dist/loader.js +13 -17
  62. package/dist/loader.js.map +1 -1
  63. package/dist/location-redirection-utilities/index.d.ts +1 -1
  64. package/dist/location-redirection-utilities/index.d.ts.map +1 -1
  65. package/dist/location-redirection-utilities/index.js +3 -3
  66. package/dist/location-redirection-utilities/index.js.map +1 -1
  67. package/dist/package.json +3 -0
  68. package/dist/packageVersion.d.ts +1 -1
  69. package/dist/packageVersion.js +1 -1
  70. package/dist/packageVersion.js.map +1 -1
  71. package/dist/protocolTreeDocumentStorageService.d.ts +1 -1
  72. package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
  73. package/dist/protocolTreeDocumentStorageService.js +1 -3
  74. package/dist/protocolTreeDocumentStorageService.js.map +1 -1
  75. package/dist/retriableDocumentStorageService.d.ts +2 -2
  76. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  77. package/dist/retriableDocumentStorageService.js +8 -6
  78. package/dist/retriableDocumentStorageService.js.map +1 -1
  79. package/dist/serializedStateManager.d.ts +44 -0
  80. package/dist/serializedStateManager.d.ts.map +1 -0
  81. package/dist/serializedStateManager.js +149 -0
  82. package/dist/serializedStateManager.js.map +1 -0
  83. package/dist/tsdoc-metadata.json +1 -1
  84. package/dist/utils.d.ts +16 -11
  85. package/dist/utils.d.ts.map +1 -1
  86. package/dist/utils.js +107 -32
  87. package/dist/utils.js.map +1 -1
  88. package/lib/attachment.d.ts +115 -0
  89. package/lib/attachment.d.ts.map +1 -0
  90. package/lib/attachment.js +79 -0
  91. package/lib/attachment.js.map +1 -0
  92. package/lib/{audience.d.mts → audience.d.ts} +14 -5
  93. package/lib/audience.d.ts.map +1 -0
  94. package/lib/{audience.mjs → audience.js} +14 -4
  95. package/lib/audience.js.map +1 -0
  96. package/lib/{catchUpMonitor.d.mts → catchUpMonitor.d.ts} +1 -1
  97. package/lib/catchUpMonitor.d.ts.map +1 -0
  98. package/lib/{catchUpMonitor.mjs → catchUpMonitor.js} +1 -1
  99. package/lib/catchUpMonitor.js.map +1 -0
  100. package/lib/{connectionManager.d.mts → connectionManager.d.ts} +4 -4
  101. package/lib/connectionManager.d.ts.map +1 -0
  102. package/lib/{connectionManager.mjs → connectionManager.js} +7 -10
  103. package/lib/connectionManager.js.map +1 -0
  104. package/lib/{connectionState.d.mts → connectionState.d.ts} +2 -1
  105. package/lib/connectionState.d.ts.map +1 -0
  106. package/lib/{connectionState.mjs → connectionState.js} +2 -1
  107. package/lib/connectionState.js.map +1 -0
  108. package/lib/{connectionStateHandler.d.mts → connectionStateHandler.d.ts} +8 -8
  109. package/lib/connectionStateHandler.d.ts.map +1 -0
  110. package/lib/{connectionStateHandler.mjs → connectionStateHandler.js} +3 -3
  111. package/lib/connectionStateHandler.js.map +1 -0
  112. package/lib/{container-loader-alpha.d.mts → container-loader-alpha.d.ts} +2 -1
  113. package/lib/{container-loader-beta.d.mts → container-loader-beta.d.ts} +3 -0
  114. package/lib/{container-loader-public.d.mts → container-loader-public.d.ts} +3 -0
  115. package/lib/{container-loader-untrimmed.d.mts → container-loader-untrimmed.d.ts} +5 -5
  116. package/lib/{container.d.mts → container.d.ts} +30 -28
  117. package/lib/container.d.ts.map +1 -0
  118. package/lib/{container.mjs → container.js} +179 -247
  119. package/lib/container.js.map +1 -0
  120. package/lib/{containerContext.d.mts → containerContext.d.ts} +4 -3
  121. package/lib/containerContext.d.ts.map +1 -0
  122. package/lib/{containerContext.mjs → containerContext.js} +3 -2
  123. package/lib/containerContext.js.map +1 -0
  124. package/lib/{containerStorageAdapter.d.mts → containerStorageAdapter.d.ts} +6 -7
  125. package/lib/containerStorageAdapter.d.ts.map +1 -0
  126. package/lib/{containerStorageAdapter.mjs → containerStorageAdapter.js} +13 -20
  127. package/lib/containerStorageAdapter.js.map +1 -0
  128. package/lib/{contracts.d.mts → contracts.d.ts} +4 -4
  129. package/lib/contracts.d.ts.map +1 -0
  130. package/lib/{contracts.mjs → contracts.js} +1 -1
  131. package/lib/contracts.js.map +1 -0
  132. package/lib/{debugLogger.d.mts → debugLogger.d.ts} +1 -1
  133. package/lib/debugLogger.d.ts.map +1 -0
  134. package/lib/{debugLogger.mjs → debugLogger.js} +2 -1
  135. package/lib/debugLogger.js.map +1 -0
  136. package/lib/{deltaManager.d.mts → deltaManager.d.ts} +6 -6
  137. package/lib/deltaManager.d.ts.map +1 -0
  138. package/lib/{deltaManager.mjs → deltaManager.js} +4 -4
  139. package/lib/deltaManager.js.map +1 -0
  140. package/lib/{deltaQueue.d.mts → deltaQueue.d.ts} +1 -1
  141. package/lib/deltaQueue.d.ts.map +1 -0
  142. package/lib/{deltaQueue.mjs → deltaQueue.js} +1 -1
  143. package/lib/deltaQueue.js.map +1 -0
  144. package/lib/{disposal.d.mts → disposal.d.ts} +1 -1
  145. package/lib/disposal.d.ts.map +1 -0
  146. package/lib/{disposal.mjs → disposal.js} +1 -1
  147. package/lib/disposal.js.map +1 -0
  148. package/lib/{error.d.mts → error.d.ts} +1 -1
  149. package/lib/error.d.ts.map +1 -0
  150. package/lib/{error.mjs → error.js} +1 -1
  151. package/lib/error.js.map +1 -0
  152. package/lib/{index.d.mts → index.d.ts} +7 -7
  153. package/lib/index.d.ts.map +1 -0
  154. package/lib/index.js +10 -0
  155. package/lib/index.js.map +1 -0
  156. package/lib/{loader.d.mts → loader.d.ts} +4 -4
  157. package/lib/loader.d.ts.map +1 -0
  158. package/lib/{loader.mjs → loader.js} +7 -11
  159. package/lib/loader.js.map +1 -0
  160. package/lib/location-redirection-utilities/{index.mjs → index.d.ts} +2 -2
  161. package/lib/location-redirection-utilities/index.d.ts.map +1 -0
  162. package/lib/location-redirection-utilities/{index.d.mts → index.js} +2 -2
  163. package/lib/location-redirection-utilities/index.js.map +1 -0
  164. package/lib/location-redirection-utilities/{resolveWithLocationRedirection.d.mts → resolveWithLocationRedirection.d.ts} +1 -1
  165. package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
  166. package/lib/location-redirection-utilities/{resolveWithLocationRedirection.mjs → resolveWithLocationRedirection.js} +1 -1
  167. package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
  168. package/lib/{noopHeuristic.d.mts → noopHeuristic.d.ts} +1 -1
  169. package/lib/noopHeuristic.d.ts.map +1 -0
  170. package/lib/{noopHeuristic.mjs → noopHeuristic.js} +1 -1
  171. package/lib/noopHeuristic.js.map +1 -0
  172. package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
  173. package/lib/packageVersion.d.ts.map +1 -0
  174. package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
  175. package/lib/packageVersion.js.map +1 -0
  176. package/lib/{protocol.d.mts → protocol.d.ts} +1 -1
  177. package/lib/protocol.d.ts.map +1 -0
  178. package/lib/{protocol.mjs → protocol.js} +1 -1
  179. package/lib/protocol.js.map +1 -0
  180. package/lib/{protocolTreeDocumentStorageService.d.mts → protocolTreeDocumentStorageService.d.ts} +2 -2
  181. package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -0
  182. package/lib/{protocolTreeDocumentStorageService.mjs → protocolTreeDocumentStorageService.js} +2 -4
  183. package/lib/protocolTreeDocumentStorageService.js.map +1 -0
  184. package/lib/{quorum.d.mts → quorum.d.ts} +5 -1
  185. package/lib/quorum.d.ts.map +1 -0
  186. package/lib/{quorum.mjs → quorum.js} +1 -1
  187. package/lib/quorum.js.map +1 -0
  188. package/lib/{retriableDocumentStorageService.d.mts → retriableDocumentStorageService.d.ts} +3 -3
  189. package/lib/retriableDocumentStorageService.d.ts.map +1 -0
  190. package/lib/{retriableDocumentStorageService.mjs → retriableDocumentStorageService.js} +10 -8
  191. package/lib/retriableDocumentStorageService.js.map +1 -0
  192. package/lib/serializedStateManager.d.ts +44 -0
  193. package/lib/serializedStateManager.d.ts.map +1 -0
  194. package/lib/serializedStateManager.js +145 -0
  195. package/lib/serializedStateManager.js.map +1 -0
  196. package/lib/test/attachment.spec.js +380 -0
  197. package/lib/test/attachment.spec.js.map +1 -0
  198. package/lib/test/catchUpMonitor.spec.js +88 -0
  199. package/lib/test/catchUpMonitor.spec.js.map +1 -0
  200. package/lib/test/connectionManager.spec.js +201 -0
  201. package/lib/test/connectionManager.spec.js.map +1 -0
  202. package/lib/test/connectionStateHandler.spec.js +555 -0
  203. package/lib/test/connectionStateHandler.spec.js.map +1 -0
  204. package/lib/test/container.spec.js +64 -0
  205. package/lib/test/container.spec.js.map +1 -0
  206. package/lib/test/deltaManager.spec.js +405 -0
  207. package/lib/test/deltaManager.spec.js.map +1 -0
  208. package/lib/test/loader.spec.js +212 -0
  209. package/lib/test/loader.spec.js.map +1 -0
  210. package/lib/test/locationRedirectionTests.spec.js +44 -0
  211. package/lib/test/locationRedirectionTests.spec.js.map +1 -0
  212. package/lib/test/serializedStateManager.spec.js +148 -0
  213. package/lib/test/serializedStateManager.spec.js.map +1 -0
  214. package/lib/test/snapshotConversionTest.spec.js +79 -0
  215. package/lib/test/snapshotConversionTest.spec.js.map +1 -0
  216. package/lib/test/types/validateContainerLoaderPrevious.generated.js +38 -0
  217. package/lib/test/types/validateContainerLoaderPrevious.generated.js.map +1 -0
  218. package/lib/test/utils.spec.js +31 -0
  219. package/lib/test/utils.spec.js.map +1 -0
  220. package/lib/{utils.d.mts → utils.d.ts} +17 -12
  221. package/lib/utils.d.ts.map +1 -0
  222. package/lib/utils.js +206 -0
  223. package/lib/utils.js.map +1 -0
  224. package/package.json +63 -63
  225. package/src/attachment.ts +222 -0
  226. package/src/audience.ts +9 -3
  227. package/src/connectionManager.ts +9 -11
  228. package/src/connectionState.ts +1 -0
  229. package/src/connectionStateHandler.ts +8 -7
  230. package/src/container.ts +297 -323
  231. package/src/containerContext.ts +2 -1
  232. package/src/containerStorageAdapter.ts +21 -26
  233. package/src/contracts.ts +3 -3
  234. package/src/debugLogger.ts +2 -2
  235. package/src/deltaManager.ts +8 -8
  236. package/src/error.ts +2 -2
  237. package/src/index.ts +6 -6
  238. package/src/loader.ts +9 -13
  239. package/src/location-redirection-utilities/index.ts +1 -1
  240. package/src/packageVersion.ts +1 -1
  241. package/src/protocolTreeDocumentStorageService.ts +1 -3
  242. package/src/retriableDocumentStorageService.ts +18 -8
  243. package/src/serializedStateManager.ts +217 -0
  244. package/src/utils.ts +140 -43
  245. package/tsconfig.cjs.json +7 -0
  246. package/tsconfig.json +2 -5
  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 +0 -133
  298. package/lib/utils.mjs.map +0 -1
package/dist/container.js CHANGED
@@ -3,6 +3,9 @@
3
3
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
4
  * Licensed under the MIT License.
5
5
  */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
6
9
  Object.defineProperty(exports, "__esModule", { value: true });
7
10
  exports.Container = exports.ReportIfTooLong = exports.waitContainerToCatchUp = void 0;
8
11
  const uuid_1 = require("uuid");
@@ -13,25 +16,27 @@ const container_definitions_1 = require("@fluidframework/container-definitions")
13
16
  const driver_utils_1 = require("@fluidframework/driver-utils");
14
17
  const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
15
18
  const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
16
- const audience_1 = require("./audience");
17
- const containerContext_1 = require("./containerContext");
18
- const contracts_1 = require("./contracts");
19
- const deltaManager_1 = require("./deltaManager");
20
- const loader_1 = require("./loader");
21
- const packageVersion_1 = require("./packageVersion");
22
- const containerStorageAdapter_1 = require("./containerStorageAdapter");
23
- const connectionStateHandler_1 = require("./connectionStateHandler");
24
- const utils_1 = require("./utils");
25
- const quorum_1 = require("./quorum");
26
- const noopHeuristic_1 = require("./noopHeuristic");
27
- const connectionManager_1 = require("./connectionManager");
28
- const connectionState_1 = require("./connectionState");
29
- const protocol_1 = require("./protocol");
19
+ const structured_clone_1 = __importDefault(require("@ungap/structured-clone"));
20
+ const audience_js_1 = require("./audience.js");
21
+ const containerContext_js_1 = require("./containerContext.js");
22
+ const contracts_js_1 = require("./contracts.js");
23
+ const deltaManager_js_1 = require("./deltaManager.js");
24
+ const loader_js_1 = require("./loader.js");
25
+ const packageVersion_js_1 = require("./packageVersion.js");
26
+ const containerStorageAdapter_js_1 = require("./containerStorageAdapter.js");
27
+ const connectionStateHandler_js_1 = require("./connectionStateHandler.js");
28
+ const utils_js_1 = require("./utils.js");
29
+ const quorum_js_1 = require("./quorum.js");
30
+ const noopHeuristic_js_1 = require("./noopHeuristic.js");
31
+ const connectionManager_js_1 = require("./connectionManager.js");
32
+ const connectionState_js_1 = require("./connectionState.js");
33
+ const protocol_js_1 = require("./protocol.js");
34
+ const attachment_js_1 = require("./attachment.js");
35
+ const serializedStateManager_js_1 = require("./serializedStateManager.js");
30
36
  const detachedContainerRefSeqNumber = 0;
31
37
  const dirtyContainerEvent = "dirty";
32
38
  const savedContainerEvent = "saved";
33
39
  const packageNotFactoryError = "Code package does not implement IRuntimeFactory";
34
- const hasBlobsSummaryTree = ".hasAttachmentBlobs";
35
40
  /**
36
41
  * Waits until container connects to delta storage and gets up-to-date.
37
42
  *
@@ -69,8 +74,8 @@ async function waitContainerToCatchUp(container) {
69
74
  // Waiting for "connected" state in either case gets us at least to our own Join op
70
75
  // which is a reasonable approximation of "caught up"
71
76
  const waitForOps = () => {
72
- (0, core_utils_1.assert)(container.connectionState === connectionState_1.ConnectionState.CatchingUp ||
73
- container.connectionState === connectionState_1.ConnectionState.Connected, 0x0cd /* "Container disconnected while waiting for ops!" */);
77
+ (0, core_utils_1.assert)(container.connectionState === connectionState_js_1.ConnectionState.CatchingUp ||
78
+ container.connectionState === connectionState_js_1.ConnectionState.Connected, 0x0cd /* "Container disconnected while waiting for ops!" */);
74
79
  const hasCheckpointSequenceNumber = deltaManager.hasCheckpointSequenceNumber;
75
80
  const connectionOpSeqNumber = deltaManager.lastKnownSeqNumber;
76
81
  (0, core_utils_1.assert)(deltaManager.lastSequenceNumber <= connectionOpSeqNumber, 0x266 /* "lastKnownSeqNumber should never be below last processed sequence number" */);
@@ -92,7 +97,7 @@ async function waitContainerToCatchUp(container) {
92
97
  // But that works only if service provides us checkPointSequenceNumber
93
98
  // Our internal testing is based on R11S that does not, but almost all tests connect as "write" and
94
99
  // use this function to catch up, so leveraging our own join op as a fence/barrier
95
- if (container.connectionState === connectionState_1.ConnectionState.Connected) {
100
+ if (container.connectionState === connectionState_js_1.ConnectionState.Connected) {
96
101
  waitForOps();
97
102
  return;
98
103
  }
@@ -101,15 +106,13 @@ async function waitContainerToCatchUp(container) {
101
106
  waitForOps();
102
107
  };
103
108
  container.on(telemetry_utils_1.connectedEventName, callback);
104
- if (container.connectionState === connectionState_1.ConnectionState.Disconnected) {
109
+ if (container.connectionState === connectionState_js_1.ConnectionState.Disconnected) {
105
110
  container.connect();
106
111
  }
107
112
  });
108
113
  }
109
114
  exports.waitContainerToCatchUp = waitContainerToCatchUp;
110
- const getCodeProposal =
111
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
112
- (quorum) => quorum.get("code") ?? quorum.get("code2");
115
+ const getCodeProposal = (quorum) => quorum.get("code") ?? quorum.get("code2");
113
116
  /**
114
117
  * Helper function to report to telemetry cases where operation takes longer than expected (200ms)
115
118
  * @param logger - logger to use
@@ -128,7 +131,6 @@ const summarizerClientType = "summarizer";
128
131
  class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
129
132
  /**
130
133
  * Load an existing container.
131
- * @internal
132
134
  */
133
135
  static async load(loadProps, createProps) {
134
136
  const { version, pendingLocalState, loadMode, resolvedUrl, loadToSequenceNumber } = loadProps;
@@ -185,11 +187,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
185
187
  static async rehydrateDetachedFromSnapshot(createProps, snapshot) {
186
188
  const container = new Container(createProps);
187
189
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
188
- const deserializedSummary = JSON.parse(snapshot);
189
- if (!(0, driver_utils_1.isCombinedAppAndProtocolSummary)(deserializedSummary, hasBlobsSummaryTree)) {
190
- throw new telemetry_utils_1.UsageError("Cannot rehydrate detached container. Incorrect format");
191
- }
192
- await container.rehydrateDetachedFromSnapshot(deserializedSummary);
190
+ const detachedContainerState = (0, utils_js_1.getDetachedContainerStateFromSerializedContainer)(snapshot);
191
+ await container.rehydrateDetachedFromSnapshot(detachedContainerState);
193
192
  return container;
194
193
  }, { start: true, end: true, cancel: "generic" });
195
194
  }
@@ -240,6 +239,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
240
239
  get readOnlyInfo() {
241
240
  return this._deltaManager.readOnlyInfo;
242
241
  }
242
+ get containerMetadata() {
243
+ return this._containerMetadata;
244
+ }
243
245
  /**
244
246
  * Sends signal to runtime (and data stores) to be read-only.
245
247
  * Hosts may have read only views, indicating to data stores that no edits are allowed.
@@ -267,7 +269,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
267
269
  return this.connectionStateHandler.connectionState;
268
270
  }
269
271
  get connected() {
270
- return this.connectionStateHandler.connectionState === connectionState_1.ConnectionState.Connected;
272
+ return this.connectionStateHandler.connectionState === connectionState_js_1.ConnectionState.Connected;
271
273
  }
272
274
  /**
273
275
  * The server provided id of the client.
@@ -276,11 +278,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
276
278
  get clientId() {
277
279
  return this._clientId;
278
280
  }
279
- get offlineLoadEnabled() {
280
- const enabled = this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ??
281
- this.options?.enableOfflineLoad === true;
282
- // summarizer will not have any pending state we want to save
283
- return enabled && this.deltaManager.clientDetails.capabilities.interactive;
281
+ get isInteractiveClient() {
282
+ return this.deltaManager.clientDetails.capabilities.interactive;
284
283
  }
285
284
  /**
286
285
  * Get the code details that are currently specified for the container.
@@ -335,9 +334,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
335
334
  this._lifecycleEvents.once("disposed", disposedHandler);
336
335
  });
337
336
  }
338
- /**
339
- * @internal
340
- */
341
337
  constructor(createProps, loadProps) {
342
338
  super((name, error) => {
343
339
  this.mc.logger.sendErrorEvent({
@@ -361,23 +357,101 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
361
357
  * disposed: Container has been disposed
362
358
  */
363
359
  this._lifecycleState = "loading";
364
- this._attachState = container_definitions_1.AttachState.Detached;
365
360
  /** During initialization we pause the inbound queues. We track this state to ensure we only call resume once */
366
361
  this.inboundQueuePausedFromInit = true;
367
362
  this.firstConnection = true;
368
363
  this.connectionTransitionTimes = [];
369
- this.attachStarted = false;
370
364
  this._dirtyContainer = false;
371
- this.savedOps = [];
365
+ this.attachmentData = { state: container_definitions_1.AttachState.Detached };
372
366
  this.clientsWhoShouldHaveLeft = new Set();
367
+ this._containerMetadata = {};
373
368
  this.setAutoReconnectTime = client_utils_1.performance.now();
374
369
  this._lifecycleEvents = new client_utils_1.TypedEventEmitter();
375
370
  this._disposed = false;
371
+ this.attach = (0, utils_js_1.runSingle)(async (request, attachProps) => {
372
+ await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
373
+ if (this._lifecycleState !== "loaded" ||
374
+ this.attachmentData.state === container_definitions_1.AttachState.Attached) {
375
+ // pre-0.58 error message: containerNotValidForAttach
376
+ throw new telemetry_utils_1.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}] and [${this.attachState}]`);
377
+ }
378
+ const normalizeErrorAndClose = (error) => {
379
+ const newError = (0, telemetry_utils_1.normalizeError)(error);
380
+ this.close(newError);
381
+ // add resolved URL on error object so that host has the ability to find this document and delete it
382
+ newError.addTelemetryProperties({
383
+ resolvedUrl: this.service?.resolvedUrl?.url,
384
+ });
385
+ return newError;
386
+ };
387
+ const setAttachmentData = (attachmentData) => {
388
+ const previousState = this.attachmentData.state;
389
+ this.attachmentData = attachmentData;
390
+ const state = this.attachmentData.state;
391
+ if (state !== previousState && state !== container_definitions_1.AttachState.Detached) {
392
+ try {
393
+ this.runtime.setAttachState(state);
394
+ this.emit(state.toLocaleLowerCase());
395
+ }
396
+ catch (error) {
397
+ throw normalizeErrorAndClose(error);
398
+ }
399
+ }
400
+ };
401
+ const createAttachmentSummary = (redirectTable) => {
402
+ try {
403
+ (0, core_utils_1.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
404
+ return (0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(redirectTable), this.captureProtocolSummary());
405
+ }
406
+ catch (error) {
407
+ throw normalizeErrorAndClose(error);
408
+ }
409
+ };
410
+ const createOrGetStorageService = async (summary) => {
411
+ // Actually go and create the resolved document
412
+ if (this.service === undefined) {
413
+ const createNewResolvedUrl = await this.urlResolver.resolve(request);
414
+ (0, core_utils_1.assert)(this.client.details.type !== summarizerClientType &&
415
+ createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
416
+ this.service = await (0, driver_utils_1.runWithRetry)(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
417
+ cancel: this._deltaManager.closeAbortController.signal,
418
+ });
419
+ }
420
+ this.storageAdapter.connectToService(this.service);
421
+ return this.storageAdapter;
422
+ };
423
+ let attachP = (0, attachment_js_1.runRetriableAttachProcess)({
424
+ initialAttachmentData: this.attachmentData,
425
+ offlineLoadEnabled: this.serializedStateManager.offlineLoadEnabled,
426
+ detachedBlobStorage: this.detachedBlobStorage,
427
+ setAttachmentData,
428
+ createAttachmentSummary,
429
+ createOrGetStorageService,
430
+ });
431
+ // only enable the new behavior if the config is set
432
+ if (this.mc.config.getBoolean("Fluid.Container.RetryOnAttachFailure") !== true) {
433
+ attachP = attachP.catch((error) => {
434
+ throw normalizeErrorAndClose(error);
435
+ });
436
+ }
437
+ this.serializedStateManager.setSnapshot(await attachP);
438
+ if (!this.closed) {
439
+ this.handleDeltaConnectionArg({
440
+ fetchOpsFromStorage: false,
441
+ reason: { text: "createDetached" },
442
+ }, attachProps?.deltaConnection);
443
+ }
444
+ }, { start: true, end: true, cancel: "generic" });
445
+ });
376
446
  this.getAbsoluteUrl = async (relativeUrl) => {
377
447
  if (this.resolvedUrl === undefined) {
378
448
  return undefined;
379
449
  }
380
- return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (0, contracts_1.getPackageName)(this._loadedCodeDetails));
450
+ return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (0, contracts_js_1.getPackageName)(this._loadedCodeDetails));
451
+ };
452
+ this.metadataUpdateHandler = (metadata) => {
453
+ this._containerMetadata = { ...this._containerMetadata, ...metadata };
454
+ this.emit("metadataUpdate", metadata);
381
455
  };
382
456
  this.updateDirtyContainerState = (dirty) => {
383
457
  if (this._dirtyContainer === dirty) {
@@ -387,7 +461,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
387
461
  this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
388
462
  };
389
463
  const { canReconnect, clientDetailsOverride, urlResolver, documentServiceFactory, codeLoader, options, scope, subLogger, detachedBlobStorage, protocolHandlerBuilder, } = createProps;
390
- this.connectionTransitionTimes[connectionState_1.ConnectionState.Disconnected] = client_utils_1.performance.now();
464
+ this.connectionTransitionTimes[connectionState_js_1.ConnectionState.Disconnected] = client_utils_1.performance.now();
391
465
  const pendingLocalState = loadProps?.pendingLocalState;
392
466
  this._clientId = pendingLocalState?.clientId;
393
467
  this._canReconnect = canReconnect ?? true;
@@ -403,7 +477,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
403
477
  this.detachedBlobStorage = detachedBlobStorage;
404
478
  this.protocolHandlerBuilder =
405
479
  protocolHandlerBuilder ??
406
- ((attributes, quorumSnapshot, sendProposal) => new protocol_1.ProtocolHandler(attributes, quorumSnapshot, sendProposal, new audience_1.Audience(), (clientId) => this.clientsWhoShouldHaveLeft.has(clientId)));
480
+ ((attributes, quorumSnapshot, sendProposal) => new protocol_js_1.ProtocolHandler(attributes, quorumSnapshot, sendProposal, new audience_js_1.Audience(), (clientId) => this.clientsWhoShouldHaveLeft.has(clientId)));
407
481
  // Note that we capture the createProps here so we can replicate the creation call when we want to clone.
408
482
  this.clone = async (_loadProps, createParamOverrides) => {
409
483
  return Container.load(_loadProps, {
@@ -412,7 +486,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
412
486
  });
413
487
  };
414
488
  this._containerId = (0, uuid_1.v4)();
415
- this.client = Container.setupClient(this._containerId, this.options, this.clientDetailsOverride);
489
+ this.client = Container.setupClient(this._containerId, options.client, this.clientDetailsOverride);
416
490
  // Create logger for data stores to use
417
491
  const type = this.client.details.type;
418
492
  const interactive = this.client.details.capabilities.interactive;
@@ -426,9 +500,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
426
500
  clientType,
427
501
  containerId: this._containerId,
428
502
  docId: () => this.resolvedUrl?.id,
429
- containerAttachState: () => this._attachState,
503
+ containerAttachState: () => this.attachState,
430
504
  containerLifecycleState: () => this._lifecycleState,
431
- containerConnectionState: () => connectionState_1.ConnectionState[this.connectionState],
505
+ containerConnectionState: () => connectionState_js_1.ConnectionState[this.connectionState],
432
506
  serializedContainer: pendingLocalState !== undefined,
433
507
  },
434
508
  // we need to be judicious with our logging here to avoid generating too much data
@@ -456,15 +530,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
456
530
  // Prefix all events in this file with container-loader
457
531
  this.mc = (0, telemetry_utils_1.createChildMonitoringContext)({ logger: this.subLogger, namespace: "Container" });
458
532
  this._deltaManager = this.createDeltaManager();
459
- this.connectionStateHandler = (0, connectionStateHandler_1.createConnectionStateHandler)({
533
+ this.connectionStateHandler = (0, connectionStateHandler_js_1.createConnectionStateHandler)({
460
534
  logger: this.mc.logger,
461
535
  connectionStateChanged: (value, oldState, reason) => {
462
- if (value === connectionState_1.ConnectionState.Connected) {
536
+ if (value === connectionState_js_1.ConnectionState.Connected) {
463
537
  this._clientId = this.connectionStateHandler.pendingClientId;
464
538
  }
465
539
  this.logConnectionStateChangeTelemetry(value, oldState, reason);
466
540
  if (this._lifecycleState === "loaded") {
467
- this.propagateConnectionState(false /* initial transition */, value === connectionState_1.ConnectionState.Disconnected
541
+ this.propagateConnectionState(false /* initial transition */, value === connectionState_js_1.ConnectionState.Disconnected
468
542
  ? reason
469
543
  : undefined /* disconnectedReason */);
470
544
  }
@@ -483,7 +557,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
483
557
  mode,
484
558
  category: this._lifecycleState === "loading" ? "generic" : category,
485
559
  duration: client_utils_1.performance.now() -
486
- this.connectionTransitionTimes[connectionState_1.ConnectionState.CatchingUp],
560
+ this.connectionTransitionTimes[connectionState_js_1.ConnectionState.CatchingUp],
487
561
  ...(details === undefined ? {} : { details: JSON.stringify(details) }),
488
562
  });
489
563
  // If this is "write" connection, it took too long to receive join op. But in most cases that's due
@@ -512,12 +586,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
512
586
  // using this callback and fix them up.
513
587
  const addProtocolSummaryIfMissing = (summaryTree) => (0, driver_utils_1.isCombinedAppAndProtocolSummary)(summaryTree) === true
514
588
  ? summaryTree
515
- : (0, utils_1.combineAppAndProtocolSummary)(summaryTree, this.captureProtocolSummary());
589
+ : (0, utils_js_1.combineAppAndProtocolSummary)(summaryTree, this.captureProtocolSummary());
516
590
  // Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
517
591
  // Even if not forced on via this flag, combined summaries may still be enabled by service policy.
518
592
  const forceEnableSummarizeProtocolTree = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2") ??
519
593
  options.summarizeProtocolTree;
520
- this.storageAdapter = new containerStorageAdapter_1.ContainerStorageAdapter(detachedBlobStorage, this.mc.logger, pendingLocalState?.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
594
+ this.storageAdapter = new containerStorageAdapter_js_1.ContainerStorageAdapter(detachedBlobStorage, this.mc.logger, pendingLocalState?.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
595
+ const offlineLoadEnabled = (this.isInteractiveClient &&
596
+ this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad")) ??
597
+ options.enableOfflineLoad === true;
598
+ this.serializedStateManager = new serializedStateManager_js_1.SerializedStateManager(pendingLocalState, this.subLogger, this.storageAdapter, offlineLoadEnabled);
521
599
  const isDomAvailable = typeof document === "object" &&
522
600
  document !== null &&
523
601
  typeof document.addEventListener === "function" &&
@@ -558,7 +636,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
558
636
  this.verifyClosed();
559
637
  }
560
638
  verifyClosed() {
561
- (0, core_utils_1.assert)(this.connectionState === connectionState_1.ConnectionState.Disconnected, 0x0cf /* "disconnect event was not raised!" */);
639
+ (0, core_utils_1.assert)(this.connectionState === connectionState_js_1.ConnectionState.Disconnected, 0x0cf /* "disconnect event was not raised!" */);
562
640
  (0, core_utils_1.assert)(this._lifecycleState === "closed" || this._lifecycleState === "disposed", 0x314 /* Container properly closed */);
563
641
  }
564
642
  closeCore(error) {
@@ -577,6 +655,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
577
655
  : "generic",
578
656
  }, error);
579
657
  this._lifecycleState = "closing";
658
+ // Back-compat for Old driver
659
+ if (this.service?.off !== undefined) {
660
+ this.service?.off("metadataUpdate", this.metadataUpdateHandler);
661
+ }
580
662
  this._protocolHandler?.close();
581
663
  this.connectionStateHandler.dispose();
582
664
  }
@@ -652,149 +734,35 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
652
734
  return this.getPendingLocalStateCore({ notifyImminentClosure: false });
653
735
  }
654
736
  async getPendingLocalStateCore(props) {
655
- return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, {
656
- eventName: "getPendingLocalState",
657
- notifyImminentClosure: props.notifyImminentClosure,
658
- savedOpsSize: this.savedOps.length,
659
- clientId: this.clientId,
660
- }, async () => {
661
- if (!this.offlineLoadEnabled) {
662
- throw new telemetry_utils_1.UsageError("Can't get pending local state unless offline load is enabled");
663
- }
664
- if (this.closed || this._disposed) {
665
- throw new telemetry_utils_1.UsageError("Pending state cannot be retried if the container is closed or disposed");
666
- }
667
- (0, core_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
668
- (0, core_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
669
- (0, core_utils_1.assert)(!!this.baseSnapshot, 0x5d4 /* no base snapshot */);
670
- (0, core_utils_1.assert)(!!this.baseSnapshotBlobs, 0x5d5 /* no snapshot blobs */);
671
- const pendingRuntimeState = await this.runtime.getPendingLocalState(props);
672
- const pendingState = {
673
- pendingRuntimeState,
674
- baseSnapshot: this.baseSnapshot,
675
- snapshotBlobs: this.baseSnapshotBlobs,
676
- savedOps: this.savedOps,
677
- url: this.resolvedUrl.url,
678
- // no need to save this if there is no pending runtime state
679
- clientId: pendingRuntimeState !== undefined ? this.clientId : undefined,
680
- };
681
- return JSON.stringify(pendingState);
682
- });
737
+ if (this.closed || this._disposed) {
738
+ throw new telemetry_utils_1.UsageError("Pending state cannot be retried if the container is closed or disposed");
739
+ }
740
+ (0, core_utils_1.assert)(this.attachmentData.state === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
741
+ (0, core_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
742
+ const pendingState = await this.serializedStateManager.getPendingLocalStateCore(props, this.clientId, this.runtime, this.resolvedUrl);
743
+ return pendingState;
683
744
  }
684
745
  get attachState() {
685
- return this._attachState;
746
+ return this.attachmentData.state;
686
747
  }
687
748
  serialize() {
688
- (0, core_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Detached, 0x0d3 /* "Should only be called in detached container" */);
689
- const appSummary = this.runtime.createSummary();
690
- const protocolSummary = this.captureProtocolSummary();
691
- const combinedSummary = (0, utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
692
- if (this.detachedBlobStorage && this.detachedBlobStorage.size > 0) {
693
- combinedSummary.tree[hasBlobsSummaryTree] = {
694
- type: protocol_definitions_1.SummaryType.Blob,
695
- content: "true",
696
- };
749
+ if (this.attachmentData.state === container_definitions_1.AttachState.Attached || this.closed) {
750
+ throw new telemetry_utils_1.UsageError("Container must not be attached or closed.");
697
751
  }
698
- return JSON.stringify(combinedSummary);
699
- }
700
- async attach(request, attachProps) {
701
- await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
702
- if (this._lifecycleState !== "loaded") {
703
- // pre-0.58 error message: containerNotValidForAttach
704
- throw new telemetry_utils_1.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}]`);
705
- }
706
- // If container is already attached or attach is in progress, throw an error.
707
- (0, core_utils_1.assert)(this._attachState === container_definitions_1.AttachState.Detached && !this.attachStarted, 0x205 /* "attach() called more than once" */);
708
- this.attachStarted = true;
709
- // If attachment blobs were uploaded in detached state we will go through a different attach flow
710
- const hasAttachmentBlobs = this.detachedBlobStorage !== undefined && this.detachedBlobStorage.size > 0;
711
- try {
712
- (0, core_utils_1.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
713
- let summary;
714
- if (!hasAttachmentBlobs) {
715
- // Get the document state post attach - possibly can just call attach but we need to change the
716
- // semantics around what the attach means as far as async code goes.
717
- const appSummary = this.runtime.createSummary();
718
- const protocolSummary = this.captureProtocolSummary();
719
- summary = (0, utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
720
- // Set the state as attaching as we are starting the process of attaching container.
721
- // This should be fired after taking the summary because it is the place where we are
722
- // starting to attach the container to storage.
723
- // Also, this should only be fired in detached container.
724
- this._attachState = container_definitions_1.AttachState.Attaching;
725
- this.runtime.setAttachState(container_definitions_1.AttachState.Attaching);
726
- this.emit("attaching");
727
- if (this.offlineLoadEnabled) {
728
- const snapshot = (0, utils_1.getSnapshotTreeFromSerializedContainer)(summary);
729
- this.baseSnapshot = snapshot;
730
- this.baseSnapshotBlobs =
731
- (0, containerStorageAdapter_1.getBlobContentsFromTreeWithBlobContents)(snapshot);
732
- }
733
- }
734
- // Actually go and create the resolved document
735
- if (this.service === undefined) {
736
- const createNewResolvedUrl = await this.urlResolver.resolve(request);
737
- (0, core_utils_1.assert)(this.client.details.type !== summarizerClientType &&
738
- createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
739
- this.service = await (0, driver_utils_1.runWithRetry)(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
740
- cancel: this._deltaManager.closeAbortController.signal,
741
- });
742
- }
743
- this.storageAdapter.connectToService(this.service);
744
- if (hasAttachmentBlobs) {
745
- // upload blobs to storage
746
- (0, core_utils_1.assert)(!!this.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
747
- // build a table mapping IDs assigned locally to IDs assigned by storage and pass it to runtime to
748
- // support blob handles that only know about the local IDs
749
- const redirectTable = new Map();
750
- // if new blobs are added while uploading, upload them too
751
- while (redirectTable.size < this.detachedBlobStorage.size) {
752
- const newIds = this.detachedBlobStorage
753
- .getBlobIds()
754
- .filter((id) => !redirectTable.has(id));
755
- for (const id of newIds) {
756
- const blob = await this.detachedBlobStorage.readBlob(id);
757
- const response = await this.storageAdapter.createBlob(blob);
758
- redirectTable.set(id, response.id);
759
- }
760
- }
761
- // take summary and upload
762
- const appSummary = this.runtime.createSummary(redirectTable);
763
- const protocolSummary = this.captureProtocolSummary();
764
- summary = (0, utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
765
- this._attachState = container_definitions_1.AttachState.Attaching;
766
- this.runtime.setAttachState(container_definitions_1.AttachState.Attaching);
767
- this.emit("attaching");
768
- if (this.offlineLoadEnabled) {
769
- const snapshot = (0, utils_1.getSnapshotTreeFromSerializedContainer)(summary);
770
- this.baseSnapshot = snapshot;
771
- this.baseSnapshotBlobs =
772
- (0, containerStorageAdapter_1.getBlobContentsFromTreeWithBlobContents)(snapshot);
773
- }
774
- await this.storageAdapter.uploadSummaryWithContext(summary, {
775
- referenceSequenceNumber: 0,
776
- ackHandle: undefined,
777
- proposalHandle: undefined,
778
- });
779
- }
780
- this._attachState = container_definitions_1.AttachState.Attached;
781
- this.runtime.setAttachState(container_definitions_1.AttachState.Attached);
782
- this.emit("attached");
783
- if (!this.closed) {
784
- this.handleDeltaConnectionArg({
785
- fetchOpsFromStorage: false,
786
- reason: { text: "createDetached" },
787
- }, attachProps?.deltaConnection);
788
- }
789
- }
790
- catch (error) {
791
- // add resolved URL on error object so that host has the ability to find this document and delete it
792
- const newError = (0, telemetry_utils_1.normalizeError)(error);
793
- newError.addTelemetryProperties({ resolvedUrl: this.resolvedUrl?.url });
794
- this.close(newError);
795
- throw newError;
796
- }
797
- }, { start: true, end: true, cancel: "generic" });
752
+ const attachingData = this.attachmentData.state === container_definitions_1.AttachState.Attaching ? this.attachmentData : undefined;
753
+ const combinedSummary = attachingData?.summary ??
754
+ (0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(), this.captureProtocolSummary());
755
+ const { tree: snapshot, blobs } = (0, utils_js_1.getSnapshotTreeAndBlobsFromSerializedContainer)(combinedSummary);
756
+ const pendingRuntimeState = attachingData !== undefined ? this.runtime.getPendingLocalState() : undefined;
757
+ (0, core_utils_1.assert)(!(0, core_utils_1.isPromiseLike)(pendingRuntimeState), 0x8e3 /* should not be a promise */);
758
+ const detachedContainerState = {
759
+ attached: false,
760
+ baseSnapshot: snapshot,
761
+ snapshotBlobs: blobs,
762
+ pendingRuntimeState,
763
+ hasAttachmentBlobs: !!this.detachedBlobStorage && this.detachedBlobStorage.size > 0,
764
+ };
765
+ return JSON.stringify(detachedContainerState);
798
766
  }
799
767
  setAutoReconnectInternal(mode, reason) {
800
768
  const currentMode = this._deltaManager.connectionManager.reconnectMode;
@@ -805,9 +773,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
805
773
  const duration = now - this.setAutoReconnectTime;
806
774
  this.setAutoReconnectTime = now;
807
775
  this.mc.logger.sendTelemetryEvent({
808
- eventName: mode === contracts_1.ReconnectMode.Enabled ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
776
+ eventName: mode === contracts_js_1.ReconnectMode.Enabled ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
809
777
  connectionMode: this.connectionMode,
810
- connectionState: connectionState_1.ConnectionState[this.connectionState],
778
+ connectionState: connectionState_js_1.ConnectionState[this.connectionState],
811
779
  duration,
812
780
  });
813
781
  this._deltaManager.connectionManager.setAutoReconnect(mode, reason);
@@ -816,7 +784,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
816
784
  if (this.closed) {
817
785
  throw new telemetry_utils_1.UsageError(`The Container is closed and cannot be connected`);
818
786
  }
819
- else if (this._attachState !== container_definitions_1.AttachState.Attached) {
787
+ else if (this.attachState !== container_definitions_1.AttachState.Attached) {
820
788
  throw new telemetry_utils_1.UsageError(`The Container is not attached and cannot be connected`);
821
789
  }
822
790
  else if (!this.connected) {
@@ -831,11 +799,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
831
799
  }
832
800
  connectInternal(args) {
833
801
  (0, core_utils_1.assert)(!this.closed, 0x2c5 /* "Attempting to connect() a closed Container" */);
834
- (0, core_utils_1.assert)(this._attachState === container_definitions_1.AttachState.Attached, 0x2c6 /* "Attempting to connect() a container that is not attached" */);
802
+ (0, core_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x2c6 /* "Attempting to connect() a container that is not attached" */);
835
803
  // Resume processing ops and connect to delta stream
836
804
  this.resumeInternal(args);
837
805
  // Set Auto Reconnect Mode
838
- const mode = contracts_1.ReconnectMode.Enabled;
806
+ const mode = contracts_js_1.ReconnectMode.Enabled;
839
807
  this.setAutoReconnectInternal(mode, args.reason);
840
808
  }
841
809
  disconnect() {
@@ -849,7 +817,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
849
817
  disconnectInternal(reason) {
850
818
  (0, core_utils_1.assert)(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
851
819
  // Set Auto Reconnect Mode
852
- const mode = contracts_1.ReconnectMode.Disabled;
820
+ const mode = contracts_js_1.ReconnectMode.Disabled;
853
821
  this.setAutoReconnectInternal(mode, reason);
854
822
  }
855
823
  resumeInternal(args) {
@@ -924,10 +892,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
924
892
  }
925
893
  return true;
926
894
  }
927
- async getVersion(version) {
928
- const versions = await this.storageAdapter.getVersions(version, 1);
929
- return versions[0];
930
- }
931
895
  connectToDeltaStream(args) {
932
896
  // All agents need "write" access, including summarizer.
933
897
  if (!this._canReconnect || !this.client.details.capabilities.interactive) {
@@ -935,6 +899,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
935
899
  }
936
900
  this._deltaManager.connect(args);
937
901
  }
902
+ async createDocumentService(serviceProvider) {
903
+ const service = await serviceProvider();
904
+ // Back-compat for Old driver
905
+ if (service.on !== undefined) {
906
+ service.on("metadataUpdate", this.metadataUpdateHandler);
907
+ }
908
+ return service;
909
+ }
938
910
  /**
939
911
  * Load container.
940
912
  *
@@ -942,7 +914,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
942
914
  */
943
915
  async load(specifiedVersion, loadMode, resolvedUrl, pendingLocalState, loadToSequenceNumber) {
944
916
  const timings = { phase1: client_utils_1.performance.now() };
945
- this.service = await this.serviceFactory.createDocumentService(resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
917
+ this.service = await this.createDocumentService(async () => this.serviceFactory.createDocumentService(resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType));
946
918
  // Except in cases where it has stashed ops or requested by feature gate, the container will connect in "read" mode
947
919
  const mode = this.mc.config.getBoolean("Fluid.Container.ForceWriteConnection") === true ||
948
920
  (pendingLocalState?.savedOps.length ?? 0) > 0
@@ -959,25 +931,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
959
931
  this.connectToDeltaStream(connectionArgs);
960
932
  }
961
933
  this.storageAdapter.connectToService(this.service);
962
- this._attachState = container_definitions_1.AttachState.Attached;
934
+ this.attachmentData = {
935
+ state: container_definitions_1.AttachState.Attached,
936
+ };
963
937
  timings.phase2 = client_utils_1.performance.now();
964
938
  // Fetch specified snapshot.
965
- const { snapshot, versionId } = pendingLocalState === undefined
966
- ? await this.fetchSnapshotTree(specifiedVersion)
967
- : { snapshot: pendingLocalState.baseSnapshot, versionId: undefined };
968
- if (pendingLocalState) {
969
- this.baseSnapshot = pendingLocalState.baseSnapshot;
970
- this.baseSnapshotBlobs = pendingLocalState.snapshotBlobs;
971
- }
972
- else {
973
- (0, core_utils_1.assert)(snapshot !== undefined, 0x237 /* "Snapshot should exist" */);
974
- if (this.offlineLoadEnabled) {
975
- this.baseSnapshot = snapshot;
976
- // Save contents of snapshot now, otherwise closeAndGetPendingLocalState() must be async
977
- this.baseSnapshotBlobs = await (0, containerStorageAdapter_1.getBlobContentsFromTree)(snapshot, this.storageAdapter);
978
- }
979
- }
980
- const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshot);
939
+ const { snapshotTree, version } = await this.serializedStateManager.fetchSnapshot(specifiedVersion, this.service?.policies?.supportGetSnapshotApi);
940
+ this._loadedFromVersion = version;
941
+ const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshotTree);
981
942
  // If we saved ops, we will replay them and don't need DeltaManager to fetch them
982
943
  const sequenceNumber = pendingLocalState?.savedOps[pendingLocalState.savedOps.length - 1]?.sequenceNumber;
983
944
  const dmAttributes = sequenceNumber !== undefined ? { ...attributes, sequenceNumber } : attributes;
@@ -1042,12 +1003,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1042
1003
  }
1043
1004
  // ...load in the existing quorum
1044
1005
  // Initialize the protocol handler
1045
- await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter, snapshot);
1006
+ await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter, snapshotTree);
1046
1007
  timings.phase3 = client_utils_1.performance.now();
1047
1008
  const codeDetails = this.getCodeDetailsFromQuorum();
1048
- await this.instantiateRuntime(codeDetails, snapshot,
1009
+ await this.instantiateRuntime(codeDetails, snapshotTree,
1049
1010
  // give runtime a dummy value so it knows we're loading from a stash blob
1050
- pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined);
1011
+ pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined, (0, driver_utils_1.isInstanceOfISnapshot)(snapshotTree) ? snapshotTree : undefined);
1051
1012
  // replay saved ops
1052
1013
  if (pendingLocalState) {
1053
1014
  for (const message of pendingLocalState.savedOps) {
@@ -1102,7 +1063,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1102
1063
  }, undefined, core_interfaces_1.LogLevel.verbose);
1103
1064
  return {
1104
1065
  sequenceNumber: attributes.sequenceNumber,
1105
- version: versionId,
1066
+ version: version?.id,
1106
1067
  dmLastProcessedSeqNumber: this._deltaManager.lastSequenceNumber,
1107
1068
  dmLastKnownSeqNumber: this._deltaManager.lastKnownSeqNumber,
1108
1069
  };
@@ -1114,7 +1075,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1114
1075
  };
1115
1076
  await this.attachDeltaManagerOpHandler(attributes);
1116
1077
  // Need to just seed the source data in the code quorum. Quorum itself is empty
1117
- const qValues = (0, quorum_1.initQuorumValuesFromCodeDetails)(codeDetails);
1078
+ const qValues = (0, quorum_js_1.initQuorumValuesFromCodeDetails)(codeDetails);
1118
1079
  this.initializeProtocolState(attributes, {
1119
1080
  members: [],
1120
1081
  proposals: [],
@@ -1123,18 +1084,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1123
1084
  await this.instantiateRuntime(codeDetails, undefined);
1124
1085
  this.setLoaded();
1125
1086
  }
1126
- async rehydrateDetachedFromSnapshot(detachedContainerSnapshot) {
1127
- if (detachedContainerSnapshot.tree[hasBlobsSummaryTree] !== undefined) {
1087
+ async rehydrateDetachedFromSnapshot({ baseSnapshot, snapshotBlobs, hasAttachmentBlobs, pendingRuntimeState, }) {
1088
+ if (hasAttachmentBlobs) {
1128
1089
  (0, core_utils_1.assert)(!!this.detachedBlobStorage && this.detachedBlobStorage.size > 0, 0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */);
1129
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
1130
- delete detachedContainerSnapshot.tree[hasBlobsSummaryTree];
1131
1090
  }
1132
- const snapshotTree = (0, utils_1.getSnapshotTreeFromSerializedContainer)(detachedContainerSnapshot);
1133
- this.storageAdapter.loadSnapshotForRehydratingContainer(snapshotTree);
1134
- const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshotTree);
1091
+ const snapshotTreeWithBlobContents = (0, utils_js_1.combineSnapshotTreeAndSnapshotBlobs)(baseSnapshot, snapshotBlobs);
1092
+ this.storageAdapter.loadSnapshotFromSnapshotBlobs(snapshotBlobs);
1093
+ const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshotTreeWithBlobContents);
1135
1094
  await this.attachDeltaManagerOpHandler(attributes);
1136
1095
  // Initialize the protocol handler
1137
- const baseTree = (0, utils_1.getProtocolSnapshotTree)(snapshotTree);
1096
+ const baseTree = (0, utils_js_1.getProtocolSnapshotTree)(snapshotTreeWithBlobContents);
1138
1097
  const qValues = await (0, driver_utils_1.readAndParse)(this.storageAdapter, baseTree.blobs.quorumValues);
1139
1098
  this.initializeProtocolState(attributes, {
1140
1099
  members: [],
@@ -1142,7 +1101,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1142
1101
  values: qValues,
1143
1102
  });
1144
1103
  const codeDetails = this.getCodeDetailsFromQuorum();
1145
- await this.instantiateRuntime(codeDetails, snapshotTree);
1104
+ await this.instantiateRuntime(codeDetails, snapshotTreeWithBlobContents, pendingRuntimeState);
1146
1105
  this.setLoaded();
1147
1106
  }
1148
1107
  async getDocumentAttributes(storage, tree) {
@@ -1166,7 +1125,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1166
1125
  values: [],
1167
1126
  };
1168
1127
  if (snapshot !== undefined) {
1169
- const baseTree = (0, utils_1.getProtocolSnapshotTree)(snapshot);
1128
+ const baseTree = (0, utils_js_1.getProtocolSnapshotTree)(snapshot);
1170
1129
  [quorumSnapshot.members, quorumSnapshot.proposals, quorumSnapshot.values] =
1171
1130
  await Promise.all([
1172
1131
  (0, driver_utils_1.readAndParse)(storage, baseTree.blobs.quorumMembers),
@@ -1242,10 +1201,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1242
1201
  const pkg = getCodeProposal(quorum);
1243
1202
  return pkg;
1244
1203
  }
1245
- static setupClient(containerId, options, clientDetailsOverride) {
1246
- const loaderOptionsClient = structuredClone(options?.client);
1204
+ static setupClient(containerId, loaderOptionsClient, clientDetailsOverride) {
1247
1205
  const client = loaderOptionsClient !== undefined
1248
- ? loaderOptionsClient
1206
+ ? (0, structured_clone_1.default)(loaderOptionsClient)
1249
1207
  : {
1250
1208
  details: {
1251
1209
  capabilities: { interactive: true },
@@ -1267,7 +1225,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1267
1225
  }
1268
1226
  client.details.environment = [
1269
1227
  client.details.environment,
1270
- ` loaderVersion:${packageVersion_1.pkgVersion}`,
1228
+ ` loaderVersion:${packageVersion_js_1.pkgVersion}`,
1271
1229
  ` containerId:${containerId}`,
1272
1230
  ].join(";");
1273
1231
  return client;
@@ -1279,11 +1237,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1279
1237
  * If it's not true, runtime is not in position to send ops.
1280
1238
  */
1281
1239
  activeConnection() {
1282
- return (this.connectionState === connectionState_1.ConnectionState.Connected && this.connectionMode === "write");
1240
+ return (this.connectionState === connectionState_js_1.ConnectionState.Connected && this.connectionMode === "write");
1283
1241
  }
1284
1242
  createDeltaManager() {
1285
1243
  const serviceProvider = () => this.service;
1286
- const deltaManager = new deltaManager_1.DeltaManager(serviceProvider, (0, telemetry_utils_1.createChildLogger)({ logger: this.subLogger, namespace: "DeltaManager" }), () => this.activeConnection(), (props) => new connectionManager_1.ConnectionManager(serviceProvider, () => this.isDirty, this.client, this._canReconnect, (0, telemetry_utils_1.createChildLogger)({ logger: this.subLogger, namespace: "ConnectionManager" }), props));
1244
+ const deltaManager = new deltaManager_js_1.DeltaManager(serviceProvider, (0, telemetry_utils_1.createChildLogger)({ logger: this.subLogger, namespace: "DeltaManager" }), () => this.activeConnection(), (props) => new connectionManager_js_1.ConnectionManager(serviceProvider, () => this.isDirty, this.client, this._canReconnect, (0, telemetry_utils_1.createChildLogger)({ logger: this.subLogger, namespace: "ConnectionManager" }), props));
1287
1245
  // Disable inbound queues as Container is not ready to accept any ops until we are fully loaded!
1288
1246
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1289
1247
  deltaManager.inbound.pause();
@@ -1299,10 +1257,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1299
1257
  deltaManager.on("cancelEstablishingConnection", (reason) => {
1300
1258
  this.connectionStateHandler.cancelEstablishingConnection(reason);
1301
1259
  });
1302
- deltaManager.on("disconnect", (reason) => {
1260
+ deltaManager.on("disconnect", (text, error) => {
1303
1261
  this.noopHeuristic?.notifyDisconnect();
1304
1262
  if (!this.closed) {
1305
- this.connectionStateHandler.receivedDisconnectEvent(reason);
1263
+ this.connectionStateHandler.receivedDisconnectEvent({ text, error });
1306
1264
  }
1307
1265
  });
1308
1266
  deltaManager.on("throttled", (warning) => {
@@ -1315,7 +1273,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1315
1273
  this.emit("warning", warn);
1316
1274
  });
1317
1275
  deltaManager.on("readonly", (readonly) => {
1318
- this.setContextConnectedState(this.connectionState === connectionState_1.ConnectionState.Connected, readonly);
1276
+ this.setContextConnectedState(this.connectionState === connectionState_js_1.ConnectionState.Connected, readonly);
1319
1277
  this.emit("readonly", readonly);
1320
1278
  });
1321
1279
  deltaManager.on("closed", (error) => {
@@ -1344,16 +1302,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1344
1302
  let autoReconnect;
1345
1303
  let checkpointSequenceNumber;
1346
1304
  let opsBehind;
1347
- if (value === connectionState_1.ConnectionState.Disconnected) {
1305
+ if (value === connectionState_js_1.ConnectionState.Disconnected) {
1348
1306
  autoReconnect = this._deltaManager.connectionManager.reconnectMode;
1349
1307
  }
1350
1308
  else {
1351
- if (value === connectionState_1.ConnectionState.Connected) {
1309
+ if (value === connectionState_js_1.ConnectionState.Connected) {
1352
1310
  durationFromDisconnected =
1353
- time - this.connectionTransitionTimes[connectionState_1.ConnectionState.Disconnected];
1311
+ time - this.connectionTransitionTimes[connectionState_js_1.ConnectionState.Disconnected];
1354
1312
  durationFromDisconnected = (0, telemetry_utils_1.formatTick)(durationFromDisconnected);
1355
1313
  }
1356
- else if (value === connectionState_1.ConnectionState.CatchingUp) {
1314
+ else if (value === connectionState_js_1.ConnectionState.CatchingUp) {
1357
1315
  // This info is of most interesting while Catching Up.
1358
1316
  checkpointSequenceNumber = this.deltaManager.lastKnownSeqNumber;
1359
1317
  // Need to check that we have already loaded and fetched the snapshot.
@@ -1365,8 +1323,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1365
1323
  connectionInitiationReason = this.firstConnection ? "InitialConnect" : "AutoReconnect";
1366
1324
  }
1367
1325
  this.mc.logger.sendPerformanceEvent({
1368
- eventName: `ConnectionStateChange_${connectionState_1.ConnectionState[value]}`,
1369
- from: connectionState_1.ConnectionState[oldState],
1326
+ eventName: `ConnectionStateChange_${connectionState_js_1.ConnectionState[value]}`,
1327
+ from: connectionState_js_1.ConnectionState[oldState],
1370
1328
  duration,
1371
1329
  durationFromDisconnected,
1372
1330
  reason: reason?.text,
@@ -1384,7 +1342,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1384
1342
  isDirty: this.isDirty,
1385
1343
  ...this._deltaManager.connectionProps,
1386
1344
  }, reason?.error);
1387
- if (value === connectionState_1.ConnectionState.Connected) {
1345
+ if (value === connectionState_js_1.ConnectionState.Connected) {
1388
1346
  this.firstConnection = false;
1389
1347
  }
1390
1348
  }
@@ -1393,11 +1351,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1393
1351
  // After that, we communicate only transitions to Connected & Disconnected states, skipping all other states.
1394
1352
  // This can be changed in the future, for example we likely should add "CatchingUp" event on Container.
1395
1353
  if (!initialTransition &&
1396
- this.connectionState !== connectionState_1.ConnectionState.Connected &&
1397
- this.connectionState !== connectionState_1.ConnectionState.Disconnected) {
1354
+ this.connectionState !== connectionState_js_1.ConnectionState.Connected &&
1355
+ this.connectionState !== connectionState_js_1.ConnectionState.Disconnected) {
1398
1356
  return;
1399
1357
  }
1400
- const state = this.connectionState === connectionState_1.ConnectionState.Connected;
1358
+ const state = this.connectionState === connectionState_js_1.ConnectionState.Connected;
1401
1359
  // Both protocol and context should not be undefined if we got so far.
1402
1360
  this.setContextConnectedState(state, this.readOnlyInfo.readonly ?? false);
1403
1361
  this.protocolHandler.setConnectionState(state, this.clientId);
@@ -1439,7 +1397,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1439
1397
  return this.submitMessage(protocol_definitions_1.MessageType.Summarize, JSON.stringify(summary), false /* batch */, undefined /* metadata */, undefined /* compression */, referenceSequenceNumber);
1440
1398
  }
1441
1399
  submitMessage(type, contents, batch, metadata, compression, referenceSequenceNumber) {
1442
- if (this.connectionState !== connectionState_1.ConnectionState.Connected) {
1400
+ if (this.connectionState !== connectionState_js_1.ConnectionState.Connected) {
1443
1401
  this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
1444
1402
  return -1;
1445
1403
  }
@@ -1447,14 +1405,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1447
1405
  return this._deltaManager.submit(type, contents, batch, metadata, compression, referenceSequenceNumber);
1448
1406
  }
1449
1407
  processRemoteMessage(message) {
1450
- if (this.offlineLoadEnabled) {
1451
- this.savedOps.push(message);
1452
- }
1453
1408
  const local = this.clientId === message.clientId;
1454
1409
  // Allow the protocol handler to process the message
1455
1410
  const result = this.protocolHandler.processMessage(message, local);
1456
1411
  // Forward messages to the loaded runtime for processing
1457
1412
  this.runtime.process(message, local);
1413
+ this.serializedStateManager.addProcessedOp(message);
1458
1414
  // Inactive (not in quorum or not writers) clients don't take part in the minimum sequence number calculation.
1459
1415
  if (this.activeConnection()) {
1460
1416
  if (this.noopHeuristic === undefined) {
@@ -1464,7 +1420,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1464
1420
  // clients.
1465
1421
  // All existing will continue to use settings they got earlier.
1466
1422
  (0, core_utils_1.assert)(serviceConfiguration !== undefined, 0x2e4 /* "there should be service config for active connection" */);
1467
- this.noopHeuristic = new noopHeuristic_1.NoopHeuristic(serviceConfiguration.noopTimeFrequency, serviceConfiguration.noopCountFrequency);
1423
+ this.noopHeuristic = new noopHeuristic_js_1.NoopHeuristic(serviceConfiguration.noopTimeFrequency, serviceConfiguration.noopCountFrequency);
1468
1424
  this.noopHeuristic.on("wantsNoop", () => {
1469
1425
  // On disconnect we notify the heuristic which should prevent it from wanting a noop.
1470
1426
  // Hitting this assert would imply we lost activeConnection between notifying the heuristic of a processed message and
@@ -1487,7 +1443,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1487
1443
  }
1488
1444
  processSignal(message) {
1489
1445
  // No clientId indicates a system signal message.
1490
- if ((0, protocol_1.protocolHandlerShouldProcessSignal)(message)) {
1446
+ if ((0, protocol_js_1.protocolHandlerShouldProcessSignal)(message)) {
1491
1447
  this.protocolHandler.processSignal(message);
1492
1448
  }
1493
1449
  else {
@@ -1495,33 +1451,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1495
1451
  this.runtime.processSignal(message, local);
1496
1452
  }
1497
1453
  }
1498
- /**
1499
- * Get the most recent snapshot, or a specific version.
1500
- * @param specifiedVersion - The specific version of the snapshot to retrieve
1501
- * @returns The snapshot requested, or the latest snapshot if no version was specified, plus version ID
1502
- */
1503
- async fetchSnapshotTree(specifiedVersion) {
1504
- const version = await this.getVersion(specifiedVersion ?? null);
1505
- if (version === undefined && specifiedVersion !== undefined) {
1506
- // We should have a defined version to load from if specified version requested
1507
- this.mc.logger.sendErrorEvent({
1508
- eventName: "NoVersionFoundWhenSpecified",
1509
- id: specifiedVersion,
1510
- });
1511
- }
1512
- this._loadedFromVersion = version;
1513
- const snapshot = (await this.storageAdapter.getSnapshotTree(version)) ?? undefined;
1514
- if (snapshot === undefined && version !== undefined) {
1515
- this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
1516
- }
1517
- return { snapshot, versionId: version?.id };
1518
- }
1519
- async instantiateRuntime(codeDetails, snapshot, pendingLocalState) {
1454
+ async instantiateRuntime(codeDetails, snapshotTree, pendingLocalState, snapshot) {
1520
1455
  (0, core_utils_1.assert)(this._runtime?.disposed !== false, 0x0dd /* "Existing runtime not disposed" */);
1521
1456
  // The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
1522
1457
  // are set. Global requests will still go directly to the loader
1523
1458
  const maybeLoader = this.scope;
1524
- const loader = new loader_1.RelativeLoader(this, maybeLoader.ILoader);
1459
+ const loader = new loader_js_1.RelativeLoader(this, maybeLoader.ILoader);
1525
1460
  const loadCodeResult = await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.subLogger, { eventName: "CodeLoad" }, async () => this.codeLoader.load(codeDetails));
1526
1461
  this._loadedModule = {
1527
1462
  module: loadCodeResult.module,
@@ -1537,8 +1472,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1537
1472
  }
1538
1473
  const getSpecifiedCodeDetails = () => (this.protocolHandler.quorum.get("code") ??
1539
1474
  this.protocolHandler.quorum.get("code2"));
1540
- const existing = snapshot !== undefined;
1541
- const context = new containerContext_1.ContainerContext(this.options, this.scope, snapshot, this._loadedFromVersion, this._deltaManager, this.storageAdapter, this.protocolHandler.quorum, this.protocolHandler.audience, loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (content, targetClientId) => this.submitSignal(content, targetClientId), (error) => this.dispose(error), (error) => this.close(error), this.updateDirtyContainerState, this.getAbsoluteUrl, () => this.resolvedUrl?.id, () => this.clientId, () => this.attachState, () => this.connected, getSpecifiedCodeDetails, this._deltaManager.clientDetails, existing, this.subLogger, pendingLocalState);
1475
+ const existing = snapshotTree !== undefined;
1476
+ const context = new containerContext_js_1.ContainerContext(this.options, this.scope, snapshotTree, this._loadedFromVersion, this._deltaManager, this.storageAdapter, this.protocolHandler.quorum, this.protocolHandler.audience, loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (content, targetClientId) => this.submitSignal(content, targetClientId), (error) => this.dispose(error), (error) => this.close(error), this.updateDirtyContainerState, this.getAbsoluteUrl, () => this.resolvedUrl?.id, () => this.clientId, () => this.attachState, () => this.connected, getSpecifiedCodeDetails, this._deltaManager.clientDetails, existing, this.subLogger, pendingLocalState, snapshot);
1542
1477
  this._runtime = await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.subLogger, { eventName: "InstantiateRuntime" }, async () => runtimeFactory.instantiateRuntime(context, existing));
1543
1478
  this._lifecycleEvents.emit("runtimeInstantiated");
1544
1479
  this._loadedCodeDetails = codeDetails;