@fluidframework/container-loader 2.0.0-dev.6.4.0.191515 → 2.0.0-dev.7.2.0.203917
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 +122 -0
- package/api-extractor.json +9 -1
- package/api-report/container-loader.api.md +153 -0
- package/dist/catchUpMonitor.d.ts +2 -2
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/connectionManager.d.ts +2 -15
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +110 -98
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionState.js +1 -1
- package/dist/connectionState.js.map +1 -1
- package/dist/connectionStateHandler.js +9 -9
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container-loader-alpha.d.ts +333 -0
- package/dist/container-loader-beta.d.ts +333 -0
- package/dist/container-loader-public.d.ts +333 -0
- package/dist/container-loader-untrimmed.d.ts +333 -0
- package/dist/container.d.ts +22 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +235 -222
- package/dist/container.js.map +1 -1
- package/dist/containerContext.js +16 -16
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +9 -11
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +5 -4
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js +5 -4
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +92 -96
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.js +14 -14
- package/dist/deltaQueue.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +6 -9
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +26 -91
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/index.d.ts +6 -0
- package/dist/location-redirection-utilities/index.d.ts.map +1 -0
- package/dist/location-redirection-utilities/index.js +11 -0
- package/dist/location-redirection-utilities/index.js.map +1 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +22 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +51 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
- 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 +1 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +3 -5
- package/dist/protocol.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +3 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +18 -11
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/utils.d.ts +23 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -3
- package/dist/utils.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +2 -2
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/connectionManager.d.ts +2 -15
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +113 -99
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.js +9 -9
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +22 -2
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +236 -223
- package/lib/container.js.map +1 -1
- package/lib/containerContext.js +16 -16
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +9 -11
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +5 -4
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js +5 -4
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +92 -96
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.js +14 -14
- package/lib/deltaQueue.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +6 -9
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +27 -92
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/index.d.ts +6 -0
- package/lib/location-redirection-utilities/index.d.ts.map +1 -0
- package/lib/location-redirection-utilities/index.js +6 -0
- package/lib/location-redirection-utilities/index.js.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +22 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +46 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
- 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 +1 -2
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +1 -3
- package/lib/protocol.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +3 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +18 -11
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts +23 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +9 -1
- package/lib/utils.js.map +1 -1
- package/package.json +24 -26
- package/src/connectionManager.ts +58 -31
- package/src/container.ts +48 -30
- package/src/containerStorageAdapter.ts +3 -9
- package/src/contracts.ts +8 -4
- package/src/debugLogger.ts +5 -1
- package/src/deltaManager.ts +16 -31
- package/src/index.ts +5 -0
- package/src/loader.ts +31 -99
- package/src/location-redirection-utilities/index.ts +9 -0
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +59 -0
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +2 -6
- package/src/retriableDocumentStorageService.ts +29 -15
- package/src/utils.ts +23 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,127 @@
|
|
|
1
1
|
# @fluidframework/container-loader
|
|
2
2
|
|
|
3
|
+
## 2.0.0-internal.7.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Move `location-redirection-utils` APIs to `container-loader` ([#17554](https://github.com/microsoft/FluidFramework/issues/17554)) [17acf10a71](https://github.com/microsoft/FluidFramework/commits/17acf10a71e51e2490d1df57c89430c1be04c345)
|
|
8
|
+
|
|
9
|
+
Moves the 2 package exports of `location-redirection-utils` to the `container-loader` package.
|
|
10
|
+
|
|
11
|
+
Exports from `location-redirection-utils` are now deprecated, and the package itself will be removed in an upcoming release.
|
|
12
|
+
|
|
13
|
+
## 2.0.0-internal.7.0.0
|
|
14
|
+
|
|
15
|
+
### Major Changes
|
|
16
|
+
|
|
17
|
+
- odsp-driver: Load container in readonly mode when driver throws DriverErrorType.outOfStorage [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
18
|
+
|
|
19
|
+
Handle DriverErrorType.outOfStorage error from driver and load the container in readonly mode. Currently there is no
|
|
20
|
+
handling and when the join session throws this error, the container will get closed. With this we use NoDeltaStream
|
|
21
|
+
object as connection and load the container in read mode, so that it loads properly. We also notify the that the
|
|
22
|
+
container is "readonly" through the event on delta manager so that apps can listen to this and show any UX etc. The app
|
|
23
|
+
can listen to the event like this:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
container.deltaManager.on(
|
|
27
|
+
"readonly",
|
|
28
|
+
(readonly?: boolean, readonlyConnectionReason?: { text: string; error?: IErrorBase }) => {
|
|
29
|
+
// error?.errorType will be equal to DriverErrorType.outOfStorage in this case
|
|
30
|
+
// App logic
|
|
31
|
+
},
|
|
32
|
+
);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- Dependencies on @fluidframework/protocol-definitions package updated to 3.0.0 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
36
|
+
|
|
37
|
+
This included the following changes from the protocol-definitions release:
|
|
38
|
+
|
|
39
|
+
- Updating signal interfaces for some planned improvements. The intention is split the interface between signals
|
|
40
|
+
submitted by clients to the server and the resulting signals sent from the server to clients.
|
|
41
|
+
- A new optional type member is available on the ISignalMessage interface and a new ISentSignalMessage interface has
|
|
42
|
+
been added, which will be the typing for signals sent from the client to the server. Both extend a new
|
|
43
|
+
ISignalMessageBase interface that contains common members.
|
|
44
|
+
- The @fluidframework/common-definitions package dependency has been updated to version 1.0.0.
|
|
45
|
+
|
|
46
|
+
- DEPRECATED: container-loader: Various request related APIs have been deprecated [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
47
|
+
|
|
48
|
+
Please remove all calls to the following functions and instead use the new `entryPoint` pattern:
|
|
49
|
+
|
|
50
|
+
- `requestFluidObject`
|
|
51
|
+
- `requestResolvedObjectFromContainer`
|
|
52
|
+
- `getDefaultObjectFromContainer`
|
|
53
|
+
- `getObjectWithIdFromContainer`
|
|
54
|
+
- `getObjectFromContainer`
|
|
55
|
+
|
|
56
|
+
See [Removing-IFluidRouter.md](https://github.com/microsoft/FluidFramework/blob/main/packages/common/core-interfaces/Removing-IFluidRouter.md) for more details.
|
|
57
|
+
|
|
58
|
+
- container-definitions: IContainer's and IDataStore's IFluidRouter capabilities are deprecated [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
59
|
+
|
|
60
|
+
`IFluidRouter` and `request({ url: "/" })` on `IContainer` and `IDataStore` are deprecated and will be removed in a future major release. Please migrate all usage to the appropriate `getEntryPoint()` or `entryPoint` APIs.
|
|
61
|
+
|
|
62
|
+
See [Removing-IFluidRouter.md](https://github.com/microsoft/FluidFramework/blob/main/packages/common/core-interfaces/Removing-IFluidRouter.md) for more details.
|
|
63
|
+
|
|
64
|
+
- routerlicious-driver: remove dead blob aggregation concepts and code [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
65
|
+
|
|
66
|
+
Dead concepts blob aggregation like `aggregateBlobsSmallerThanBytes` and `minBlobSize` have been removed.
|
|
67
|
+
|
|
68
|
+
- Server upgrade: dependencies on Fluid server packages updated to 2.0.1 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
69
|
+
|
|
70
|
+
Dependencies on the following Fluid server package have been updated to version 2.0.1:
|
|
71
|
+
|
|
72
|
+
- @fluidframework/gitresources: 2.0.1
|
|
73
|
+
- @fluidframework/server-kafka-orderer: 2.0.1
|
|
74
|
+
- @fluidframework/server-lambdas: 2.0.1
|
|
75
|
+
- @fluidframework/server-lambdas-driver: 2.0.1
|
|
76
|
+
- @fluidframework/server-local-server: 2.0.1
|
|
77
|
+
- @fluidframework/server-memory-orderer: 2.0.1
|
|
78
|
+
- @fluidframework/protocol-base: 2.0.1
|
|
79
|
+
- @fluidframework/server-routerlicious: 2.0.1
|
|
80
|
+
- @fluidframework/server-routerlicious-base: 2.0.1
|
|
81
|
+
- @fluidframework/server-services: 2.0.1
|
|
82
|
+
- @fluidframework/server-services-client: 2.0.1
|
|
83
|
+
- @fluidframework/server-services-core: 2.0.1
|
|
84
|
+
- @fluidframework/server-services-ordering-kafkanode: 2.0.1
|
|
85
|
+
- @fluidframework/server-services-ordering-rdkafka: 2.0.1
|
|
86
|
+
- @fluidframework/server-services-ordering-zookeeper: 2.0.1
|
|
87
|
+
- @fluidframework/server-services-shared: 2.0.1
|
|
88
|
+
- @fluidframework/server-services-telemetry: 2.0.1
|
|
89
|
+
- @fluidframework/server-services-utils: 2.0.1
|
|
90
|
+
- @fluidframework/server-test-utils: 2.0.1
|
|
91
|
+
- tinylicious: 2.0.1
|
|
92
|
+
|
|
93
|
+
- test-utils: provideEntryPoint is required [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
94
|
+
|
|
95
|
+
The optional `provideEntryPoint` method has become required on a number of constructors. A value will need to be provided to the following classes:
|
|
96
|
+
|
|
97
|
+
- `BaseContainerRuntimeFactory`
|
|
98
|
+
- `RuntimeFactory`
|
|
99
|
+
- `ContainerRuntime` (constructor and `loadRuntime`)
|
|
100
|
+
- `FluidDataStoreRuntime`
|
|
101
|
+
|
|
102
|
+
See [testContainerRuntimeFactoryWithDefaultDataStore.ts](https://github.com/microsoft/FluidFramework/tree/main/packages/test/test-utils/src/testContainerRuntimeFactoryWithDefaultDataStore.ts) for an example implemtation of `provideEntryPoint` for ContainerRuntime.
|
|
103
|
+
See [pureDataObjectFactory.ts](https://github.com/microsoft/FluidFramework/tree/main/packages/framework/aqueduct/src/data-object-factories/pureDataObjectFactory.ts#L83) for an example implementation of `provideEntryPoint` for DataStoreRuntime.
|
|
104
|
+
|
|
105
|
+
Subsequently, various `entryPoint` and `getEntryPoint()` endpoints have become required. Please see [containerRuntime.ts](https://github.com/microsoft/FluidFramework/tree/main/packages/runtime/container-runtime/src/containerRuntime.ts) for example implementations of these APIs.
|
|
106
|
+
|
|
107
|
+
For more details, see [Removing-IFluidRouter.md](https://github.com/microsoft/FluidFramework/blob/main/packages/common/core-interfaces/Removing-IFluidRouter.md)
|
|
108
|
+
|
|
109
|
+
- Minimum TypeScript version now 5.1.6 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
110
|
+
|
|
111
|
+
The minimum supported TypeScript version for Fluid 2.0 clients is now 5.1.6.
|
|
112
|
+
|
|
113
|
+
- container-loader: Containers will connect in read-mode by default [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
114
|
+
|
|
115
|
+
When a container is loaded, it will connect in read-mode unless it is loaded with a pending state containing stashed ops.
|
|
116
|
+
|
|
117
|
+
- container-loader: Container caching in the Loader is removed [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
118
|
+
|
|
119
|
+
Container caching in the Loader has been removed. Do not to rely on caching and inform the FluidFramework team ASAP if you cannot do so.
|
|
120
|
+
|
|
121
|
+
## 2.0.0-internal.6.4.0
|
|
122
|
+
|
|
123
|
+
Dependency updates only.
|
|
124
|
+
|
|
3
125
|
## 2.0.0-internal.6.3.0
|
|
4
126
|
|
|
5
127
|
Dependency updates only.
|
package/api-extractor.json
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
-
"extends": "@fluidframework/build-common/api-extractor-
|
|
3
|
+
"extends": "@fluidframework/build-common/api-extractor-base.json",
|
|
4
|
+
"messages": {
|
|
5
|
+
"extractorMessageReporting": {
|
|
6
|
+
"ae-missing-release-tag": {
|
|
7
|
+
// TODO: Fix violations and remove this rule override
|
|
8
|
+
"logLevel": "none"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
4
12
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
## API Report File for "@fluidframework/container-loader"
|
|
2
|
+
|
|
3
|
+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
|
|
7
|
+
import { FluidObject } from '@fluidframework/core-interfaces';
|
|
8
|
+
import { IAudienceOwner } from '@fluidframework/container-definitions';
|
|
9
|
+
import { IClientDetails } from '@fluidframework/protocol-definitions';
|
|
10
|
+
import { IConfigProviderBase } from '@fluidframework/telemetry-utils';
|
|
11
|
+
import { IContainer } from '@fluidframework/container-definitions';
|
|
12
|
+
import { IDocumentAttributes } from '@fluidframework/protocol-definitions';
|
|
13
|
+
import { IDocumentServiceFactory } from '@fluidframework/driver-definitions';
|
|
14
|
+
import { IDocumentStorageService } from '@fluidframework/driver-definitions';
|
|
15
|
+
import { IFluidCodeDetails } from '@fluidframework/container-definitions';
|
|
16
|
+
import { IFluidModule } from '@fluidframework/container-definitions';
|
|
17
|
+
import { IFluidRouter } from '@fluidframework/core-interfaces';
|
|
18
|
+
import { IHostLoader } from '@fluidframework/container-definitions';
|
|
19
|
+
import { ILoaderOptions as ILoaderOptions_2 } from '@fluidframework/container-definitions';
|
|
20
|
+
import { ILocationRedirectionError } from '@fluidframework/driver-definitions';
|
|
21
|
+
import { IProtocolHandler as IProtocolHandler_2 } from '@fluidframework/protocol-base';
|
|
22
|
+
import { IProvideFluidCodeDetailsComparer } from '@fluidframework/container-definitions';
|
|
23
|
+
import { IQuorumSnapshot } from '@fluidframework/protocol-base';
|
|
24
|
+
import { IRequest } from '@fluidframework/core-interfaces';
|
|
25
|
+
import { IRequestHeader } from '@fluidframework/core-interfaces';
|
|
26
|
+
import { IResponse } from '@fluidframework/core-interfaces';
|
|
27
|
+
import { ISignalMessage } from '@fluidframework/protocol-definitions';
|
|
28
|
+
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
29
|
+
import { ITelemetryLoggerExt } from '@fluidframework/telemetry-utils';
|
|
30
|
+
import { IUrlResolver } from '@fluidframework/driver-definitions';
|
|
31
|
+
|
|
32
|
+
// @public (undocumented)
|
|
33
|
+
export enum ConnectionState {
|
|
34
|
+
CatchingUp = 1,
|
|
35
|
+
Connected = 2,
|
|
36
|
+
Disconnected = 0,
|
|
37
|
+
EstablishingConnection = 3
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// @public @deprecated (undocumented)
|
|
41
|
+
export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComparer> {
|
|
42
|
+
load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// @public
|
|
46
|
+
export interface IContainerExperimental extends IContainer {
|
|
47
|
+
closeAndGetPendingLocalState?(): Promise<string>;
|
|
48
|
+
getPendingLocalState?(): Promise<string>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// @public
|
|
52
|
+
export type IDetachedBlobStorage = Pick<IDocumentStorageService, "createBlob" | "readBlob"> & {
|
|
53
|
+
size: number;
|
|
54
|
+
getBlobIds(): string[];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// @public @deprecated (undocumented)
|
|
58
|
+
export interface IFluidModuleWithDetails {
|
|
59
|
+
details: IFluidCodeDetails;
|
|
60
|
+
module: IFluidModule;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// @public (undocumented)
|
|
64
|
+
export interface ILoaderOptions extends ILoaderOptions_2 {
|
|
65
|
+
// (undocumented)
|
|
66
|
+
summarizeProtocolTree?: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// @public
|
|
70
|
+
export interface ILoaderProps {
|
|
71
|
+
readonly codeLoader: ICodeDetailsLoader;
|
|
72
|
+
readonly configProvider?: IConfigProviderBase;
|
|
73
|
+
readonly detachedBlobStorage?: IDetachedBlobStorage;
|
|
74
|
+
readonly documentServiceFactory: IDocumentServiceFactory;
|
|
75
|
+
readonly logger?: ITelemetryBaseLogger;
|
|
76
|
+
readonly options?: ILoaderOptions;
|
|
77
|
+
readonly protocolHandlerBuilder?: ProtocolHandlerBuilder;
|
|
78
|
+
readonly scope?: FluidObject;
|
|
79
|
+
readonly urlResolver: IUrlResolver;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// @public
|
|
83
|
+
export interface ILoaderServices {
|
|
84
|
+
readonly codeLoader: ICodeDetailsLoader;
|
|
85
|
+
readonly detachedBlobStorage?: IDetachedBlobStorage;
|
|
86
|
+
readonly documentServiceFactory: IDocumentServiceFactory;
|
|
87
|
+
readonly options: ILoaderOptions;
|
|
88
|
+
readonly protocolHandlerBuilder?: ProtocolHandlerBuilder;
|
|
89
|
+
readonly scope: FluidObject;
|
|
90
|
+
readonly subLogger: ITelemetryLoggerExt;
|
|
91
|
+
readonly urlResolver: IUrlResolver;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// @public
|
|
95
|
+
export interface IParsedUrl {
|
|
96
|
+
id: string;
|
|
97
|
+
path: string;
|
|
98
|
+
query: string;
|
|
99
|
+
version: string | null | undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// @public (undocumented)
|
|
103
|
+
export interface IProtocolHandler extends IProtocolHandler_2 {
|
|
104
|
+
// (undocumented)
|
|
105
|
+
readonly audience: IAudienceOwner;
|
|
106
|
+
// (undocumented)
|
|
107
|
+
processSignal(message: ISignalMessage): any;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// @public
|
|
111
|
+
export function isLocationRedirectionError(error: any): error is ILocationRedirectionError;
|
|
112
|
+
|
|
113
|
+
// @public
|
|
114
|
+
export class Loader implements IHostLoader {
|
|
115
|
+
constructor(loaderProps: ILoaderProps);
|
|
116
|
+
// (undocumented)
|
|
117
|
+
createDetachedContainer(codeDetails: IFluidCodeDetails, createDetachedProps?: {
|
|
118
|
+
canReconnect?: boolean;
|
|
119
|
+
clientDetailsOverride?: IClientDetails;
|
|
120
|
+
}): Promise<IContainer>;
|
|
121
|
+
// @deprecated (undocumented)
|
|
122
|
+
get IFluidRouter(): IFluidRouter;
|
|
123
|
+
// (undocumented)
|
|
124
|
+
rehydrateDetachedContainerFromSnapshot(snapshot: string, createDetachedProps?: {
|
|
125
|
+
canReconnect?: boolean;
|
|
126
|
+
clientDetailsOverride?: IClientDetails;
|
|
127
|
+
}): Promise<IContainer>;
|
|
128
|
+
// @deprecated (undocumented)
|
|
129
|
+
request(request: IRequest): Promise<IResponse>;
|
|
130
|
+
// (undocumented)
|
|
131
|
+
resolve(request: IRequest, pendingLocalState?: string): Promise<IContainer>;
|
|
132
|
+
// (undocumented)
|
|
133
|
+
readonly services: ILoaderServices;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// @public
|
|
137
|
+
export type ProtocolHandlerBuilder = (attributes: IDocumentAttributes, snapshot: IQuorumSnapshot, sendProposal: (key: string, value: any) => number) => IProtocolHandler;
|
|
138
|
+
|
|
139
|
+
// @public @deprecated
|
|
140
|
+
export function requestResolvedObjectFromContainer(container: IContainer, headers?: IRequestHeader): Promise<IResponse>;
|
|
141
|
+
|
|
142
|
+
// @public
|
|
143
|
+
export function resolveWithLocationRedirectionHandling<T>(api: (request: IRequest) => Promise<T>, request: IRequest, urlResolver: IUrlResolver, logger?: ITelemetryBaseLogger): Promise<T>;
|
|
144
|
+
|
|
145
|
+
// @public
|
|
146
|
+
export function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined;
|
|
147
|
+
|
|
148
|
+
// @public
|
|
149
|
+
export function waitContainerToCatchUp(container: IContainer): Promise<boolean>;
|
|
150
|
+
|
|
151
|
+
// (No @packageDocumentation comment for this package)
|
|
152
|
+
|
|
153
|
+
```
|
package/dist/catchUpMonitor.d.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
6
6
|
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
7
7
|
/** @see CatchUpMonitor for usage */
|
|
8
|
-
|
|
8
|
+
type CaughtUpListener = () => void;
|
|
9
9
|
/** Monitor that emits an event when a Container has caught up to a given point in the op stream */
|
|
10
|
-
export
|
|
10
|
+
export type ICatchUpMonitor = IDisposable;
|
|
11
11
|
/**
|
|
12
12
|
* Monitors a Container's DeltaManager, notifying listeners when all ops have been processed
|
|
13
13
|
* that were known at the time the monitor was created.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catchUpMonitor.d.ts","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAGtE,oCAAoC;AACpC,
|
|
1
|
+
{"version":3,"file":"catchUpMonitor.d.ts","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAGtE,oCAAoC;AACpC,KAAK,gBAAgB,GAAG,MAAM,IAAI,CAAC;AAEnC,mGAAmG;AACnG,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC;AAE1C;;;GAGG;AACH,qBAAa,cAAe,YAAW,eAAe;IAepD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAf1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAkB;IAElC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAKxB;IAEF;;OAEG;gBAEe,YAAY,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,EACrC,QAAQ,EAAE,gBAAgB;IAerC,QAAQ,EAAE,OAAO,CAAS;IAC1B,OAAO;CAQd"}
|
|
@@ -93,21 +93,7 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
93
93
|
*/
|
|
94
94
|
setAutoReconnect(mode: ReconnectMode, reason: IConnectionStateChangeReason): void;
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
97
|
-
* Hosts may have read only views, indicating to data stores that no edits are allowed.
|
|
98
|
-
* This is independent from this._readonlyPermissions (permissions) and this.connectionMode
|
|
99
|
-
* (server can return "write" mode even when asked for "read")
|
|
100
|
-
* Leveraging same "readonly" event as runtime & data stores should behave the same in such case
|
|
101
|
-
* as in read-only permissions.
|
|
102
|
-
* But this.active can be used by some DDSes to figure out if ops can be sent
|
|
103
|
-
* (for example, read-only view still participates in code proposals / upgrades decisions)
|
|
104
|
-
*
|
|
105
|
-
* Forcing Readonly does not prevent DDS from generating ops. It is up to user code to honour
|
|
106
|
-
* the readonly flag. If ops are generated, they will accumulate locally and not be sent. If
|
|
107
|
-
* there are pending in the outbound queue, it will stop sending until force readonly is
|
|
108
|
-
* cleared.
|
|
109
|
-
*
|
|
110
|
-
* @param readonly - set or clear force readonly.
|
|
96
|
+
* {@inheritDoc Container.forceReadonly}
|
|
111
97
|
*/
|
|
112
98
|
forceReadonly(readonly: boolean): void;
|
|
113
99
|
private set_readonlyPermissions;
|
|
@@ -157,6 +143,7 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
157
143
|
sendMessages(messages: IDocumentMessage[]): void;
|
|
158
144
|
beforeProcessingIncomingOp(message: ISequencedDocumentMessage): void;
|
|
159
145
|
private readonly opHandler;
|
|
146
|
+
private readonly signalHandler;
|
|
160
147
|
private readonly nackHandler;
|
|
161
148
|
private readonly disconnectHandlerInternal;
|
|
162
149
|
private readonly errorHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAe,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGpF,OAAO,EACN,uBAAuB,EACvB,WAAW,EACX,YAAY,EACZ,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAEN,gBAAgB,
|
|
1
|
+
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.ConnectionManager = void 0;
|
|
8
8
|
const core_utils_1 = require("@fluidframework/core-utils");
|
|
9
9
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
10
|
+
const driver_definitions_1 = require("@fluidframework/driver-definitions");
|
|
10
11
|
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
11
12
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
12
13
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
@@ -36,9 +37,15 @@ const clientNoDeltaStream = {
|
|
|
36
37
|
};
|
|
37
38
|
const clientIdNoDeltaStream = "storage-only client";
|
|
38
39
|
class NoDeltaStream extends client_utils_1.TypedEventEmitter {
|
|
39
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Connection which is not connected to socket.
|
|
42
|
+
* @param storageOnlyReason - Reason on why the connection to delta stream is not allowed.
|
|
43
|
+
* @param readonlyConnectionReason - reason/error if any which lead to using NoDeltaStream.
|
|
44
|
+
*/
|
|
45
|
+
constructor(storageOnlyReason, readonlyConnectionReason) {
|
|
40
46
|
super();
|
|
41
47
|
this.storageOnlyReason = storageOnlyReason;
|
|
48
|
+
this.readonlyConnectionReason = readonlyConnectionReason;
|
|
42
49
|
this.clientId = clientIdNoDeltaStream;
|
|
43
50
|
this.claims = {
|
|
44
51
|
scopes: [protocol_definitions_1.ScopeType.DocRead],
|
|
@@ -101,67 +108,6 @@ const waitForOnline = async () => {
|
|
|
101
108
|
* Exposes various controls to influence this process, including manual reconnects, forced read-only mode, etc.
|
|
102
109
|
*/
|
|
103
110
|
class ConnectionManager {
|
|
104
|
-
constructor(serviceProvider, containerDirty, client, reconnectAllowed, logger, props) {
|
|
105
|
-
this.serviceProvider = serviceProvider;
|
|
106
|
-
this.containerDirty = containerDirty;
|
|
107
|
-
this.client = client;
|
|
108
|
-
this.logger = logger;
|
|
109
|
-
this.props = props;
|
|
110
|
-
/** tracks host requiring read-only mode. */
|
|
111
|
-
this._forceReadonly = false;
|
|
112
|
-
/** True if there is pending (async) reconnection from "read" to "write" */
|
|
113
|
-
this.pendingReconnect = false;
|
|
114
|
-
this.clientSequenceNumber = 0;
|
|
115
|
-
this.clientSequenceNumberObserved = 0;
|
|
116
|
-
/** Counts the number of non-runtime ops sent by the client which may not be acked. */
|
|
117
|
-
this.localOpsToIgnore = 0;
|
|
118
|
-
this.connectFirstConnection = true;
|
|
119
|
-
this._connectionVerboseProps = {};
|
|
120
|
-
this._connectionProps = {};
|
|
121
|
-
this._disposed = false;
|
|
122
|
-
this.opHandler = (documentId, messagesArg) => {
|
|
123
|
-
const messages = Array.isArray(messagesArg) ? messagesArg : [messagesArg];
|
|
124
|
-
this.props.incomingOpHandler(messages, "opHandler");
|
|
125
|
-
};
|
|
126
|
-
// Always connect in write mode after getting nacked.
|
|
127
|
-
this.nackHandler = (documentId, messages) => {
|
|
128
|
-
const message = messages[0];
|
|
129
|
-
if (this._readonlyPermissions === true) {
|
|
130
|
-
this.props.closeHandler((0, driver_utils_1.createWriteError)("writeOnReadOnlyDocument", { driverVersion: undefined }));
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const reconnectInfo = getNackReconnectInfo(message.content);
|
|
134
|
-
// If the nack indicates we cannot retry, then close the container outright
|
|
135
|
-
if (!reconnectInfo.canRetry) {
|
|
136
|
-
this.props.closeHandler(reconnectInfo);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
this.reconnectOnError("write", reconnectInfo);
|
|
140
|
-
};
|
|
141
|
-
// Connection mode is always read on disconnect/error unless the system mode was write.
|
|
142
|
-
this.disconnectHandlerInternal = (disconnectReason) => {
|
|
143
|
-
// Note: we might get multiple disconnect calls on same socket, as early disconnect notification
|
|
144
|
-
// ("server_disconnect", ODSP-specific) is mapped to "disconnect"
|
|
145
|
-
this.reconnectOnError(this.defaultReconnectionMode, disconnectReason);
|
|
146
|
-
};
|
|
147
|
-
this.errorHandler = (error) => {
|
|
148
|
-
this.reconnectOnError(this.defaultReconnectionMode, error);
|
|
149
|
-
};
|
|
150
|
-
this.clientDetails = this.client.details;
|
|
151
|
-
this.defaultReconnectionMode = this.client.mode;
|
|
152
|
-
this._reconnectMode = reconnectAllowed ? contracts_1.ReconnectMode.Enabled : contracts_1.ReconnectMode.Never;
|
|
153
|
-
// Outbound message queue. The outbound queue is represented as a queue of an array of ops. Ops contained
|
|
154
|
-
// within an array *must* fit within the maxMessageSize and are guaranteed to be ordered sequentially.
|
|
155
|
-
this._outbound = new deltaQueue_1.DeltaQueue((messages) => {
|
|
156
|
-
if (this.connection === undefined) {
|
|
157
|
-
throw new Error("Attempted to submit an outbound message without connection");
|
|
158
|
-
}
|
|
159
|
-
this.connection.submit(messages);
|
|
160
|
-
});
|
|
161
|
-
this._outbound.on("error", (error) => {
|
|
162
|
-
this.props.closeHandler((0, telemetry_utils_1.normalizeError)(error));
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
111
|
get connectionVerboseProps() {
|
|
166
112
|
return this._connectionVerboseProps;
|
|
167
113
|
}
|
|
@@ -275,6 +221,71 @@ class ConnectionManager {
|
|
|
275
221
|
reason,
|
|
276
222
|
};
|
|
277
223
|
}
|
|
224
|
+
constructor(serviceProvider, containerDirty, client, reconnectAllowed, logger, props) {
|
|
225
|
+
this.serviceProvider = serviceProvider;
|
|
226
|
+
this.containerDirty = containerDirty;
|
|
227
|
+
this.client = client;
|
|
228
|
+
this.logger = logger;
|
|
229
|
+
this.props = props;
|
|
230
|
+
/** tracks host requiring read-only mode. */
|
|
231
|
+
this._forceReadonly = false;
|
|
232
|
+
/** True if there is pending (async) reconnection from "read" to "write" */
|
|
233
|
+
this.pendingReconnect = false;
|
|
234
|
+
this.clientSequenceNumber = 0;
|
|
235
|
+
this.clientSequenceNumberObserved = 0;
|
|
236
|
+
/** Counts the number of non-runtime ops sent by the client which may not be acked. */
|
|
237
|
+
this.localOpsToIgnore = 0;
|
|
238
|
+
this.connectFirstConnection = true;
|
|
239
|
+
this._connectionVerboseProps = {};
|
|
240
|
+
this._connectionProps = {};
|
|
241
|
+
this._disposed = false;
|
|
242
|
+
this.opHandler = (documentId, messagesArg) => {
|
|
243
|
+
const messages = Array.isArray(messagesArg) ? messagesArg : [messagesArg];
|
|
244
|
+
this.props.incomingOpHandler(messages, "opHandler");
|
|
245
|
+
};
|
|
246
|
+
this.signalHandler = (signalsArg) => {
|
|
247
|
+
const signals = Array.isArray(signalsArg) ? signalsArg : [signalsArg];
|
|
248
|
+
this.props.signalHandler(signals);
|
|
249
|
+
};
|
|
250
|
+
// Always connect in write mode after getting nacked.
|
|
251
|
+
this.nackHandler = (documentId, messages) => {
|
|
252
|
+
const message = messages[0];
|
|
253
|
+
if (this._readonlyPermissions === true) {
|
|
254
|
+
this.props.closeHandler((0, driver_utils_1.createWriteError)("writeOnReadOnlyDocument", { driverVersion: undefined }));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const reconnectInfo = getNackReconnectInfo(message.content);
|
|
258
|
+
// If the nack indicates we cannot retry, then close the container outright
|
|
259
|
+
if (!reconnectInfo.canRetry) {
|
|
260
|
+
this.props.closeHandler(reconnectInfo);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
this.reconnectOnError("write", reconnectInfo);
|
|
264
|
+
};
|
|
265
|
+
// Connection mode is always read on disconnect/error unless the system mode was write.
|
|
266
|
+
this.disconnectHandlerInternal = (disconnectReason) => {
|
|
267
|
+
// Note: we might get multiple disconnect calls on same socket, as early disconnect notification
|
|
268
|
+
// ("server_disconnect", ODSP-specific) is mapped to "disconnect"
|
|
269
|
+
this.reconnectOnError(this.defaultReconnectionMode, disconnectReason);
|
|
270
|
+
};
|
|
271
|
+
this.errorHandler = (error) => {
|
|
272
|
+
this.reconnectOnError(this.defaultReconnectionMode, error);
|
|
273
|
+
};
|
|
274
|
+
this.clientDetails = this.client.details;
|
|
275
|
+
this.defaultReconnectionMode = this.client.mode;
|
|
276
|
+
this._reconnectMode = reconnectAllowed ? contracts_1.ReconnectMode.Enabled : contracts_1.ReconnectMode.Never;
|
|
277
|
+
// Outbound message queue. The outbound queue is represented as a queue of an array of ops. Ops contained
|
|
278
|
+
// within an array *must* fit within the maxMessageSize and are guaranteed to be ordered sequentially.
|
|
279
|
+
this._outbound = new deltaQueue_1.DeltaQueue((messages) => {
|
|
280
|
+
if (this.connection === undefined) {
|
|
281
|
+
throw new Error("Attempted to submit an outbound message without connection");
|
|
282
|
+
}
|
|
283
|
+
this.connection.submit(messages);
|
|
284
|
+
});
|
|
285
|
+
this._outbound.on("error", (error) => {
|
|
286
|
+
this.props.closeHandler((0, telemetry_utils_1.normalizeError)(error));
|
|
287
|
+
});
|
|
288
|
+
}
|
|
278
289
|
dispose(error, switchToReadonly = true) {
|
|
279
290
|
if (this._disposed) {
|
|
280
291
|
return;
|
|
@@ -294,7 +305,7 @@ class ConnectionManager {
|
|
|
294
305
|
// Notify everyone we are in read-only state.
|
|
295
306
|
// Useful for data stores in case we hit some critical error,
|
|
296
307
|
// to switch to a mode where user edits are not accepted
|
|
297
|
-
this.set_readonlyPermissions(true, oldReadonlyValue);
|
|
308
|
+
this.set_readonlyPermissions(true, oldReadonlyValue, disconnectReason);
|
|
298
309
|
}
|
|
299
310
|
}
|
|
300
311
|
/**
|
|
@@ -310,21 +321,7 @@ class ConnectionManager {
|
|
|
310
321
|
}
|
|
311
322
|
}
|
|
312
323
|
/**
|
|
313
|
-
*
|
|
314
|
-
* Hosts may have read only views, indicating to data stores that no edits are allowed.
|
|
315
|
-
* This is independent from this._readonlyPermissions (permissions) and this.connectionMode
|
|
316
|
-
* (server can return "write" mode even when asked for "read")
|
|
317
|
-
* Leveraging same "readonly" event as runtime & data stores should behave the same in such case
|
|
318
|
-
* as in read-only permissions.
|
|
319
|
-
* But this.active can be used by some DDSes to figure out if ops can be sent
|
|
320
|
-
* (for example, read-only view still participates in code proposals / upgrades decisions)
|
|
321
|
-
*
|
|
322
|
-
* Forcing Readonly does not prevent DDS from generating ops. It is up to user code to honour
|
|
323
|
-
* the readonly flag. If ops are generated, they will accumulate locally and not be sent. If
|
|
324
|
-
* there are pending in the outbound queue, it will stop sending until force readonly is
|
|
325
|
-
* cleared.
|
|
326
|
-
*
|
|
327
|
-
* @param readonly - set or clear force readonly.
|
|
324
|
+
* {@inheritDoc Container.forceReadonly}
|
|
328
325
|
*/
|
|
329
326
|
forceReadonly(readonly) {
|
|
330
327
|
if (readonly !== this._forceReadonly) {
|
|
@@ -358,10 +355,10 @@ class ConnectionManager {
|
|
|
358
355
|
}
|
|
359
356
|
}
|
|
360
357
|
}
|
|
361
|
-
set_readonlyPermissions(newReadonlyValue, oldReadonlyValue) {
|
|
358
|
+
set_readonlyPermissions(newReadonlyValue, oldReadonlyValue, readonlyConnectionReason) {
|
|
362
359
|
this._readonlyPermissions = newReadonlyValue;
|
|
363
360
|
if (oldReadonlyValue !== this.readonly) {
|
|
364
|
-
this.props.readonlyChangeHandler(this.readonly);
|
|
361
|
+
this.props.readonlyChangeHandler(this.readonly, readonlyConnectionReason);
|
|
365
362
|
}
|
|
366
363
|
}
|
|
367
364
|
connect(reason, connectionMode) {
|
|
@@ -442,7 +439,22 @@ class ConnectionManager {
|
|
|
442
439
|
}
|
|
443
440
|
catch (origError) {
|
|
444
441
|
if ((0, utils_1.isDeltaStreamConnectionForbiddenError)(origError)) {
|
|
445
|
-
connection = new NoDeltaStream(origError.storageOnlyReason
|
|
442
|
+
connection = new NoDeltaStream(origError.storageOnlyReason, {
|
|
443
|
+
text: origError.message,
|
|
444
|
+
error: origError,
|
|
445
|
+
});
|
|
446
|
+
requestedMode = "read";
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
else if ((0, telemetry_utils_1.isFluidError)(origError) &&
|
|
450
|
+
// eslint-disable-next-line import/no-deprecated
|
|
451
|
+
origError.errorType === driver_definitions_1.DriverErrorType.outOfStorageError) {
|
|
452
|
+
// If we get out of storage error from calling joinsession, then use the NoDeltaStream object so
|
|
453
|
+
// that user can at least load the container.
|
|
454
|
+
connection = new NoDeltaStream(undefined, {
|
|
455
|
+
text: origError.message,
|
|
456
|
+
error: origError,
|
|
457
|
+
});
|
|
446
458
|
requestedMode = "read";
|
|
447
459
|
break;
|
|
448
460
|
}
|
|
@@ -550,7 +562,7 @@ class ConnectionManager {
|
|
|
550
562
|
this.connection = undefined;
|
|
551
563
|
// Remove listeners first so we don't try to retrigger this flow accidentally through reconnectOnError
|
|
552
564
|
connection.off("op", this.opHandler);
|
|
553
|
-
connection.off("signal", this.
|
|
565
|
+
connection.off("signal", this.signalHandler);
|
|
554
566
|
connection.off("nack", this.nackHandler);
|
|
555
567
|
connection.off("disconnect", this.disconnectHandlerInternal);
|
|
556
568
|
connection.off("error", this.errorHandler);
|
|
@@ -603,7 +615,7 @@ class ConnectionManager {
|
|
|
603
615
|
// removed after those packages have released and become ubiquitous.
|
|
604
616
|
(0, core_utils_1.assert)(requestedMode === "read" || readonly === (this.connectionMode === "read"), 0x0e7 /* "claims/connectionMode mismatch" */);
|
|
605
617
|
(0, core_utils_1.assert)(!readonly || this.connectionMode === "read", 0x0e8 /* "readonly perf with write connection" */);
|
|
606
|
-
this.set_readonlyPermissions(readonly, oldReadonlyValue);
|
|
618
|
+
this.set_readonlyPermissions(readonly, oldReadonlyValue, isNoDeltaStreamConnection(connection) ? connection.readonlyConnectionReason : undefined);
|
|
607
619
|
if (this._disposed) {
|
|
608
620
|
// Raise proper events, Log telemetry event and close connection.
|
|
609
621
|
this.disconnectFromDeltaStream({ text: "ConnectionManager already closed" });
|
|
@@ -611,7 +623,7 @@ class ConnectionManager {
|
|
|
611
623
|
}
|
|
612
624
|
this._outbound.resume();
|
|
613
625
|
connection.on("op", this.opHandler);
|
|
614
|
-
connection.on("signal", this.
|
|
626
|
+
connection.on("signal", this.signalHandler);
|
|
615
627
|
connection.on("nack", this.nackHandler);
|
|
616
628
|
connection.on("disconnect", this.disconnectHandlerInternal);
|
|
617
629
|
connection.on("error", this.errorHandler);
|
|
@@ -662,26 +674,26 @@ class ConnectionManager {
|
|
|
662
674
|
type: protocol_1.SignalType.Clear,
|
|
663
675
|
}),
|
|
664
676
|
};
|
|
665
|
-
this
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
677
|
+
// list of signals to process due to this new connection
|
|
678
|
+
let signalsToProcess = [clearSignal];
|
|
679
|
+
const clientJoinSignals = (connection.initialClients ?? []).map((priorClient) => ({
|
|
680
|
+
clientId: null,
|
|
681
|
+
content: JSON.stringify({
|
|
682
|
+
type: protocol_1.SignalType.ClientJoin,
|
|
683
|
+
content: priorClient, // ISignalClient
|
|
684
|
+
}),
|
|
685
|
+
}));
|
|
686
|
+
if (clientJoinSignals.length > 0) {
|
|
687
|
+
signalsToProcess = signalsToProcess.concat(clientJoinSignals);
|
|
675
688
|
}
|
|
676
689
|
// Unfortunately, there is no defined order between initialSignals (including join & leave signals)
|
|
677
690
|
// and connection.initialClients. In practice, connection.initialSignals quite often contains join signal
|
|
678
691
|
// for "self" and connection.initialClients does not contain "self", so we have to process them after
|
|
679
692
|
// "clear" signal above.
|
|
680
|
-
if (connection.initialSignals !== undefined) {
|
|
681
|
-
|
|
682
|
-
this.props.signalHandler(signal);
|
|
683
|
-
}
|
|
693
|
+
if (connection.initialSignals !== undefined && connection.initialSignals.length > 0) {
|
|
694
|
+
signalsToProcess = signalsToProcess.concat(connection.initialSignals);
|
|
684
695
|
}
|
|
696
|
+
this.props.signalHandler(signalsToProcess);
|
|
685
697
|
}
|
|
686
698
|
/**
|
|
687
699
|
* Disconnect the current connection and reconnect. Closes the container if it fails.
|