@fluidframework/test-utils 2.5.0 → 2.10.0-305357
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/dist/containerUtils.d.ts +7 -1
- package/dist/containerUtils.d.ts.map +1 -1
- package/dist/containerUtils.js +9 -1
- package/dist/containerUtils.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/loaderContainerTracker.d.ts.map +1 -1
- package/dist/loaderContainerTracker.js +27 -22
- package/dist/loaderContainerTracker.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/containerUtils.d.ts +7 -1
- package/lib/containerUtils.d.ts.map +1 -1
- package/lib/containerUtils.js +7 -0
- package/lib/containerUtils.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/loaderContainerTracker.d.ts.map +1 -1
- package/lib/loaderContainerTracker.js +28 -23
- package/lib/loaderContainerTracker.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +39 -26
- package/src/containerUtils.ts +27 -1
- package/src/index.ts +1 -0
- package/src/loaderContainerTracker.ts +34 -23
- package/src/packageVersion.ts +1 -1
package/lib/containerUtils.js
CHANGED
|
@@ -76,4 +76,11 @@ export async function getDataStoreEntryPointBackCompat(dataStore) {
|
|
|
76
76
|
assert(response.status === 200, "empty request should return data object");
|
|
77
77
|
return response.value;
|
|
78
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
export function toIDeltaManagerFull(deltaManager) {
|
|
83
|
+
assert("inbound" in deltaManager && "outbound" in deltaManager, "Delta manager does not have inbound/outbound queues.");
|
|
84
|
+
return deltaManager;
|
|
85
|
+
}
|
|
79
86
|
//# sourceMappingURL=containerUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerUtils.js","sourceRoot":"","sources":["../src/containerUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"containerUtils.js","sourceRoot":"","sources":["../src/containerUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEnE,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAQ7D,OAAO,EAAqC,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC/C,SAAqB,EACrB,uBAAgC,IAAI,EACpC,cAAiC;IAEjC,IAAI,SAAS,CAAC,eAAe,KAAK,eAAe,CAAC,SAAS,EAAE,CAAC;QAC7D,MAAM,QAAQ,GAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrD,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7C,IAAI,oBAAoB,EAAE,CAAC;gBAC1B,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACpD,CAAC;QACF,CAAC,CAAC;QAEF,OAAO,cAAc,KAAK,SAAS;YAClC,CAAC,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC;YACvB,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAC7C,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAI,SAAqB;IAC9E,IAAI,SAAS,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,aAAa,EAAE,CAAC;QACnD,0GAA0G;QAC1G,qGAAqG;QACrG,gHAAgH;QAChH,oGAAoG;QACpG,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,UAAe,CAAC;QACxB,CAAC;IACF,CAAC;IACD,MAAM,QAAQ,GAAc,MAAO,SAAiB,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3E,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,kDAAkD,CAAC,CAAC;IACpF,OAAO,QAAQ,CAAC,KAAU,CAAC;AAC5B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAI,SAAqB;IAC9E,IAAI,SAAS,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,SAAS,CAAC,UAAU,CAAC,GAAG,EAAgB,CAAC;IACjD,CAAC;IACD,MAAM,QAAQ,GAAc,MAAO,SAAiB,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1E,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,yCAAyC,CAAC,CAAC;IAC3E,OAAO,QAAQ,CAAC,KAAU,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAClC,YAEsB;IAEtB,MAAM,CACL,SAAS,IAAI,YAAY,IAAI,UAAU,IAAI,YAAY,EACvD,sDAAsD,CACtD,CAAC;IACF,OAAO,YAE2E,CAAC;AACpF,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tIContainer,\n\tIDeltaManager,\n\ttype IDeltaManagerFull,\n} from \"@fluidframework/container-definitions/internal\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport { IResponse } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { IDeltaManagerErased } from \"@fluidframework/datastore-definitions/internal\";\nimport type {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { IDataStore } from \"@fluidframework/runtime-definitions/internal\";\n\nimport { PromiseExecutor, TimeoutWithError, timeoutPromise } from \"./timeoutUtils.js\";\n\n/**\n * Utility function to wait for the specified Container to be in Connected state.\n * If the Container is already connected, the Promise returns immediately; otherwise it resolves when the Container emits\n * its 'connected' event.\n * If failOnContainerClose === true, the returned Promise will be rejected if the container emits a 'closed' event\n * before a 'connected' event.\n * @param container - The container to wait for.\n * @param failOnContainerClose - If true, the returned Promise will be rejected if the container emits a 'closed' event\n * before a 'connected' event.\n * Defaults to true.\n * @param timeoutOptions - Options related to the behavior of the timeout.\n * If provided, the returned Promise will reject if the container hasn't emitted relevant events in timeoutOptions.durationMs.\n * If not provided, the Promise will wait indefinitely for the Container to emit its 'connected' (or 'closed', if\n * failOnContainerClose === true) event.\n *\n * @returns A Promise that either:\n * - Resolves when the specified container emits a 'connected' event (or immediately if the Container is already connected).\n * - Rejects if failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event.\n * - Rejects after timeoutOptions.durationMs if timeoutOptions !== undefined and the container does not emit relevant\n * events, within that timeframe.\n * @internal\n */\nexport async function waitForContainerConnection(\n\tcontainer: IContainer,\n\tfailOnContainerClose: boolean = true,\n\ttimeoutOptions?: TimeoutWithError,\n): Promise<void> {\n\tif (container.connectionState !== ConnectionState.Connected) {\n\t\tconst executor: PromiseExecutor = (resolve, reject) => {\n\t\t\tcontainer.once(\"connected\", () => resolve());\n\t\t\tif (failOnContainerClose) {\n\t\t\t\tcontainer.once(\"closed\", (error) => reject(error));\n\t\t\t}\n\t\t};\n\n\t\treturn timeoutOptions === undefined\n\t\t\t? new Promise(executor)\n\t\t\t: timeoutPromise(executor, timeoutOptions);\n\t}\n}\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 */\nexport async function getContainerEntryPointBackCompat<T>(container: IContainer): Promise<T> {\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 version 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 T;\n\t\t}\n\t}\n\tconst response: IResponse = await (container as any).request({ url: \"/\" });\n\tassert(response.status === 200, \"requesting '/' should return default data object\");\n\treturn response.value as T;\n}\n\n/**\n * This function should ONLY be used for back compat purposes\n * Older supported versions of IDataStore do not have the \"entryPoint\" property, so we need to fallback to \"request\"\n * This function can be removed once back-compat support for IDataStore moves to 2.0.0-internal.7.0.0\n *\n * @internal\n */\nexport async function getDataStoreEntryPointBackCompat<T>(dataStore: IDataStore): Promise<T> {\n\tif (dataStore.entryPoint !== undefined) {\n\t\treturn dataStore.entryPoint.get() as Promise<T>;\n\t}\n\tconst response: IResponse = await (dataStore as any).request({ url: \"\" });\n\tassert(response.status === 200, \"empty request should return data object\");\n\treturn response.value as T;\n}\n\n/**\n * @internal\n */\nexport function toIDeltaManagerFull(\n\tdeltaManager:\n\t\t| IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>\n\t\t| IDeltaManagerErased,\n): IDeltaManagerFull {\n\tassert(\n\t\t\"inbound\" in deltaManager && \"outbound\" in deltaManager,\n\t\t\"Delta manager does not have inbound/outbound queues.\",\n\t);\n\treturn deltaManager as unknown as\n\t\t| IDeltaManagerErased\n\t\t| IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> as IDeltaManagerFull;\n}\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -14,6 +14,6 @@ export { ChannelFactoryRegistry, TestFluidObject, TestFluidObjectFactory, } from
|
|
|
14
14
|
export { createDocumentId, DataObjectFactoryType, EventAndErrorTrackingLogger, type IEventAndErrorTrackingLogger, getUnexpectedLogErrorException, IDocumentIdStrategy, IOpProcessingController, ITestContainerConfig, ITestObjectProvider, TestObjectProvider, TestObjectProviderWithVersionedLoad, } from "./testObjectProvider.js";
|
|
15
15
|
export { createSummarizer, createSummarizerCore, createSummarizerFromFactory, summarizeNow, SummaryInfo, } from "./TestSummaryUtils.js";
|
|
16
16
|
export { defaultTimeoutDurationMs, timeoutAwait, timeoutPromise, type TimeoutDurationOption, type TimeoutWithError, type TimeoutWithValue, } from "./timeoutUtils.js";
|
|
17
|
-
export { waitForContainerConnection, getContainerEntryPointBackCompat, getDataStoreEntryPointBackCompat, } from "./containerUtils.js";
|
|
17
|
+
export { toIDeltaManagerFull, waitForContainerConnection, getContainerEntryPointBackCompat, getDataStoreEntryPointBackCompat, } from "./containerUtils.js";
|
|
18
18
|
export { createContainerRuntimeFactoryWithDefaultDataStore } from "./testContainerRuntimeFactoryWithDefaultDataStore.js";
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACN,eAAe,EACf,eAAe,EACf,yBAAyB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACN,iCAAiC,EACjC,2BAA2B,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACN,sBAAsB,EACtB,eAAe,EACf,sBAAsB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,KAAK,4BAA4B,EACjC,8BAA8B,EAC9B,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,mCAAmC,GACnC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,YAAY,EACZ,WAAW,GACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,0BAA0B,EAC1B,gCAAgC,EAChC,gCAAgC,GAChC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iDAAiD,EAAE,MAAM,sDAAsD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACN,eAAe,EACf,eAAe,EACf,yBAAyB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACN,iCAAiC,EACjC,2BAA2B,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACN,sBAAsB,EACtB,eAAe,EACf,sBAAsB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,KAAK,4BAA4B,EACjC,8BAA8B,EAC9B,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,mCAAmC,GACnC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,YAAY,EACZ,WAAW,GACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,gCAAgC,EAChC,gCAAgC,GAChC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iDAAiD,EAAE,MAAM,sDAAsD,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -13,6 +13,6 @@ export { TestFluidObject, TestFluidObjectFactory, } from "./testFluidObject.js";
|
|
|
13
13
|
export { createDocumentId, DataObjectFactoryType, EventAndErrorTrackingLogger, getUnexpectedLogErrorException, TestObjectProvider, TestObjectProviderWithVersionedLoad, } from "./testObjectProvider.js";
|
|
14
14
|
export { createSummarizer, createSummarizerCore, createSummarizerFromFactory, summarizeNow, } from "./TestSummaryUtils.js";
|
|
15
15
|
export { defaultTimeoutDurationMs, timeoutAwait, timeoutPromise, } from "./timeoutUtils.js";
|
|
16
|
-
export { waitForContainerConnection, getContainerEntryPointBackCompat, getDataStoreEntryPointBackCompat, } from "./containerUtils.js";
|
|
16
|
+
export { toIDeltaManagerFull, waitForContainerConnection, getContainerEntryPointBackCompat, getDataStoreEntryPointBackCompat, } from "./containerUtils.js";
|
|
17
17
|
export { createContainerRuntimeFactoryWithDefaultDataStore } from "./testContainerRuntimeFactoryWithDefaultDataStore.js";
|
|
18
18
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAEN,eAAe,GAEf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAuB,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACN,iCAAiC,EACjC,2BAA2B,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEN,eAAe,EACf,sBAAsB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAE3B,8BAA8B,EAK9B,kBAAkB,EAClB,mCAAmC,GACnC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,YAAY,GAEZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,cAAc,GAId,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,0BAA0B,EAC1B,gCAAgC,EAChC,gCAAgC,GAChC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iDAAiD,EAAE,MAAM,sDAAsD,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\twrapDocumentService,\n\twrapDocumentServiceFactory,\n\twrapDocumentStorageService,\n} from \"./DriverWrappers.js\";\nexport { IProvideTestFluidObject, ITestFluidObject } from \"./interfaces.js\";\nexport { LoaderContainerTracker } from \"./loaderContainerTracker.js\";\nexport {\n\tfluidEntryPoint,\n\tLocalCodeLoader,\n\tSupportedExportInterfaces,\n} from \"./localCodeLoader.js\";\nexport { createAndAttachContainer, createLoader } from \"./localLoader.js\";\nexport { retryWithEventualValue } from \"./retry.js\";\nexport { createTestConfigProvider, ITestConfigProvider } from \"./TestConfigs.js\";\nexport {\n\tcreateTestContainerRuntimeFactory,\n\tTestContainerRuntimeFactory,\n} from \"./testContainerRuntimeFactory.js\";\nexport {\n\tChannelFactoryRegistry,\n\tTestFluidObject,\n\tTestFluidObjectFactory,\n} from \"./testFluidObject.js\";\nexport {\n\tcreateDocumentId,\n\tDataObjectFactoryType,\n\tEventAndErrorTrackingLogger,\n\ttype IEventAndErrorTrackingLogger,\n\tgetUnexpectedLogErrorException,\n\tIDocumentIdStrategy,\n\tIOpProcessingController,\n\tITestContainerConfig,\n\tITestObjectProvider,\n\tTestObjectProvider,\n\tTestObjectProviderWithVersionedLoad,\n} from \"./testObjectProvider.js\";\nexport {\n\tcreateSummarizer,\n\tcreateSummarizerCore,\n\tcreateSummarizerFromFactory,\n\tsummarizeNow,\n\tSummaryInfo,\n} from \"./TestSummaryUtils.js\";\nexport {\n\tdefaultTimeoutDurationMs,\n\ttimeoutAwait,\n\ttimeoutPromise,\n\ttype TimeoutDurationOption,\n\ttype TimeoutWithError,\n\ttype TimeoutWithValue,\n} from \"./timeoutUtils.js\";\nexport {\n\twaitForContainerConnection,\n\tgetContainerEntryPointBackCompat,\n\tgetDataStoreEntryPointBackCompat,\n} from \"./containerUtils.js\";\nexport { createContainerRuntimeFactoryWithDefaultDataStore } from \"./testContainerRuntimeFactoryWithDefaultDataStore.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAEN,eAAe,GAEf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAuB,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACN,iCAAiC,EACjC,2BAA2B,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEN,eAAe,EACf,sBAAsB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAE3B,8BAA8B,EAK9B,kBAAkB,EAClB,mCAAmC,GACnC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,YAAY,GAEZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,cAAc,GAId,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,gCAAgC,EAChC,gCAAgC,GAChC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iDAAiD,EAAE,MAAM,sDAAsD,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\twrapDocumentService,\n\twrapDocumentServiceFactory,\n\twrapDocumentStorageService,\n} from \"./DriverWrappers.js\";\nexport { IProvideTestFluidObject, ITestFluidObject } from \"./interfaces.js\";\nexport { LoaderContainerTracker } from \"./loaderContainerTracker.js\";\nexport {\n\tfluidEntryPoint,\n\tLocalCodeLoader,\n\tSupportedExportInterfaces,\n} from \"./localCodeLoader.js\";\nexport { createAndAttachContainer, createLoader } from \"./localLoader.js\";\nexport { retryWithEventualValue } from \"./retry.js\";\nexport { createTestConfigProvider, ITestConfigProvider } from \"./TestConfigs.js\";\nexport {\n\tcreateTestContainerRuntimeFactory,\n\tTestContainerRuntimeFactory,\n} from \"./testContainerRuntimeFactory.js\";\nexport {\n\tChannelFactoryRegistry,\n\tTestFluidObject,\n\tTestFluidObjectFactory,\n} from \"./testFluidObject.js\";\nexport {\n\tcreateDocumentId,\n\tDataObjectFactoryType,\n\tEventAndErrorTrackingLogger,\n\ttype IEventAndErrorTrackingLogger,\n\tgetUnexpectedLogErrorException,\n\tIDocumentIdStrategy,\n\tIOpProcessingController,\n\tITestContainerConfig,\n\tITestObjectProvider,\n\tTestObjectProvider,\n\tTestObjectProviderWithVersionedLoad,\n} from \"./testObjectProvider.js\";\nexport {\n\tcreateSummarizer,\n\tcreateSummarizerCore,\n\tcreateSummarizerFromFactory,\n\tsummarizeNow,\n\tSummaryInfo,\n} from \"./TestSummaryUtils.js\";\nexport {\n\tdefaultTimeoutDurationMs,\n\ttimeoutAwait,\n\ttimeoutPromise,\n\ttype TimeoutDurationOption,\n\ttype TimeoutWithError,\n\ttype TimeoutWithValue,\n} from \"./timeoutUtils.js\";\nexport {\n\ttoIDeltaManagerFull,\n\twaitForContainerConnection,\n\tgetContainerEntryPointBackCompat,\n\tgetDataStoreEntryPointBackCompat,\n} from \"./containerUtils.js\";\nexport { createContainerRuntimeFactoryWithDefaultDataStore } from \"./testContainerRuntimeFactoryWithDefaultDataStore.js\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loaderContainerTracker.d.ts","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEN,UAAU,EACV,WAAW,EACX,MAAM,gDAAgD,CAAC;AAiBxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAuBlE;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,uBAAuB;IAIzD,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAHlD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,kBAAkB,CAAa;gBAEV,qBAAqB,GAAE,OAAe;IAEnE;;;OAGG;IACI,GAAG,CAAC,UAAU,SAAS,WAAW,EAAE,MAAM,EAAE,UAAU;IAmB7D;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAoDpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;
|
|
1
|
+
{"version":3,"file":"loaderContainerTracker.d.ts","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEN,UAAU,EACV,WAAW,EACX,MAAM,gDAAgD,CAAC;AAiBxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAuBlE;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,uBAAuB;IAIzD,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAHlD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,kBAAkB,CAAa;gBAEV,qBAAqB,GAAE,OAAe;IAEnE;;;OAGG;IACI,GAAG,CAAC,UAAU,SAAS,WAAW,EAAE,MAAM,EAAE,UAAU;IAmB7D;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAoDpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAwC1B,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACI,KAAK;IAUZ;;;;;;;;;;;;;;;OAeG;IACU,kBAAkB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA2E3E;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;;;;OAKG;IACH,OAAO,CAAC,6BAA6B;IAmErC,OAAO,CAAC,qBAAqB;IAO7B;;;;;;;OAOG;YACW,qBAAqB;IAkCnC;;;OAGG;YACW,oBAAoB;IAclC;;OAEG;IACI,gBAAgB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAqBnD;;;;;;;;OAQG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAexD;;;;;;;;OAQG;YACW,cAAc;IAyD5B;;;;;;OAMG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAOxD;;;;;;OAMG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAOxD;;OAEG;YACW,YAAY;IAgD1B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IA4BzB;;OAEG;IACH,OAAO,CAAC,UAAU;IAuElB;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAKrB"}
|
|
@@ -6,7 +6,7 @@ import { ConnectionState } from "@fluidframework/container-loader";
|
|
|
6
6
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
7
7
|
import { MessageType, } from "@fluidframework/driver-definitions/internal";
|
|
8
8
|
import { canBeCoalescedByService } from "@fluidframework/driver-utils/internal";
|
|
9
|
-
import { waitForContainerConnection } from "./containerUtils.js";
|
|
9
|
+
import { toIDeltaManagerFull, waitForContainerConnection } from "./containerUtils.js";
|
|
10
10
|
import { debug } from "./debug.js";
|
|
11
11
|
import { timeoutAwait, timeoutPromise } from "./timeoutUtils.js";
|
|
12
12
|
const debugOp = debug.extend("ops");
|
|
@@ -89,7 +89,8 @@ export class LoaderContainerTracker {
|
|
|
89
89
|
* @param record - the record to update the trailing op information
|
|
90
90
|
*/
|
|
91
91
|
trackTrailingNoOps(container, record) {
|
|
92
|
-
container.deltaManager
|
|
92
|
+
const deltaManagerFull = toIDeltaManagerFull(container.deltaManager);
|
|
93
|
+
deltaManagerFull.outbound.on("op", (messages) => {
|
|
93
94
|
for (const msg of messages) {
|
|
94
95
|
if (canBeCoalescedByService(msg)) {
|
|
95
96
|
// Track the NoOp that was sent.
|
|
@@ -105,7 +106,7 @@ export class LoaderContainerTracker {
|
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
});
|
|
108
|
-
|
|
109
|
+
deltaManagerFull.inbound.on("push", (message) => {
|
|
109
110
|
// Received the no op back, update the record if we are tracking
|
|
110
111
|
if (canBeCoalescedByService(message) &&
|
|
111
112
|
message.clientId === container.clientId &&
|
|
@@ -358,12 +359,12 @@ export class LoaderContainerTracker {
|
|
|
358
359
|
return new Promise((resolve) => {
|
|
359
360
|
const handler = () => {
|
|
360
361
|
containersToApply.map((c) => {
|
|
361
|
-
c.deltaManager.inbound.off("push", handler);
|
|
362
|
+
toIDeltaManagerFull(c.deltaManager).inbound.off("push", handler);
|
|
362
363
|
});
|
|
363
364
|
resolve();
|
|
364
365
|
};
|
|
365
366
|
containersToApply.map((c) => {
|
|
366
|
-
c.deltaManager.inbound.on("push", handler);
|
|
367
|
+
toIDeltaManagerFull(c.deltaManager).inbound.on("push", handler);
|
|
367
368
|
});
|
|
368
369
|
});
|
|
369
370
|
}
|
|
@@ -378,8 +379,9 @@ export class LoaderContainerTracker {
|
|
|
378
379
|
assert(record?.pauseP === undefined, "Cannot resume container while pausing is in progress");
|
|
379
380
|
if (record?.paused === true) {
|
|
380
381
|
debugWait(`${record.index}: container resumed`);
|
|
381
|
-
container.deltaManager
|
|
382
|
-
|
|
382
|
+
const deltaManagerFull = toIDeltaManagerFull(container.deltaManager);
|
|
383
|
+
deltaManagerFull.inbound.resume();
|
|
384
|
+
deltaManagerFull.outbound.resume();
|
|
383
385
|
resumed.push(container);
|
|
384
386
|
record.paused = false;
|
|
385
387
|
}
|
|
@@ -420,11 +422,12 @@ export class LoaderContainerTracker {
|
|
|
420
422
|
*/
|
|
421
423
|
async pauseContainer(container, record) {
|
|
422
424
|
debugWait(`${record.index}: pausing container`);
|
|
423
|
-
|
|
424
|
-
assert(!
|
|
425
|
+
const deltaManagerFull = toIDeltaManagerFull(container.deltaManager);
|
|
426
|
+
assert(!deltaManagerFull.outbound.paused, "Container should not be paused yet");
|
|
427
|
+
assert(!deltaManagerFull.inbound.paused, "Container should not be paused yet");
|
|
425
428
|
// Pause outbound
|
|
426
429
|
debugWait(`${record.index}: pausing container outbound queues`);
|
|
427
|
-
await
|
|
430
|
+
await deltaManagerFull.outbound.pause();
|
|
428
431
|
// Ensure the container is connected first.
|
|
429
432
|
if (container.connectionState !== ConnectionState.Connected) {
|
|
430
433
|
debugWait(`${record.index}: Wait for container connection`);
|
|
@@ -433,7 +436,7 @@ export class LoaderContainerTracker {
|
|
|
433
436
|
// Check if the container is in write mode
|
|
434
437
|
if (!container.deltaManager.active) {
|
|
435
438
|
let proposalP;
|
|
436
|
-
if (
|
|
439
|
+
if (deltaManagerFull.outbound.idle) {
|
|
437
440
|
// Need to generate an op to force write mode
|
|
438
441
|
debugWait(`${record.index}: container force write connection`);
|
|
439
442
|
const maybeContainer = container;
|
|
@@ -445,11 +448,11 @@ export class LoaderContainerTracker {
|
|
|
445
448
|
}
|
|
446
449
|
// Wait for nack
|
|
447
450
|
debugWait(`${record.index}: Wait for container disconnect`);
|
|
448
|
-
|
|
451
|
+
deltaManagerFull.outbound.resume();
|
|
449
452
|
await new Promise((resolve) => container.once("disconnected", resolve));
|
|
450
453
|
const accepted = proposalP ? await proposalP : false;
|
|
451
454
|
assert(!accepted, "A proposal in read mode should be rejected");
|
|
452
|
-
await
|
|
455
|
+
await deltaManagerFull.outbound.pause();
|
|
453
456
|
// Ensure the container is reconnect.
|
|
454
457
|
if (container.connectionState !== ConnectionState.Connected) {
|
|
455
458
|
debugWait(`${record.index}: Wait for container reconnection`);
|
|
@@ -458,7 +461,7 @@ export class LoaderContainerTracker {
|
|
|
458
461
|
}
|
|
459
462
|
debugWait(`${record.index}: pausing container inbound queues`);
|
|
460
463
|
// Pause inbound
|
|
461
|
-
await
|
|
464
|
+
await deltaManagerFull.inbound.pause();
|
|
462
465
|
debugWait(`${record.index}: container paused`);
|
|
463
466
|
record.pauseP = undefined;
|
|
464
467
|
record.paused = true;
|
|
@@ -471,7 +474,7 @@ export class LoaderContainerTracker {
|
|
|
471
474
|
* Pausing will switch the container to write mode. See `pauseProcessing`
|
|
472
475
|
*/
|
|
473
476
|
async processIncoming(...containers) {
|
|
474
|
-
return this.processQueue(containers, (container) => container.deltaManager.inbound);
|
|
477
|
+
return this.processQueue(containers, (container) => toIDeltaManagerFull(container.deltaManager).inbound);
|
|
475
478
|
}
|
|
476
479
|
/**
|
|
477
480
|
* Pause all queue activities on all tracked containers, and resume only
|
|
@@ -481,7 +484,7 @@ export class LoaderContainerTracker {
|
|
|
481
484
|
* Pausing will switch the container to write mode. See `pauseProcessing`
|
|
482
485
|
*/
|
|
483
486
|
async processOutgoing(...containers) {
|
|
484
|
-
return this.processQueue(containers, (container) => container.deltaManager.outbound);
|
|
487
|
+
return this.processQueue(containers, (container) => toIDeltaManagerFull(container.deltaManager).outbound);
|
|
485
488
|
}
|
|
486
489
|
/**
|
|
487
490
|
* Implementation of processIncoming and processOutgoing
|
|
@@ -541,11 +544,12 @@ export class LoaderContainerTracker {
|
|
|
541
544
|
inflightTracker.delete(container);
|
|
542
545
|
}
|
|
543
546
|
};
|
|
544
|
-
container.deltaManager
|
|
545
|
-
|
|
547
|
+
const deltaManagerFull = toIDeltaManagerFull(container.deltaManager);
|
|
548
|
+
deltaManagerFull.outbound.on("op", outHandler);
|
|
549
|
+
deltaManagerFull.inbound.on("push", inHandler);
|
|
546
550
|
return () => {
|
|
547
|
-
|
|
548
|
-
|
|
551
|
+
deltaManagerFull.outbound.off("op", outHandler);
|
|
552
|
+
deltaManagerFull.inbound.off("push", inHandler);
|
|
549
553
|
};
|
|
550
554
|
}
|
|
551
555
|
/**
|
|
@@ -588,7 +592,8 @@ export class LoaderContainerTracker {
|
|
|
588
592
|
}
|
|
589
593
|
};
|
|
590
594
|
debugOp(`${index}: ADD: clientId: ${container.clientId}`);
|
|
591
|
-
container.deltaManager
|
|
595
|
+
const deltaManagerFull = toIDeltaManagerFull(container.deltaManager);
|
|
596
|
+
deltaManagerFull.outbound.on("op", (messages) => {
|
|
592
597
|
for (const msg of messages) {
|
|
593
598
|
debugOp(`${index}: OUT: ` +
|
|
594
599
|
`cli: ${msg.clientSequenceNumber.toString().padStart(3)} ` +
|
|
@@ -606,8 +611,8 @@ export class LoaderContainerTracker {
|
|
|
606
611
|
`${msg.type} ${getContentsString(msg.type, msg.contents)}`);
|
|
607
612
|
};
|
|
608
613
|
};
|
|
609
|
-
|
|
610
|
-
|
|
614
|
+
deltaManagerFull.inbound.on("push", getInboundHandler("IN "));
|
|
615
|
+
deltaManagerFull.inbound.on("op", getInboundHandler("OP "));
|
|
611
616
|
container.deltaManager.on("connect", (details) => {
|
|
612
617
|
debugOp(`${index}: CON: clientId: ${details.clientId}`);
|
|
613
618
|
});
|
|
@@ -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\tIHostLoader,\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 { waitForContainerConnection } from \"./containerUtils.js\";\nimport { debug } from \"./debug.js\";\nimport { 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\n * @alpha\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\tprivate 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\tcontainer.deltaManager.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\tcontainer.deltaManager.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}\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 (containersToApply.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Ignore readonly dirty containers, because it can't sent ops and nothing can be done about it 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: 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\tc.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\tc.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\tcontainer.deltaManager.inbound.resume();\n\t\t\t\tcontainer.deltaManager.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\tassert(!container.deltaManager.outbound.paused, \"Container should not be paused yet\");\n\t\tassert(!container.deltaManager.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 container.deltaManager.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 (container.deltaManager.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\tcontainer.deltaManager.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 container.deltaManager.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 container.deltaManager.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(containers, (container) => container.deltaManager.inbound);\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(containers, (container) => container.deltaManager.outbound);\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\tcontainer.deltaManager.outbound.on(\"op\", outHandler);\n\t\tcontainer.deltaManager.inbound.on(\"push\", inHandler);\n\n\t\treturn () => {\n\t\t\tcontainer.deltaManager.outbound.off(\"op\", outHandler);\n\t\t\tcontainer.deltaManager.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\tcontainer.deltaManager.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\tcontainer.deltaManager.inbound.on(\"push\", getInboundHandler(\"IN \"));\n\t\t\tcontainer.deltaManager.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\tIHostLoader,\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 { 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\n * @alpha\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\tprivate 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}\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 (containersToApply.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Ignore readonly dirty containers, because it can't sent ops and nothing can be done about it 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: 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/lib/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.10.0-305357";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,+BAA+B,CAAC;AACpD,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,+BAA+B,CAAC;AACpD,eAAO,MAAM,UAAU,kBAAkB,CAAC"}
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AACpD,MAAM,CAAC,MAAM,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AACpD,MAAM,CAAC,MAAM,UAAU,GAAG,eAAe,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.10.0-305357\";\n"]}
|