@fluidframework/test-utils 2.0.0-internal.3.4.1 → 2.0.0-internal.4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"TestSummaryUtils.d.ts","sourceRoot":"","sources":["../src/TestSummaryUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,2CAA2C,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,UAAU,EAA6B,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EACN,iBAAiB,EACjB,WAAW,EAEX,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEN,sBAAsB,EACtB,kCAAkC,EAClC,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAwB,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAsDjF;;;;GAIG;AACH,wBAAsB,2BAA2B,CAChD,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,UAAU,EACrB,gBAAgB,EAAE,sBAAsB,EACxC,cAAc,CAAC,EAAE,MAAM,EACvB,2BAA2B,qDAA8C,EACzE,eAAe,CAAC,EAAE,kCAAkC,EACpD,MAAM,CAAC,EAAE,oBAAoB,GAC3B,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,WAAW,CAAA;CAAE,CAAC,CAgB7D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,UAAU,EACrB,cAAc,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,iBAAiB,EAC7B,cAAc,GAAE,mBAA0C,EAC1D,MAAM,CAAC,EAAE,oBAAoB,GAC3B,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,WAAW,CAAA;CAAE,CAAC,CAU7D;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,GAAE,MAA0B;;;;GAwB7F"}
1
+ {"version":3,"file":"TestSummaryUtils.d.ts","sourceRoot":"","sources":["../src/TestSummaryUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,2CAA2C,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,UAAU,EAA6B,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EACN,iBAAiB,EACjB,WAAW,EAEX,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEN,sBAAsB,EACtB,kCAAkC,EAClC,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAwB,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAwDjF;;;;GAIG;AACH,wBAAsB,2BAA2B,CAChD,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,UAAU,EACrB,gBAAgB,EAAE,sBAAsB,EACxC,cAAc,CAAC,EAAE,MAAM,EACvB,2BAA2B,qDAA8C,EACzE,eAAe,CAAC,EAAE,kCAAkC,EACpD,MAAM,CAAC,EAAE,oBAAoB,GAC3B,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,WAAW,CAAA;CAAE,CAAC,CAgB7D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,UAAU,EACrB,cAAc,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,iBAAiB,EAC7B,cAAc,GAAE,mBAA0C,EAC1D,MAAM,CAAC,EAAE,oBAAoB,GAC3B,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,WAAW,CAAA;CAAE,CAAC,CAU7D;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,GAAE,MAA0B;;;;GAwB7F"}
@@ -15,6 +15,7 @@ const containerUtils_1 = require("./containerUtils");
15
15
  const timeoutUtils_1 = require("./timeoutUtils");
16
16
  const summarizerClientType = "summarizer";
17
17
  async function createSummarizerCore(container, loader, summaryVersion) {
18
+ var _a;
18
19
  const absoluteUrl = await container.getAbsoluteUrl("");
19
20
  if (absoluteUrl === undefined) {
20
21
  throw new Error("URL could not be resolved");
@@ -33,10 +34,12 @@ async function createSummarizerCore(container, loader, summaryVersion) {
33
34
  };
34
35
  const summarizerContainer = await loader.resolve(request);
35
36
  await (0, containerUtils_1.waitForContainerConnection)(summarizerContainer);
36
- const fluidObject = await (0, runtime_utils_1.requestFluidObject)(summarizerContainer, {
37
- url: "_summarizer",
38
- });
39
- if (fluidObject.ISummarizer === undefined) {
37
+ const fluidObject = summarizerContainer.getEntryPoint
38
+ ? await ((_a = summarizerContainer.getEntryPoint) === null || _a === void 0 ? void 0 : _a.call(summarizerContainer))
39
+ : await (0, runtime_utils_1.requestFluidObject)(summarizerContainer, {
40
+ url: "_summarizer",
41
+ });
42
+ if ((fluidObject === null || fluidObject === void 0 ? void 0 : fluidObject.ISummarizer) === undefined) {
40
43
  throw new Error("Fluid object does not implement ISummarizer");
41
44
  }
42
45
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"TestSummaryUtils.js","sourceRoot":"","sources":["../src/TestSummaryUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ContainerRuntimeFactoryWithDefaultDataStore } from \"@fluidframework/aqueduct\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainer, IHostLoader, LoaderHeader } from \"@fluidframework/container-definitions\";\nimport {\n\tIGCRuntimeOptions,\n\tISummarizer,\n\tISummaryRuntimeOptions,\n} from \"@fluidframework/container-runtime\";\nimport { FluidObject, IRequest } from \"@fluidframework/core-interfaces\";\nimport { DriverHeader } from \"@fluidframework/driver-definitions\";\nimport {\n\tIContainerRuntimeBase,\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { IConfigProviderBase } from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport { ITestContainerConfig, ITestObjectProvider } from \"./testObjectProvider\";\nimport { mockConfigProvider } from \"./TestConfigs\";\nimport { waitForContainerConnection } from \"./containerUtils\";\nimport { timeoutAwait } from \"./timeoutUtils\";\n\nconst summarizerClientType = \"summarizer\";\n\nasync function createSummarizerCore(\n\tcontainer: IContainer,\n\tloader: IHostLoader,\n\tsummaryVersion?: string,\n) {\n\tconst absoluteUrl = await container.getAbsoluteUrl(\"\");\n\tif (absoluteUrl === undefined) {\n\t\tthrow new Error(\"URL could not be resolved\");\n\t}\n\n\tconst request: IRequest = {\n\t\theaders: {\n\t\t\t[LoaderHeader.cache]: false,\n\t\t\t[LoaderHeader.clientDetails]: {\n\t\t\t\tcapabilities: { interactive: false },\n\t\t\t\ttype: summarizerClientType,\n\t\t\t},\n\t\t\t[DriverHeader.summarizingClient]: true,\n\t\t\t[LoaderHeader.version]: summaryVersion,\n\t\t},\n\t\turl: absoluteUrl,\n\t};\n\tconst summarizerContainer = await loader.resolve(request);\n\tawait waitForContainerConnection(summarizerContainer);\n\n\tconst fluidObject = await requestFluidObject<FluidObject<ISummarizer>>(summarizerContainer, {\n\t\turl: \"_summarizer\",\n\t});\n\tif (fluidObject.ISummarizer === undefined) {\n\t\tthrow new Error(\"Fluid object does not implement ISummarizer\");\n\t}\n\n\treturn {\n\t\tcontainer: summarizerContainer,\n\t\tsummarizer: fluidObject.ISummarizer,\n\t};\n}\n\nconst defaultSummaryOptions: ISummaryRuntimeOptions = {\n\tsummaryConfigOverrides: {\n\t\tstate: \"disableHeuristics\",\n\t\tmaxAckWaitTime: 10000,\n\t\tmaxOpsSinceLastSummary: 7000,\n\t\tinitialSummarizerDelayMs: 0,\n\t},\n};\n\n/**\n * Creates a summarizer client from the given container and data store factory, and returns the summarizer client's\n * IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n */\nexport async function createSummarizerFromFactory(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tdataStoreFactory: IFluidDataStoreFactory,\n\tsummaryVersion?: string,\n\tcontainerRuntimeFactoryType = ContainerRuntimeFactoryWithDefaultDataStore,\n\tregistryEntries?: NamedFluidDataStoreRegistryEntries,\n\tlogger?: ITelemetryBaseLogger,\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) =>\n\t\truntime.IFluidHandleContext.resolveHandle(request);\n\tconst runtimeFactory = new containerRuntimeFactoryType(\n\t\tdataStoreFactory,\n\t\tregistryEntries ?? [[dataStoreFactory.type, Promise.resolve(dataStoreFactory)]],\n\t\tundefined,\n\t\t[innerRequestHandler],\n\t\t{ summaryOptions: defaultSummaryOptions },\n\t);\n\n\tconst loader = provider.createLoader([[provider.defaultCodeDetails, runtimeFactory]], {\n\t\tconfigProvider: mockConfigProvider(),\n\t\tlogger,\n\t});\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Creates a summarizer client from the given container and returns the summarizer client's IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n */\nexport async function createSummarizer(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tsummaryVersion?: string,\n\tgcOptions?: IGCRuntimeOptions,\n\tconfigProvider: IConfigProviderBase = mockConfigProvider(),\n\tlogger?: ITelemetryBaseLogger,\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst testContainerConfig: ITestContainerConfig = {\n\t\truntimeOptions: {\n\t\t\tsummaryOptions: defaultSummaryOptions,\n\t\t\tgcOptions,\n\t\t},\n\t\tloaderProps: { configProvider, logger },\n\t};\n\tconst loader = provider.makeTestLoader(testContainerConfig);\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Summarizes on demand and returns the summary tree, the version number and the reference sequence number of the\n * submitted summary.\n */\nexport async function summarizeNow(summarizer: ISummarizer, reason: string = \"end-to-end test\") {\n\tconst result = summarizer.summarizeOnDemand({ reason });\n\n\tconst submitResult = await timeoutAwait(result.summarySubmitted);\n\tassert(submitResult.success, \"on-demand summary should submit\");\n\tassert(\n\t\tsubmitResult.data.stage === \"submit\",\n\t\t\"on-demand summary submitted data stage should be submit\",\n\t);\n\tassert(submitResult.data.summaryTree !== undefined, \"summary tree should exist\");\n\n\tconst broadcastResult = await timeoutAwait(result.summaryOpBroadcasted);\n\tassert(broadcastResult.success, \"summary op should be broadcast\");\n\n\tconst ackNackResult = await timeoutAwait(result.receivedSummaryAckOrNack);\n\tassert(ackNackResult.success, \"summary op should be acked\");\n\n\tawait new Promise((resolve) => process.nextTick(resolve));\n\n\treturn {\n\t\tsummaryTree: submitResult.data.summaryTree,\n\t\tsummaryVersion: ackNackResult.data.summaryAckOp.contents.handle,\n\t\tsummaryRefSeq: submitResult.data.referenceSequenceNumber,\n\t};\n}\n"]}
1
+ {"version":3,"file":"TestSummaryUtils.js","sourceRoot":"","sources":["../src/TestSummaryUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ContainerRuntimeFactoryWithDefaultDataStore } from \"@fluidframework/aqueduct\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainer, IHostLoader, LoaderHeader } from \"@fluidframework/container-definitions\";\nimport {\n\tIGCRuntimeOptions,\n\tISummarizer,\n\tISummaryRuntimeOptions,\n} from \"@fluidframework/container-runtime\";\nimport { FluidObject, IRequest } from \"@fluidframework/core-interfaces\";\nimport { DriverHeader } from \"@fluidframework/driver-definitions\";\nimport {\n\tIContainerRuntimeBase,\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { IConfigProviderBase } from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport { ITestContainerConfig, ITestObjectProvider } from \"./testObjectProvider\";\nimport { mockConfigProvider } from \"./TestConfigs\";\nimport { waitForContainerConnection } from \"./containerUtils\";\nimport { timeoutAwait } from \"./timeoutUtils\";\n\nconst summarizerClientType = \"summarizer\";\n\nasync function createSummarizerCore(\n\tcontainer: IContainer,\n\tloader: IHostLoader,\n\tsummaryVersion?: string,\n) {\n\tconst absoluteUrl = await container.getAbsoluteUrl(\"\");\n\tif (absoluteUrl === undefined) {\n\t\tthrow new Error(\"URL could not be resolved\");\n\t}\n\n\tconst request: IRequest = {\n\t\theaders: {\n\t\t\t[LoaderHeader.cache]: false,\n\t\t\t[LoaderHeader.clientDetails]: {\n\t\t\t\tcapabilities: { interactive: false },\n\t\t\t\ttype: summarizerClientType,\n\t\t\t},\n\t\t\t[DriverHeader.summarizingClient]: true,\n\t\t\t[LoaderHeader.version]: summaryVersion,\n\t\t},\n\t\turl: absoluteUrl,\n\t};\n\tconst summarizerContainer = await loader.resolve(request);\n\tawait waitForContainerConnection(summarizerContainer);\n\n\tconst fluidObject: FluidObject<ISummarizer> | undefined = summarizerContainer.getEntryPoint\n\t\t? await summarizerContainer.getEntryPoint?.()\n\t\t: await requestFluidObject<FluidObject<ISummarizer>>(summarizerContainer, {\n\t\t\t\turl: \"_summarizer\",\n\t\t });\n\tif (fluidObject?.ISummarizer === undefined) {\n\t\tthrow new Error(\"Fluid object does not implement ISummarizer\");\n\t}\n\n\treturn {\n\t\tcontainer: summarizerContainer,\n\t\tsummarizer: fluidObject.ISummarizer,\n\t};\n}\n\nconst defaultSummaryOptions: ISummaryRuntimeOptions = {\n\tsummaryConfigOverrides: {\n\t\tstate: \"disableHeuristics\",\n\t\tmaxAckWaitTime: 10000,\n\t\tmaxOpsSinceLastSummary: 7000,\n\t\tinitialSummarizerDelayMs: 0,\n\t},\n};\n\n/**\n * Creates a summarizer client from the given container and data store factory, and returns the summarizer client's\n * IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n */\nexport async function createSummarizerFromFactory(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tdataStoreFactory: IFluidDataStoreFactory,\n\tsummaryVersion?: string,\n\tcontainerRuntimeFactoryType = ContainerRuntimeFactoryWithDefaultDataStore,\n\tregistryEntries?: NamedFluidDataStoreRegistryEntries,\n\tlogger?: ITelemetryBaseLogger,\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) =>\n\t\truntime.IFluidHandleContext.resolveHandle(request);\n\tconst runtimeFactory = new containerRuntimeFactoryType(\n\t\tdataStoreFactory,\n\t\tregistryEntries ?? [[dataStoreFactory.type, Promise.resolve(dataStoreFactory)]],\n\t\tundefined,\n\t\t[innerRequestHandler],\n\t\t{ summaryOptions: defaultSummaryOptions },\n\t);\n\n\tconst loader = provider.createLoader([[provider.defaultCodeDetails, runtimeFactory]], {\n\t\tconfigProvider: mockConfigProvider(),\n\t\tlogger,\n\t});\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Creates a summarizer client from the given container and returns the summarizer client's IContainer and ISummarizer.\n * The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.\n */\nexport async function createSummarizer(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\tsummaryVersion?: string,\n\tgcOptions?: IGCRuntimeOptions,\n\tconfigProvider: IConfigProviderBase = mockConfigProvider(),\n\tlogger?: ITelemetryBaseLogger,\n): Promise<{ container: IContainer; summarizer: ISummarizer }> {\n\tconst testContainerConfig: ITestContainerConfig = {\n\t\truntimeOptions: {\n\t\t\tsummaryOptions: defaultSummaryOptions,\n\t\t\tgcOptions,\n\t\t},\n\t\tloaderProps: { configProvider, logger },\n\t};\n\tconst loader = provider.makeTestLoader(testContainerConfig);\n\treturn createSummarizerCore(container, loader, summaryVersion);\n}\n\n/**\n * Summarizes on demand and returns the summary tree, the version number and the reference sequence number of the\n * submitted summary.\n */\nexport async function summarizeNow(summarizer: ISummarizer, reason: string = \"end-to-end test\") {\n\tconst result = summarizer.summarizeOnDemand({ reason });\n\n\tconst submitResult = await timeoutAwait(result.summarySubmitted);\n\tassert(submitResult.success, \"on-demand summary should submit\");\n\tassert(\n\t\tsubmitResult.data.stage === \"submit\",\n\t\t\"on-demand summary submitted data stage should be submit\",\n\t);\n\tassert(submitResult.data.summaryTree !== undefined, \"summary tree should exist\");\n\n\tconst broadcastResult = await timeoutAwait(result.summaryOpBroadcasted);\n\tassert(broadcastResult.success, \"summary op should be broadcast\");\n\n\tconst ackNackResult = await timeoutAwait(result.receivedSummaryAckOrNack);\n\tassert(ackNackResult.success, \"summary op should be acked\");\n\n\tawait new Promise((resolve) => process.nextTick(resolve));\n\n\treturn {\n\t\tsummaryTree: submitResult.data.summaryTree,\n\t\tsummaryVersion: ackNackResult.data.summaryAckOp.contents.handle,\n\t\tsummaryRefSeq: submitResult.data.referenceSequenceNumber,\n\t};\n}\n"]}
@@ -4,15 +4,6 @@
4
4
  */
5
5
  import { IContainer } from "@fluidframework/container-definitions";
6
6
  import { TimeoutWithError } from "./timeoutUtils";
7
- /**
8
- * Waits for the specified container to emit a 'connected' event.
9
- *
10
- * @deprecated Use waitForContainerConnection instead.
11
- * Note that an upcoming release will change the default parameters on that function to:
12
- * - failOnContainerClose = true
13
- * - timeoutOptions.durationMs = 1s
14
- */
15
- export declare function ensureContainerConnected(container: IContainer): Promise<void>;
16
7
  /**
17
8
  * Utility function to wait for the specified Container to be in Connected state.
18
9
  * If the Container is already connected, the Promise returns immediately; otherwise it resolves when the Container emits
@@ -22,16 +13,17 @@ export declare function ensureContainerConnected(container: IContainer): Promise
22
13
  * @param container - The container to wait for.
23
14
  * @param failOnContainerClose - If true, the returned Promise will be rejected if the container emits a 'closed' event
24
15
  * before a 'connected' event.
25
- * Defaults to false (but this will change in an upcoming version).
16
+ * Defaults to true.
26
17
  * @param timeoutOptions - Options related to the behavior of the timeout.
27
- * If not provided, no timeout will be applied and the promise will wait indefinitely for the Container to emit its
28
- * 'connected' (or 'closed, if failOnContainerClose === true) event.
29
- * @returns A Promise that resolves when the specified container emits a 'connected' event (or immediately if the
30
- * Container is already connected).
31
- * If failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event, the Promise
32
- * is rejected with the error from the 'closed' event, if any.
33
- * If timeoutOptions is provided, the Promise will reject if the container hasn't emmited a relevant event before
34
- * timeoutOptions.durationMs (which defaults to 250ms if left undefined).
18
+ * If provided, the returned Promise will reject if the container hasn't emitted relevant events in timeoutOptions.durationMs.
19
+ * If not provided, the Promise will wait indefinitely for the Container to emit its 'connected' (or 'closed', if
20
+ * failOnContainerClose === true) event.
21
+ *
22
+ * @returns A Promise that either:
23
+ * - Resolves when the specified container emits a 'connected' event (or immediately if the Container is already connected).
24
+ * - Rejects if failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event.
25
+ * - Rejects after timeoutOptions.durationMs if timeoutOptions !== undefined and the container does not emit relevant
26
+ * events, within that timeframe.
35
27
  */
36
28
  export declare function waitForContainerConnection(container: IContainer, failOnContainerClose?: boolean, timeoutOptions?: TimeoutWithError): Promise<void>;
37
29
  //# sourceMappingURL=containerUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"containerUtils.d.ts","sourceRoot":"","sources":["../src/containerUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAEnE,OAAO,EAAmC,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEnF;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAInF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,0BAA0B,CAC/C,SAAS,EAAE,UAAU,EACrB,oBAAoB,GAAE,OAAe,EACrC,cAAc,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAaf"}
1
+ {"version":3,"file":"containerUtils.d.ts","sourceRoot":"","sources":["../src/containerUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAEnE,OAAO,EAAmC,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,0BAA0B,CAC/C,SAAS,EAAE,UAAU,EACrB,oBAAoB,GAAE,OAAc,EACpC,cAAc,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -4,23 +4,9 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.waitForContainerConnection = exports.ensureContainerConnected = void 0;
7
+ exports.waitForContainerConnection = void 0;
8
8
  const container_loader_1 = require("@fluidframework/container-loader");
9
9
  const timeoutUtils_1 = require("./timeoutUtils");
10
- /**
11
- * Waits for the specified container to emit a 'connected' event.
12
- *
13
- * @deprecated Use waitForContainerConnection instead.
14
- * Note that an upcoming release will change the default parameters on that function to:
15
- * - failOnContainerClose = true
16
- * - timeoutOptions.durationMs = 1s
17
- */
18
- async function ensureContainerConnected(container) {
19
- if (container.connectionState !== container_loader_1.ConnectionState.Connected) {
20
- return (0, timeoutUtils_1.timeoutPromise)((resolve) => container.once("connected", () => resolve()));
21
- }
22
- }
23
- exports.ensureContainerConnected = ensureContainerConnected;
24
10
  /**
25
11
  * Utility function to wait for the specified Container to be in Connected state.
26
12
  * If the Container is already connected, the Promise returns immediately; otherwise it resolves when the Container emits
@@ -30,18 +16,19 @@ exports.ensureContainerConnected = ensureContainerConnected;
30
16
  * @param container - The container to wait for.
31
17
  * @param failOnContainerClose - If true, the returned Promise will be rejected if the container emits a 'closed' event
32
18
  * before a 'connected' event.
33
- * Defaults to false (but this will change in an upcoming version).
19
+ * Defaults to true.
34
20
  * @param timeoutOptions - Options related to the behavior of the timeout.
35
- * If not provided, no timeout will be applied and the promise will wait indefinitely for the Container to emit its
36
- * 'connected' (or 'closed, if failOnContainerClose === true) event.
37
- * @returns A Promise that resolves when the specified container emits a 'connected' event (or immediately if the
38
- * Container is already connected).
39
- * If failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event, the Promise
40
- * is rejected with the error from the 'closed' event, if any.
41
- * If timeoutOptions is provided, the Promise will reject if the container hasn't emmited a relevant event before
42
- * timeoutOptions.durationMs (which defaults to 250ms if left undefined).
21
+ * If provided, the returned Promise will reject if the container hasn't emitted relevant events in timeoutOptions.durationMs.
22
+ * If not provided, the Promise will wait indefinitely for the Container to emit its 'connected' (or 'closed', if
23
+ * failOnContainerClose === true) event.
24
+ *
25
+ * @returns A Promise that either:
26
+ * - Resolves when the specified container emits a 'connected' event (or immediately if the Container is already connected).
27
+ * - Rejects if failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event.
28
+ * - Rejects after timeoutOptions.durationMs if timeoutOptions !== undefined and the container does not emit relevant
29
+ * events, within that timeframe.
43
30
  */
44
- async function waitForContainerConnection(container, failOnContainerClose = false, timeoutOptions) {
31
+ async function waitForContainerConnection(container, failOnContainerClose = true, timeoutOptions) {
45
32
  if (container.connectionState !== container_loader_1.ConnectionState.Connected) {
46
33
  const executor = (resolve, reject) => {
47
34
  container.once("connected", () => resolve());
@@ -1 +1 @@
1
- {"version":3,"file":"containerUtils.js","sourceRoot":"","sources":["../src/containerUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,uEAAmE;AACnE,iDAAmF;AAEnF;;;;;;;GAOG;AACI,KAAK,UAAU,wBAAwB,CAAC,SAAqB;IACnE,IAAI,SAAS,CAAC,eAAe,KAAK,kCAAe,CAAC,SAAS,EAAE;QAC5D,OAAO,IAAA,6BAAc,EAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;KACjF;AACF,CAAC;AAJD,4DAIC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,0BAA0B,CAC/C,SAAqB,EACrB,uBAAgC,KAAK,EACrC,cAAiC;IAEjC,IAAI,SAAS,CAAC,eAAe,KAAK,kCAAe,CAAC,SAAS,EAAE;QAC5D,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;gBACzB,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;aACnD;QACF,CAAC,CAAC;QAEF,OAAO,cAAc,KAAK,SAAS;YAClC,CAAC,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC;YACvB,CAAC,CAAC,IAAA,6BAAc,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;KAC5C;AACF,CAAC;AAjBD,gEAiBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IContainer } from \"@fluidframework/container-definitions\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport { PromiseExecutor, timeoutPromise, TimeoutWithError } from \"./timeoutUtils\";\n\n/**\n * Waits for the specified container to emit a 'connected' event.\n *\n * @deprecated Use waitForContainerConnection instead.\n * Note that an upcoming release will change the default parameters on that function to:\n * - failOnContainerClose = true\n * - timeoutOptions.durationMs = 1s\n */\nexport async function ensureContainerConnected(container: IContainer): Promise<void> {\n\tif (container.connectionState !== ConnectionState.Connected) {\n\t\treturn timeoutPromise((resolve) => container.once(\"connected\", () => resolve()));\n\t}\n}\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 false (but this will change in an upcoming version).\n * @param timeoutOptions - Options related to the behavior of the timeout.\n * If not provided, no timeout will be applied and the promise will wait indefinitely for the Container to emit its\n * 'connected' (or 'closed, if failOnContainerClose === true) event.\n * @returns A Promise that resolves when the specified container emits a 'connected' event (or immediately if the\n * Container is already connected).\n * If failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event, the Promise\n * is rejected with the error from the 'closed' event, if any.\n * If timeoutOptions is provided, the Promise will reject if the container hasn't emmited a relevant event before\n * timeoutOptions.durationMs (which defaults to 250ms if left undefined).\n */\nexport async function waitForContainerConnection(\n\tcontainer: IContainer,\n\tfailOnContainerClose: boolean = false,\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"]}
1
+ {"version":3,"file":"containerUtils.js","sourceRoot":"","sources":["../src/containerUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,uEAAmE;AACnE,iDAAmF;AAEnF;;;;;;;;;;;;;;;;;;;;GAoBG;AACI,KAAK,UAAU,0BAA0B,CAC/C,SAAqB,EACrB,uBAAgC,IAAI,EACpC,cAAiC;IAEjC,IAAI,SAAS,CAAC,eAAe,KAAK,kCAAe,CAAC,SAAS,EAAE;QAC5D,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;gBACzB,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;aACnD;QACF,CAAC,CAAC;QAEF,OAAO,cAAc,KAAK,SAAS;YAClC,CAAC,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC;YACvB,CAAC,CAAC,IAAA,6BAAc,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;KAC5C;AACF,CAAC;AAjBD,gEAiBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IContainer } from \"@fluidframework/container-definitions\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport { PromiseExecutor, timeoutPromise, TimeoutWithError } from \"./timeoutUtils\";\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 */\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"]}
package/dist/index.d.ts CHANGED
@@ -14,5 +14,5 @@ export { ChannelFactoryRegistry, TestFluidObject, TestFluidObjectFactory } from
14
14
  export { createDocumentId, DataObjectFactoryType, EventAndErrorTrackingLogger, getUnexpectedLogErrorException, IOpProcessingController, ITestContainerConfig, ITestObjectProvider, TestObjectProvider, } from "./testObjectProvider";
15
15
  export { createSummarizer, createSummarizerFromFactory, summarizeNow } from "./TestSummaryUtils";
16
16
  export { defaultTimeoutDurationMs, timeoutAwait, timeoutPromise, TimeoutWithError, TimeoutWithValue, } from "./timeoutUtils";
17
- export { ensureContainerConnected, waitForContainerConnection } from "./containerUtils";
17
+ export { waitForContainerConnection } from "./containerUtils";
18
18
  //# sourceMappingURL=index.d.ts.map
@@ -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,kBAAkB,CAAC;AAC1B,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EACN,iCAAiC,EACjC,2BAA2B,GAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,8BAA8B,EAC9B,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,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,kBAAkB,CAAC;AAC1B,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EACN,iCAAiC,EACjC,2BAA2B,GAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,8BAA8B,EAC9B,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.waitForContainerConnection = exports.ensureContainerConnected = exports.timeoutPromise = exports.timeoutAwait = exports.defaultTimeoutDurationMs = exports.summarizeNow = exports.createSummarizerFromFactory = exports.createSummarizer = exports.TestObjectProvider = exports.getUnexpectedLogErrorException = exports.EventAndErrorTrackingLogger = exports.DataObjectFactoryType = exports.createDocumentId = exports.TestFluidObjectFactory = exports.TestFluidObject = exports.TestContainerRuntimeFactory = exports.createTestContainerRuntimeFactory = exports.mockConfigProvider = exports.retryWithEventualValue = exports.createLoader = exports.createAndAttachContainer = exports.LocalCodeLoader = exports.LoaderContainerTracker = exports.wrapDocumentStorageService = exports.wrapDocumentServiceFactory = exports.wrapDocumentService = void 0;
7
+ exports.waitForContainerConnection = exports.timeoutPromise = exports.timeoutAwait = exports.defaultTimeoutDurationMs = exports.summarizeNow = exports.createSummarizerFromFactory = exports.createSummarizer = exports.TestObjectProvider = exports.getUnexpectedLogErrorException = exports.EventAndErrorTrackingLogger = exports.DataObjectFactoryType = exports.createDocumentId = exports.TestFluidObjectFactory = exports.TestFluidObject = exports.TestContainerRuntimeFactory = exports.createTestContainerRuntimeFactory = exports.mockConfigProvider = exports.retryWithEventualValue = exports.createLoader = exports.createAndAttachContainer = exports.LocalCodeLoader = exports.LoaderContainerTracker = exports.wrapDocumentStorageService = exports.wrapDocumentServiceFactory = exports.wrapDocumentService = void 0;
8
8
  var DriverWrappers_1 = require("./DriverWrappers");
9
9
  Object.defineProperty(exports, "wrapDocumentService", { enumerable: true, get: function () { return DriverWrappers_1.wrapDocumentService; } });
10
10
  Object.defineProperty(exports, "wrapDocumentServiceFactory", { enumerable: true, get: function () { return DriverWrappers_1.wrapDocumentServiceFactory; } });
@@ -41,6 +41,5 @@ Object.defineProperty(exports, "defaultTimeoutDurationMs", { enumerable: true, g
41
41
  Object.defineProperty(exports, "timeoutAwait", { enumerable: true, get: function () { return timeoutUtils_1.timeoutAwait; } });
42
42
  Object.defineProperty(exports, "timeoutPromise", { enumerable: true, get: function () { return timeoutUtils_1.timeoutPromise; } });
43
43
  var containerUtils_1 = require("./containerUtils");
44
- Object.defineProperty(exports, "ensureContainerConnected", { enumerable: true, get: function () { return containerUtils_1.ensureContainerConnected; } });
45
44
  Object.defineProperty(exports, "waitForContainerConnection", { enumerable: true, get: function () { return containerUtils_1.waitForContainerConnection; } });
46
45
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mDAI0B;AAHzB,qHAAA,mBAAmB,OAAA;AACnB,4HAAA,0BAA0B,OAAA;AAC1B,4HAAA,0BAA0B,OAAA;AAG3B,mEAAkE;AAAzD,gIAAA,sBAAsB,OAAA;AAC/B,qDAAgG;AAAtE,kHAAA,eAAe,OAAA;AACzC,6CAAuE;AAA9D,uHAAA,wBAAwB,OAAA;AAAE,2GAAA,YAAY,OAAA;AAC/C,iCAAiD;AAAxC,+GAAA,sBAAsB,OAAA;AAC/B,6CAAmD;AAA1C,iHAAA,kBAAkB,OAAA;AAC3B,6EAGuC;AAFtC,gJAAA,iCAAiC,OAAA;AACjC,0IAAA,2BAA2B,OAAA;AAE5B,qDAAoG;AAAnE,kHAAA,eAAe,OAAA;AAAE,yHAAA,sBAAsB,OAAA;AACxE,2DAS8B;AAR7B,sHAAA,gBAAgB,OAAA;AAChB,2HAAA,qBAAqB,OAAA;AACrB,iIAAA,2BAA2B,OAAA;AAC3B,oIAAA,8BAA8B,OAAA;AAI9B,wHAAA,kBAAkB,OAAA;AAEnB,uDAAiG;AAAxF,oHAAA,gBAAgB,OAAA;AAAE,+HAAA,2BAA2B,OAAA;AAAE,gHAAA,YAAY,OAAA;AACpE,+CAMwB;AALvB,wHAAA,wBAAwB,OAAA;AACxB,4GAAA,YAAY,OAAA;AACZ,8GAAA,cAAc,OAAA;AAIf,mDAAwF;AAA/E,0HAAA,wBAAwB,OAAA;AAAE,4HAAA,0BAA0B,OAAA","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\";\nexport { IProvideTestFluidObject, ITestFluidObject } from \"./interfaces\";\nexport { LoaderContainerTracker } from \"./loaderContainerTracker\";\nexport { fluidEntryPoint, LocalCodeLoader, SupportedExportInterfaces } from \"./localCodeLoader\";\nexport { createAndAttachContainer, createLoader } from \"./localLoader\";\nexport { retryWithEventualValue } from \"./retry\";\nexport { mockConfigProvider } from \"./TestConfigs\";\nexport {\n\tcreateTestContainerRuntimeFactory,\n\tTestContainerRuntimeFactory,\n} from \"./testContainerRuntimeFactory\";\nexport { ChannelFactoryRegistry, TestFluidObject, TestFluidObjectFactory } from \"./testFluidObject\";\nexport {\n\tcreateDocumentId,\n\tDataObjectFactoryType,\n\tEventAndErrorTrackingLogger,\n\tgetUnexpectedLogErrorException,\n\tIOpProcessingController,\n\tITestContainerConfig,\n\tITestObjectProvider,\n\tTestObjectProvider,\n} from \"./testObjectProvider\";\nexport { createSummarizer, createSummarizerFromFactory, summarizeNow } from \"./TestSummaryUtils\";\nexport {\n\tdefaultTimeoutDurationMs,\n\ttimeoutAwait,\n\ttimeoutPromise,\n\tTimeoutWithError,\n\tTimeoutWithValue,\n} from \"./timeoutUtils\";\nexport { ensureContainerConnected, waitForContainerConnection } from \"./containerUtils\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mDAI0B;AAHzB,qHAAA,mBAAmB,OAAA;AACnB,4HAAA,0BAA0B,OAAA;AAC1B,4HAAA,0BAA0B,OAAA;AAG3B,mEAAkE;AAAzD,gIAAA,sBAAsB,OAAA;AAC/B,qDAAgG;AAAtE,kHAAA,eAAe,OAAA;AACzC,6CAAuE;AAA9D,uHAAA,wBAAwB,OAAA;AAAE,2GAAA,YAAY,OAAA;AAC/C,iCAAiD;AAAxC,+GAAA,sBAAsB,OAAA;AAC/B,6CAAmD;AAA1C,iHAAA,kBAAkB,OAAA;AAC3B,6EAGuC;AAFtC,gJAAA,iCAAiC,OAAA;AACjC,0IAAA,2BAA2B,OAAA;AAE5B,qDAAoG;AAAnE,kHAAA,eAAe,OAAA;AAAE,yHAAA,sBAAsB,OAAA;AACxE,2DAS8B;AAR7B,sHAAA,gBAAgB,OAAA;AAChB,2HAAA,qBAAqB,OAAA;AACrB,iIAAA,2BAA2B,OAAA;AAC3B,oIAAA,8BAA8B,OAAA;AAI9B,wHAAA,kBAAkB,OAAA;AAEnB,uDAAiG;AAAxF,oHAAA,gBAAgB,OAAA;AAAE,+HAAA,2BAA2B,OAAA;AAAE,gHAAA,YAAY,OAAA;AACpE,+CAMwB;AALvB,wHAAA,wBAAwB,OAAA;AACxB,4GAAA,YAAY,OAAA;AACZ,8GAAA,cAAc,OAAA;AAIf,mDAA8D;AAArD,4HAAA,0BAA0B,OAAA","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\";\nexport { IProvideTestFluidObject, ITestFluidObject } from \"./interfaces\";\nexport { LoaderContainerTracker } from \"./loaderContainerTracker\";\nexport { fluidEntryPoint, LocalCodeLoader, SupportedExportInterfaces } from \"./localCodeLoader\";\nexport { createAndAttachContainer, createLoader } from \"./localLoader\";\nexport { retryWithEventualValue } from \"./retry\";\nexport { mockConfigProvider } from \"./TestConfigs\";\nexport {\n\tcreateTestContainerRuntimeFactory,\n\tTestContainerRuntimeFactory,\n} from \"./testContainerRuntimeFactory\";\nexport { ChannelFactoryRegistry, TestFluidObject, TestFluidObjectFactory } from \"./testFluidObject\";\nexport {\n\tcreateDocumentId,\n\tDataObjectFactoryType,\n\tEventAndErrorTrackingLogger,\n\tgetUnexpectedLogErrorException,\n\tIOpProcessingController,\n\tITestContainerConfig,\n\tITestObjectProvider,\n\tTestObjectProvider,\n} from \"./testObjectProvider\";\nexport { createSummarizer, createSummarizerFromFactory, summarizeNow } from \"./TestSummaryUtils\";\nexport {\n\tdefaultTimeoutDurationMs,\n\ttimeoutAwait,\n\ttimeoutPromise,\n\tTimeoutWithError,\n\tTimeoutWithValue,\n} from \"./timeoutUtils\";\nexport { waitForContainerConnection } from \"./containerUtils\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"loaderContainerTracker.d.ts","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAe,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAS7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAsB/D,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;IA2BpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACI,KAAK;IAUZ;;OAEG;IACU,kBAAkB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E;;OAEG;IACU,6BAA6B,CAAC,CAC1C,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,GAAG,UAAU,EAAE,UAAU,EAAE;IAK5B;;;;;;;;;;;;;;;;;;OAkBG;YACW,mBAAmB;IA+EjC;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;IA4CpC;;;;;;;OAOG;YACW,qBAAqB;IAoCnC;;;OAGG;YACW,oBAAoB;IAclC;;OAEG;IACI,gBAAgB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAgBnD;;;OAGG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAexD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;OAEG;YACW,YAAY;IA0C1B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;IACH,OAAO,CAAC,UAAU;IAwElB;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAKrB"}
1
+ {"version":3,"file":"loaderContainerTracker.d.ts","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAe,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAS7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAsB/D,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;IA2BpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACI,KAAK;IAUZ;;OAEG;IACU,kBAAkB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E;;OAEG;IACU,6BAA6B,CAAC,CAC1C,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,GAAG,UAAU,EAAE,UAAU,EAAE;IAK5B;;;;;;;;;;;;;;;;;;OAkBG;YACW,mBAAmB;IA+EjC;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IA8BzB;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;IA4CpC;;;;;;;OAOG;YACW,qBAAqB;IAoCnC;;;OAGG;YACW,oBAAoB;IAclC;;OAEG;IACI,gBAAgB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAgBnD;;;OAGG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAexD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;OAEG;YACW,YAAY;IA0C1B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;IACH,OAAO,CAAC,UAAU;IAwElB;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAKrB"}
@@ -6,6 +6,7 @@ exports.LoaderContainerTracker = void 0;
6
6
  * Licensed under the MIT License.
7
7
  */
8
8
  const common_utils_1 = require("@fluidframework/common-utils");
9
+ const container_loader_1 = require("@fluidframework/container-loader");
9
10
  const driver_utils_1 = require("@fluidframework/driver-utils");
10
11
  const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
11
12
  const debug_1 = require("./debug");
@@ -304,7 +305,7 @@ class LoaderContainerTracker {
304
305
  * @param containersToApply - the set of containers to wait for any inbound ops for
305
306
  */
306
307
  async waitForPendingClients(pendingClients) {
307
- const unconnectedClients = Array.from(this.containers.keys()).filter((c) => !c.closed && !c.connected);
308
+ const unconnectedClients = Array.from(this.containers.keys()).filter((c) => !c.closed && c.connectionState !== container_loader_1.ConnectionState.Connected);
308
309
  return Promise.all(pendingClients.map(async ([container, pendingClientId]) => {
309
310
  return new Promise((resolve) => {
310
311
  const cleanup = () => {
@@ -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 */\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainer, IDeltaQueue, IHostLoader } from \"@fluidframework/container-definitions\";\nimport { Container } from \"@fluidframework/container-loader\";\nimport { canBeCoalescedByService } from \"@fluidframework/driver-utils\";\nimport {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n\tMessageType,\n} from \"@fluidframework/protocol-definitions\";\nimport { debug } from \"./debug\";\nimport { IOpProcessingController } from \"./testObjectProvider\";\nimport { timeoutAwait, timeoutPromise } from \"./timeoutUtils\";\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\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\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// 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\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\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 as 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 * Ensure all tracked containers are synchronized\n\t */\n\tpublic async ensureSynchronized(...containers: IContainer[]): Promise<void> {\n\t\tawait this.processSynchronized(undefined, ...containers);\n\t}\n\n\t/**\n\t * Ensure all tracked containers are synchronized with a time limit\n\t */\n\tpublic async ensureSynchronizedWithTimeout?(\n\t\ttimeoutDuration: number | undefined,\n\t\t...containers: IContainer[]\n\t) {\n\t\tawait this.processSynchronized(timeoutDuration, ...containers);\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 *\n\t * No extra clientId in quorum of any container that is not tracked and still opened.\n\t *\n\t * - i.e. no pending Join/Leave message.\n\t *\n\t * No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n\t *\n\t * lastSequenceNumber of all container is the same\n\t *\n\t * clientSequenceNumberObserved is the same as clientSequenceNumber sent\n\t *\n\t * - this overlaps with !isDirty, but include task scheduler ops.\n\t *\n\t * - Trailing NoOp is tracked and don't count as pending ops.\n\t */\n\tprivate async processSynchronized(\n\t\ttimeoutDuration: number | undefined,\n\t\t...containers: IContainer[]\n\t) {\n\t\tconst resumed = this.resumeProcessing(...containers);\n\n\t\tlet waitingSequenceNumberSynchronized = false;\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\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 up 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\tif (this.isSequenceNumberSynchronized(containersToApply)) {\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) {\n\t\t\t\t\t\t// Only write it out once\n\t\t\t\t\t\twaitingSequenceNumberSynchronized = true;\n\t\t\t\t\t\tdebugWait(\"Waiting for sequence number synchronized\");\n\t\t\t\t\t\tawait timeoutAwait(this.waitForAnyInboundOps(containersToApply), {\n\t\t\t\t\t\t\terrorMsg: \"Timeout on waiting for sequence number synchronized\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twaitingSequenceNumberSynchronized = false;\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 ${dirtyContainers.map(\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\t\t(c) => this.containers.get(c)!.index,\n\t\t\t\t\t)}`,\n\t\t\t\t);\n\t\t\t\twaitingSequenceNumberSynchronized = false;\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\n\t\t\t// yield a turn to allow side effect of the ops we just processed execute before we check again\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// 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(\n\t\t\t(container) => (container as Container).clientId,\n\t\t);\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 (\n\t\t\t\t\t!client.client.details.capabilities.interactive &&\n\t\t\t\t\t!this.syncSummarizerClients\n\t\t\t\t) {\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 isSequenceNumberSynchronized(containersToApply: IContainer[]) {\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 isClientSequenceNumberSynchronized = containersToApply.every((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 true;\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: 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\treturn (\n\t\t\t\tdeltaManager.clientSequenceNumber ===\n\t\t\t\t(deltaManager.clientSequenceNumberObserved as number) + trailingNoOps\n\t\t\t);\n\t\t});\n\n\t\tif (!isClientSequenceNumberSynchronized) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n\t\tif (minSeqNum < this.lastProposalSeqNum) {\n\t\t\t// There is an unresolved proposal\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check to see if all the container has process the same number of ops.\n\t\tconst seqNum = containersToApply[0].deltaManager.lastSequenceNumber;\n\t\treturn containersToApply.every((c) => c.deltaManager.lastSequenceNumber === seqNum);\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 as Container).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(\n\t\t\t\t\t\t\tpendingClientId.keys(),\n\t\t\t\t\t\t)}`,\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\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\tpublic async pauseProcessing(...containers: IContainer[]) {\n\t\tconst pauseP: 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\tdebugWait(`${record.index}: container paused`);\n\t\t\t\tpauseP.push(container.deltaManager.inbound.pause());\n\t\t\t\tpauseP.push(container.deltaManager.outbound.pause());\n\t\t\t\trecord.paused = true;\n\t\t\t}\n\t\t}\n\t\tawait Promise.all(pauseP);\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\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\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\t\tconst inflightTracker = new Map<IContainer, number>();\n\t\tconst cleanup: (() => void)[] = [];\n\t\tfor (const container of containersToApply) {\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 as 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 as 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 as 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\n\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t.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 */\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainer, IDeltaQueue, IHostLoader } from \"@fluidframework/container-definitions\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport { canBeCoalescedByService } from \"@fluidframework/driver-utils\";\nimport {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n\tMessageType,\n} from \"@fluidframework/protocol-definitions\";\nimport { debug } from \"./debug\";\nimport { IOpProcessingController } from \"./testObjectProvider\";\nimport { timeoutAwait, timeoutPromise } from \"./timeoutUtils\";\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\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\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// 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\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\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 * Ensure all tracked containers are synchronized\n\t */\n\tpublic async ensureSynchronized(...containers: IContainer[]): Promise<void> {\n\t\tawait this.processSynchronized(undefined, ...containers);\n\t}\n\n\t/**\n\t * Ensure all tracked containers are synchronized with a time limit\n\t */\n\tpublic async ensureSynchronizedWithTimeout?(\n\t\ttimeoutDuration: number | undefined,\n\t\t...containers: IContainer[]\n\t) {\n\t\tawait this.processSynchronized(timeoutDuration, ...containers);\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 *\n\t * No extra clientId in quorum of any container that is not tracked and still opened.\n\t *\n\t * - i.e. no pending Join/Leave message.\n\t *\n\t * No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n\t *\n\t * lastSequenceNumber of all container is the same\n\t *\n\t * clientSequenceNumberObserved is the same as clientSequenceNumber sent\n\t *\n\t * - this overlaps with !isDirty, but include task scheduler ops.\n\t *\n\t * - Trailing NoOp is tracked and don't count as pending ops.\n\t */\n\tprivate async processSynchronized(\n\t\ttimeoutDuration: number | undefined,\n\t\t...containers: IContainer[]\n\t) {\n\t\tconst resumed = this.resumeProcessing(...containers);\n\n\t\tlet waitingSequenceNumberSynchronized = false;\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\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 up 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\tif (this.isSequenceNumberSynchronized(containersToApply)) {\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) {\n\t\t\t\t\t\t// Only write it out once\n\t\t\t\t\t\twaitingSequenceNumberSynchronized = true;\n\t\t\t\t\t\tdebugWait(\"Waiting for sequence number synchronized\");\n\t\t\t\t\t\tawait timeoutAwait(this.waitForAnyInboundOps(containersToApply), {\n\t\t\t\t\t\t\terrorMsg: \"Timeout on waiting for sequence number synchronized\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twaitingSequenceNumberSynchronized = false;\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 ${dirtyContainers.map(\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\t\t(c) => this.containers.get(c)!.index,\n\t\t\t\t\t)}`,\n\t\t\t\t);\n\t\t\t\twaitingSequenceNumberSynchronized = false;\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\n\t\t\t// yield a turn to allow side effect of the ops we just processed execute before we check again\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// 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 (\n\t\t\t\t\t!client.client.details.capabilities.interactive &&\n\t\t\t\t\t!this.syncSummarizerClients\n\t\t\t\t) {\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 isSequenceNumberSynchronized(containersToApply: IContainer[]) {\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 isClientSequenceNumberSynchronized = containersToApply.every((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 true;\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: 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\treturn (\n\t\t\t\tdeltaManager.clientSequenceNumber ===\n\t\t\t\t(deltaManager.clientSequenceNumberObserved as number) + trailingNoOps\n\t\t\t);\n\t\t});\n\n\t\tif (!isClientSequenceNumberSynchronized) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n\t\tif (minSeqNum < this.lastProposalSeqNum) {\n\t\t\t// There is an unresolved proposal\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check to see if all the container has process the same number of ops.\n\t\tconst seqNum = containersToApply[0].deltaManager.lastSequenceNumber;\n\t\treturn containersToApply.every((c) => c.deltaManager.lastSequenceNumber === seqNum);\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(\n\t\t\t\t\t\t\tpendingClientId.keys(),\n\t\t\t\t\t\t)}`,\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\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\tpublic async pauseProcessing(...containers: IContainer[]) {\n\t\tconst pauseP: 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\tdebugWait(`${record.index}: container paused`);\n\t\t\t\tpauseP.push(container.deltaManager.inbound.pause());\n\t\t\t\tpauseP.push(container.deltaManager.outbound.pause());\n\t\t\t\trecord.paused = true;\n\t\t\t}\n\t\t}\n\t\tawait Promise.all(pauseP);\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\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\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\t\tconst inflightTracker = new Map<IContainer, number>();\n\t\tconst cleanup: (() => void)[] = [];\n\t\tfor (const container of containersToApply) {\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\n\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t.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"]}
@@ -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.0.0-internal.3.4.1";
8
+ export declare const pkgVersion = "2.0.0-internal.4.0.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluidframework/test-utils";
11
- exports.pkgVersion = "2.0.0-internal.3.4.1";
11
+ exports.pkgVersion = "2.0.0-internal.4.0.0";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,sBAAsB,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.0.0-internal.3.4.1\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,sBAAsB,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.0.0-internal.4.0.0\";\n"]}
@@ -2,7 +2,6 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { Container } from "@fluidframework/container-loader";
6
5
  export declare const defaultTimeoutDurationMs = 250;
7
6
  export interface TimeoutWithError {
8
7
  /**
@@ -26,6 +25,5 @@ export interface TimeoutWithValue<T = void> {
26
25
  }
27
26
  export declare type PromiseExecutor<T = void> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void;
28
27
  export declare function timeoutAwait<T = void>(promise: PromiseLike<T>, timeoutOptions?: TimeoutWithError | TimeoutWithValue<T>): Promise<T>;
29
- export declare function ensureContainerConnected(container: Container): Promise<void>;
30
28
  export declare function timeoutPromise<T = void>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void, timeoutOptions?: TimeoutWithError | TimeoutWithValue<T>): Promise<T>;
31
29
  //# sourceMappingURL=timeoutUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAI7D,eAAO,MAAM,wBAAwB,MAAM,CAAC;AA6F5C,MAAM,WAAW,gBAAgB;IAChC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACzC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACT;AAED,oBAAY,eAAe,CAAC,CAAC,GAAG,IAAI,IAAI,CACvC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAC1B,IAAI,CAAC;AAEV,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EAC1C,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,cAG3D;AAED,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlF;AA6CD,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EAC5C,QAAQ,EAAE,CACT,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAC1B,IAAI,EACT,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GACzD,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
1
+ {"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AA6F5C,MAAM,WAAW,gBAAgB;IAChC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACzC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACT;AAED,oBAAY,eAAe,CAAC,CAAC,GAAG,IAAI,IAAI,CACvC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAC1B,IAAI,CAAC;AAEV,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EAC1C,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,cAG3D;AA6CD,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EAC5C,QAAQ,EAAE,CACT,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAC1B,IAAI,EACT,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GACzD,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.timeoutPromise = exports.ensureContainerConnected = exports.timeoutAwait = exports.defaultTimeoutDurationMs = void 0;
7
+ exports.timeoutPromise = exports.timeoutAwait = exports.defaultTimeoutDurationMs = void 0;
8
8
  const common_utils_1 = require("@fluidframework/common-utils");
9
9
  // @deprecated this value is no longer used
10
10
  exports.defaultTimeoutDurationMs = 250;
@@ -88,12 +88,6 @@ async function timeoutAwait(promise, timeoutOptions = {}) {
88
88
  return Promise.race([promise, timeoutPromise(() => { }, timeoutOptions)]);
89
89
  }
90
90
  exports.timeoutAwait = timeoutAwait;
91
- async function ensureContainerConnected(container) {
92
- if (!container.connected) {
93
- return timeoutPromise((resolve) => container.once("connected", () => resolve()));
94
- }
95
- }
96
- exports.ensureContainerConnected = ensureContainerConnected;
97
91
  // Create a promise based on the timeout options
98
92
  async function getTimeoutPromise(executor, timeoutOptions, err) {
99
93
  var _a;
@@ -1 +1 @@
1
- {"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.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 { Container } from \"@fluidframework/container-loader\";\nimport { assert, Deferred } from \"@fluidframework/common-utils\";\n\n// @deprecated this value is no longer used\nexport const defaultTimeoutDurationMs = 250;\n\n// TestTimeout class manage tracking of test timeout. It create a timer when timeout is in effect,\n// and provide a promise that will be reject before the test timeout happen with a `timeBuffer` of 15 ms.\n// Once rejected, a new TestTimeout object will be create for the timeout.\n\nconst timeBuffer = 15; // leave 15 ms leeway for finish processing\n\nclass TestTimeout {\n\tprivate timeout: number = 0;\n\tprivate timer: NodeJS.Timeout | undefined;\n\tprivate readonly deferred: Deferred<void>;\n\tprivate rejected = false;\n\n\tprivate static instance: TestTimeout = new TestTimeout();\n\tpublic static reset(runnable: Mocha.Runnable) {\n\t\tTestTimeout.clear();\n\t\tTestTimeout.instance.resetTimer(runnable);\n\t}\n\n\tpublic static clear() {\n\t\tif (TestTimeout.instance.rejected) {\n\t\t\tTestTimeout.instance = new TestTimeout();\n\t\t} else {\n\t\t\tTestTimeout.instance.clearTimer();\n\t\t}\n\t}\n\n\tpublic static getInstance() {\n\t\treturn TestTimeout.instance;\n\t}\n\n\tpublic async getPromise() {\n\t\treturn this.deferred.promise;\n\t}\n\n\tpublic getTimeout() {\n\t\treturn this.timeout;\n\t}\n\n\tprivate constructor() {\n\t\tthis.deferred = new Deferred();\n\t\t// Ignore rejection for timeout promise if no one is waiting for it.\n\t\tthis.deferred.promise.catch(() => {});\n\t}\n\n\tprivate resetTimer(runnable: Mocha.Runnable) {\n\t\tassert(!this.timer, \"clearTimer should have been called before reset\");\n\t\tassert(!this.deferred.isCompleted, \"can't reset a completed TestTimeout\");\n\n\t\t// Check the test timeout setting\n\t\tconst timeout = runnable.timeout();\n\t\tif (!(Number.isFinite(timeout) && timeout > 0)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// subtract a buffer\n\t\tthis.timeout = Math.max(timeout - timeBuffer, 1);\n\n\t\t// Set up timer to reject near the test timeout.\n\t\tthis.timer = setTimeout(() => {\n\t\t\tthis.deferred.reject(this);\n\t\t\tthis.rejected = true;\n\t\t}, this.timeout);\n\t}\n\tprivate clearTimer() {\n\t\tif (this.timer) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = undefined;\n\t\t}\n\t}\n}\n\n// only register if we are running with mocha-test-setup loaded\nif (globalThis.getMochaModule !== undefined) {\n\t// patching resetTimeout and clearTimeout on the runnable object\n\t// so we can track when test timeout are enforced\n\tconst mochaModule = globalThis.getMochaModule() as typeof Mocha;\n\tconst runnablePrototype = mochaModule.Runnable.prototype;\n\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\tconst oldResetTimeoutFunc = runnablePrototype.resetTimeout;\n\trunnablePrototype.resetTimeout = function (this: Mocha.Runnable) {\n\t\toldResetTimeoutFunc.call(this);\n\t\tTestTimeout.reset(this);\n\t};\n\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\tconst oldClearTimeoutFunc = runnablePrototype.clearTimeout;\n\trunnablePrototype.clearTimeout = function (this: Mocha.Runnable) {\n\t\tTestTimeout.clear();\n\t\toldClearTimeoutFunc.call(this);\n\t};\n}\n\nexport interface TimeoutWithError {\n\t/**\n\t * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n\t * If it is undefined, then it will use test timeout if we are in side the test function\n\t * Otherwise, there is no timeout\n\t */\n\tdurationMs?: number;\n\treject?: true;\n\terrorMsg?: string;\n}\nexport interface TimeoutWithValue<T = void> {\n\t/**\n\t * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n\t * If it is undefined, then it will use test timeout if we are in side the test function\n\t * Otherwise, there is no timeout\n\t */\n\tdurationMs?: number;\n\treject: false;\n\tvalue: T;\n}\n\nexport type PromiseExecutor<T = void> = (\n\tresolve: (value: T | PromiseLike<T>) => void,\n\treject: (reason?: any) => void,\n) => void;\n\nexport async function timeoutAwait<T = void>(\n\tpromise: PromiseLike<T>,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n) {\n\treturn Promise.race([promise, timeoutPromise<T>(() => {}, timeoutOptions)]);\n}\n\nexport async function ensureContainerConnected(container: Container): Promise<void> {\n\tif (!container.connected) {\n\t\treturn timeoutPromise((resolve) => container.once(\"connected\", () => resolve()));\n\t}\n}\n\n// Create a promise based on the timeout options\nasync function getTimeoutPromise<T = void>(\n\texecutor: (\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: any) => void,\n\t) => void,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T>,\n\terr: Error | undefined,\n) {\n\tconst timeout = timeoutOptions.durationMs ?? 0;\n\tif (timeout <= 0 || !Number.isFinite(timeout)) {\n\t\treturn new Promise(executor);\n\t}\n\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst timeoutRejections = () => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst errorObject = err!;\n\t\t\terrorObject.message = `${errorObject.message} (${timeout}ms)`;\n\t\t\treject(err);\n\t\t};\n\t\tconst timer = setTimeout(\n\t\t\t() =>\n\t\t\t\ttimeoutOptions.reject === false\n\t\t\t\t\t? resolve(timeoutOptions.value)\n\t\t\t\t\t: timeoutRejections(),\n\t\t\ttimeout,\n\t\t);\n\n\t\texecutor(\n\t\t\t(value) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(reason) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(reason);\n\t\t\t},\n\t\t);\n\t});\n}\n\n// Create a promise based on test timeout and the timeout options\nexport async function timeoutPromise<T = void>(\n\texecutor: (\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: any) => void,\n\t) => void,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n\t// create the timeout error outside the async task, so its callstack includes\n\t// the original call site, this makes it easier to debug\n\tconst err =\n\t\ttimeoutOptions.reject === false\n\t\t\t? undefined\n\t\t\t: new Error(timeoutOptions.errorMsg ?? \"Timed out\");\n\tconst executorPromise = getTimeoutPromise(executor, timeoutOptions, err);\n\n\tconst currentTestTimeout = TestTimeout.getInstance();\n\tif (currentTestTimeout === undefined) {\n\t\treturn executorPromise;\n\t}\n\n\treturn Promise.race([executorPromise, currentTestTimeout.getPromise()]).catch((e) => {\n\t\tif (e === currentTestTimeout) {\n\t\t\tif (timeoutOptions.reject !== false) {\n\t\t\t\t// If the rejection is because of the timeout then\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst errorObject = err!;\n\t\t\t\terrorObject.message = `${\n\t\t\t\t\ttimeoutOptions.errorMsg ?? \"Test timed out\"\n\t\t\t\t} (${currentTestTimeout.getTimeout()}ms)`;\n\t\t\t\tthrow errorObject;\n\t\t\t}\n\t\t\treturn timeoutOptions.value;\n\t\t}\n\t\tthrow e;\n\t}) as Promise<T>;\n}\n"]}
1
+ {"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAgE;AAEhE,2CAA2C;AAC9B,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAE5C,kGAAkG;AAClG,yGAAyG;AACzG,0EAA0E;AAE1E,MAAM,UAAU,GAAG,EAAE,CAAC,CAAC,2CAA2C;AAElE,MAAM,WAAW;IAgChB;QA/BQ,YAAO,GAAW,CAAC,CAAC;QAGpB,aAAQ,GAAG,KAAK,CAAC;QA6BxB,IAAI,CAAC,QAAQ,GAAG,IAAI,uBAAQ,EAAE,CAAC;QAC/B,oEAAoE;QACpE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvC,CAAC;IA7BM,MAAM,CAAC,KAAK,CAAC,QAAwB;QAC3C,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAEM,MAAM,CAAC,KAAK;QAClB,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAClC,WAAW,CAAC,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;SACzC;aAAM;YACN,WAAW,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;SAClC;IACF,CAAC;IAEM,MAAM,CAAC,WAAW;QACxB,OAAO,WAAW,CAAC,QAAQ,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,UAAU;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;IAC9B,CAAC;IAEM,UAAU;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAQO,UAAU,CAAC,QAAwB;QAC1C,IAAA,qBAAM,EAAC,CAAC,IAAI,CAAC,KAAK,EAAE,iDAAiD,CAAC,CAAC;QACvE,IAAA,qBAAM,EAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,qCAAqC,CAAC,CAAC;QAE1E,iCAAiC;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,EAAE;YAC/C,OAAO;SACP;QAED,oBAAoB;QACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QAEjD,gDAAgD;QAChD,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACtB,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC;IACO,UAAU;QACjB,IAAI,IAAI,CAAC,KAAK,EAAE;YACf,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;SACvB;IACF,CAAC;;AAxDc,oBAAQ,GAAgB,IAAI,WAAW,EAAE,CAAC;AA2D1D,+DAA+D;AAC/D,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,EAAE;IAC5C,gEAAgE;IAChE,iDAAiD;IACjD,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,EAAkB,CAAC;IAChE,MAAM,iBAAiB,GAAG,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC;IACzD,6DAA6D;IAC7D,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,YAAY,CAAC;IAC3D,iBAAiB,CAAC,YAAY,GAAG;QAChC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC;IACF,6DAA6D;IAC7D,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,YAAY,CAAC;IAC3D,iBAAiB,CAAC,YAAY,GAAG;QAChC,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC,CAAC;CACF;AA4BM,KAAK,UAAU,YAAY,CACjC,OAAuB,EACvB,iBAAyD,EAAE;IAE3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAI,GAAG,EAAE,GAAE,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AALD,oCAKC;AAED,gDAAgD;AAChD,KAAK,UAAU,iBAAiB,CAC/B,QAGS,EACT,cAAsD,EACtD,GAAsB;;IAEtB,MAAM,OAAO,GAAG,MAAA,cAAc,CAAC,UAAU,mCAAI,CAAC,CAAC;IAC/C,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QAC9C,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;KAC7B;IAED,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACzC,MAAM,iBAAiB,GAAG,GAAG,EAAE;YAC9B,oEAAoE;YACpE,MAAM,WAAW,GAAG,GAAI,CAAC;YACzB,WAAW,CAAC,OAAO,GAAG,GAAG,WAAW,CAAC,OAAO,KAAK,OAAO,KAAK,CAAC;YAC9D,MAAM,CAAC,GAAG,CAAC,CAAC;QACb,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CACvB,GAAG,EAAE,CACJ,cAAc,CAAC,MAAM,KAAK,KAAK;YAC9B,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC;YAC/B,CAAC,CAAC,iBAAiB,EAAE,EACvB,OAAO,CACP,CAAC;QAEF,QAAQ,CACP,CAAC,KAAK,EAAE,EAAE;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,EACD,CAAC,MAAM,EAAE,EAAE;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,CAAC;QAChB,CAAC,CACD,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,iEAAiE;AAC1D,KAAK,UAAU,cAAc,CACnC,QAGS,EACT,iBAAyD,EAAE;;IAE3D,6EAA6E;IAC7E,wDAAwD;IACxD,MAAM,GAAG,GACR,cAAc,CAAC,MAAM,KAAK,KAAK;QAC9B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,CAAC,MAAA,cAAc,CAAC,QAAQ,mCAAI,WAAW,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,iBAAiB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,CAAC,CAAC;IAEzE,MAAM,kBAAkB,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IACrD,IAAI,kBAAkB,KAAK,SAAS,EAAE;QACrC,OAAO,eAAe,CAAC;KACvB;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,kBAAkB,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;;QACnF,IAAI,CAAC,KAAK,kBAAkB,EAAE;YAC7B,IAAI,cAAc,CAAC,MAAM,KAAK,KAAK,EAAE;gBACpC,kDAAkD;gBAClD,oEAAoE;gBACpE,MAAM,WAAW,GAAG,GAAI,CAAC;gBACzB,WAAW,CAAC,OAAO,GAAG,GACrB,MAAA,cAAc,CAAC,QAAQ,mCAAI,gBAC5B,KAAK,kBAAkB,CAAC,UAAU,EAAE,KAAK,CAAC;gBAC1C,MAAM,WAAW,CAAC;aAClB;YACD,OAAO,cAAc,CAAC,KAAK,CAAC;SAC5B;QACD,MAAM,CAAC,CAAC;IACT,CAAC,CAAe,CAAC;AAClB,CAAC;AAnCD,wCAmCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, Deferred } from \"@fluidframework/common-utils\";\n\n// @deprecated this value is no longer used\nexport const defaultTimeoutDurationMs = 250;\n\n// TestTimeout class manage tracking of test timeout. It create a timer when timeout is in effect,\n// and provide a promise that will be reject before the test timeout happen with a `timeBuffer` of 15 ms.\n// Once rejected, a new TestTimeout object will be create for the timeout.\n\nconst timeBuffer = 15; // leave 15 ms leeway for finish processing\n\nclass TestTimeout {\n\tprivate timeout: number = 0;\n\tprivate timer: NodeJS.Timeout | undefined;\n\tprivate readonly deferred: Deferred<void>;\n\tprivate rejected = false;\n\n\tprivate static instance: TestTimeout = new TestTimeout();\n\tpublic static reset(runnable: Mocha.Runnable) {\n\t\tTestTimeout.clear();\n\t\tTestTimeout.instance.resetTimer(runnable);\n\t}\n\n\tpublic static clear() {\n\t\tif (TestTimeout.instance.rejected) {\n\t\t\tTestTimeout.instance = new TestTimeout();\n\t\t} else {\n\t\t\tTestTimeout.instance.clearTimer();\n\t\t}\n\t}\n\n\tpublic static getInstance() {\n\t\treturn TestTimeout.instance;\n\t}\n\n\tpublic async getPromise() {\n\t\treturn this.deferred.promise;\n\t}\n\n\tpublic getTimeout() {\n\t\treturn this.timeout;\n\t}\n\n\tprivate constructor() {\n\t\tthis.deferred = new Deferred();\n\t\t// Ignore rejection for timeout promise if no one is waiting for it.\n\t\tthis.deferred.promise.catch(() => {});\n\t}\n\n\tprivate resetTimer(runnable: Mocha.Runnable) {\n\t\tassert(!this.timer, \"clearTimer should have been called before reset\");\n\t\tassert(!this.deferred.isCompleted, \"can't reset a completed TestTimeout\");\n\n\t\t// Check the test timeout setting\n\t\tconst timeout = runnable.timeout();\n\t\tif (!(Number.isFinite(timeout) && timeout > 0)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// subtract a buffer\n\t\tthis.timeout = Math.max(timeout - timeBuffer, 1);\n\n\t\t// Set up timer to reject near the test timeout.\n\t\tthis.timer = setTimeout(() => {\n\t\t\tthis.deferred.reject(this);\n\t\t\tthis.rejected = true;\n\t\t}, this.timeout);\n\t}\n\tprivate clearTimer() {\n\t\tif (this.timer) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = undefined;\n\t\t}\n\t}\n}\n\n// only register if we are running with mocha-test-setup loaded\nif (globalThis.getMochaModule !== undefined) {\n\t// patching resetTimeout and clearTimeout on the runnable object\n\t// so we can track when test timeout are enforced\n\tconst mochaModule = globalThis.getMochaModule() as typeof Mocha;\n\tconst runnablePrototype = mochaModule.Runnable.prototype;\n\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\tconst oldResetTimeoutFunc = runnablePrototype.resetTimeout;\n\trunnablePrototype.resetTimeout = function (this: Mocha.Runnable) {\n\t\toldResetTimeoutFunc.call(this);\n\t\tTestTimeout.reset(this);\n\t};\n\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\tconst oldClearTimeoutFunc = runnablePrototype.clearTimeout;\n\trunnablePrototype.clearTimeout = function (this: Mocha.Runnable) {\n\t\tTestTimeout.clear();\n\t\toldClearTimeoutFunc.call(this);\n\t};\n}\n\nexport interface TimeoutWithError {\n\t/**\n\t * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n\t * If it is undefined, then it will use test timeout if we are in side the test function\n\t * Otherwise, there is no timeout\n\t */\n\tdurationMs?: number;\n\treject?: true;\n\terrorMsg?: string;\n}\nexport interface TimeoutWithValue<T = void> {\n\t/**\n\t * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n\t * If it is undefined, then it will use test timeout if we are in side the test function\n\t * Otherwise, there is no timeout\n\t */\n\tdurationMs?: number;\n\treject: false;\n\tvalue: T;\n}\n\nexport type PromiseExecutor<T = void> = (\n\tresolve: (value: T | PromiseLike<T>) => void,\n\treject: (reason?: any) => void,\n) => void;\n\nexport async function timeoutAwait<T = void>(\n\tpromise: PromiseLike<T>,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n) {\n\treturn Promise.race([promise, timeoutPromise<T>(() => {}, timeoutOptions)]);\n}\n\n// Create a promise based on the timeout options\nasync function getTimeoutPromise<T = void>(\n\texecutor: (\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: any) => void,\n\t) => void,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T>,\n\terr: Error | undefined,\n) {\n\tconst timeout = timeoutOptions.durationMs ?? 0;\n\tif (timeout <= 0 || !Number.isFinite(timeout)) {\n\t\treturn new Promise(executor);\n\t}\n\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst timeoutRejections = () => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst errorObject = err!;\n\t\t\terrorObject.message = `${errorObject.message} (${timeout}ms)`;\n\t\t\treject(err);\n\t\t};\n\t\tconst timer = setTimeout(\n\t\t\t() =>\n\t\t\t\ttimeoutOptions.reject === false\n\t\t\t\t\t? resolve(timeoutOptions.value)\n\t\t\t\t\t: timeoutRejections(),\n\t\t\ttimeout,\n\t\t);\n\n\t\texecutor(\n\t\t\t(value) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(reason) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(reason);\n\t\t\t},\n\t\t);\n\t});\n}\n\n// Create a promise based on test timeout and the timeout options\nexport async function timeoutPromise<T = void>(\n\texecutor: (\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: any) => void,\n\t) => void,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n\t// create the timeout error outside the async task, so its callstack includes\n\t// the original call site, this makes it easier to debug\n\tconst err =\n\t\ttimeoutOptions.reject === false\n\t\t\t? undefined\n\t\t\t: new Error(timeoutOptions.errorMsg ?? \"Timed out\");\n\tconst executorPromise = getTimeoutPromise(executor, timeoutOptions, err);\n\n\tconst currentTestTimeout = TestTimeout.getInstance();\n\tif (currentTestTimeout === undefined) {\n\t\treturn executorPromise;\n\t}\n\n\treturn Promise.race([executorPromise, currentTestTimeout.getPromise()]).catch((e) => {\n\t\tif (e === currentTestTimeout) {\n\t\t\tif (timeoutOptions.reject !== false) {\n\t\t\t\t// If the rejection is because of the timeout then\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst errorObject = err!;\n\t\t\t\terrorObject.message = `${\n\t\t\t\t\ttimeoutOptions.errorMsg ?? \"Test timed out\"\n\t\t\t\t} (${currentTestTimeout.getTimeout()}ms)`;\n\t\t\t\tthrow errorObject;\n\t\t\t}\n\t\t\treturn timeoutOptions.value;\n\t\t}\n\t\tthrow e;\n\t}) as Promise<T>;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/test-utils",
3
- "version": "2.0.0-internal.3.4.1",
3
+ "version": "2.0.0-internal.4.0.0",
4
4
  "description": "Utilities for Fluid tests",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -35,25 +35,28 @@
35
35
  "temp-directory": "nyc/.nyc_output"
36
36
  },
37
37
  "dependencies": {
38
- "@fluidframework/aqueduct": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
38
+ "@fluidframework/aqueduct": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
39
39
  "@fluidframework/common-definitions": "^0.20.1",
40
40
  "@fluidframework/common-utils": "^1.1.1",
41
- "@fluidframework/container-definitions": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
42
- "@fluidframework/container-loader": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
43
- "@fluidframework/container-runtime": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
44
- "@fluidframework/container-runtime-definitions": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
45
- "@fluidframework/core-interfaces": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
46
- "@fluidframework/datastore": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
47
- "@fluidframework/datastore-definitions": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
48
- "@fluidframework/driver-definitions": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
49
- "@fluidframework/driver-utils": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
50
- "@fluidframework/map": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
41
+ "@fluidframework/container-definitions": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
42
+ "@fluidframework/container-loader": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
43
+ "@fluidframework/container-runtime": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
44
+ "@fluidframework/container-runtime-definitions": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
45
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
46
+ "@fluidframework/datastore": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
47
+ "@fluidframework/datastore-definitions": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
48
+ "@fluidframework/driver-definitions": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
49
+ "@fluidframework/driver-utils": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
50
+ "@fluidframework/local-driver": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
51
+ "@fluidframework/map": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
51
52
  "@fluidframework/protocol-definitions": "^1.1.0",
52
- "@fluidframework/request-handler": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
53
- "@fluidframework/runtime-definitions": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
54
- "@fluidframework/runtime-utils": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
55
- "@fluidframework/telemetry-utils": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
56
- "@fluidframework/test-driver-definitions": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
53
+ "@fluidframework/request-handler": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
54
+ "@fluidframework/routerlicious-driver": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
55
+ "@fluidframework/runtime-definitions": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
56
+ "@fluidframework/runtime-utils": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
57
+ "@fluidframework/telemetry-utils": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
58
+ "@fluidframework/test-driver-definitions": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
59
+ "@fluidframework/test-runtime-utils": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
57
60
  "best-random": "^1.0.0",
58
61
  "debug": "^4.1.1",
59
62
  "uuid": "^8.3.1"
@@ -63,7 +66,7 @@
63
66
  "@fluidframework/build-common": "^1.1.0",
64
67
  "@fluidframework/build-tools": "^0.13.0",
65
68
  "@fluidframework/eslint-config-fluid": "^2.0.0",
66
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.3.4.1 <2.0.0-internal.4.0.0",
69
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.0.0 <2.0.0-internal.5.0.0",
67
70
  "@fluidframework/test-utils-previous": "npm:@fluidframework/test-utils@2.0.0-internal.3.2.0",
68
71
  "@microsoft/api-extractor": "^7.34.4",
69
72
  "@types/debug": "^4.1.5",
@@ -85,7 +88,26 @@
85
88
  "typescript": "~4.5.5"
86
89
  },
87
90
  "typeValidation": {
88
- "broken": {}
91
+ "broken": {
92
+ "RemovedFunctionDeclaration_ensureContainerConnected": {
93
+ "backCompat": false,
94
+ "forwardCompat": false
95
+ },
96
+ "FunctionDeclaration_createSummarizerWithContainer": {
97
+ "forwardCompat": false,
98
+ "backCompat": false
99
+ },
100
+ "RemovedFunctionDeclaration_createSummarizerWithContainer": {
101
+ "forwardCompat": false,
102
+ "backCompat": false
103
+ },
104
+ "InterfaceDeclaration_ITestObjectProvider": {
105
+ "backCompat": false
106
+ },
107
+ "ClassDeclaration_TestObjectProvider": {
108
+ "backCompat": false
109
+ }
110
+ }
89
111
  },
90
112
  "scripts": {
91
113
  "build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
@@ -53,10 +53,12 @@ async function createSummarizerCore(
53
53
  const summarizerContainer = await loader.resolve(request);
54
54
  await waitForContainerConnection(summarizerContainer);
55
55
 
56
- const fluidObject = await requestFluidObject<FluidObject<ISummarizer>>(summarizerContainer, {
57
- url: "_summarizer",
58
- });
59
- if (fluidObject.ISummarizer === undefined) {
56
+ const fluidObject: FluidObject<ISummarizer> | undefined = summarizerContainer.getEntryPoint
57
+ ? await summarizerContainer.getEntryPoint?.()
58
+ : await requestFluidObject<FluidObject<ISummarizer>>(summarizerContainer, {
59
+ url: "_summarizer",
60
+ });
61
+ if (fluidObject?.ISummarizer === undefined) {
60
62
  throw new Error("Fluid object does not implement ISummarizer");
61
63
  }
62
64
 
@@ -7,20 +7,6 @@ import { IContainer } from "@fluidframework/container-definitions";
7
7
  import { ConnectionState } from "@fluidframework/container-loader";
8
8
  import { PromiseExecutor, timeoutPromise, TimeoutWithError } from "./timeoutUtils";
9
9
 
10
- /**
11
- * Waits for the specified container to emit a 'connected' event.
12
- *
13
- * @deprecated Use waitForContainerConnection instead.
14
- * Note that an upcoming release will change the default parameters on that function to:
15
- * - failOnContainerClose = true
16
- * - timeoutOptions.durationMs = 1s
17
- */
18
- export async function ensureContainerConnected(container: IContainer): Promise<void> {
19
- if (container.connectionState !== ConnectionState.Connected) {
20
- return timeoutPromise((resolve) => container.once("connected", () => resolve()));
21
- }
22
- }
23
-
24
10
  /**
25
11
  * Utility function to wait for the specified Container to be in Connected state.
26
12
  * If the Container is already connected, the Promise returns immediately; otherwise it resolves when the Container emits
@@ -30,20 +16,21 @@ export async function ensureContainerConnected(container: IContainer): Promise<v
30
16
  * @param container - The container to wait for.
31
17
  * @param failOnContainerClose - If true, the returned Promise will be rejected if the container emits a 'closed' event
32
18
  * before a 'connected' event.
33
- * Defaults to false (but this will change in an upcoming version).
19
+ * Defaults to true.
34
20
  * @param timeoutOptions - Options related to the behavior of the timeout.
35
- * If not provided, no timeout will be applied and the promise will wait indefinitely for the Container to emit its
36
- * 'connected' (or 'closed, if failOnContainerClose === true) event.
37
- * @returns A Promise that resolves when the specified container emits a 'connected' event (or immediately if the
38
- * Container is already connected).
39
- * If failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event, the Promise
40
- * is rejected with the error from the 'closed' event, if any.
41
- * If timeoutOptions is provided, the Promise will reject if the container hasn't emmited a relevant event before
42
- * timeoutOptions.durationMs (which defaults to 250ms if left undefined).
21
+ * If provided, the returned Promise will reject if the container hasn't emitted relevant events in timeoutOptions.durationMs.
22
+ * If not provided, the Promise will wait indefinitely for the Container to emit its 'connected' (or 'closed', if
23
+ * failOnContainerClose === true) event.
24
+ *
25
+ * @returns A Promise that either:
26
+ * - Resolves when the specified container emits a 'connected' event (or immediately if the Container is already connected).
27
+ * - Rejects if failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event.
28
+ * - Rejects after timeoutOptions.durationMs if timeoutOptions !== undefined and the container does not emit relevant
29
+ * events, within that timeframe.
43
30
  */
44
31
  export async function waitForContainerConnection(
45
32
  container: IContainer,
46
- failOnContainerClose: boolean = false,
33
+ failOnContainerClose: boolean = true,
47
34
  timeoutOptions?: TimeoutWithError,
48
35
  ): Promise<void> {
49
36
  if (container.connectionState !== ConnectionState.Connected) {
package/src/index.ts CHANGED
@@ -37,4 +37,4 @@ export {
37
37
  TimeoutWithError,
38
38
  TimeoutWithValue,
39
39
  } from "./timeoutUtils";
40
- export { ensureContainerConnected, waitForContainerConnection } from "./containerUtils";
40
+ export { waitForContainerConnection } from "./containerUtils";
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { assert } from "@fluidframework/common-utils";
6
6
  import { IContainer, IDeltaQueue, IHostLoader } from "@fluidframework/container-definitions";
7
- import { Container } from "@fluidframework/container-loader";
7
+ import { ConnectionState } from "@fluidframework/container-loader";
8
8
  import { canBeCoalescedByService } from "@fluidframework/driver-utils";
9
9
  import {
10
10
  IDocumentMessage,
@@ -123,7 +123,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
123
123
  // Received the no op back, update the record if we are tracking
124
124
  if (
125
125
  canBeCoalescedByService(message) &&
126
- message.clientId === (container as Container).clientId &&
126
+ message.clientId === container.clientId &&
127
127
  record.trailingNoOps !== 0 &&
128
128
  record.startTrailingNoOps <= message.clientSequenceNumber
129
129
  ) {
@@ -287,9 +287,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
287
287
  // All the clientId we track should be a superset of the quorum, otherwise, we are missing
288
288
  // leave messages
289
289
  const openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);
290
- const openedClientId = openedDocuments.map(
291
- (container) => (container as Container).clientId,
292
- );
290
+ const openedClientId = openedDocuments.map((container) => container.clientId);
293
291
 
294
292
  const pendingClients: [IContainer, Set<string>][] = [];
295
293
  containersToApply.forEach((container) => {
@@ -375,7 +373,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
375
373
  */
376
374
  private async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {
377
375
  const unconnectedClients = Array.from(this.containers.keys()).filter(
378
- (c) => !c.closed && !(c as Container).connected,
376
+ (c) => !c.closed && c.connectionState !== ConnectionState.Connected,
379
377
  );
380
378
  return Promise.all(
381
379
  pendingClients.map(async ([container, pendingClientId]) => {
@@ -546,7 +544,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
546
544
  const inHandler = (message: ISequencedDocumentMessage) => {
547
545
  if (
548
546
  !canBeCoalescedByService(message) &&
549
- message.clientId === (container as Container).clientId &&
547
+ message.clientId === container.clientId &&
550
548
  inflightTracker.get(container) === message.clientSequenceNumber
551
549
  ) {
552
550
  inflightTracker.delete(container);
@@ -600,7 +598,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
600
598
  return `${e.message}: ${e.stack}`;
601
599
  }
602
600
  };
603
- debugOp(`${index}: ADD: clientId: ${(container as Container).clientId}`);
601
+ debugOp(`${index}: ADD: clientId: ${container.clientId}`);
604
602
  container.deltaManager.outbound.on("op", (messages) => {
605
603
  for (const msg of messages) {
606
604
  debugOp(
@@ -614,7 +612,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
614
612
  const getInboundHandler = (type: string) => {
615
613
  return (msg: ISequencedDocumentMessage) => {
616
614
  const clientSeq =
617
- msg.clientId === (container as Container).clientId
615
+ msg.clientId === container.clientId
618
616
  ? `cli: ${msg.clientSequenceNumber.toString().padStart(3)}`
619
617
  : " ";
620
618
  debugOp(
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/test-utils";
9
- export const pkgVersion = "2.0.0-internal.3.4.1";
9
+ export const pkgVersion = "2.0.0-internal.4.0.0";
@@ -3,7 +3,6 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { Container } from "@fluidframework/container-loader";
7
6
  import { assert, Deferred } from "@fluidframework/common-utils";
8
7
 
9
8
  // @deprecated this value is no longer used
@@ -133,12 +132,6 @@ export async function timeoutAwait<T = void>(
133
132
  return Promise.race([promise, timeoutPromise<T>(() => {}, timeoutOptions)]);
134
133
  }
135
134
 
136
- export async function ensureContainerConnected(container: Container): Promise<void> {
137
- if (!container.connected) {
138
- return timeoutPromise((resolve) => container.once("connected", () => resolve()));
139
- }
140
- }
141
-
142
135
  // Create a promise based on the timeout options
143
136
  async function getTimeoutPromise<T = void>(
144
137
  executor: (