@fluidframework/test-utils 2.71.0 → 2.73.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.
- package/.eslintrc.cjs +1 -1
- package/CHANGELOG.md +8 -13
- package/dist/TestSummaryUtils.js +2 -2
- package/dist/TestSummaryUtils.js.map +1 -1
- package/dist/containerRuntimeFactories.js +2 -2
- package/dist/containerRuntimeFactories.js.map +1 -1
- package/dist/loaderContainerTracker.js.map +1 -1
- package/dist/localCodeLoader.js +2 -2
- package/dist/localCodeLoader.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/testContainerRuntimeFactory.js +4 -4
- package/dist/testContainerRuntimeFactory.js.map +1 -1
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.js.map +1 -1
- package/lib/TestSummaryUtils.js +2 -2
- package/lib/TestSummaryUtils.js.map +1 -1
- package/lib/containerRuntimeFactories.js +3 -3
- package/lib/containerRuntimeFactories.js.map +1 -1
- package/lib/loaderContainerTracker.js.map +1 -1
- package/lib/localCodeLoader.js +2 -2
- package/lib/localCodeLoader.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/testContainerRuntimeFactory.js +5 -5
- package/lib/testContainerRuntimeFactory.js.map +1 -1
- package/lib/testContainerRuntimeFactoryWithDefaultDataStore.js.map +1 -1
- package/package.json +26 -26
- package/src/TestSummaryUtils.ts +3 -3
- package/src/containerRuntimeFactories.ts +6 -6
- package/src/loaderContainerTracker.ts +1 -1
- package/src/localCodeLoader.ts +2 -2
- package/src/packageVersion.ts +1 -1
- package/src/testContainerRuntimeFactory.ts +7 -7
- package/src/testContainerRuntimeFactoryWithDefaultDataStore.ts +2 -2
package/.eslintrc.cjs
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @fluidframework/test-utils
|
|
2
2
|
|
|
3
|
+
## 2.73.0
|
|
4
|
+
|
|
5
|
+
Dependency updates only.
|
|
6
|
+
|
|
7
|
+
## 2.72.0
|
|
8
|
+
|
|
9
|
+
Dependency updates only.
|
|
10
|
+
|
|
3
11
|
## 2.71.0
|
|
4
12
|
|
|
5
13
|
Dependency updates only.
|
|
@@ -128,7 +136,6 @@ Dependency updates only.
|
|
|
128
136
|
Similarly, `IDeltaManager.outbound` contained functionality that could break core runtime features such as generation of batches and chunking. Data loss or corruption could occur when `IDeltaManger.inbound.pause()` or `IDeltaManager.inbound.resume()` were called.
|
|
129
137
|
|
|
130
138
|
#### Alternatives
|
|
131
|
-
|
|
132
139
|
- Alternatives to `IDeltaManager.inbound.on("op", ...)` are `IDeltaManager.on("op", ...)`
|
|
133
140
|
- Alternatives to calling `IDeltaManager.inbound.pause`, `IDeltaManager.outbound.pause` for `IContainer` disconnect use `IContainer.disconnect`.
|
|
134
141
|
- Alternatives to calling `IDeltaManager.inbound.resume`, `IDeltaManager.outbound.resume` for `IContainer` reconnect use `IContainer.connect`.
|
|
@@ -176,7 +183,6 @@ Dependency updates only.
|
|
|
176
183
|
TypeScript types and implementation code.
|
|
177
184
|
|
|
178
185
|
This means that using Fluid Framework packages require the following TypeScript settings in tsconfig.json:
|
|
179
|
-
|
|
180
186
|
- `"moduleResolution": "Node16"` with `"module": "Node16"`
|
|
181
187
|
- `"moduleResolution": "Bundler"` with `"module": "ESNext"`
|
|
182
188
|
|
|
@@ -195,26 +201,21 @@ Dependency updates only.
|
|
|
195
201
|
- container-runtime: New feature: ID compression for DataStores & DDSs ([#19859](https://github.com/microsoft/FluidFramework/issues/19859)) [51f0d3db73](https://github.com/microsoft/FluidFramework/commits/51f0d3db737800e1c30ea5e3952d38ff30ffc7da)
|
|
196
202
|
|
|
197
203
|
### Key changes
|
|
198
|
-
|
|
199
204
|
1. A new API IContainerRuntimeBase.generateDocumentUniqueId() is exposed. This API will opportunistically generate IDs in short format (non-negative numbers). If it can't achieve that, it will return UUID strings. UUIDs generated will have low entropy in groups and will compress well. It can be leveraged anywhere in container where container unique IDs are required. I.e. any place that uses uuid() and stores data in container is likely candidate to start leveraging this API.
|
|
200
205
|
2. Data store internal IDs (IDs that are auto generated by FF system) will opportunistically be generated in shorter form. Data stores created in detached container will always have short IDs, data stores created in attached container will opportunistically be short (by using newly added IContainerRuntimeBase.generateDocumentUniqueId() capability)
|
|
201
206
|
3. Similar DDS names will be opportunistically short (same considerations for detached DDS vs. attached DDS)
|
|
202
207
|
|
|
203
208
|
### Implementation details
|
|
204
|
-
|
|
205
209
|
1. Container level ID Compressor can now be enabled with delay. With such setting, only new IContainerRuntimeBase.generateDocumentUniqueId() is exposed (ID Compressor is not exposed in such case, as leveraging any of its other capabilities requires future container sessions to load ID Compressor on container load, for correctness reasons). Once Container establishes connection and any changes are made in container, newly added API will start generating more compact IDs (in most cases).
|
|
206
210
|
|
|
207
211
|
### Breaking changes
|
|
208
|
-
|
|
209
212
|
1. DDS names can no longer start with "\_" symbol - this is reserved for FF needs. I've validated that's not an issue for AzureClient (it only creates root object by name, everything else is referred by handle). Our main internal partners almost never use named DDSs (I can find only 4 instances in Loop).
|
|
210
213
|
|
|
211
214
|
### Backward compatibility considerations
|
|
212
|
-
|
|
213
215
|
1. Data store internal IDs could collide with earlier used names data stores. Earlier versions of FF framework (before DataStore aliasing feature was added) allowed customers to supply IDs for data stores. And thus, files created with earlier versions of framework could have data store IDs that will be similar to names FF will use for newly created data stores ("A", ... "Z", "a"..."z", "AA", etc.). While such collision is possible, it's very unlikely (almost impossible) if user-provided names were at least 4-5 characters long.
|
|
214
216
|
2. If application runs to these problems, or wants to reduce risks, consider disabling ID compressor via IContainerRuntimeOptions.enableRuntimeIdCompressor = "off".
|
|
215
217
|
|
|
216
218
|
### Minor changes
|
|
217
|
-
|
|
218
219
|
1. IContainerRuntime.createDetachedRootDataStore() is removed. Please use IContainerRuntime.createDetachedDataStore and IDataStore.trySetAlias() instead
|
|
219
220
|
2. IContainerRuntimeOptions.enableRuntimeIdCompressor has been changes from boolean to tri-state.
|
|
220
221
|
|
|
@@ -229,7 +230,6 @@ Dependency updates only.
|
|
|
229
230
|
- Updated server dependencies ([#19122](https://github.com/microsoft/FluidFramework/issues/19122)) [25366b4229](https://github.com/microsoft/FluidFramework/commits/25366b422918cb43685c5f328b50450749592902)
|
|
230
231
|
|
|
231
232
|
The following Fluid server dependencies have been updated to the latest version, 3.0.0. [See the full changelog.](https://github.com/microsoft/FluidFramework/releases/tag/server_v3.0.0)
|
|
232
|
-
|
|
233
233
|
- @fluidframework/gitresources
|
|
234
234
|
- @fluidframework/server-kafka-orderer
|
|
235
235
|
- @fluidframework/server-lambdas
|
|
@@ -263,7 +263,6 @@ Dependency updates only.
|
|
|
263
263
|
- data-object-base: Removed IFluidRouter from DataObject interfaces and classes [9a451d4946](https://github.com/microsoft/FluidFramework/commits/9a451d4946b5c51a52e4d1ab5bf51e7b285b0d74)
|
|
264
264
|
|
|
265
265
|
The `IFluidRouter` property has been removed from a number of DataObject related classes:
|
|
266
|
-
|
|
267
266
|
- `PureDataObject`
|
|
268
267
|
- `LazyLoadedDataObject`
|
|
269
268
|
- `TestFluidObject`
|
|
@@ -297,7 +296,6 @@ Dependency updates only.
|
|
|
297
296
|
- Dependencies on @fluidframework/protocol-definitions package updated to 3.0.0 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
298
297
|
|
|
299
298
|
This included the following changes from the protocol-definitions release:
|
|
300
|
-
|
|
301
299
|
- Updating signal interfaces for some planned improvements. The intention is split the interface between signals
|
|
302
300
|
submitted by clients to the server and the resulting signals sent from the server to clients.
|
|
303
301
|
- A new optional type member is available on the ISignalMessage interface and a new ISentSignalMessage interface has
|
|
@@ -308,7 +306,6 @@ Dependency updates only.
|
|
|
308
306
|
- Server upgrade: dependencies on Fluid server packages updated to 2.0.1 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
309
307
|
|
|
310
308
|
Dependencies on the following Fluid server package have been updated to version 2.0.1:
|
|
311
|
-
|
|
312
309
|
- @fluidframework/gitresources: 2.0.1
|
|
313
310
|
- @fluidframework/server-kafka-orderer: 2.0.1
|
|
314
311
|
- @fluidframework/server-lambdas: 2.0.1
|
|
@@ -333,7 +330,6 @@ Dependency updates only.
|
|
|
333
330
|
- test-utils: provideEntryPoint is required [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
334
331
|
|
|
335
332
|
The optional `provideEntryPoint` method has become required on a number of constructors. A value will need to be provided to the following classes:
|
|
336
|
-
|
|
337
333
|
- `BaseContainerRuntimeFactory`
|
|
338
334
|
- `RuntimeFactory`
|
|
339
335
|
- `ContainerRuntime` (constructor and `loadRuntime`)
|
|
@@ -373,7 +369,6 @@ Dependency updates only.
|
|
|
373
369
|
- Request APIs deprecated from many places [8abce8cdb4](https://github.com/microsoft/FluidFramework/commits/8abce8cdb4e2832fb6405fb44e393bef03d5648a)
|
|
374
370
|
|
|
375
371
|
The `request` API (associated with the `IFluidRouter` interface) has been deprecated on a number of classes and interfaces. The following are impacted:
|
|
376
|
-
|
|
377
372
|
- `IRuntime` and `ContainerRuntime`
|
|
378
373
|
- `IFluidDataStoreRuntime` and `FluidDataStoreRuntime`
|
|
379
374
|
- `IFluidDataStoreChannel`
|
package/dist/TestSummaryUtils.js
CHANGED
|
@@ -9,7 +9,7 @@ const internal_1 = require("@fluidframework/container-definitions/internal");
|
|
|
9
9
|
const internal_2 = require("@fluidframework/core-utils/internal");
|
|
10
10
|
const internal_3 = require("@fluidframework/driver-definitions/internal");
|
|
11
11
|
const TestConfigs_js_1 = require("./TestConfigs.js");
|
|
12
|
-
// eslint-disable-next-line import/no-deprecated
|
|
12
|
+
// eslint-disable-next-line import-x/no-deprecated
|
|
13
13
|
const containerRuntimeFactories_js_1 = require("./containerRuntimeFactories.js");
|
|
14
14
|
const containerUtils_js_1 = require("./containerUtils.js");
|
|
15
15
|
const testContainerRuntimeFactoryWithDefaultDataStore_js_1 = require("./testContainerRuntimeFactoryWithDefaultDataStore.js");
|
|
@@ -84,7 +84,7 @@ const defaultSummaryOptions = {
|
|
|
84
84
|
*/
|
|
85
85
|
async function createSummarizerFromFactory(provider, container, dataStoreFactory, summaryVersion, containerRuntimeFactoryType, registryEntries, logger, configProvider = (0, TestConfigs_js_1.createTestConfigProvider)()) {
|
|
86
86
|
const runtimeFactory = (0, testContainerRuntimeFactoryWithDefaultDataStore_js_1.createContainerRuntimeFactoryWithDefaultDataStore)(
|
|
87
|
-
// eslint-disable-next-line import/no-deprecated
|
|
87
|
+
// eslint-disable-next-line import-x/no-deprecated
|
|
88
88
|
containerRuntimeFactoryType ?? containerRuntimeFactories_js_1.ContainerRuntimeFactoryWithDefaultDataStore, {
|
|
89
89
|
defaultFactory: dataStoreFactory,
|
|
90
90
|
registryEntries: registryEntries ?? [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestSummaryUtils.js","sourceRoot":"","sources":["../src/TestSummaryUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tIContainer,\n\tIHostLoader,\n\tLoaderHeader,\n} from \"@fluidframework/container-definitions/internal\";\nimport {\n\t// eslint-disable-next-line import/no-deprecated\n\tIOnDemandSummarizeOptions,\n\tISummarizer,\n\tISummaryRuntimeOptions,\n} from \"@fluidframework/container-runtime/internal\";\nimport {\n\tIConfigProviderBase,\n\tIRequest,\n\tIResponse,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport { DriverHeader } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions/internal\";\n\nimport { createTestConfigProvider } from \"./TestConfigs.js\";\n// eslint-disable-next-line import/no-deprecated\nimport { ContainerRuntimeFactoryWithDefaultDataStore } from \"./containerRuntimeFactories.js\";\nimport { waitForContainerConnection } from \"./containerUtils.js\";\nimport {\n\ttype ContainerRuntimeFactoryWithDefaultDataStoreConstructor,\n\tcreateContainerRuntimeFactoryWithDefaultDataStore,\n} from \"./testContainerRuntimeFactoryWithDefaultDataStore.js\";\nimport { ITestContainerConfig, ITestObjectProvider } from \"./testObjectProvider.js\";\nimport { timeoutAwait } from \"./timeoutUtils.js\";\n\nconst summarizerClientType = \"summarizer\";\n\n/**\n * This function should ONLY be used for back compat purposes\n * LTS versions of the Loader/Container will not have the \"getEntryPoint\" method, so we need to fallback to \"request\"\n * This function can be removed once LTS version of Loader moves to 2.0.0-internal.7.0.0\n * @internal\n */\nasync function getSummarizerBackCompat(container: IContainer): Promise<ISummarizer> {\n\tif (container.getEntryPoint !== undefined) {\n\t\tconst entryPoint = await container.getEntryPoint();\n\t\t// Note: We need to also check if the result of `getEntryPoint()` is defined. This is because when running\n\t\t// cross-client compat testing scenarios, if we create with 1.X container and load with 2.X then the\n\t\t// function container.getEntryPoint will be defined for the 2.X container. However, it will not return undefined\n\t\t// since the container's runtime will be on version 1.X, which does not have an entry point defined.\n\t\tif (entryPoint !== undefined) {\n\t\t\treturn entryPoint as ISummarizer;\n\t\t}\n\t}\n\tconst response: IResponse = await (container as any).request({ url: \"_summarizer\" });\n\tassert(response.status === 200, \"requesting '/' should return default data object\");\n\treturn response.value as ISummarizer;\n}\n\n/** @internal */\nexport async function createSummarizerCore(\n\tcontainer: IContainer,\n\tloader: IHostLoader,\n\tsummaryVersion?: string,\n) {\n\tconst absoluteUrl = await container.getAbsoluteUrl(\"\");\n\tif (absoluteUrl === undefined) {\n\t\tthrow new Error(\"URL could not be resolved\");\n\t}\n\n\tconst request: IRequest = {\n\t\theaders: {\n\t\t\t[LoaderHeader.cache]: false,\n\t\t\t[LoaderHeader.clientDetails]: {\n\t\t\t\tcapabilities: { interactive: false },\n\t\t\t\ttype: summarizerClientType,\n\t\t\t},\n\t\t\t[DriverHeader.summarizingClient]: true,\n\t\t\t[LoaderHeader.version]: summaryVersion,\n\t\t},\n\t\turl: absoluteUrl,\n\t};\n\tconst summarizerContainer = await loader.resolve(request);\n\tawait waitForContainerConnection(summarizerContainer);\n\n\t// Old loaders will not have getEntryPoint API on the container. So, use getSummarizerBackCompat which\n\t// will use request pattern to get the summarizer in these old loaders.\n\tconst fluidObject = await getSummarizerBackCompat(summarizerContainer);\n\tif (fluidObject.ISummarizer === undefined) {\n\t\tthrow new Error(\"Fluid object does not implement ISummarizer\");\n\t}\n\n\treturn {\n\t\tcontainer: summarizerContainer,\n\t\tsummarizer: fluidObject.ISummarizer,\n\t};\n}\n\nconst defaultSummaryOptions: ISummaryRuntimeOptions = {\n\tsummaryConfigOverrides: {\n\t\tstate: \"disableHeuristics\",\n\t\tmaxAckWaitTime: 20000, // Some of the AFR tests take a long time to ack.\n\t\tmaxOpsSinceLastSummary: 7000,\n\t\tinitialSummarizerDelayMs: 0,\n\t},\n};\n\n/**\n * Creates a summarizer client from the given container and data store factory, and returns the summarizer client's\n * IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n * @internal\n */\nexport async function createSummarizerFromFactory(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tdataStoreFactory: IFluidDataStoreFactory,\n\tsummaryVersion?: string,\n\tcontainerRuntimeFactoryType?: ContainerRuntimeFactoryWithDefaultDataStoreConstructor,\n\tregistryEntries?: NamedFluidDataStoreRegistryEntries,\n\tlogger?: ITelemetryBaseLogger,\n\tconfigProvider: IConfigProviderBase = createTestConfigProvider(),\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst runtimeFactory = createContainerRuntimeFactoryWithDefaultDataStore(\n\t\t// eslint-disable-next-line import/no-deprecated\n\t\tcontainerRuntimeFactoryType ?? ContainerRuntimeFactoryWithDefaultDataStore,\n\t\t{\n\t\t\tdefaultFactory: dataStoreFactory,\n\t\t\tregistryEntries: registryEntries ?? [\n\t\t\t\t[dataStoreFactory.type, Promise.resolve(dataStoreFactory)],\n\t\t\t],\n\t\t\truntimeOptions: { summaryOptions: defaultSummaryOptions },\n\t\t},\n\t);\n\n\tconst loader = provider.createLoader([[provider.defaultCodeDetails, runtimeFactory]], {\n\t\tconfigProvider,\n\t\tlogger,\n\t});\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Creates a summarizer client from the given container and returns the summarizer client's IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n *\n * Can pass in a test config provider to enable/disable features.\n * @internal\n */\nexport async function createSummarizer(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tconfig?: ITestContainerConfig,\n\tsummaryVersion?: string,\n\tlogger?: ITelemetryBaseLogger,\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst testContainerConfig: ITestContainerConfig = {\n\t\t...config,\n\t\truntimeOptions: {\n\t\t\t...config?.runtimeOptions,\n\t\t\tsummaryOptions: config?.runtimeOptions?.summaryOptions ?? defaultSummaryOptions,\n\t\t},\n\t\tloaderProps: {\n\t\t\t...config?.loaderProps,\n\t\t\tconfigProvider: config?.loaderProps?.configProvider ?? createTestConfigProvider(),\n\t\t\tlogger,\n\t\t},\n\t};\n\tconst loader = provider.makeTestLoader(testContainerConfig);\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Summarizes on demand and returns the summary tree, the version number and the reference sequence number of the\n * submitted summary.\n *\n * @param summarizer - The ISummarizer to use to summarize on demand\n * @param inputs - Either the reason string or the full IOnDemandSummarizeOptions.\n * Defaults to the reason \"end-to-end test\".\n * @internal\n */\nexport async function summarizeNow(\n\tsummarizer: ISummarizer,\n\tinputs: string | IOnDemandSummarizeOptions = \"end-to-end test\",\n): Promise<SummaryInfo> {\n\tconst options: IOnDemandSummarizeOptions =\n\t\ttypeof inputs === \"string\" ? { reason: inputs } : inputs;\n\tconst result = summarizer.summarizeOnDemand(options);\n\n\tconst submitResult = await timeoutAwait(result.summarySubmitted, {\n\t\terrorMsg: \"Promise timed out: summarySubmitted\",\n\t});\n\tif (!submitResult.success) {\n\t\tthrow submitResult.error;\n\t}\n\tassert(\n\t\tsubmitResult.data.stage === \"submit\",\n\t\t\"on-demand summary submitted data stage should be submit\",\n\t);\n\tassert(submitResult.data.summaryTree !== undefined, \"summary tree should exist\");\n\n\tconst broadcastResult = await timeoutAwait(result.summaryOpBroadcasted, {\n\t\terrorMsg: \"Promise timed out: summaryOpBroadcasted\",\n\t});\n\tif (!broadcastResult.success) {\n\t\tthrow broadcastResult.error;\n\t}\n\n\tconst ackNackResult = await timeoutAwait(result.receivedSummaryAckOrNack, {\n\t\terrorMsg: \"Promise timed out: receivedSummaryAckOrNack\",\n\t});\n\tif (!ackNackResult.success) {\n\t\tthrow ackNackResult.error;\n\t}\n\n\tawait new Promise((resolve) => process.nextTick(resolve));\n\n\treturn {\n\t\tsummaryTree: submitResult.data.summaryTree,\n\t\tsummaryVersion: ackNackResult.data.summaryAckOp.contents.handle,\n\t\tsummaryRefSeq: submitResult.data.referenceSequenceNumber,\n\t};\n}\n\n/**\n * Summary information containing the summary tree, summary version, and summary sequence number.\n * @internal\n */\nexport interface SummaryInfo {\n\t/**\n\t * The summary tree generated\n\t */\n\tsummaryTree: ISummaryTree;\n\t/**\n\t * Handle of the completed summary\n\t */\n\tsummaryVersion: string;\n\t/**\n\t * Reference sequence number of the current summary generation\n\t */\n\tsummaryRefSeq: number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TestSummaryUtils.js","sourceRoot":"","sources":["../src/TestSummaryUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tIContainer,\n\tIHostLoader,\n\tLoaderHeader,\n} from \"@fluidframework/container-definitions/internal\";\nimport {\n\t// eslint-disable-next-line import-x/no-deprecated\n\tIOnDemandSummarizeOptions,\n\tISummarizer,\n\tISummaryRuntimeOptions,\n} from \"@fluidframework/container-runtime/internal\";\nimport {\n\tIConfigProviderBase,\n\tIRequest,\n\tIResponse,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport { DriverHeader } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions/internal\";\n\nimport { createTestConfigProvider } from \"./TestConfigs.js\";\n// eslint-disable-next-line import-x/no-deprecated\nimport { ContainerRuntimeFactoryWithDefaultDataStore } from \"./containerRuntimeFactories.js\";\nimport { waitForContainerConnection } from \"./containerUtils.js\";\nimport {\n\ttype ContainerRuntimeFactoryWithDefaultDataStoreConstructor,\n\tcreateContainerRuntimeFactoryWithDefaultDataStore,\n} from \"./testContainerRuntimeFactoryWithDefaultDataStore.js\";\nimport { ITestContainerConfig, ITestObjectProvider } from \"./testObjectProvider.js\";\nimport { timeoutAwait } from \"./timeoutUtils.js\";\n\nconst summarizerClientType = \"summarizer\";\n\n/**\n * This function should ONLY be used for back compat purposes\n * LTS versions of the Loader/Container will not have the \"getEntryPoint\" method, so we need to fallback to \"request\"\n * This function can be removed once LTS version of Loader moves to 2.0.0-internal.7.0.0\n * @internal\n */\nasync function getSummarizerBackCompat(container: IContainer): Promise<ISummarizer> {\n\tif (container.getEntryPoint !== undefined) {\n\t\tconst entryPoint = await container.getEntryPoint();\n\t\t// Note: We need to also check if the result of `getEntryPoint()` is defined. This is because when running\n\t\t// cross-client compat testing scenarios, if we create with 1.X container and load with 2.X then the\n\t\t// function container.getEntryPoint will be defined for the 2.X container. However, it will not return undefined\n\t\t// since the container's runtime will be on version 1.X, which does not have an entry point defined.\n\t\tif (entryPoint !== undefined) {\n\t\t\treturn entryPoint as ISummarizer;\n\t\t}\n\t}\n\tconst response: IResponse = await (container as any).request({ url: \"_summarizer\" });\n\tassert(response.status === 200, \"requesting '/' should return default data object\");\n\treturn response.value as ISummarizer;\n}\n\n/** @internal */\nexport async function createSummarizerCore(\n\tcontainer: IContainer,\n\tloader: IHostLoader,\n\tsummaryVersion?: string,\n) {\n\tconst absoluteUrl = await container.getAbsoluteUrl(\"\");\n\tif (absoluteUrl === undefined) {\n\t\tthrow new Error(\"URL could not be resolved\");\n\t}\n\n\tconst request: IRequest = {\n\t\theaders: {\n\t\t\t[LoaderHeader.cache]: false,\n\t\t\t[LoaderHeader.clientDetails]: {\n\t\t\t\tcapabilities: { interactive: false },\n\t\t\t\ttype: summarizerClientType,\n\t\t\t},\n\t\t\t[DriverHeader.summarizingClient]: true,\n\t\t\t[LoaderHeader.version]: summaryVersion,\n\t\t},\n\t\turl: absoluteUrl,\n\t};\n\tconst summarizerContainer = await loader.resolve(request);\n\tawait waitForContainerConnection(summarizerContainer);\n\n\t// Old loaders will not have getEntryPoint API on the container. So, use getSummarizerBackCompat which\n\t// will use request pattern to get the summarizer in these old loaders.\n\tconst fluidObject = await getSummarizerBackCompat(summarizerContainer);\n\tif (fluidObject.ISummarizer === undefined) {\n\t\tthrow new Error(\"Fluid object does not implement ISummarizer\");\n\t}\n\n\treturn {\n\t\tcontainer: summarizerContainer,\n\t\tsummarizer: fluidObject.ISummarizer,\n\t};\n}\n\nconst defaultSummaryOptions: ISummaryRuntimeOptions = {\n\tsummaryConfigOverrides: {\n\t\tstate: \"disableHeuristics\",\n\t\tmaxAckWaitTime: 20000, // Some of the AFR tests take a long time to ack.\n\t\tmaxOpsSinceLastSummary: 7000,\n\t\tinitialSummarizerDelayMs: 0,\n\t},\n};\n\n/**\n * Creates a summarizer client from the given container and data store factory, and returns the summarizer client's\n * IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n * @internal\n */\nexport async function createSummarizerFromFactory(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tdataStoreFactory: IFluidDataStoreFactory,\n\tsummaryVersion?: string,\n\tcontainerRuntimeFactoryType?: ContainerRuntimeFactoryWithDefaultDataStoreConstructor,\n\tregistryEntries?: NamedFluidDataStoreRegistryEntries,\n\tlogger?: ITelemetryBaseLogger,\n\tconfigProvider: IConfigProviderBase = createTestConfigProvider(),\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst runtimeFactory = createContainerRuntimeFactoryWithDefaultDataStore(\n\t\t// eslint-disable-next-line import-x/no-deprecated\n\t\tcontainerRuntimeFactoryType ?? ContainerRuntimeFactoryWithDefaultDataStore,\n\t\t{\n\t\t\tdefaultFactory: dataStoreFactory,\n\t\t\tregistryEntries: registryEntries ?? [\n\t\t\t\t[dataStoreFactory.type, Promise.resolve(dataStoreFactory)],\n\t\t\t],\n\t\t\truntimeOptions: { summaryOptions: defaultSummaryOptions },\n\t\t},\n\t);\n\n\tconst loader = provider.createLoader([[provider.defaultCodeDetails, runtimeFactory]], {\n\t\tconfigProvider,\n\t\tlogger,\n\t});\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Creates a summarizer client from the given container and returns the summarizer client's IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n *\n * Can pass in a test config provider to enable/disable features.\n * @internal\n */\nexport async function createSummarizer(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tconfig?: ITestContainerConfig,\n\tsummaryVersion?: string,\n\tlogger?: ITelemetryBaseLogger,\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst testContainerConfig: ITestContainerConfig = {\n\t\t...config,\n\t\truntimeOptions: {\n\t\t\t...config?.runtimeOptions,\n\t\t\tsummaryOptions: config?.runtimeOptions?.summaryOptions ?? defaultSummaryOptions,\n\t\t},\n\t\tloaderProps: {\n\t\t\t...config?.loaderProps,\n\t\t\tconfigProvider: config?.loaderProps?.configProvider ?? createTestConfigProvider(),\n\t\t\tlogger,\n\t\t},\n\t};\n\tconst loader = provider.makeTestLoader(testContainerConfig);\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Summarizes on demand and returns the summary tree, the version number and the reference sequence number of the\n * submitted summary.\n *\n * @param summarizer - The ISummarizer to use to summarize on demand\n * @param inputs - Either the reason string or the full IOnDemandSummarizeOptions.\n * Defaults to the reason \"end-to-end test\".\n * @internal\n */\nexport async function summarizeNow(\n\tsummarizer: ISummarizer,\n\tinputs: string | IOnDemandSummarizeOptions = \"end-to-end test\",\n): Promise<SummaryInfo> {\n\tconst options: IOnDemandSummarizeOptions =\n\t\ttypeof inputs === \"string\" ? { reason: inputs } : inputs;\n\tconst result = summarizer.summarizeOnDemand(options);\n\n\tconst submitResult = await timeoutAwait(result.summarySubmitted, {\n\t\terrorMsg: \"Promise timed out: summarySubmitted\",\n\t});\n\tif (!submitResult.success) {\n\t\tthrow submitResult.error;\n\t}\n\tassert(\n\t\tsubmitResult.data.stage === \"submit\",\n\t\t\"on-demand summary submitted data stage should be submit\",\n\t);\n\tassert(submitResult.data.summaryTree !== undefined, \"summary tree should exist\");\n\n\tconst broadcastResult = await timeoutAwait(result.summaryOpBroadcasted, {\n\t\terrorMsg: \"Promise timed out: summaryOpBroadcasted\",\n\t});\n\tif (!broadcastResult.success) {\n\t\tthrow broadcastResult.error;\n\t}\n\n\tconst ackNackResult = await timeoutAwait(result.receivedSummaryAckOrNack, {\n\t\terrorMsg: \"Promise timed out: receivedSummaryAckOrNack\",\n\t});\n\tif (!ackNackResult.success) {\n\t\tthrow ackNackResult.error;\n\t}\n\n\tawait new Promise((resolve) => process.nextTick(resolve));\n\n\treturn {\n\t\tsummaryTree: submitResult.data.summaryTree,\n\t\tsummaryVersion: ackNackResult.data.summaryAckOp.contents.handle,\n\t\tsummaryRefSeq: submitResult.data.referenceSequenceNumber,\n\t};\n}\n\n/**\n * Summary information containing the summary tree, summary version, and summary sequence number.\n * @internal\n */\nexport interface SummaryInfo {\n\t/**\n\t * The summary tree generated\n\t */\n\tsummaryTree: ISummaryTree;\n\t/**\n\t * Handle of the completed summary\n\t */\n\tsummaryVersion: string;\n\t/**\n\t * Reference sequence number of the current summary generation\n\t */\n\tsummaryRefSeq: number;\n}\n"]}
|
|
@@ -37,7 +37,7 @@ class ContainerRuntimeFactoryWithDefaultDataStore extends internal_3.RuntimeFact
|
|
|
37
37
|
const parser = internal_3.RequestParser.create(request);
|
|
38
38
|
if (parser.pathParts.length === 0) {
|
|
39
39
|
// This cast is safe as loadContainerRuntime is called in the base class
|
|
40
|
-
// eslint-disable-next-line import/no-deprecated
|
|
40
|
+
// eslint-disable-next-line import-x/no-deprecated
|
|
41
41
|
return runtime.resolveHandle({
|
|
42
42
|
url: `/${defaultDataStoreId}${parser.query}`,
|
|
43
43
|
headers: request.headers,
|
|
@@ -67,7 +67,7 @@ class ContainerRuntimeFactoryWithDefaultDataStore extends internal_3.RuntimeFact
|
|
|
67
67
|
runtimeOptions: this.runtimeOptions,
|
|
68
68
|
registryEntries: this.registryEntries,
|
|
69
69
|
containerScope: context.scope,
|
|
70
|
-
// eslint-disable-next-line import/no-deprecated
|
|
70
|
+
// eslint-disable-next-line import-x/no-deprecated
|
|
71
71
|
requestHandler: (0, internal_2.buildRuntimeRequestHandler)(...this.requestHandlers),
|
|
72
72
|
provideEntryPoint: this.provideEntryPoint,
|
|
73
73
|
minVersionForCollab: this.minVersionForCollab,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerRuntimeFactories.js","sourceRoot":"","sources":["../src/containerRuntimeFactories.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAMH,yEAIoD;AAOpD,uEAKkD;AAQlD,qEAA6F;AAE7F,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAErC,KAAK,UAAU,qBAAqB,CAAC,OAA0B;IAC9D,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,6BAA6B,CAAC,SAAS,CAAC,CAAC;IAC1E,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,EAAE,CAAC;AACzB,CAAC;AAiCD;;;;;;;GAOG;AACH,MAAa,2CACZ,SAAQ,+BAAoB;IAK5B;;OAEG;IACH,IAAW,uBAAuB;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IA6BD,YAAmB,KAAuD;QACzE,KAAK,EAAE,CAAC;QAER,MAAM,gBAAgB,GAAG,KAAK,EAC7B,OAAiB,EACjB,OAA0B,EACO,EAAE;YACnC,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,wEAAwE;gBACxE,
|
|
1
|
+
{"version":3,"file":"containerRuntimeFactories.js","sourceRoot":"","sources":["../src/containerRuntimeFactories.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tIContainerContext,\n\tIRuntime,\n} from \"@fluidframework/container-definitions/internal\";\nimport {\n\tFluidDataStoreRegistry,\n\tloadContainerRuntime,\n\ttype IContainerRuntimeOptions,\n} from \"@fluidframework/container-runtime/internal\";\nimport type {\n\tIContainerRuntime,\n\t// eslint-disable-next-line import-x/no-deprecated\n\tIContainerRuntimeWithResolveHandle_Deprecated,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { FluidObject, IRequest, IResponse } from \"@fluidframework/core-interfaces\";\nimport {\n\t// eslint-disable-next-line import-x/no-deprecated\n\ttype RuntimeRequestHandler,\n\t// eslint-disable-next-line import-x/no-deprecated\n\tbuildRuntimeRequestHandler,\n} from \"@fluidframework/request-handler/internal\";\nimport type {\n\tIFluidDataStoreFactory,\n\tIFluidDataStoreRegistry,\n\tIProvideFluidDataStoreRegistry,\n\tMinimumVersionForCollab,\n\tNamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport { RequestParser, RuntimeFactoryHelper } from \"@fluidframework/runtime-utils/internal\";\n\nconst defaultDataStoreId = \"default\";\n\nasync function getDefaultFluidObject(runtime: IContainerRuntime): Promise<FluidObject> {\n\tconst entryPoint = await runtime.getAliasedDataStoreEntryPoint(\"default\");\n\tif (entryPoint === undefined) {\n\t\tthrow new Error(\"default dataStore must exist\");\n\t}\n\treturn entryPoint.get();\n}\n\n/**\n * {@link ContainerRuntimeFactoryWithDefaultDataStore} construction properties.\n *\n * @deprecated See notice on {@link ContainerRuntimeFactoryWithDefaultDataStore}.\n */\nexport interface ContainerRuntimeFactoryWithDefaultDataStoreProps {\n\treadonly defaultFactory: IFluidDataStoreFactory;\n\n\t/**\n\t * The data store registry for containers produced.\n\t */\n\treadonly registryEntries: NamedFluidDataStoreRegistryEntries;\n\n\t/**\n\t * The runtime options passed to the IContainerRuntime when instantiating it\n\t */\n\treadonly runtimeOptions?: IContainerRuntimeOptions;\n\n\t/**\n\t * Function that will initialize the entryPoint of the IContainerRuntime instances\n\t * created with this factory\n\t */\n\treadonly provideEntryPoint?: (runtime: IContainerRuntime) => Promise<FluidObject>;\n\n\t/**\n\t * Minimum version of the FF runtime that is required to collaborate on new documents.\n\t * See {@link @fluidframework/container-runtime#LoadContainerRuntimeParams.minVersionForCollab} for more details.\n\t */\n\treadonly minVersionForCollab?: MinimumVersionForCollab;\n}\n\n/**\n * A ContainerRuntimeFactory that initializes Containers with a single default data store, which can be requested from\n * the container with an empty URL.\n *\n * @deprecated\n * Do not reference this type directly. It will be removed in the future.\n * E.g. use {@link IRuntimeFactory} instead.\n */\nexport class ContainerRuntimeFactoryWithDefaultDataStore\n\textends RuntimeFactoryHelper\n\timplements IProvideFluidDataStoreRegistry\n{\n\tpublic static readonly defaultDataStoreId = defaultDataStoreId;\n\n\t/**\n\t * {@inheritDoc @fluidframework/runtime-definitions#IProvideFluidDataStoreRegistry.IFluidDataStoreRegistry}\n\t */\n\tpublic get IFluidDataStoreRegistry(): IFluidDataStoreRegistry {\n\t\treturn this.registry;\n\t}\n\n\tprotected readonly defaultFactory: IFluidDataStoreFactory;\n\n\tprivate readonly registry: IFluidDataStoreRegistry;\n\n\t/**\n\t * {@inheritDoc ContainerRuntimeFactoryWithDefaultDataStoreProps.registryEntries}\n\t */\n\tprivate readonly registryEntries: NamedFluidDataStoreRegistryEntries;\n\n\t/**\n\t * {@inheritDoc ContainerRuntimeFactoryWithDefaultDataStoreProps.runtimeOptions}\n\t */\n\tprivate readonly runtimeOptions?: IContainerRuntimeOptions;\n\n\t// eslint-disable-next-line import-x/no-deprecated\n\tprivate readonly requestHandlers: readonly RuntimeRequestHandler[];\n\n\t/**\n\t * {@inheritDoc ContainerRuntimeFactoryWithDefaultDataStoreProps.provideEntryPoint}\n\t */\n\tprivate readonly provideEntryPoint: (runtime: IContainerRuntime) => Promise<FluidObject>;\n\n\t/**\n\t * {@inheritDoc ContainerRuntimeFactoryWithDefaultDataStoreProps.minVersionForCollab}\n\t */\n\tprivate readonly minVersionForCollab: MinimumVersionForCollab | undefined;\n\n\tpublic constructor(props: ContainerRuntimeFactoryWithDefaultDataStoreProps) {\n\t\tsuper();\n\n\t\tconst getDefaultObject = async (\n\t\t\trequest: IRequest,\n\t\t\truntime: IContainerRuntime,\n\t\t): Promise<IResponse | undefined> => {\n\t\t\tconst parser = RequestParser.create(request);\n\t\t\tif (parser.pathParts.length === 0) {\n\t\t\t\t// This cast is safe as loadContainerRuntime is called in the base class\n\t\t\t\t// eslint-disable-next-line import-x/no-deprecated\n\t\t\t\treturn (runtime as IContainerRuntimeWithResolveHandle_Deprecated).resolveHandle({\n\t\t\t\t\turl: `/${defaultDataStoreId}${parser.query}`,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn undefined; // continue search\n\t\t};\n\n\t\tthis.defaultFactory = props.defaultFactory;\n\t\tthis.registryEntries = props.registryEntries;\n\t\tthis.runtimeOptions = props.runtimeOptions;\n\t\tthis.provideEntryPoint = props.provideEntryPoint ?? getDefaultFluidObject;\n\t\tthis.requestHandlers = [getDefaultObject];\n\t\tthis.registry = new FluidDataStoreRegistry(this.registryEntries);\n\t\tthis.minVersionForCollab = props.minVersionForCollab;\n\t}\n\n\tpublic async instantiateFirstTime(runtime: IContainerRuntime): Promise<void> {\n\t\tawait this.containerInitializingFirstTime(runtime);\n\t\tawait this.containerHasInitialized(runtime);\n\t}\n\n\tpublic async instantiateFromExisting(runtime: IContainerRuntime): Promise<void> {\n\t\tawait this.containerHasInitialized(runtime);\n\t}\n\n\tpublic async preInitialize(\n\t\tcontext: IContainerContext,\n\t\texisting: boolean,\n\t): Promise<IContainerRuntime & IRuntime> {\n\t\treturn loadContainerRuntime({\n\t\t\tcontext,\n\t\t\texisting,\n\t\t\truntimeOptions: this.runtimeOptions,\n\t\t\tregistryEntries: this.registryEntries,\n\t\t\tcontainerScope: context.scope,\n\t\t\t// eslint-disable-next-line import-x/no-deprecated\n\t\t\trequestHandler: buildRuntimeRequestHandler(...this.requestHandlers),\n\t\t\tprovideEntryPoint: this.provideEntryPoint,\n\t\t\tminVersionForCollab: this.minVersionForCollab,\n\t\t});\n\t}\n\n\t/**\n\t * Subclasses may override containerInitializingFirstTime to perform any setup steps at the time the container\n\t * is created. This likely includes creating any initial data stores that are expected to be there at the outset.\n\t * @param runtime - The container runtime for the container being initialized.\n\t * @virtual\n\t */\n\tprotected async containerInitializingFirstTime(runtime: IContainerRuntime): Promise<void> {\n\t\tconst dataStore = await runtime.createDataStore(this.defaultFactory.type);\n\t\tawait dataStore.trySetAlias(defaultDataStoreId);\n\t}\n\n\t/**\n\t * Subclasses may override containerHasInitialized to perform any steps after the container has initialized.\n\t * This likely includes loading any data stores that are expected to be there at the outset.\n\t * @param runtime - The container runtime for the container being initialized.\n\t * @virtual\n\t */\n\tprotected async containerHasInitialized(runtime: IContainerRuntime): Promise<void> {}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loaderContainerTracker.js","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tIDeltaQueue,\n\tIContainer,\n\ttype IHostLoader,\n} from \"@fluidframework/container-definitions/internal\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport {\n\tIContainerCreateProps,\n\tIContainerLoadProps,\n\t// eslint-disable-next-line import/no-internal-modules\n} from \"@fluidframework/container-loader/internal/test/container\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIDocumentMessage,\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { canBeCoalescedByService } from \"@fluidframework/driver-utils/internal\";\n\nimport { toIDeltaManagerFull, waitForContainerConnection } from \"./containerUtils.js\";\nimport { debug } from \"./debug.js\";\nimport { isNonEmptyArray, type NonEmptyArray } from \"./nonEmptyArrayType.js\";\nimport type { IOpProcessingController } from \"./testObjectProvider.js\";\nimport { timeoutAwait, timeoutPromise } from \"./timeoutUtils.js\";\n\nconst debugOp = debug.extend(\"ops\");\nconst debugWait = debug.extend(\"wait\");\n\ninterface ContainerRecord {\n\t// A short number for debug output\n\tindex: number;\n\n\t// LoaderContainerTracker paused state\n\tpaused: boolean;\n\tpauseP?: Promise<void>; // promise for for the pause that is in progress\n\n\t// Tracking trailing no-op that may or may be acked by the server so we can discount them\n\t// See issue #5629\n\tstartTrailingNoOps: number;\n\ttrailingNoOps: number;\n\n\t// Track last proposal to ensure no unresolved proposal\n\tlastProposal: number;\n}\n\n/**\n * @legacy @beta\n */\nexport class LoaderContainerTracker implements IOpProcessingController {\n\tprivate readonly containers = new Map<IContainer, ContainerRecord>();\n\tprivate lastProposalSeqNum: number = 0;\n\n\tconstructor(private readonly syncSummarizerClients: boolean = false) {}\n\n\t/**\n\t * Add a loader to start to track any container created from them\n\t * @param loader - loader to start tracking any container created.\n\t */\n\tpublic add<LoaderType extends IHostLoader>(loader: LoaderType) {\n\t\t// TODO: Expose Loader API to able to intercept container creation (See issue #5114)\n\t\tconst patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n\t\t\tconst boundFn = fn.bind(loader);\n\t\t\treturn async (...args: T[]) => {\n\t\t\t\tconst container = await boundFn(...args);\n\t\t\t\tthis.addContainer(container);\n\t\t\t\treturn container;\n\t\t\t};\n\t\t};\n\t\t/* eslint-disable @typescript-eslint/unbound-method */\n\t\tloader.resolve = patch(loader.resolve);\n\t\tloader.createDetachedContainer = patch(loader.createDetachedContainer);\n\t\tloader.rehydrateDetachedContainerFromSnapshot = patch(\n\t\t\tloader.rehydrateDetachedContainerFromSnapshot,\n\t\t);\n\t\t/* eslint-enable @typescript-eslint/unbound-method */\n\t}\n\n\t/**\n\t * Utility function to add container to be tracked.\n\t *\n\t * @param container - container to add\n\t */\n\tpublic addContainer(container: IContainer) {\n\t\t// don't add container that is already tracked\n\t\tif (this.containers.has(container)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Container has a `clone` method that can be used to create another container without going through\n\t\t// the Loader. Such containers won't be added by the `add` method so do it here. For example, summarizer\n\t\t// containers are created via the `clone` method.\n\t\t// Created a type with clone (which is not on IContainer and is readonly) rather than typing to any.\n\t\ttype ContainerWithClone = IContainer & {\n\t\t\tclone: (\n\t\t\t\tloadProps: IContainerLoadProps,\n\t\t\t\tcreateParamOverrides: Partial<IContainerCreateProps>,\n\t\t\t) => Promise<IContainer>;\n\t\t};\n\t\tconst containerWithClone = container as ContainerWithClone;\n\n\t\t// back-compat: Check for undefined because this function was added recently and older containers won't have it.\n\t\tif (containerWithClone.clone !== undefined) {\n\t\t\tconst patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n\t\t\t\tconst boundFn = fn.bind(containerWithClone);\n\t\t\t\treturn async (...args: T[]) => {\n\t\t\t\t\tconst newContainer = await boundFn(...args);\n\t\t\t\t\tthis.addContainer(newContainer);\n\t\t\t\t\treturn newContainer;\n\t\t\t\t};\n\t\t\t};\n\t\t\tcontainerWithClone.clone = patch(containerWithClone.clone);\n\t\t}\n\n\t\t// ignore summarizer\n\t\tif (\n\t\t\t!container.deltaManager.clientDetails.capabilities.interactive &&\n\t\t\t!this.syncSummarizerClients\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst record = {\n\t\t\tindex: this.containers.size,\n\t\t\tpaused: false,\n\t\t\tstartTrailingNoOps: 0,\n\t\t\ttrailingNoOps: 0,\n\t\t\tlastProposal: 0,\n\t\t};\n\t\tthis.containers.set(container, record);\n\t\tthis.trackTrailingNoOps(container, record);\n\t\tthis.trackLastProposal(container);\n\t\tthis.setupTrace(container, record.index);\n\t}\n\n\t/**\n\t * Keep track of the trailing NoOp that was sent so we can discount them in the clientSequenceNumber tracking.\n\t * The server might coalesce them with other ops, or a single NoOp, or delay it if it don't think it is necessary.\n\t *\n\t * @param container - the container to track\n\t * @param record - the record to update the trailing op information\n\t */\n\tprivate trackTrailingNoOps(container: IContainer, record: ContainerRecord) {\n\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\tdeltaManagerFull.outbound.on(\"op\", (messages) => {\n\t\t\tfor (const msg of messages) {\n\t\t\t\tif (canBeCoalescedByService(msg)) {\n\t\t\t\t\t// Track the NoOp that was sent.\n\t\t\t\t\tif (record.trailingNoOps === 0) {\n\t\t\t\t\t\t// record the starting sequence number of the trailing no ops if we haven't been tracking yet.\n\t\t\t\t\t\trecord.startTrailingNoOps = msg.clientSequenceNumber;\n\t\t\t\t\t}\n\t\t\t\t\trecord.trailingNoOps++;\n\t\t\t\t} else {\n\t\t\t\t\t// Other ops has been sent. We would like to see those ack'ed, so no more need to track NoOps\n\t\t\t\t\trecord.trailingNoOps = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tdeltaManagerFull.inbound.on(\"push\", (message) => {\n\t\t\t// Received the no op back, update the record if we are tracking\n\t\t\tif (\n\t\t\t\tcanBeCoalescedByService(message) &&\n\t\t\t\tmessage.clientId === container.clientId &&\n\t\t\t\trecord.trailingNoOps !== 0 &&\n\t\t\t\trecord.startTrailingNoOps <= message.clientSequenceNumber\n\t\t\t) {\n\t\t\t\t// NoOp might have coalesced and skipped ahead some sequence number\n\t\t\t\t// update the record and skip ahead as well\n\t\t\t\tconst oldStartTrailingNoOps = record.startTrailingNoOps;\n\t\t\t\trecord.startTrailingNoOps = message.clientSequenceNumber + 1;\n\t\t\t\trecord.trailingNoOps -= record.startTrailingNoOps - oldStartTrailingNoOps;\n\t\t\t}\n\t\t});\n\n\t\tcontainer.on(\"disconnected\", () => {\n\t\t\t// reset on disconnect.\n\t\t\trecord.trailingNoOps = 0;\n\t\t});\n\t}\n\n\tprivate trackLastProposal(container: IContainer) {\n\t\tcontainer.on(\"codeDetailsProposed\", (value, proposal) => {\n\t\t\tif (proposal.sequenceNumber > this.lastProposalSeqNum) {\n\t\t\t\tthis.lastProposalSeqNum = proposal.sequenceNumber;\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Reset the tracker, closing all containers and stop tracking them.\n\t */\n\tpublic reset() {\n\t\tthis.lastProposalSeqNum = 0;\n\t\tfor (const container of this.containers.keys()) {\n\t\t\tcontainer.close();\n\t\t\t// Optional chaining here is because containers made with LTS loaders don't have a dispose method or process\n\t\t\t// and this package is used with various previous versions of Fluid layers in our compat testing.\n\t\t\tcontainer.dispose?.();\n\t\t}\n\t\tthis.containers.clear();\n\n\t\t// REVIEW: do we need to unpatch the loaders?\n\t}\n\n\t/**\n\t * Make sure all the tracked containers are synchronized.\n\t *\n\t * No isDirty (non-readonly) containers\n\t * No extra clientId in quorum of any container that is not tracked and still opened.\n\t * - i.e. no pending Join/Leave message.\n\t * No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n\t * lastSequenceNumber of all container is the same\n\t * clientSequenceNumberObserved is the same as clientSequenceNumber sent\n\t * - this overlaps with !isDirty, but include task scheduler ops.\n\t * - Trailing NoOp is tracked and don't count as pending ops.\n\t *\n\t * Containers that are already pause will resume process and paused again once\n\t * everything is synchronized. Containers that aren't paused will remain unpaused when this\n\t * function returns.\n\t */\n\tpublic async ensureSynchronized(...containers: IContainer[]): Promise<void> {\n\t\tconst resumed = this.resumeProcessing(...containers);\n\n\t\tlet waitingSequenceNumberSynchronized: string | undefined;\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\n\t\t\t// yield a turn to allow side effect of resuming or the ops we just processed execute before we check\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tsetTimeout(resolve, 0);\n\t\t\t});\n\n\t\t\tconst containersToApply = this.getContainers(containers);\n\t\t\tif (!isNonEmptyArray(containersToApply)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Ignore readonly dirty containers because they can't send ops and nothing can be done about them being dirty.\n\t\t\tconst dirtyContainers = containersToApply.filter((c) => {\n\t\t\t\tconst { deltaManager, isDirty } = c;\n\t\t\t\treturn deltaManager.readOnlyInfo.readonly !== true && isDirty;\n\t\t\t});\n\t\t\tif (dirtyContainers.length === 0) {\n\t\t\t\t// Wait for all the leave messages\n\t\t\t\tconst pendingClients = this.getPendingClients(containersToApply);\n\t\t\t\tif (pendingClients.length === 0) {\n\t\t\t\t\tconst needSync = this.needSequenceNumberSynchronize(containersToApply);\n\t\t\t\t\tif (needSync === undefined) {\n\t\t\t\t\t\t// done, we are in sync\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (waitingSequenceNumberSynchronized !== needSync.reason) {\n\t\t\t\t\t\t// Don't repeat writing to console if it is the same reason\n\t\t\t\t\t\twaitingSequenceNumberSynchronized = needSync.reason;\n\t\t\t\t\t\tdebugWait(needSync.message);\n\t\t\t\t\t}\n\t\t\t\t\t// Wait for one inbounds ops which might change the state of things\n\t\t\t\t\tawait timeoutAwait(this.waitForAnyInboundOps(containersToApply), {\n\t\t\t\t\t\terrorMsg: `Timeout on ${needSync.message}`,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\twaitingSequenceNumberSynchronized = undefined;\n\t\t\t\t\tawait timeoutAwait(this.waitForPendingClients(pendingClients), {\n\t\t\t\t\t\terrorMsg: \"Timeout on waiting for pending join or leave op\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Wait for all the containers to be saved\n\t\t\t\tdebugWait(\n\t\t\t\t\t`Waiting container to be saved ${this.containerIndexStrings(dirtyContainers)}`,\n\t\t\t\t);\n\t\t\t\twaitingSequenceNumberSynchronized = undefined;\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tdirtyContainers.map(async (c) =>\n\t\t\t\t\t\tPromise.race([\n\t\t\t\t\t\t\ttimeoutPromise((resolve) => c.once(\"saved\", () => resolve()), {\n\t\t\t\t\t\t\t\terrorMsg: \"Timeout on waiting a container to be saved\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tnew Promise((resolve) => c.once(\"closed\", resolve)),\n\t\t\t\t\t\t]),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Pause all container that was resumed\n\t\t// don't call pause if resumed is empty and pause everything, which is not what we want\n\t\tif (resumed.length !== 0) {\n\t\t\tawait timeoutAwait(this.pauseProcessing(...resumed), {\n\t\t\t\terrorMsg: \"Timeout on waiting for pausing all resumed containers\",\n\t\t\t});\n\t\t}\n\n\t\tdebugWait(\"Synchronized\");\n\t}\n\n\t/**\n\t * Utility to calculate the set of clientId per container in quorum that is NOT associated with\n\t * any container we tracked, indicating there is a pending join or leave op that we need to wait.\n\t *\n\t * @param containersToApply - the set of containers to check\n\t */\n\tprivate getPendingClients(containersToApply: IContainer[]) {\n\t\t// All the clientId we track should be a superset of the quorum, otherwise, we are missing\n\t\t// leave messages\n\t\tconst openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);\n\t\tconst openedClientId = openedDocuments.map((container) => container.clientId);\n\n\t\tconst pendingClients: [IContainer, Set<string>][] = [];\n\t\tcontainersToApply.forEach((container) => {\n\t\t\tconst pendingClientId = new Set<string>();\n\t\t\tconst quorum = container.getQuorum();\n\t\t\tquorum.getMembers().forEach((client, clientId) => {\n\t\t\t\t// ignore summarizer\n\t\t\t\tif (!client.client.details.capabilities.interactive && !this.syncSummarizerClients) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!openedClientId.includes(clientId)) {\n\t\t\t\t\tpendingClientId.add(clientId);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (pendingClientId.size !== 0) {\n\t\t\t\tpendingClients.push([container, pendingClientId]);\n\t\t\t}\n\t\t});\n\t\treturn pendingClients;\n\t}\n\n\t/**\n\t * Utility to check synchronization based on sequence number\n\t * See ensureSynchronized for more detail\n\t *\n\t * @param containersToApply - the set of containers to check\n\t */\n\tprivate needSequenceNumberSynchronize(containersToApply: NonEmptyArray<IContainer>) {\n\t\t// If there is a pending proposal, wait for it to be accepted\n\t\tconst minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n\t\tif (minSeqNum < this.lastProposalSeqNum) {\n\t\t\treturn {\n\t\t\t\treason: \"Proposal\",\n\t\t\t\tmessage: `waiting for MSN to advance to proposal at sequence number ${this.lastProposalSeqNum}`,\n\t\t\t};\n\t\t}\n\n\t\t// clientSequenceNumber check detects ops in flight, both on the wire and in the outbound queue\n\t\t// We need both client sequence number and isDirty check because:\n\t\t// - Currently isDirty flag ignores ops for task scheduler, so we need the client sequence number check\n\t\t// - But isDirty flags include ops during forceReadonly and disconnected, because we don't submit\n\t\t// the ops in the first place, clientSequenceNumber is not assigned\n\n\t\tconst containerWithInflightOps = containersToApply.filter((container) => {\n\t\t\tif (container.deltaManager.readOnlyInfo.readonly === true) {\n\t\t\t\t// Ignore readonly container. the clientSeqNum and clientSeqNumObserved might be out of sync\n\t\t\t\t// because we transition to readonly when outbound is not empty or the in transit op got lost\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Note that in read only mode, the op won't be submitted\n\t\t\tlet deltaManager = container.deltaManager as any;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst { trailingNoOps } = this.containers.get(container)!;\n\t\t\t// Back-compat: lastSubmittedClientId/clientSequenceNumber/clientSequenceNumberObserved moved to ConnectionManager in 0.53\n\t\t\tif (!(\"clientSequenceNumber\" in deltaManager)) {\n\t\t\t\tdeltaManager = deltaManager.connectionManager;\n\t\t\t}\n\t\t\tassert(\"clientSequenceNumber\" in deltaManager, \"no clientSequenceNumber\");\n\t\t\tassert(\"clientSequenceNumberObserved\" in deltaManager, \"no clientSequenceNumber\");\n\t\t\t// If last submittedClientId isn't the current clientId, then we haven't send any ops\n\t\t\treturn (\n\t\t\t\tdeltaManager.lastSubmittedClientId === container.clientId &&\n\t\t\t\tdeltaManager.clientSequenceNumber !==\n\t\t\t\t\t(deltaManager.clientSequenceNumberObserved as number) + trailingNoOps\n\t\t\t);\n\t\t});\n\n\t\tif (containerWithInflightOps.length !== 0) {\n\t\t\treturn {\n\t\t\t\treason: \"InflightOps\",\n\t\t\t\tmessage: `waiting for containers with inflight ops: ${this.containerIndexStrings(\n\t\t\t\t\tcontainerWithInflightOps,\n\t\t\t\t)}`,\n\t\t\t};\n\t\t}\n\n\t\t// Check to see if all the container has process the same number of ops.\n\t\tconst maxSeqNum = Math.max(\n\t\t\t...containersToApply.map((c) => c.deltaManager.lastSequenceNumber),\n\t\t);\n\t\tconst containerWithPendingIncoming = containersToApply.filter(\n\t\t\t(c) => c.deltaManager.lastSequenceNumber !== maxSeqNum,\n\t\t);\n\t\tif (containerWithPendingIncoming.length !== 0) {\n\t\t\treturn {\n\t\t\t\treason: \"Pending\",\n\t\t\t\tmessage: `waiting for containers with pending incoming ops up to sequence number ${maxSeqNum}: ${this.containerIndexStrings(\n\t\t\t\t\tcontainerWithPendingIncoming,\n\t\t\t\t)}`,\n\t\t\t};\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate containerIndexStrings(containers: IContainer[]) {\n\t\treturn containers.map(\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t(c) => this.containers.get(c)!.index,\n\t\t);\n\t}\n\n\t/**\n\t * Utility to wait for any clientId in quorum that is NOT associated with any container we\n\t * tracked, indicating there is a pending join or leave op that we need to wait.\n\t *\n\t * Note that this function doesn't account for container that got added after we started waiting\n\t *\n\t * @param containersToApply - the set of containers to wait for any inbound ops for\n\t */\n\tprivate async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {\n\t\tconst unconnectedClients = Array.from(this.containers.keys()).filter(\n\t\t\t(c) => !c.closed && c.connectionState !== ConnectionState.Connected,\n\t\t);\n\t\treturn Promise.all(\n\t\t\tpendingClients.map(async ([container, pendingClientId]) => {\n\t\t\t\treturn new Promise<void>((resolve) => {\n\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\tunconnectedClients.forEach((c) => c.off(\"connected\", handler));\n\t\t\t\t\t\tcontainer.getQuorum().off(\"removeMember\", handler);\n\t\t\t\t\t};\n\t\t\t\t\tconst handler = (clientId: string) => {\n\t\t\t\t\t\tpendingClientId.delete(clientId);\n\t\t\t\t\t\tif (pendingClientId.size === 0) {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst index = this.containers.get(container)!.index;\n\t\t\t\t\tdebugWait(\n\t\t\t\t\t\t`${index}: Waiting for pending clients ${Array.from(pendingClientId.keys())}`,\n\t\t\t\t\t);\n\t\t\t\t\tunconnectedClients.forEach((c) => c.on(\"connected\", handler));\n\t\t\t\t\tcontainer.getQuorum().on(\"removeMember\", handler);\n\t\t\t\t\tcontainer.on(\"closed\", () => {\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * Utility to wait for any inbound ops from a set of containers\n\t * @param containersToApply - the set of containers to wait for any inbound ops for\n\t */\n\tprivate async waitForAnyInboundOps(containersToApply: IContainer[]) {\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tconst handler = () => {\n\t\t\t\tcontainersToApply.map((c) => {\n\t\t\t\t\ttoIDeltaManagerFull(c.deltaManager).inbound.off(\"push\", handler);\n\t\t\t\t});\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tcontainersToApply.map((c) => {\n\t\t\t\ttoIDeltaManagerFull(c.deltaManager).inbound.on(\"push\", handler);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Resume all queue activities on all paused tracked containers and return them\n\t */\n\tpublic resumeProcessing(...containers: IContainer[]) {\n\t\tconst resumed: IContainer[] = [];\n\t\tconst containersToApply = this.getContainers(containers);\n\t\tfor (const container of containersToApply) {\n\t\t\tconst record = this.containers.get(container);\n\t\t\tassert(\n\t\t\t\trecord?.pauseP === undefined,\n\t\t\t\t\"Cannot resume container while pausing is in progress\",\n\t\t\t);\n\t\t\tif (record?.paused === true) {\n\t\t\t\tdebugWait(`${record.index}: container resumed`);\n\t\t\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\t\t\tdeltaManagerFull.inbound.resume();\n\t\t\t\tdeltaManagerFull.outbound.resume();\n\t\t\t\tresumed.push(container);\n\t\t\t\trecord.paused = false;\n\t\t\t}\n\t\t}\n\t\treturn resumed;\n\t}\n\n\t/**\n\t * Pause all queue activities on the containers given, or all tracked containers\n\t * Any containers given that is not tracked will be ignored.\n\t *\n\t * When a container is paused, it is assumed that we want fine grain control over op\n\t * sequencing. This function will prepare the container and force it into write mode to\n\t * avoid missing join messages or change the sequence of event when switching from read to\n\t * write mode.\n\t */\n\tpublic async pauseProcessing(...containers: IContainer[]) {\n\t\tconst waitP: Promise<void>[] = [];\n\t\tconst containersToApply = this.getContainers(containers);\n\t\tfor (const container of containersToApply) {\n\t\t\tconst record = this.containers.get(container);\n\t\t\tif (record !== undefined && !record.paused) {\n\t\t\t\tif (record.pauseP === undefined) {\n\t\t\t\t\trecord.pauseP = this.pauseContainer(container, record);\n\t\t\t\t}\n\t\t\t\twaitP.push(record.pauseP);\n\t\t\t}\n\t\t}\n\t\tawait Promise.all(waitP);\n\t}\n\n\t/**\n\t * When a container is paused, it is assumed that we want fine grain control over op\n\t * sequencing. This function will prepare the container and force it into write mode to\n\t * avoid missing join messages or change the sequence of event when switching from read to\n\t * write mode.\n\t *\n\t * @param container - the container to pause\n\t * @param record - the record for the container\n\t */\n\tprivate async pauseContainer(container: IContainer, record: ContainerRecord) {\n\t\tdebugWait(`${record.index}: pausing container`);\n\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\tassert(!deltaManagerFull.outbound.paused, \"Container should not be paused yet\");\n\t\tassert(!deltaManagerFull.inbound.paused, \"Container should not be paused yet\");\n\n\t\t// Pause outbound\n\t\tdebugWait(`${record.index}: pausing container outbound queues`);\n\t\tawait deltaManagerFull.outbound.pause();\n\n\t\t// Ensure the container is connected first.\n\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\tdebugWait(`${record.index}: Wait for container connection`);\n\t\t\tawait waitForContainerConnection(container);\n\t\t}\n\n\t\t// Check if the container is in write mode\n\t\tif (!container.deltaManager.active) {\n\t\t\tlet proposalP: Promise<boolean> | undefined;\n\t\t\tif (deltaManagerFull.outbound.idle) {\n\t\t\t\t// Need to generate an op to force write mode\n\t\t\t\tdebugWait(`${record.index}: container force write connection`);\n\t\t\t\tconst maybeContainer = container as Partial<IContainer>;\n\t\t\t\tconst codeProposal = maybeContainer.getLoadedCodeDetails\n\t\t\t\t\t? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\t\tcontainer.getLoadedCodeDetails()!\n\t\t\t\t\t: (container as any).chaincodePackage;\n\n\t\t\t\tproposalP = container.proposeCodeDetails(codeProposal);\n\t\t\t}\n\n\t\t\t// Wait for nack\n\t\t\tdebugWait(`${record.index}: Wait for container disconnect`);\n\t\t\tdeltaManagerFull.outbound.resume();\n\t\t\tawait new Promise<void>((resolve) => container.once(\"disconnected\", resolve));\n\t\t\tconst accepted = proposalP ? await proposalP : false;\n\t\t\tassert(!accepted, \"A proposal in read mode should be rejected\");\n\t\t\tawait deltaManagerFull.outbound.pause();\n\n\t\t\t// Ensure the container is reconnect.\n\t\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\t\tdebugWait(`${record.index}: Wait for container reconnection`);\n\t\t\t\tawait waitForContainerConnection(container);\n\t\t\t}\n\t\t}\n\n\t\tdebugWait(`${record.index}: pausing container inbound queues`);\n\n\t\t// Pause inbound\n\t\tawait deltaManagerFull.inbound.pause();\n\n\t\tdebugWait(`${record.index}: container paused`);\n\n\t\trecord.pauseP = undefined;\n\t\trecord.paused = true;\n\t}\n\n\t/**\n\t * Pause all queue activities on all tracked containers, and resume only\n\t * inbound to process ops until it is idle. All queues are left in the paused state\n\t * after the function.\n\t *\n\t * Pausing will switch the container to write mode. See `pauseProcessing`\n\t */\n\tpublic async processIncoming(...containers: IContainer[]) {\n\t\treturn this.processQueue(\n\t\t\tcontainers,\n\t\t\t(container) => toIDeltaManagerFull(container.deltaManager).inbound,\n\t\t);\n\t}\n\n\t/**\n\t * Pause all queue activities on all tracked containers, and resume only\n\t * outbound to process ops until it is idle. All queues are left in the paused state\n\t * after the function.\n\t *\n\t * Pausing will switch the container to write mode. See `pauseProcessing`\n\t */\n\tpublic async processOutgoing(...containers: IContainer[]) {\n\t\treturn this.processQueue(\n\t\t\tcontainers,\n\t\t\t(container) => toIDeltaManagerFull(container.deltaManager).outbound,\n\t\t);\n\t}\n\n\t/**\n\t * Implementation of processIncoming and processOutgoing\n\t */\n\tprivate async processQueue<U>(\n\t\tcontainers: IContainer[],\n\t\tgetQueue: (container: IContainer) => IDeltaQueue<U>,\n\t) {\n\t\tawait this.pauseProcessing(...containers);\n\t\tconst resumed: IDeltaQueue<U>[] = [];\n\n\t\tconst containersToApply = this.getContainers(containers);\n\n\t\tconst inflightTracker = new Map<IContainer, number>();\n\t\tconst cleanup: (() => void)[] = [];\n\t\tfor (const container of containersToApply) {\n\t\t\tassert(\n\t\t\t\tcontainer.deltaManager.active,\n\t\t\t\t\"Container should be connected in write mode already\",\n\t\t\t);\n\n\t\t\tconst queue = getQueue(container);\n\n\t\t\t// track the outgoing ops (if any) to make sure they make the round trip to at least to the same client\n\t\t\t// to make sure they are sequenced.\n\t\t\tcleanup.push(this.setupInOutTracker(container, inflightTracker));\n\t\t\tqueue.resume();\n\t\t\tresumed.push(queue);\n\t\t}\n\n\t\twhile (resumed.some((queue) => !queue.idle)) {\n\t\t\tdebugWait(\"Wait until queue is idle\");\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tsetTimeout(resolve, 0);\n\t\t\t});\n\t\t}\n\n\t\t// Make sure all the op that we sent out are acked first\n\t\t// This is no op if we are processing incoming\n\t\tif (inflightTracker.size) {\n\t\t\tdebugWait(\"Wait for inflight ops\");\n\t\t\tdo {\n\t\t\t\tawait this.waitForAnyInboundOps(containersToApply);\n\t\t\t} while (inflightTracker.size);\n\t\t}\n\n\t\t// remove the handlers\n\t\tcleanup.forEach((clean) => clean());\n\n\t\tawait Promise.all(resumed.map(async (queue) => queue.pause()));\n\t}\n\n\t/**\n\t * Utility to set up listener to track the outbound ops until it round trip back\n\t * Returns a function to remove the handler after it is done.\n\t *\n\t * @param container - the container to setup\n\t * @param inflightTracker - a map to track the clientSequenceNumber per container it expect to get ops back\n\t */\n\tprivate setupInOutTracker(container: IContainer, inflightTracker: Map<IContainer, number>) {\n\t\tconst outHandler = (messages: IDocumentMessage[]) => {\n\t\t\tfor (const message of messages) {\n\t\t\t\tif (!canBeCoalescedByService(message)) {\n\t\t\t\t\tinflightTracker.set(container, message.clientSequenceNumber);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconst inHandler = (message: ISequencedDocumentMessage) => {\n\t\t\tif (\n\t\t\t\t!canBeCoalescedByService(message) &&\n\t\t\t\tmessage.clientId === container.clientId &&\n\t\t\t\tinflightTracker.get(container) === message.clientSequenceNumber\n\t\t\t) {\n\t\t\t\tinflightTracker.delete(container);\n\t\t\t}\n\t\t};\n\n\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\tdeltaManagerFull.outbound.on(\"op\", outHandler);\n\t\tdeltaManagerFull.inbound.on(\"push\", inHandler);\n\n\t\treturn () => {\n\t\t\tdeltaManagerFull.outbound.off(\"op\", outHandler);\n\t\t\tdeltaManagerFull.inbound.off(\"push\", inHandler);\n\t\t};\n\t}\n\n\t/**\n\t * Setup debug traces for connection and ops\n\t */\n\tprivate setupTrace(container: IContainer, index: number) {\n\t\tif (debugOp.enabled) {\n\t\t\tconst getContentsString = (type: string, msgContents: any) => {\n\t\t\t\ttry {\n\t\t\t\t\tif (type !== MessageType.Operation) {\n\t\t\t\t\t\tif (typeof msgContents === \"string\") {\n\t\t\t\t\t\t\treturn msgContents;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn JSON.stringify(msgContents);\n\t\t\t\t\t}\n\t\t\t\t\tlet address = \"\";\n\n\t\t\t\t\t// contents comes in the wire as JSON string (\"push\" event)\n\t\t\t\t\t// But already parsed when apply (\"op\" event)\n\t\t\t\t\tlet contents =\n\t\t\t\t\t\ttypeof msgContents === \"string\" ? JSON.parse(msgContents) : msgContents;\n\t\t\t\t\twhile (contents !== undefined && contents !== null) {\n\t\t\t\t\t\tif (contents.contents?.address !== undefined) {\n\t\t\t\t\t\t\taddress += `/${contents.contents.address}`;\n\t\t\t\t\t\t\tcontents = contents.contents.contents;\n\t\t\t\t\t\t} else if (contents.content?.address !== undefined) {\n\t\t\t\t\t\t\taddress += `/${contents.content.address}`;\n\t\t\t\t\t\t\tcontents = contents.content.contents;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (address) {\n\t\t\t\t\t\treturn `${address} ${JSON.stringify(contents)}`;\n\t\t\t\t\t}\n\t\t\t\t\treturn JSON.stringify(contents);\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\treturn `${e.message}: ${e.stack}`;\n\t\t\t\t}\n\t\t\t};\n\t\t\tdebugOp(`${index}: ADD: clientId: ${container.clientId}`);\n\t\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\t\tdeltaManagerFull.outbound.on(\"op\", (messages) => {\n\t\t\t\tfor (const msg of messages) {\n\t\t\t\t\tdebugOp(\n\t\t\t\t\t\t`${index}: OUT: ` +\n\t\t\t\t\t\t\t`cli: ${msg.clientSequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`rsq: ${msg.referenceSequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`${msg.type} ${getContentsString(msg.type, msg.contents)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst getInboundHandler = (type: string) => {\n\t\t\t\treturn (msg: ISequencedDocumentMessage) => {\n\t\t\t\t\tconst clientSeq =\n\t\t\t\t\t\tmsg.clientId === container.clientId\n\t\t\t\t\t\t\t? `cli: ${msg.clientSequenceNumber.toString().padStart(3)}`\n\t\t\t\t\t\t\t: \" \";\n\t\t\t\t\tdebugOp(\n\t\t\t\t\t\t`${index}: ${type}: seq: ${msg.sequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`${clientSeq} min: ${msg.minimumSequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`${msg.type} ${getContentsString(msg.type, msg.contents)}`,\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t};\n\t\t\tdeltaManagerFull.inbound.on(\"push\", getInboundHandler(\"IN \"));\n\t\t\tdeltaManagerFull.inbound.on(\"op\", getInboundHandler(\"OP \"));\n\t\t\tcontainer.deltaManager.on(\"connect\", (details) => {\n\t\t\t\tdebugOp(`${index}: CON: clientId: ${details.clientId}`);\n\t\t\t});\n\t\t\tcontainer.deltaManager.on(\"disconnect\", (reason) => {\n\t\t\t\tdebugOp(`${index}: DIS: ${reason}`);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Filter out the opened containers based on param.\n\t * @param containers - The container to filter to. If the array is empty, it means don't filter and return\n\t * all open containers.\n\t */\n\tprivate getContainers(containers: IContainer[]) {\n\t\tconst containersToApply =\n\t\t\tcontainers.length === 0 ? Array.from(this.containers.keys()) : containers;\n\t\treturn containersToApply.filter((container) => !container.closed);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"loaderContainerTracker.js","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tIDeltaQueue,\n\tIContainer,\n\ttype IHostLoader,\n} from \"@fluidframework/container-definitions/internal\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport {\n\tIContainerCreateProps,\n\tIContainerLoadProps,\n\t// eslint-disable-next-line import-x/no-internal-modules\n} from \"@fluidframework/container-loader/internal/test/container\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIDocumentMessage,\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { canBeCoalescedByService } from \"@fluidframework/driver-utils/internal\";\n\nimport { toIDeltaManagerFull, waitForContainerConnection } from \"./containerUtils.js\";\nimport { debug } from \"./debug.js\";\nimport { isNonEmptyArray, type NonEmptyArray } from \"./nonEmptyArrayType.js\";\nimport type { IOpProcessingController } from \"./testObjectProvider.js\";\nimport { timeoutAwait, timeoutPromise } from \"./timeoutUtils.js\";\n\nconst debugOp = debug.extend(\"ops\");\nconst debugWait = debug.extend(\"wait\");\n\ninterface ContainerRecord {\n\t// A short number for debug output\n\tindex: number;\n\n\t// LoaderContainerTracker paused state\n\tpaused: boolean;\n\tpauseP?: Promise<void>; // promise for for the pause that is in progress\n\n\t// Tracking trailing no-op that may or may be acked by the server so we can discount them\n\t// See issue #5629\n\tstartTrailingNoOps: number;\n\ttrailingNoOps: number;\n\n\t// Track last proposal to ensure no unresolved proposal\n\tlastProposal: number;\n}\n\n/**\n * @legacy @beta\n */\nexport class LoaderContainerTracker implements IOpProcessingController {\n\tprivate readonly containers = new Map<IContainer, ContainerRecord>();\n\tprivate lastProposalSeqNum: number = 0;\n\n\tconstructor(private readonly syncSummarizerClients: boolean = false) {}\n\n\t/**\n\t * Add a loader to start to track any container created from them\n\t * @param loader - loader to start tracking any container created.\n\t */\n\tpublic add<LoaderType extends IHostLoader>(loader: LoaderType) {\n\t\t// TODO: Expose Loader API to able to intercept container creation (See issue #5114)\n\t\tconst patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n\t\t\tconst boundFn = fn.bind(loader);\n\t\t\treturn async (...args: T[]) => {\n\t\t\t\tconst container = await boundFn(...args);\n\t\t\t\tthis.addContainer(container);\n\t\t\t\treturn container;\n\t\t\t};\n\t\t};\n\t\t/* eslint-disable @typescript-eslint/unbound-method */\n\t\tloader.resolve = patch(loader.resolve);\n\t\tloader.createDetachedContainer = patch(loader.createDetachedContainer);\n\t\tloader.rehydrateDetachedContainerFromSnapshot = patch(\n\t\t\tloader.rehydrateDetachedContainerFromSnapshot,\n\t\t);\n\t\t/* eslint-enable @typescript-eslint/unbound-method */\n\t}\n\n\t/**\n\t * Utility function to add container to be tracked.\n\t *\n\t * @param container - container to add\n\t */\n\tpublic addContainer(container: IContainer) {\n\t\t// don't add container that is already tracked\n\t\tif (this.containers.has(container)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Container has a `clone` method that can be used to create another container without going through\n\t\t// the Loader. Such containers won't be added by the `add` method so do it here. For example, summarizer\n\t\t// containers are created via the `clone` method.\n\t\t// Created a type with clone (which is not on IContainer and is readonly) rather than typing to any.\n\t\ttype ContainerWithClone = IContainer & {\n\t\t\tclone: (\n\t\t\t\tloadProps: IContainerLoadProps,\n\t\t\t\tcreateParamOverrides: Partial<IContainerCreateProps>,\n\t\t\t) => Promise<IContainer>;\n\t\t};\n\t\tconst containerWithClone = container as ContainerWithClone;\n\n\t\t// back-compat: Check for undefined because this function was added recently and older containers won't have it.\n\t\tif (containerWithClone.clone !== undefined) {\n\t\t\tconst patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n\t\t\t\tconst boundFn = fn.bind(containerWithClone);\n\t\t\t\treturn async (...args: T[]) => {\n\t\t\t\t\tconst newContainer = await boundFn(...args);\n\t\t\t\t\tthis.addContainer(newContainer);\n\t\t\t\t\treturn newContainer;\n\t\t\t\t};\n\t\t\t};\n\t\t\tcontainerWithClone.clone = patch(containerWithClone.clone);\n\t\t}\n\n\t\t// ignore summarizer\n\t\tif (\n\t\t\t!container.deltaManager.clientDetails.capabilities.interactive &&\n\t\t\t!this.syncSummarizerClients\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst record = {\n\t\t\tindex: this.containers.size,\n\t\t\tpaused: false,\n\t\t\tstartTrailingNoOps: 0,\n\t\t\ttrailingNoOps: 0,\n\t\t\tlastProposal: 0,\n\t\t};\n\t\tthis.containers.set(container, record);\n\t\tthis.trackTrailingNoOps(container, record);\n\t\tthis.trackLastProposal(container);\n\t\tthis.setupTrace(container, record.index);\n\t}\n\n\t/**\n\t * Keep track of the trailing NoOp that was sent so we can discount them in the clientSequenceNumber tracking.\n\t * The server might coalesce them with other ops, or a single NoOp, or delay it if it don't think it is necessary.\n\t *\n\t * @param container - the container to track\n\t * @param record - the record to update the trailing op information\n\t */\n\tprivate trackTrailingNoOps(container: IContainer, record: ContainerRecord) {\n\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\tdeltaManagerFull.outbound.on(\"op\", (messages) => {\n\t\t\tfor (const msg of messages) {\n\t\t\t\tif (canBeCoalescedByService(msg)) {\n\t\t\t\t\t// Track the NoOp that was sent.\n\t\t\t\t\tif (record.trailingNoOps === 0) {\n\t\t\t\t\t\t// record the starting sequence number of the trailing no ops if we haven't been tracking yet.\n\t\t\t\t\t\trecord.startTrailingNoOps = msg.clientSequenceNumber;\n\t\t\t\t\t}\n\t\t\t\t\trecord.trailingNoOps++;\n\t\t\t\t} else {\n\t\t\t\t\t// Other ops has been sent. We would like to see those ack'ed, so no more need to track NoOps\n\t\t\t\t\trecord.trailingNoOps = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tdeltaManagerFull.inbound.on(\"push\", (message) => {\n\t\t\t// Received the no op back, update the record if we are tracking\n\t\t\tif (\n\t\t\t\tcanBeCoalescedByService(message) &&\n\t\t\t\tmessage.clientId === container.clientId &&\n\t\t\t\trecord.trailingNoOps !== 0 &&\n\t\t\t\trecord.startTrailingNoOps <= message.clientSequenceNumber\n\t\t\t) {\n\t\t\t\t// NoOp might have coalesced and skipped ahead some sequence number\n\t\t\t\t// update the record and skip ahead as well\n\t\t\t\tconst oldStartTrailingNoOps = record.startTrailingNoOps;\n\t\t\t\trecord.startTrailingNoOps = message.clientSequenceNumber + 1;\n\t\t\t\trecord.trailingNoOps -= record.startTrailingNoOps - oldStartTrailingNoOps;\n\t\t\t}\n\t\t});\n\n\t\tcontainer.on(\"disconnected\", () => {\n\t\t\t// reset on disconnect.\n\t\t\trecord.trailingNoOps = 0;\n\t\t});\n\t}\n\n\tprivate trackLastProposal(container: IContainer) {\n\t\tcontainer.on(\"codeDetailsProposed\", (value, proposal) => {\n\t\t\tif (proposal.sequenceNumber > this.lastProposalSeqNum) {\n\t\t\t\tthis.lastProposalSeqNum = proposal.sequenceNumber;\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Reset the tracker, closing all containers and stop tracking them.\n\t */\n\tpublic reset() {\n\t\tthis.lastProposalSeqNum = 0;\n\t\tfor (const container of this.containers.keys()) {\n\t\t\tcontainer.close();\n\t\t\t// Optional chaining here is because containers made with LTS loaders don't have a dispose method or process\n\t\t\t// and this package is used with various previous versions of Fluid layers in our compat testing.\n\t\t\tcontainer.dispose?.();\n\t\t}\n\t\tthis.containers.clear();\n\n\t\t// REVIEW: do we need to unpatch the loaders?\n\t}\n\n\t/**\n\t * Make sure all the tracked containers are synchronized.\n\t *\n\t * No isDirty (non-readonly) containers\n\t * No extra clientId in quorum of any container that is not tracked and still opened.\n\t * - i.e. no pending Join/Leave message.\n\t * No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n\t * lastSequenceNumber of all container is the same\n\t * clientSequenceNumberObserved is the same as clientSequenceNumber sent\n\t * - this overlaps with !isDirty, but include task scheduler ops.\n\t * - Trailing NoOp is tracked and don't count as pending ops.\n\t *\n\t * Containers that are already pause will resume process and paused again once\n\t * everything is synchronized. Containers that aren't paused will remain unpaused when this\n\t * function returns.\n\t */\n\tpublic async ensureSynchronized(...containers: IContainer[]): Promise<void> {\n\t\tconst resumed = this.resumeProcessing(...containers);\n\n\t\tlet waitingSequenceNumberSynchronized: string | undefined;\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\n\t\t\t// yield a turn to allow side effect of resuming or the ops we just processed execute before we check\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tsetTimeout(resolve, 0);\n\t\t\t});\n\n\t\t\tconst containersToApply = this.getContainers(containers);\n\t\t\tif (!isNonEmptyArray(containersToApply)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Ignore readonly dirty containers because they can't send ops and nothing can be done about them being dirty.\n\t\t\tconst dirtyContainers = containersToApply.filter((c) => {\n\t\t\t\tconst { deltaManager, isDirty } = c;\n\t\t\t\treturn deltaManager.readOnlyInfo.readonly !== true && isDirty;\n\t\t\t});\n\t\t\tif (dirtyContainers.length === 0) {\n\t\t\t\t// Wait for all the leave messages\n\t\t\t\tconst pendingClients = this.getPendingClients(containersToApply);\n\t\t\t\tif (pendingClients.length === 0) {\n\t\t\t\t\tconst needSync = this.needSequenceNumberSynchronize(containersToApply);\n\t\t\t\t\tif (needSync === undefined) {\n\t\t\t\t\t\t// done, we are in sync\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (waitingSequenceNumberSynchronized !== needSync.reason) {\n\t\t\t\t\t\t// Don't repeat writing to console if it is the same reason\n\t\t\t\t\t\twaitingSequenceNumberSynchronized = needSync.reason;\n\t\t\t\t\t\tdebugWait(needSync.message);\n\t\t\t\t\t}\n\t\t\t\t\t// Wait for one inbounds ops which might change the state of things\n\t\t\t\t\tawait timeoutAwait(this.waitForAnyInboundOps(containersToApply), {\n\t\t\t\t\t\terrorMsg: `Timeout on ${needSync.message}`,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\twaitingSequenceNumberSynchronized = undefined;\n\t\t\t\t\tawait timeoutAwait(this.waitForPendingClients(pendingClients), {\n\t\t\t\t\t\terrorMsg: \"Timeout on waiting for pending join or leave op\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Wait for all the containers to be saved\n\t\t\t\tdebugWait(\n\t\t\t\t\t`Waiting container to be saved ${this.containerIndexStrings(dirtyContainers)}`,\n\t\t\t\t);\n\t\t\t\twaitingSequenceNumberSynchronized = undefined;\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tdirtyContainers.map(async (c) =>\n\t\t\t\t\t\tPromise.race([\n\t\t\t\t\t\t\ttimeoutPromise((resolve) => c.once(\"saved\", () => resolve()), {\n\t\t\t\t\t\t\t\terrorMsg: \"Timeout on waiting a container to be saved\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tnew Promise((resolve) => c.once(\"closed\", resolve)),\n\t\t\t\t\t\t]),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Pause all container that was resumed\n\t\t// don't call pause if resumed is empty and pause everything, which is not what we want\n\t\tif (resumed.length !== 0) {\n\t\t\tawait timeoutAwait(this.pauseProcessing(...resumed), {\n\t\t\t\terrorMsg: \"Timeout on waiting for pausing all resumed containers\",\n\t\t\t});\n\t\t}\n\n\t\tdebugWait(\"Synchronized\");\n\t}\n\n\t/**\n\t * Utility to calculate the set of clientId per container in quorum that is NOT associated with\n\t * any container we tracked, indicating there is a pending join or leave op that we need to wait.\n\t *\n\t * @param containersToApply - the set of containers to check\n\t */\n\tprivate getPendingClients(containersToApply: IContainer[]) {\n\t\t// All the clientId we track should be a superset of the quorum, otherwise, we are missing\n\t\t// leave messages\n\t\tconst openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);\n\t\tconst openedClientId = openedDocuments.map((container) => container.clientId);\n\n\t\tconst pendingClients: [IContainer, Set<string>][] = [];\n\t\tcontainersToApply.forEach((container) => {\n\t\t\tconst pendingClientId = new Set<string>();\n\t\t\tconst quorum = container.getQuorum();\n\t\t\tquorum.getMembers().forEach((client, clientId) => {\n\t\t\t\t// ignore summarizer\n\t\t\t\tif (!client.client.details.capabilities.interactive && !this.syncSummarizerClients) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!openedClientId.includes(clientId)) {\n\t\t\t\t\tpendingClientId.add(clientId);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (pendingClientId.size !== 0) {\n\t\t\t\tpendingClients.push([container, pendingClientId]);\n\t\t\t}\n\t\t});\n\t\treturn pendingClients;\n\t}\n\n\t/**\n\t * Utility to check synchronization based on sequence number\n\t * See ensureSynchronized for more detail\n\t *\n\t * @param containersToApply - the set of containers to check\n\t */\n\tprivate needSequenceNumberSynchronize(containersToApply: NonEmptyArray<IContainer>) {\n\t\t// If there is a pending proposal, wait for it to be accepted\n\t\tconst minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n\t\tif (minSeqNum < this.lastProposalSeqNum) {\n\t\t\treturn {\n\t\t\t\treason: \"Proposal\",\n\t\t\t\tmessage: `waiting for MSN to advance to proposal at sequence number ${this.lastProposalSeqNum}`,\n\t\t\t};\n\t\t}\n\n\t\t// clientSequenceNumber check detects ops in flight, both on the wire and in the outbound queue\n\t\t// We need both client sequence number and isDirty check because:\n\t\t// - Currently isDirty flag ignores ops for task scheduler, so we need the client sequence number check\n\t\t// - But isDirty flags include ops during forceReadonly and disconnected, because we don't submit\n\t\t// the ops in the first place, clientSequenceNumber is not assigned\n\n\t\tconst containerWithInflightOps = containersToApply.filter((container) => {\n\t\t\tif (container.deltaManager.readOnlyInfo.readonly === true) {\n\t\t\t\t// Ignore readonly container. the clientSeqNum and clientSeqNumObserved might be out of sync\n\t\t\t\t// because we transition to readonly when outbound is not empty or the in transit op got lost\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Note that in read only mode, the op won't be submitted\n\t\t\tlet deltaManager = container.deltaManager as any;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst { trailingNoOps } = this.containers.get(container)!;\n\t\t\t// Back-compat: lastSubmittedClientId/clientSequenceNumber/clientSequenceNumberObserved moved to ConnectionManager in 0.53\n\t\t\tif (!(\"clientSequenceNumber\" in deltaManager)) {\n\t\t\t\tdeltaManager = deltaManager.connectionManager;\n\t\t\t}\n\t\t\tassert(\"clientSequenceNumber\" in deltaManager, \"no clientSequenceNumber\");\n\t\t\tassert(\"clientSequenceNumberObserved\" in deltaManager, \"no clientSequenceNumber\");\n\t\t\t// If last submittedClientId isn't the current clientId, then we haven't send any ops\n\t\t\treturn (\n\t\t\t\tdeltaManager.lastSubmittedClientId === container.clientId &&\n\t\t\t\tdeltaManager.clientSequenceNumber !==\n\t\t\t\t\t(deltaManager.clientSequenceNumberObserved as number) + trailingNoOps\n\t\t\t);\n\t\t});\n\n\t\tif (containerWithInflightOps.length !== 0) {\n\t\t\treturn {\n\t\t\t\treason: \"InflightOps\",\n\t\t\t\tmessage: `waiting for containers with inflight ops: ${this.containerIndexStrings(\n\t\t\t\t\tcontainerWithInflightOps,\n\t\t\t\t)}`,\n\t\t\t};\n\t\t}\n\n\t\t// Check to see if all the container has process the same number of ops.\n\t\tconst maxSeqNum = Math.max(\n\t\t\t...containersToApply.map((c) => c.deltaManager.lastSequenceNumber),\n\t\t);\n\t\tconst containerWithPendingIncoming = containersToApply.filter(\n\t\t\t(c) => c.deltaManager.lastSequenceNumber !== maxSeqNum,\n\t\t);\n\t\tif (containerWithPendingIncoming.length !== 0) {\n\t\t\treturn {\n\t\t\t\treason: \"Pending\",\n\t\t\t\tmessage: `waiting for containers with pending incoming ops up to sequence number ${maxSeqNum}: ${this.containerIndexStrings(\n\t\t\t\t\tcontainerWithPendingIncoming,\n\t\t\t\t)}`,\n\t\t\t};\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate containerIndexStrings(containers: IContainer[]) {\n\t\treturn containers.map(\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t(c) => this.containers.get(c)!.index,\n\t\t);\n\t}\n\n\t/**\n\t * Utility to wait for any clientId in quorum that is NOT associated with any container we\n\t * tracked, indicating there is a pending join or leave op that we need to wait.\n\t *\n\t * Note that this function doesn't account for container that got added after we started waiting\n\t *\n\t * @param containersToApply - the set of containers to wait for any inbound ops for\n\t */\n\tprivate async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {\n\t\tconst unconnectedClients = Array.from(this.containers.keys()).filter(\n\t\t\t(c) => !c.closed && c.connectionState !== ConnectionState.Connected,\n\t\t);\n\t\treturn Promise.all(\n\t\t\tpendingClients.map(async ([container, pendingClientId]) => {\n\t\t\t\treturn new Promise<void>((resolve) => {\n\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\tunconnectedClients.forEach((c) => c.off(\"connected\", handler));\n\t\t\t\t\t\tcontainer.getQuorum().off(\"removeMember\", handler);\n\t\t\t\t\t};\n\t\t\t\t\tconst handler = (clientId: string) => {\n\t\t\t\t\t\tpendingClientId.delete(clientId);\n\t\t\t\t\t\tif (pendingClientId.size === 0) {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst index = this.containers.get(container)!.index;\n\t\t\t\t\tdebugWait(\n\t\t\t\t\t\t`${index}: Waiting for pending clients ${Array.from(pendingClientId.keys())}`,\n\t\t\t\t\t);\n\t\t\t\t\tunconnectedClients.forEach((c) => c.on(\"connected\", handler));\n\t\t\t\t\tcontainer.getQuorum().on(\"removeMember\", handler);\n\t\t\t\t\tcontainer.on(\"closed\", () => {\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * Utility to wait for any inbound ops from a set of containers\n\t * @param containersToApply - the set of containers to wait for any inbound ops for\n\t */\n\tprivate async waitForAnyInboundOps(containersToApply: IContainer[]) {\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tconst handler = () => {\n\t\t\t\tcontainersToApply.map((c) => {\n\t\t\t\t\ttoIDeltaManagerFull(c.deltaManager).inbound.off(\"push\", handler);\n\t\t\t\t});\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tcontainersToApply.map((c) => {\n\t\t\t\ttoIDeltaManagerFull(c.deltaManager).inbound.on(\"push\", handler);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Resume all queue activities on all paused tracked containers and return them\n\t */\n\tpublic resumeProcessing(...containers: IContainer[]) {\n\t\tconst resumed: IContainer[] = [];\n\t\tconst containersToApply = this.getContainers(containers);\n\t\tfor (const container of containersToApply) {\n\t\t\tconst record = this.containers.get(container);\n\t\t\tassert(\n\t\t\t\trecord?.pauseP === undefined,\n\t\t\t\t\"Cannot resume container while pausing is in progress\",\n\t\t\t);\n\t\t\tif (record?.paused === true) {\n\t\t\t\tdebugWait(`${record.index}: container resumed`);\n\t\t\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\t\t\tdeltaManagerFull.inbound.resume();\n\t\t\t\tdeltaManagerFull.outbound.resume();\n\t\t\t\tresumed.push(container);\n\t\t\t\trecord.paused = false;\n\t\t\t}\n\t\t}\n\t\treturn resumed;\n\t}\n\n\t/**\n\t * Pause all queue activities on the containers given, or all tracked containers\n\t * Any containers given that is not tracked will be ignored.\n\t *\n\t * When a container is paused, it is assumed that we want fine grain control over op\n\t * sequencing. This function will prepare the container and force it into write mode to\n\t * avoid missing join messages or change the sequence of event when switching from read to\n\t * write mode.\n\t */\n\tpublic async pauseProcessing(...containers: IContainer[]) {\n\t\tconst waitP: Promise<void>[] = [];\n\t\tconst containersToApply = this.getContainers(containers);\n\t\tfor (const container of containersToApply) {\n\t\t\tconst record = this.containers.get(container);\n\t\t\tif (record !== undefined && !record.paused) {\n\t\t\t\tif (record.pauseP === undefined) {\n\t\t\t\t\trecord.pauseP = this.pauseContainer(container, record);\n\t\t\t\t}\n\t\t\t\twaitP.push(record.pauseP);\n\t\t\t}\n\t\t}\n\t\tawait Promise.all(waitP);\n\t}\n\n\t/**\n\t * When a container is paused, it is assumed that we want fine grain control over op\n\t * sequencing. This function will prepare the container and force it into write mode to\n\t * avoid missing join messages or change the sequence of event when switching from read to\n\t * write mode.\n\t *\n\t * @param container - the container to pause\n\t * @param record - the record for the container\n\t */\n\tprivate async pauseContainer(container: IContainer, record: ContainerRecord) {\n\t\tdebugWait(`${record.index}: pausing container`);\n\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\tassert(!deltaManagerFull.outbound.paused, \"Container should not be paused yet\");\n\t\tassert(!deltaManagerFull.inbound.paused, \"Container should not be paused yet\");\n\n\t\t// Pause outbound\n\t\tdebugWait(`${record.index}: pausing container outbound queues`);\n\t\tawait deltaManagerFull.outbound.pause();\n\n\t\t// Ensure the container is connected first.\n\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\tdebugWait(`${record.index}: Wait for container connection`);\n\t\t\tawait waitForContainerConnection(container);\n\t\t}\n\n\t\t// Check if the container is in write mode\n\t\tif (!container.deltaManager.active) {\n\t\t\tlet proposalP: Promise<boolean> | undefined;\n\t\t\tif (deltaManagerFull.outbound.idle) {\n\t\t\t\t// Need to generate an op to force write mode\n\t\t\t\tdebugWait(`${record.index}: container force write connection`);\n\t\t\t\tconst maybeContainer = container as Partial<IContainer>;\n\t\t\t\tconst codeProposal = maybeContainer.getLoadedCodeDetails\n\t\t\t\t\t? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\t\tcontainer.getLoadedCodeDetails()!\n\t\t\t\t\t: (container as any).chaincodePackage;\n\n\t\t\t\tproposalP = container.proposeCodeDetails(codeProposal);\n\t\t\t}\n\n\t\t\t// Wait for nack\n\t\t\tdebugWait(`${record.index}: Wait for container disconnect`);\n\t\t\tdeltaManagerFull.outbound.resume();\n\t\t\tawait new Promise<void>((resolve) => container.once(\"disconnected\", resolve));\n\t\t\tconst accepted = proposalP ? await proposalP : false;\n\t\t\tassert(!accepted, \"A proposal in read mode should be rejected\");\n\t\t\tawait deltaManagerFull.outbound.pause();\n\n\t\t\t// Ensure the container is reconnect.\n\t\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\t\tdebugWait(`${record.index}: Wait for container reconnection`);\n\t\t\t\tawait waitForContainerConnection(container);\n\t\t\t}\n\t\t}\n\n\t\tdebugWait(`${record.index}: pausing container inbound queues`);\n\n\t\t// Pause inbound\n\t\tawait deltaManagerFull.inbound.pause();\n\n\t\tdebugWait(`${record.index}: container paused`);\n\n\t\trecord.pauseP = undefined;\n\t\trecord.paused = true;\n\t}\n\n\t/**\n\t * Pause all queue activities on all tracked containers, and resume only\n\t * inbound to process ops until it is idle. All queues are left in the paused state\n\t * after the function.\n\t *\n\t * Pausing will switch the container to write mode. See `pauseProcessing`\n\t */\n\tpublic async processIncoming(...containers: IContainer[]) {\n\t\treturn this.processQueue(\n\t\t\tcontainers,\n\t\t\t(container) => toIDeltaManagerFull(container.deltaManager).inbound,\n\t\t);\n\t}\n\n\t/**\n\t * Pause all queue activities on all tracked containers, and resume only\n\t * outbound to process ops until it is idle. All queues are left in the paused state\n\t * after the function.\n\t *\n\t * Pausing will switch the container to write mode. See `pauseProcessing`\n\t */\n\tpublic async processOutgoing(...containers: IContainer[]) {\n\t\treturn this.processQueue(\n\t\t\tcontainers,\n\t\t\t(container) => toIDeltaManagerFull(container.deltaManager).outbound,\n\t\t);\n\t}\n\n\t/**\n\t * Implementation of processIncoming and processOutgoing\n\t */\n\tprivate async processQueue<U>(\n\t\tcontainers: IContainer[],\n\t\tgetQueue: (container: IContainer) => IDeltaQueue<U>,\n\t) {\n\t\tawait this.pauseProcessing(...containers);\n\t\tconst resumed: IDeltaQueue<U>[] = [];\n\n\t\tconst containersToApply = this.getContainers(containers);\n\n\t\tconst inflightTracker = new Map<IContainer, number>();\n\t\tconst cleanup: (() => void)[] = [];\n\t\tfor (const container of containersToApply) {\n\t\t\tassert(\n\t\t\t\tcontainer.deltaManager.active,\n\t\t\t\t\"Container should be connected in write mode already\",\n\t\t\t);\n\n\t\t\tconst queue = getQueue(container);\n\n\t\t\t// track the outgoing ops (if any) to make sure they make the round trip to at least to the same client\n\t\t\t// to make sure they are sequenced.\n\t\t\tcleanup.push(this.setupInOutTracker(container, inflightTracker));\n\t\t\tqueue.resume();\n\t\t\tresumed.push(queue);\n\t\t}\n\n\t\twhile (resumed.some((queue) => !queue.idle)) {\n\t\t\tdebugWait(\"Wait until queue is idle\");\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tsetTimeout(resolve, 0);\n\t\t\t});\n\t\t}\n\n\t\t// Make sure all the op that we sent out are acked first\n\t\t// This is no op if we are processing incoming\n\t\tif (inflightTracker.size) {\n\t\t\tdebugWait(\"Wait for inflight ops\");\n\t\t\tdo {\n\t\t\t\tawait this.waitForAnyInboundOps(containersToApply);\n\t\t\t} while (inflightTracker.size);\n\t\t}\n\n\t\t// remove the handlers\n\t\tcleanup.forEach((clean) => clean());\n\n\t\tawait Promise.all(resumed.map(async (queue) => queue.pause()));\n\t}\n\n\t/**\n\t * Utility to set up listener to track the outbound ops until it round trip back\n\t * Returns a function to remove the handler after it is done.\n\t *\n\t * @param container - the container to setup\n\t * @param inflightTracker - a map to track the clientSequenceNumber per container it expect to get ops back\n\t */\n\tprivate setupInOutTracker(container: IContainer, inflightTracker: Map<IContainer, number>) {\n\t\tconst outHandler = (messages: IDocumentMessage[]) => {\n\t\t\tfor (const message of messages) {\n\t\t\t\tif (!canBeCoalescedByService(message)) {\n\t\t\t\t\tinflightTracker.set(container, message.clientSequenceNumber);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconst inHandler = (message: ISequencedDocumentMessage) => {\n\t\t\tif (\n\t\t\t\t!canBeCoalescedByService(message) &&\n\t\t\t\tmessage.clientId === container.clientId &&\n\t\t\t\tinflightTracker.get(container) === message.clientSequenceNumber\n\t\t\t) {\n\t\t\t\tinflightTracker.delete(container);\n\t\t\t}\n\t\t};\n\n\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\tdeltaManagerFull.outbound.on(\"op\", outHandler);\n\t\tdeltaManagerFull.inbound.on(\"push\", inHandler);\n\n\t\treturn () => {\n\t\t\tdeltaManagerFull.outbound.off(\"op\", outHandler);\n\t\t\tdeltaManagerFull.inbound.off(\"push\", inHandler);\n\t\t};\n\t}\n\n\t/**\n\t * Setup debug traces for connection and ops\n\t */\n\tprivate setupTrace(container: IContainer, index: number) {\n\t\tif (debugOp.enabled) {\n\t\t\tconst getContentsString = (type: string, msgContents: any) => {\n\t\t\t\ttry {\n\t\t\t\t\tif (type !== MessageType.Operation) {\n\t\t\t\t\t\tif (typeof msgContents === \"string\") {\n\t\t\t\t\t\t\treturn msgContents;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn JSON.stringify(msgContents);\n\t\t\t\t\t}\n\t\t\t\t\tlet address = \"\";\n\n\t\t\t\t\t// contents comes in the wire as JSON string (\"push\" event)\n\t\t\t\t\t// But already parsed when apply (\"op\" event)\n\t\t\t\t\tlet contents =\n\t\t\t\t\t\ttypeof msgContents === \"string\" ? JSON.parse(msgContents) : msgContents;\n\t\t\t\t\twhile (contents !== undefined && contents !== null) {\n\t\t\t\t\t\tif (contents.contents?.address !== undefined) {\n\t\t\t\t\t\t\taddress += `/${contents.contents.address}`;\n\t\t\t\t\t\t\tcontents = contents.contents.contents;\n\t\t\t\t\t\t} else if (contents.content?.address !== undefined) {\n\t\t\t\t\t\t\taddress += `/${contents.content.address}`;\n\t\t\t\t\t\t\tcontents = contents.content.contents;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (address) {\n\t\t\t\t\t\treturn `${address} ${JSON.stringify(contents)}`;\n\t\t\t\t\t}\n\t\t\t\t\treturn JSON.stringify(contents);\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\treturn `${e.message}: ${e.stack}`;\n\t\t\t\t}\n\t\t\t};\n\t\t\tdebugOp(`${index}: ADD: clientId: ${container.clientId}`);\n\t\t\tconst deltaManagerFull = toIDeltaManagerFull(container.deltaManager);\n\t\t\tdeltaManagerFull.outbound.on(\"op\", (messages) => {\n\t\t\t\tfor (const msg of messages) {\n\t\t\t\t\tdebugOp(\n\t\t\t\t\t\t`${index}: OUT: ` +\n\t\t\t\t\t\t\t`cli: ${msg.clientSequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`rsq: ${msg.referenceSequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`${msg.type} ${getContentsString(msg.type, msg.contents)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst getInboundHandler = (type: string) => {\n\t\t\t\treturn (msg: ISequencedDocumentMessage) => {\n\t\t\t\t\tconst clientSeq =\n\t\t\t\t\t\tmsg.clientId === container.clientId\n\t\t\t\t\t\t\t? `cli: ${msg.clientSequenceNumber.toString().padStart(3)}`\n\t\t\t\t\t\t\t: \" \";\n\t\t\t\t\tdebugOp(\n\t\t\t\t\t\t`${index}: ${type}: seq: ${msg.sequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`${clientSeq} min: ${msg.minimumSequenceNumber.toString().padStart(3)} ` +\n\t\t\t\t\t\t\t`${msg.type} ${getContentsString(msg.type, msg.contents)}`,\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t};\n\t\t\tdeltaManagerFull.inbound.on(\"push\", getInboundHandler(\"IN \"));\n\t\t\tdeltaManagerFull.inbound.on(\"op\", getInboundHandler(\"OP \"));\n\t\t\tcontainer.deltaManager.on(\"connect\", (details) => {\n\t\t\t\tdebugOp(`${index}: CON: clientId: ${details.clientId}`);\n\t\t\t});\n\t\t\tcontainer.deltaManager.on(\"disconnect\", (reason) => {\n\t\t\t\tdebugOp(`${index}: DIS: ${reason}`);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Filter out the opened containers based on param.\n\t * @param containers - The container to filter to. If the array is empty, it means don't filter and return\n\t * all open containers.\n\t */\n\tprivate getContainers(containers: IContainer[]) {\n\t\tconst containersToApply =\n\t\t\tcontainers.length === 0 ? Array.from(this.containers.keys()) : containers;\n\t\treturn containersToApply.filter((container) => !container.closed);\n\t}\n}\n"]}
|
package/dist/localCodeLoader.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.LocalCodeLoader = exports.createDataStoreFactory = void 0;
|
|
8
8
|
const assert_1 = require("assert");
|
|
9
|
-
// eslint-disable-next-line import/no-deprecated
|
|
9
|
+
// eslint-disable-next-line import-x/no-deprecated
|
|
10
10
|
const containerRuntimeFactories_js_1 = require("./containerRuntimeFactories.js");
|
|
11
11
|
/**
|
|
12
12
|
* @internal
|
|
@@ -53,7 +53,7 @@ class LocalCodeLoader {
|
|
|
53
53
|
fluidModule = {
|
|
54
54
|
fluidExport: {
|
|
55
55
|
...maybeExport,
|
|
56
|
-
// eslint-disable-next-line import/no-deprecated
|
|
56
|
+
// eslint-disable-next-line import-x/no-deprecated
|
|
57
57
|
IRuntimeFactory: new containerRuntimeFactories_js_1.ContainerRuntimeFactoryWithDefaultDataStore({
|
|
58
58
|
defaultFactory,
|
|
59
59
|
registryEntries: [[defaultFactory.type, Promise.resolve(defaultFactory)]],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localCodeLoader.js","sourceRoot":"","sources":["../src/localCodeLoader.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mCAA0C;AAkB1C,
|
|
1
|
+
{"version":3,"file":"localCodeLoader.js","sourceRoot":"","sources":["../src/localCodeLoader.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\n\nimport {\n\tICodeDetailsLoader,\n\tIFluidCodeDetails,\n\tIFluidModule,\n\tIFluidModuleWithDetails,\n\tIProvideFluidCodeDetailsComparer,\n\tIProvideRuntimeFactory,\n} from \"@fluidframework/container-definitions/internal\";\nimport { IContainerRuntimeOptions } from \"@fluidframework/container-runtime/internal\";\nimport {\n\tIProvideFluidDataStoreFactory,\n\tIProvideFluidDataStoreRegistry,\n\ttype IFluidDataStoreFactory,\n\ttype IFluidDataStoreRegistry,\n} from \"@fluidframework/runtime-definitions/internal\";\n\n// eslint-disable-next-line import-x/no-deprecated\nimport { ContainerRuntimeFactoryWithDefaultDataStore } from \"./containerRuntimeFactories.js\";\n\n/**\n * @internal\n */\nexport type SupportedExportInterfaces = Partial<\n\tIProvideRuntimeFactory &\n\t\tIProvideFluidDataStoreFactory &\n\t\tIProvideFluidDataStoreRegistry &\n\t\tIProvideFluidCodeDetailsComparer\n>;\n\n// Represents the entry point for a Fluid container.\n/**\n * @internal\n */\nexport type fluidEntryPoint = SupportedExportInterfaces | IFluidModule;\n\n/**\n * @internal\n */\nexport type Factory = IFluidDataStoreFactory & Partial<IProvideFluidDataStoreRegistry>;\n\n/**\n * @internal\n */\nexport function createDataStoreFactory(\n\ttype: string,\n\tfactory: Factory | Promise<Factory>,\n): IFluidDataStoreFactory & IFluidDataStoreRegistry {\n\treturn {\n\t\ttype,\n\t\tget IFluidDataStoreFactory() {\n\t\t\treturn this;\n\t\t},\n\t\tget IFluidDataStoreRegistry() {\n\t\t\treturn this;\n\t\t},\n\t\tinstantiateDataStore: async (context, existing) =>\n\t\t\t(await factory).instantiateDataStore(context, existing),\n\t\tget: async (name: string) => (await factory).IFluidDataStoreRegistry?.get(name),\n\t};\n}\n\n/**\n * A simple code loader that caches a mapping of package name to a Fluid entry point.\n * On load, it retrieves the entry point matching the package name in the given code details.\n * @internal\n */\nexport class LocalCodeLoader implements ICodeDetailsLoader {\n\tprivate readonly fluidPackageCache = new Map<string, IFluidModuleWithDetails>();\n\n\tconstructor(\n\t\tpackageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n\t\truntimeOptions?: IContainerRuntimeOptions,\n\t) {\n\t\tfor (const entry of packageEntries) {\n\t\t\t// Store the entry point against a unique id in the fluidPackageCache.\n\t\t\t// For code details containing a package name, use the package name as the id.\n\t\t\t// For code details containing a Fluid package, create a unique id from the package name and version.\n\t\t\tconst source = entry[0];\n\t\t\tconst pkgId =\n\t\t\t\ttypeof source.package === \"string\"\n\t\t\t\t\t? source.package\n\t\t\t\t\t: `${source.package.name}@${source.package.version}`;\n\t\t\tlet fluidModule = entry[1] as IFluidModule;\n\t\t\tif (fluidModule?.fluidExport === undefined) {\n\t\t\t\tconst maybeExport = fluidModule as SupportedExportInterfaces;\n\n\t\t\t\tif (maybeExport.IRuntimeFactory !== undefined) {\n\t\t\t\t\tfluidModule = { fluidExport: maybeExport };\n\t\t\t\t} else {\n\t\t\t\t\tassert(maybeExport.IFluidDataStoreFactory !== undefined);\n\t\t\t\t\tconst defaultFactory = createDataStoreFactory(\n\t\t\t\t\t\t\"default\",\n\t\t\t\t\t\tmaybeExport.IFluidDataStoreFactory,\n\t\t\t\t\t);\n\t\t\t\t\tfluidModule = {\n\t\t\t\t\t\tfluidExport: {\n\t\t\t\t\t\t\t...maybeExport,\n\t\t\t\t\t\t\t// eslint-disable-next-line import-x/no-deprecated\n\t\t\t\t\t\t\tIRuntimeFactory: new ContainerRuntimeFactoryWithDefaultDataStore({\n\t\t\t\t\t\t\t\tdefaultFactory,\n\t\t\t\t\t\t\t\tregistryEntries: [[defaultFactory.type, Promise.resolve(defaultFactory)]],\n\t\t\t\t\t\t\t\truntimeOptions,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst runtimeFactory = {\n\t\t\t\tmodule: fluidModule,\n\t\t\t\tdetails: source,\n\t\t\t};\n\n\t\t\tthis.fluidPackageCache.set(pkgId, runtimeFactory);\n\t\t}\n\t}\n\n\t/**\n\t * It finds the entry point for the package name in the given source and return it\n\t * as a Fluid module.\n\t * @param source - Details of where to find chaincode\n\t */\n\tpublic async load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails> {\n\t\t// Get the entry point for from the fluidPackageCache for the given code details.\n\t\t// For code details containing a package name, use the package name as the id.\n\t\t// For code details containing a Fluid package, create a unique id from the package name and version.\n\t\tconst pkdId =\n\t\t\ttypeof source.package === \"string\"\n\t\t\t\t? source.package\n\t\t\t\t: `${source.package.name}@${source.package.version}`;\n\n\t\tconst entryPoint = this.fluidPackageCache.get(pkdId);\n\t\tif (entryPoint === undefined) {\n\t\t\tthrow new Error(`Cannot find package ${pkdId}`);\n\t\t}\n\t\treturn entryPoint;\n\t}\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/test-utils";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.73.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/test-utils";
|
|
11
|
-
exports.pkgVersion = "2.
|
|
11
|
+
exports.pkgVersion = "2.73.0";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/test-utils\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/test-utils\";\nexport const pkgVersion = \"2.73.0\";\n"]}
|