@fluidframework/container-loader 2.0.0-dev-rc.3.0.0.254674 → 2.0.0-dev-rc.4.0.0.261659
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/api-report/container-loader.api.md +7 -3
- package/dist/audience.d.ts +6 -4
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +18 -3
- package/dist/audience.js.map +1 -1
- package/dist/connectionManager.d.ts +6 -2
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +40 -16
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +29 -8
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +49 -36
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +6 -10
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +126 -113
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +1 -1
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +12 -3
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +42 -4
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/debugLogger.d.ts +1 -2
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +3 -4
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +8 -3
- package/dist/deltaManager.js.map +1 -1
- package/dist/error.d.ts +1 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/{alpha.d.ts → legacy.d.ts} +5 -2
- package/dist/loadPaused.d.ts +35 -0
- package/dist/loadPaused.d.ts.map +1 -0
- package/dist/loadPaused.js +115 -0
- package/dist/loadPaused.js.map +1 -0
- package/dist/loader.d.ts +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +0 -13
- package/dist/loader.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +3 -0
- package/dist/protocol.js.map +1 -1
- package/dist/public.d.ts +2 -1
- package/dist/retriableDocumentStorageService.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +23 -5
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +72 -22
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +2 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -3
- package/dist/utils.js.map +1 -1
- package/{dist/beta.d.ts → internal.d.ts} +2 -4
- package/{lib/beta.d.ts → legacy.d.ts} +2 -4
- package/lib/audience.d.ts +6 -4
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +19 -4
- package/lib/audience.js.map +1 -1
- package/lib/connectionManager.d.ts +6 -2
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +41 -17
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +29 -8
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +49 -36
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +6 -10
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +126 -113
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +1 -1
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +12 -3
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +42 -4
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/debugLogger.d.ts +1 -2
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +3 -4
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +9 -4
- package/lib/deltaManager.js.map +1 -1
- package/lib/error.d.ts +1 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/{alpha.d.ts → legacy.d.ts} +5 -2
- package/lib/loadPaused.d.ts +35 -0
- package/lib/loadPaused.d.ts.map +1 -0
- package/lib/loadPaused.js +111 -0
- package/lib/loadPaused.js.map +1 -0
- package/lib/loader.d.ts +1 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +1 -14
- package/lib/loader.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +3 -0
- package/lib/protocol.js.map +1 -1
- package/lib/public.d.ts +2 -1
- package/lib/retriableDocumentStorageService.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +23 -5
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +66 -16
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/utils.d.ts +2 -2
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -3
- package/lib/utils.js.map +1 -1
- package/package.json +29 -27
- package/src/audience.ts +30 -9
- package/src/connectionManager.ts +50 -21
- package/src/connectionStateHandler.ts +76 -43
- package/src/container.ts +150 -153
- package/src/containerContext.ts +1 -1
- package/src/containerStorageAdapter.ts +59 -7
- package/src/debugLogger.ts +1 -1
- package/src/deltaManager.ts +13 -6
- package/src/error.ts +1 -1
- package/src/index.ts +1 -0
- package/src/loadPaused.ts +140 -0
- package/src/loader.ts +1 -21
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +4 -0
- package/src/retriableDocumentStorageService.ts +5 -2
- package/src/serializedStateManager.ts +107 -31
- package/src/utils.ts +3 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @fluidframework/container-loader
|
|
2
2
|
|
|
3
|
+
## 2.0.0-rc.3.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- container-definitions: IContainerContext.getSpecifiedCodeDetails() removed [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
8
|
+
|
|
9
|
+
IContainerContext.getSpecifiedCodeDetails() was deprecated in 0.42 and has now been removed.
|
|
10
|
+
|
|
11
|
+
- Packages now use package.json "exports" and require modern module resolution [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
12
|
+
|
|
13
|
+
Fluid Framework packages have been updated to use the [package.json "exports"
|
|
14
|
+
field](https://nodejs.org/docs/latest-v18.x/api/packages.html#exports) to define explicit entry points for both
|
|
15
|
+
TypeScript types and implementation code.
|
|
16
|
+
|
|
17
|
+
This means that using Fluid Framework packages require the following TypeScript settings in tsconfig.json:
|
|
18
|
+
|
|
19
|
+
- `"moduleResolution": "Node16"` with `"module": "Node16"`
|
|
20
|
+
- `"moduleResolution": "Bundler"` with `"module": "ESNext"`
|
|
21
|
+
|
|
22
|
+
We recommend using Node16/Node16 unless absolutely necessary. That will produce transpiled JavaScript that is suitable
|
|
23
|
+
for use with modern versions of Node.js _and_ Bundlers.
|
|
24
|
+
[See the TypeScript documentation](https://www.typescriptlang.org/tsconfig#moduleResolution) for more information
|
|
25
|
+
regarding the module and moduleResolution options.
|
|
26
|
+
|
|
27
|
+
**Node10 moduleResolution is not supported; it does not support Fluid Framework's API structuring pattern that is used
|
|
28
|
+
to distinguish stable APIs from those that are in development.**
|
|
29
|
+
|
|
30
|
+
### Minor Changes
|
|
31
|
+
|
|
32
|
+
- driver-definitions: update submitSignal content type to string [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
33
|
+
|
|
34
|
+
Change IDocumentDeltaConnection.submitSignal's content argument type to string which represents actual/known use.
|
|
35
|
+
|
|
3
36
|
## 2.0.0-rc.2.0.0
|
|
4
37
|
|
|
5
38
|
### Minor Changes
|
|
@@ -15,6 +15,7 @@ import { IDocumentStorageService } from '@fluidframework/driver-definitions/inte
|
|
|
15
15
|
import { IFluidCodeDetails } from '@fluidframework/container-definitions/internal';
|
|
16
16
|
import { IFluidModule } from '@fluidframework/container-definitions/internal';
|
|
17
17
|
import { IHostLoader } from '@fluidframework/container-definitions/internal';
|
|
18
|
+
import { ILoader } from '@fluidframework/container-definitions/internal';
|
|
18
19
|
import { ILoaderOptions as ILoaderOptions_2 } from '@fluidframework/container-definitions/internal';
|
|
19
20
|
import { ILocationRedirectionError } from '@fluidframework/driver-definitions/internal';
|
|
20
21
|
import { IProtocolHandler as IProtocolHandler_2 } from '@fluidframework/protocol-base';
|
|
@@ -23,7 +24,7 @@ import { IQuorumSnapshot } from '@fluidframework/protocol-base';
|
|
|
23
24
|
import { IRequest } from '@fluidframework/core-interfaces';
|
|
24
25
|
import { ISignalMessage } from '@fluidframework/protocol-definitions';
|
|
25
26
|
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
26
|
-
import { ITelemetryLoggerExt } from '@fluidframework/telemetry-utils';
|
|
27
|
+
import { ITelemetryLoggerExt } from '@fluidframework/telemetry-utils/internal';
|
|
27
28
|
import { IUrlResolver } from '@fluidframework/driver-definitions/internal';
|
|
28
29
|
|
|
29
30
|
// @public
|
|
@@ -88,7 +89,7 @@ export interface ILoaderServices {
|
|
|
88
89
|
readonly urlResolver: IUrlResolver;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
// @
|
|
92
|
+
// @alpha
|
|
92
93
|
export interface IParsedUrl {
|
|
93
94
|
id: string;
|
|
94
95
|
path: string;
|
|
@@ -107,6 +108,9 @@ export interface IProtocolHandler extends IProtocolHandler_2 {
|
|
|
107
108
|
// @internal
|
|
108
109
|
export function isLocationRedirectionError(error: any): error is ILocationRedirectionError;
|
|
109
110
|
|
|
111
|
+
// @internal
|
|
112
|
+
export function loadContainerPaused(loader: ILoader, request: IRequest, loadToSequenceNumber?: number, signal?: AbortSignal): Promise<IContainer>;
|
|
113
|
+
|
|
110
114
|
// @alpha
|
|
111
115
|
export class Loader implements IHostLoader {
|
|
112
116
|
constructor(loaderProps: ILoaderProps);
|
|
@@ -132,7 +136,7 @@ export type ProtocolHandlerBuilder = (attributes: IDocumentAttributes, snapshot:
|
|
|
132
136
|
// @alpha
|
|
133
137
|
export function resolveWithLocationRedirectionHandling<T>(api: (request: IRequest) => Promise<T>, request: IRequest, urlResolver: IUrlResolver, logger?: ITelemetryBaseLogger): Promise<T>;
|
|
134
138
|
|
|
135
|
-
// @
|
|
139
|
+
// @alpha
|
|
136
140
|
export function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined;
|
|
137
141
|
|
|
138
142
|
// @alpha
|
package/dist/audience.d.ts
CHANGED
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import { IAudienceOwner } from "@fluidframework/container-definitions/internal";
|
|
5
|
+
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
6
|
+
import { IAudienceEvents, IAudienceOwner, ISelf } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
import { IClient } from "@fluidframework/protocol-definitions";
|
|
8
8
|
/**
|
|
9
9
|
* Audience represents all clients connected to the op stream.
|
|
10
10
|
*/
|
|
11
|
-
export declare class Audience extends
|
|
11
|
+
export declare class Audience extends TypedEventEmitter<IAudienceEvents> implements IAudienceOwner {
|
|
12
12
|
private readonly members;
|
|
13
|
+
private _currentClientId;
|
|
13
14
|
constructor();
|
|
14
|
-
|
|
15
|
+
getSelf(): ISelf | undefined;
|
|
16
|
+
setCurrentClientId(clientId: string): void;
|
|
15
17
|
/**
|
|
16
18
|
* Adds a new client to the audience
|
|
17
19
|
*/
|
package/dist/audience.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EACN,eAAe,EACf,cAAc,EACd,KAAK,EACL,MAAM,gDAAgD,CAAC;AAExD,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAE/D;;GAEG;AACH,qBAAa,QAAS,SAAQ,iBAAiB,CAAC,eAAe,CAAE,YAAW,cAAc;IACzF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAqB;;IAQtC,OAAO,IAAI,KAAK,GAAG,SAAS;IAS5B,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAejD;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAenD;;;OAGG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAW9C;;;;;OAKG;IACI,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAIzC;;;;;OAKG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;CAGvD"}
|
package/dist/audience.js
CHANGED
|
@@ -10,15 +10,30 @@ const internal_1 = require("@fluidframework/core-utils/internal");
|
|
|
10
10
|
/**
|
|
11
11
|
* Audience represents all clients connected to the op stream.
|
|
12
12
|
*/
|
|
13
|
-
class Audience extends client_utils_1.
|
|
13
|
+
class Audience extends client_utils_1.TypedEventEmitter {
|
|
14
14
|
constructor() {
|
|
15
15
|
super();
|
|
16
16
|
this.members = new Map();
|
|
17
17
|
// We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging.
|
|
18
18
|
super.setMaxListeners(0);
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
return
|
|
20
|
+
getSelf() {
|
|
21
|
+
return this._currentClientId === undefined
|
|
22
|
+
? undefined
|
|
23
|
+
: {
|
|
24
|
+
clientId: this._currentClientId,
|
|
25
|
+
client: this.getMember(this._currentClientId),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
setCurrentClientId(clientId) {
|
|
29
|
+
if (this._currentClientId !== clientId) {
|
|
30
|
+
const oldId = this._currentClientId;
|
|
31
|
+
this._currentClientId = clientId;
|
|
32
|
+
// this.getMember(clientId) could resolve to undefined in these two cases:
|
|
33
|
+
// 1) Feature gates controlling ConnectionStateHandler() behavior are off
|
|
34
|
+
// 2) we are loading from stashed state and audience is empty, but we remember and set prior clientId
|
|
35
|
+
this.emit("selfChanged", oldId === undefined ? undefined : ({ clientId: oldId }), { clientId, client: this.getMember(clientId) });
|
|
36
|
+
}
|
|
22
37
|
}
|
|
23
38
|
/**
|
|
24
39
|
* Adds a new client to the audience
|
package/dist/audience.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+
|
|
1
|
+
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAMjE,kEAA6D;AAG7D;;GAEG;AACH,MAAa,QAAS,SAAQ,gCAAkC;IAI/D;QACC,KAAK,EAAE,CAAC;QAJQ,YAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QAKrD,kHAAkH;QAClH,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAEM,OAAO;QACb,OAAO,IAAI,CAAC,gBAAgB,KAAK,SAAS;YACzC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC;gBACA,QAAQ,EAAE,IAAI,CAAC,gBAAgB;gBAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC;aAC5C,CAAC;IACN,CAAC;IAEM,kBAAkB,CAAC,QAAgB;QACzC,IAAI,IAAI,CAAC,gBAAgB,KAAK,QAAQ,EAAE;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;YACjC,0EAA0E;YAC1E,yEAAyE;YACzE,qGAAqG;YACrG,IAAI,CAAC,IAAI,CACR,aAAa,EACb,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAkB,CAAC,EACvE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAkB,CAC9D,CAAC;SACF;IACF,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,QAAgB,EAAE,OAAgB;QAClD,mGAAmG;QACnG,+FAA+F;QAC/F,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAA,iBAAM,EACL,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAClD,KAAK,CAAC,wDAAwD,CAC9D,CAAC;SACF;aAAM;YACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;SAC1C;IACF,CAAC;IAED;;;OAGG;IACI,YAAY,CAAC,QAAgB;QACnC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,aAAa,KAAK,SAAS,EAAE;YAChC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC;SACZ;aAAM;YACN,OAAO,KAAK,CAAC;SACb;IACF,CAAC;IAED;;;;;OAKG;IACI,UAAU;QAChB,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACI,SAAS,CAAC,QAAgB;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;CACD;AAtFD,4BAsFC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport {\n\tIAudienceEvents,\n\tIAudienceOwner,\n\tISelf,\n} from \"@fluidframework/container-definitions/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { IClient } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Audience represents all clients connected to the op stream.\n */\nexport class Audience extends TypedEventEmitter<IAudienceEvents> implements IAudienceOwner {\n\tprivate readonly members = new Map<string, IClient>();\n\tprivate _currentClientId: string | undefined;\n\n\tconstructor() {\n\t\tsuper();\n\t\t// We are expecting this class to have many listeners, so we suppress noisy \"MaxListenersExceededWarning\" logging.\n\t\tsuper.setMaxListeners(0);\n\t}\n\n\tpublic getSelf(): ISelf | undefined {\n\t\treturn this._currentClientId === undefined\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\tclientId: this._currentClientId,\n\t\t\t\t\tclient: this.getMember(this._currentClientId),\n\t\t\t };\n\t}\n\n\tpublic setCurrentClientId(clientId: string): void {\n\t\tif (this._currentClientId !== clientId) {\n\t\t\tconst oldId = this._currentClientId;\n\t\t\tthis._currentClientId = clientId;\n\t\t\t// this.getMember(clientId) could resolve to undefined in these two cases:\n\t\t\t// 1) Feature gates controlling ConnectionStateHandler() behavior are off\n\t\t\t// 2) we are loading from stashed state and audience is empty, but we remember and set prior clientId\n\t\t\tthis.emit(\n\t\t\t\t\"selfChanged\",\n\t\t\t\toldId === undefined ? undefined : ({ clientId: oldId } satisfies ISelf),\n\t\t\t\t{ clientId, client: this.getMember(clientId) } satisfies ISelf,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Adds a new client to the audience\n\t */\n\tpublic addMember(clientId: string, details: IClient) {\n\t\t// Given that signal delivery is unreliable process, we might observe same client being added twice\n\t\t// In such case we should see exactly same payload (IClient), and should not raise event twice!\n\t\tif (this.members.has(clientId)) {\n\t\t\tconst client = this.members.get(clientId);\n\t\t\tassert(\n\t\t\t\tJSON.stringify(client) === JSON.stringify(details),\n\t\t\t\t0x4b2 /* new client has different payload from existing one */,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.members.set(clientId, details);\n\t\t\tthis.emit(\"addMember\", clientId, details);\n\t\t}\n\t}\n\n\t/**\n\t * Removes a client from the audience. Only emits an event if a client is actually removed\n\t * @returns if a client was removed from the audience\n\t */\n\tpublic removeMember(clientId: string): boolean {\n\t\tconst removedClient = this.members.get(clientId);\n\t\tif (removedClient !== undefined) {\n\t\t\tthis.members.delete(clientId);\n\t\t\tthis.emit(\"removeMember\", clientId, removedClient);\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves all the members in the audience.\n\t *\n\t * @remarks When the container is disconnected, this will keep returning the audience as it was last seen before the\n\t * container disconnected.\n\t */\n\tpublic getMembers(): Map<string, IClient> {\n\t\treturn new Map(this.members);\n\t}\n\n\t/**\n\t * Retrieves a specific member of the audience.\n\t *\n\t * @remarks When the container is disconnected, this will keep returning members from the audience as it was last seen\n\t * before the container disconnected.\n\t */\n\tpublic getMember(clientId: string): IClient | undefined {\n\t\treturn this.members.get(clientId);\n\t}\n}\n"]}
|
|
@@ -6,8 +6,8 @@ import { ICriticalContainerError, IDeltaQueue, ReadOnlyInfo } from "@fluidframew
|
|
|
6
6
|
import { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { IDocumentService } from "@fluidframework/driver-definitions/internal";
|
|
8
8
|
import { ConnectionMode, IClient, IClientConfiguration, IClientDetails, IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
9
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
10
|
-
import { IConnectionManager, IConnectionManagerFactoryArgs, IConnectionStateChangeReason, ReconnectMode } from "./contracts.js";
|
|
9
|
+
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
10
|
+
import { IConnectionDetailsInternal, IConnectionManager, IConnectionManagerFactoryArgs, IConnectionStateChangeReason, ReconnectMode } from "./contracts.js";
|
|
11
11
|
/**
|
|
12
12
|
* Implementation of IConnectionManager, used by Container class
|
|
13
13
|
* Implements constant connectivity to relay service, by reconnecting in case of lost connection or error.
|
|
@@ -28,6 +28,8 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
28
28
|
*/
|
|
29
29
|
private pendingConnection;
|
|
30
30
|
private connection;
|
|
31
|
+
/** Details about connection. undefined if there is no active connection. */
|
|
32
|
+
private _connectionDetails?;
|
|
31
33
|
/** file ACL - whether user has only read-only access to a file */
|
|
32
34
|
private _readonlyPermissions;
|
|
33
35
|
/** tracks host requiring read-only mode. */
|
|
@@ -57,6 +59,8 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
57
59
|
get connectionMode(): ConnectionMode;
|
|
58
60
|
get connected(): boolean;
|
|
59
61
|
get clientId(): string | undefined;
|
|
62
|
+
/** Details about connection. undefined if there is no active connection. */
|
|
63
|
+
get connectionDetails(): IConnectionDetailsInternal | undefined;
|
|
60
64
|
/**
|
|
61
65
|
* Automatic reconnecting enabled or disabled.
|
|
62
66
|
* If set to Never, then reconnecting will never be allowed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,uBAAuB,EACvB,WAAW,EACX,YAAY,EACZ,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAe,wBAAwB,EAAY,MAAM,iCAAiC,CAAC;AAGlG,OAAO,EAGN,gBAAgB,EAChB,MAAM,6CAA6C,CAAC;AAUrD,OAAO,EACN,cAAc,EACd,OAAO,EACP,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAGhB,yBAAyB,EAOzB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -125,6 +125,10 @@ class ConnectionManager {
|
|
|
125
125
|
get clientId() {
|
|
126
126
|
return this.connection?.clientId;
|
|
127
127
|
}
|
|
128
|
+
/** Details about connection. undefined if there is no active connection. */
|
|
129
|
+
get connectionDetails() {
|
|
130
|
+
return this._connectionDetails;
|
|
131
|
+
}
|
|
128
132
|
/**
|
|
129
133
|
* Automatic reconnecting enabled or disabled.
|
|
130
134
|
* If set to Never, then reconnecting will never be allowed.
|
|
@@ -371,17 +375,7 @@ class ConnectionManager {
|
|
|
371
375
|
}
|
|
372
376
|
async connectCore(reason, connectionMode) {
|
|
373
377
|
(0, internal_1.assert)(!this._disposed, 0x26a /* "not closed" */);
|
|
374
|
-
|
|
375
|
-
return; // Connection attempt already completed successfully
|
|
376
|
-
}
|
|
377
|
-
let pendingConnectionMode;
|
|
378
|
-
if (this.pendingConnection !== undefined) {
|
|
379
|
-
pendingConnectionMode = this.pendingConnection.connectionMode;
|
|
380
|
-
this.cancelConnection(reason); // Throw out in-progress connection attempt in favor of new attempt
|
|
381
|
-
(0, internal_1.assert)(this.pendingConnection === undefined, 0x344 /* this.pendingConnection should be undefined */);
|
|
382
|
-
}
|
|
383
|
-
// If there is no specified ConnectionMode, try the previous mode, if there is no previous mode use default
|
|
384
|
-
let requestedMode = connectionMode ?? pendingConnectionMode ?? this.defaultReconnectionMode;
|
|
378
|
+
let requestedMode = connectionMode ?? this.defaultReconnectionMode;
|
|
385
379
|
// if we have any non-acked ops from last connection, reconnect as "write".
|
|
386
380
|
// without that we would connect in view-only mode, which will result in immediate
|
|
387
381
|
// firing of "connected" event from Container and switch of current clientId (as tracked
|
|
@@ -390,8 +384,30 @@ class ConnectionManager {
|
|
|
390
384
|
if (this.shouldJoinWrite()) {
|
|
391
385
|
requestedMode = "write";
|
|
392
386
|
}
|
|
387
|
+
if (this.connection !== undefined || this.pendingConnection !== undefined) {
|
|
388
|
+
// Connection attempt already completed successfully or is in progress
|
|
389
|
+
// In general, there should be no issues if the modes do not match:
|
|
390
|
+
// If at some point it was Ok to connect as "read" (i.e. there were no pending ops we had to track),
|
|
391
|
+
// then it should be Ok to use "read" connection even if for some reason request came in to connect as "write"
|
|
392
|
+
// (though that should never happen)
|
|
393
|
+
// The opposite should be fine as well: we may have had idle "write" connection, and request to reconnect came in,
|
|
394
|
+
// using default "read" mode.
|
|
395
|
+
// That all said, let's understand better where such mismatches are coming from.
|
|
396
|
+
const mode = this.connection?.mode ?? this.pendingConnection?.connectionMode;
|
|
397
|
+
if (mode !== requestedMode) {
|
|
398
|
+
this.logger.sendTelemetryEvent({
|
|
399
|
+
eventName: "ConnectionModeMismatch",
|
|
400
|
+
connected: this.connection !== undefined,
|
|
401
|
+
mode,
|
|
402
|
+
requestedMode,
|
|
403
|
+
stack: (0, internal_3.generateStack)(),
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
393
408
|
const docService = this.serviceProvider();
|
|
394
409
|
(0, internal_1.assert)(docService !== undefined, 0x2a7 /* "Container is not attached" */);
|
|
410
|
+
this.props.establishConnectionHandler(reason);
|
|
395
411
|
let connection;
|
|
396
412
|
if (docService.policies?.storageOnly === true) {
|
|
397
413
|
connection = new NoDeltaStream();
|
|
@@ -411,7 +427,6 @@ class ConnectionManager {
|
|
|
411
427
|
},
|
|
412
428
|
connectionMode: requestedMode,
|
|
413
429
|
};
|
|
414
|
-
this.props.establishConnectionHandler(reason);
|
|
415
430
|
// This loop will keep trying to connect until successful, with a delay between each iteration.
|
|
416
431
|
while (connection === undefined) {
|
|
417
432
|
if (this._disposed) {
|
|
@@ -481,6 +496,11 @@ class ConnectionManager {
|
|
|
481
496
|
duration: (0, internal_3.formatTick)(client_utils_1.performance.now() - connectStartTime),
|
|
482
497
|
}, origError);
|
|
483
498
|
lastError = origError;
|
|
499
|
+
// We will not perform retries if the container disconnected and the ReconnectMode is set to Disabled or Never
|
|
500
|
+
// so break out of the re-connecting while-loop after first attempt
|
|
501
|
+
if (this.reconnectMode !== contracts_js_1.ReconnectMode.Enabled) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
484
504
|
const waitStartTime = client_utils_1.performance.now();
|
|
485
505
|
const retryDelayFromError = (0, internal_2.getRetryDelayFromError)(origError);
|
|
486
506
|
// If the error told us to wait or browser signals us that we are offline, then calculate the time we
|
|
@@ -569,6 +589,7 @@ class ConnectionManager {
|
|
|
569
589
|
const connection = this.connection;
|
|
570
590
|
// Avoid any re-entrancy - clear object reference
|
|
571
591
|
this.connection = undefined;
|
|
592
|
+
this._connectionDetails = undefined;
|
|
572
593
|
// Remove listeners first so we don't try to retrigger this flow accidentally through reconnectOnError
|
|
573
594
|
connection.off("op", this.opHandler);
|
|
574
595
|
connection.off("signal", this.signalHandler);
|
|
@@ -591,7 +612,10 @@ class ConnectionManager {
|
|
|
591
612
|
(0, internal_1.assert)(this.pendingConnection !== undefined, 0x345 /* this.pendingConnection is undefined when trying to cancel */);
|
|
592
613
|
this.pendingConnection.abort();
|
|
593
614
|
this.pendingConnection = undefined;
|
|
594
|
-
this.logger.sendTelemetryEvent({
|
|
615
|
+
this.logger.sendTelemetryEvent({
|
|
616
|
+
eventName: "ConnectionCancelReceived",
|
|
617
|
+
reason: reason.text,
|
|
618
|
+
});
|
|
595
619
|
this.props.cancelConnectionHandler({
|
|
596
620
|
text: `Cancel Pending Connection due to ${reason.text}`,
|
|
597
621
|
error: reason.error,
|
|
@@ -670,9 +694,9 @@ class ConnectionManager {
|
|
|
670
694
|
}
|
|
671
695
|
}
|
|
672
696
|
this.props.incomingOpHandler(initialMessages, this.connectFirstConnection ? "InitialOps" : "ReconnectOps");
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
this.props.connectHandler(
|
|
697
|
+
this._connectionDetails = ConnectionManager.detailsFromConnection(connection, reason);
|
|
698
|
+
this._connectionDetails.checkpointSequenceNumber = checkpointSequenceNumber;
|
|
699
|
+
this.props.connectHandler(this._connectionDetails);
|
|
676
700
|
this.connectFirstConnection = false;
|
|
677
701
|
// Synthesize clear & join signals out of initialClients state.
|
|
678
702
|
// This allows us to have single way to process signals, and makes it simpler to initialize
|