@fluidframework/container-loader 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.225277
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +18 -21
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +364 -0
- package/README.md +152 -56
- package/api-extractor-esm.json +4 -0
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/container-loader.api.md +143 -0
- package/dist/{audience.js → audience.cjs} +15 -13
- package/dist/audience.cjs.map +1 -0
- package/dist/audience.d.ts +4 -6
- package/dist/audience.d.ts.map +1 -1
- package/dist/catchUpMonitor.cjs +43 -0
- package/dist/catchUpMonitor.cjs.map +1 -0
- package/dist/catchUpMonitor.d.ts +29 -0
- package/dist/catchUpMonitor.d.ts.map +1 -0
- package/dist/{connectionManager.js → connectionManager.cjs} +397 -240
- package/dist/connectionManager.cjs.map +1 -0
- package/dist/connectionManager.d.ts +23 -33
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/{connectionState.js → connectionState.cjs} +5 -7
- package/dist/connectionState.cjs.map +1 -0
- package/dist/connectionState.d.ts +3 -5
- package/dist/connectionState.d.ts.map +1 -1
- package/dist/connectionStateHandler.cjs +474 -0
- package/dist/connectionStateHandler.cjs.map +1 -0
- package/dist/connectionStateHandler.d.ts +127 -29
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/container-loader-alpha.d.ts +274 -0
- package/dist/container-loader-beta.d.ts +75 -0
- package/dist/container-loader-public.d.ts +75 -0
- package/dist/container-loader-untrimmed.d.ts +331 -0
- package/dist/container.cjs +1585 -0
- package/dist/container.cjs.map +1 -0
- package/dist/container.d.ts +227 -83
- package/dist/container.d.ts.map +1 -1
- package/dist/containerContext.cjs +74 -0
- package/dist/containerContext.cjs.map +1 -0
- package/dist/containerContext.d.ts +33 -59
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerStorageAdapter.cjs +234 -0
- package/dist/containerStorageAdapter.cjs.map +1 -0
- package/dist/containerStorageAdapter.d.ts +48 -23
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/{contracts.js → contracts.cjs} +5 -5
- package/dist/contracts.cjs.map +1 -0
- package/dist/contracts.d.ts +45 -17
- package/dist/contracts.d.ts.map +1 -1
- package/dist/debugLogger.cjs +101 -0
- package/dist/debugLogger.cjs.map +1 -0
- package/dist/debugLogger.d.ts +30 -0
- package/dist/debugLogger.d.ts.map +1 -0
- package/dist/{deltaManager.js → deltaManager.cjs} +379 -186
- package/dist/deltaManager.cjs.map +1 -0
- package/dist/deltaManager.d.ts +54 -18
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/{deltaQueue.js → deltaQueue.cjs} +29 -28
- package/dist/deltaQueue.cjs.map +1 -0
- package/dist/deltaQueue.d.ts +3 -4
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/disposal.cjs +25 -0
- package/dist/disposal.cjs.map +1 -0
- package/dist/disposal.d.ts +13 -0
- package/dist/disposal.d.ts.map +1 -0
- package/dist/error.cjs +32 -0
- package/dist/error.cjs.map +1 -0
- package/dist/error.d.ts +23 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/index.cjs +19 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/loader.cjs +148 -0
- package/dist/loader.cjs.map +1 -0
- package/dist/loader.d.ts +38 -19
- package/dist/loader.d.ts.map +1 -1
- package/dist/location-redirection-utilities/index.cjs +11 -0
- package/dist/location-redirection-utilities/index.cjs.map +1 -0
- 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/resolveWithLocationRedirection.cjs +53 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.cjs.map +1 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +24 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/dist/{collabWindowTracker.js → noopHeuristic.cjs} +37 -39
- package/dist/noopHeuristic.cjs.map +1 -0
- package/dist/noopHeuristic.d.ts +23 -0
- package/dist/noopHeuristic.d.ts.map +1 -0
- package/dist/{packageVersion.js → packageVersion.cjs} +2 -2
- package/dist/packageVersion.cjs.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/protocol.cjs +99 -0
- package/dist/protocol.cjs.map +1 -0
- package/dist/protocol.d.ts +38 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/{protocolTreeDocumentStorageService.js → protocolTreeDocumentStorageService.cjs} +8 -5
- package/dist/protocolTreeDocumentStorageService.cjs.map +1 -0
- package/dist/protocolTreeDocumentStorageService.d.ts +8 -4
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/quorum.cjs +16 -0
- package/dist/quorum.cjs.map +1 -0
- package/dist/quorum.d.ts +1 -14
- package/dist/quorum.d.ts.map +1 -1
- package/dist/{retriableDocumentStorageService.js → retriableDocumentStorageService.cjs} +36 -21
- package/dist/retriableDocumentStorageService.cjs.map +1 -0
- package/dist/retriableDocumentStorageService.d.ts +7 -5
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/{utils.js → utils.cjs} +52 -14
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.ts +34 -1
- package/dist/utils.d.ts.map +1 -1
- package/lib/{audience.d.ts → audience.d.mts} +5 -11
- package/lib/audience.d.mts.map +1 -0
- package/lib/{audience.js → audience.mjs} +15 -17
- package/lib/audience.mjs.map +1 -0
- package/lib/catchUpMonitor.d.mts +29 -0
- package/lib/catchUpMonitor.d.mts.map +1 -0
- package/lib/catchUpMonitor.mjs +39 -0
- package/lib/catchUpMonitor.mjs.map +1 -0
- package/lib/{connectionManager.d.ts → connectionManager.d.mts} +24 -34
- package/lib/connectionManager.d.mts.map +1 -0
- package/lib/{connectionManager.js → connectionManager.mjs} +378 -218
- package/lib/connectionManager.mjs.map +1 -0
- package/lib/{connectionState.d.ts → connectionState.d.mts} +4 -6
- package/lib/connectionState.d.mts.map +1 -0
- package/lib/{connectionState.js → connectionState.mjs} +4 -6
- package/lib/connectionState.mjs.map +1 -0
- package/lib/connectionStateHandler.d.mts +179 -0
- package/lib/connectionStateHandler.d.mts.map +1 -0
- package/lib/connectionStateHandler.mjs +469 -0
- package/lib/connectionStateHandler.mjs.map +1 -0
- package/lib/container-loader-alpha.d.mts +274 -0
- package/lib/container-loader-beta.d.mts +75 -0
- package/lib/container-loader-public.d.mts +75 -0
- package/lib/container-loader-untrimmed.d.mts +331 -0
- package/lib/container.d.mts +382 -0
- package/lib/container.d.mts.map +1 -0
- package/lib/container.mjs +1579 -0
- package/lib/container.mjs.map +1 -0
- package/lib/containerContext.d.mts +58 -0
- package/lib/containerContext.d.mts.map +1 -0
- package/lib/containerContext.mjs +70 -0
- package/lib/containerContext.mjs.map +1 -0
- package/lib/containerStorageAdapter.d.mts +73 -0
- package/lib/containerStorageAdapter.d.mts.map +1 -0
- package/lib/containerStorageAdapter.mjs +228 -0
- package/lib/containerStorageAdapter.mjs.map +1 -0
- package/lib/{contracts.d.ts → contracts.d.mts} +46 -18
- package/lib/contracts.d.mts.map +1 -0
- package/lib/{contracts.js → contracts.mjs} +4 -4
- package/lib/contracts.mjs.map +1 -0
- package/lib/debugLogger.d.mts +30 -0
- package/lib/debugLogger.d.mts.map +1 -0
- package/lib/debugLogger.mjs +93 -0
- package/lib/debugLogger.mjs.map +1 -0
- package/lib/{deltaManager.d.ts → deltaManager.d.mts} +55 -19
- package/lib/deltaManager.d.mts.map +1 -0
- package/lib/{deltaManager.js → deltaManager.mjs} +361 -165
- package/lib/deltaManager.mjs.map +1 -0
- package/lib/{deltaQueue.d.ts → deltaQueue.d.mts} +4 -5
- package/lib/deltaQueue.d.mts.map +1 -0
- package/lib/{deltaQueue.js → deltaQueue.mjs} +25 -24
- package/lib/deltaQueue.mjs.map +1 -0
- package/lib/disposal.d.mts +13 -0
- package/lib/disposal.d.mts.map +1 -0
- package/lib/disposal.mjs +21 -0
- package/lib/disposal.mjs.map +1 -0
- package/lib/error.d.mts +23 -0
- package/lib/error.d.mts.map +1 -0
- package/lib/error.mjs +28 -0
- package/lib/error.mjs.map +1 -0
- package/lib/index.d.mts +11 -0
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +10 -0
- package/lib/index.mjs.map +1 -0
- package/lib/{loader.d.ts → loader.d.mts} +40 -21
- package/lib/loader.d.mts.map +1 -0
- package/lib/loader.mjs +143 -0
- package/lib/loader.mjs.map +1 -0
- package/lib/location-redirection-utilities/index.d.mts +6 -0
- package/lib/location-redirection-utilities/index.d.mts.map +1 -0
- package/lib/location-redirection-utilities/index.mjs +6 -0
- package/lib/location-redirection-utilities/index.mjs.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.mts +24 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.mts.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.mjs +48 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.mjs.map +1 -0
- package/lib/noopHeuristic.d.mts +23 -0
- package/lib/noopHeuristic.d.mts.map +1 -0
- package/lib/{collabWindowTracker.js → noopHeuristic.mjs} +33 -35
- package/lib/noopHeuristic.mjs.map +1 -0
- package/lib/{packageVersion.d.ts → packageVersion.d.mts} +2 -2
- package/lib/packageVersion.d.mts.map +1 -0
- package/lib/{packageVersion.js → packageVersion.mjs} +2 -2
- package/lib/packageVersion.mjs.map +1 -0
- package/lib/protocol.d.mts +38 -0
- package/lib/protocol.d.mts.map +1 -0
- package/lib/protocol.mjs +94 -0
- package/lib/protocol.mjs.map +1 -0
- package/lib/{protocolTreeDocumentStorageService.d.ts → protocolTreeDocumentStorageService.d.mts} +9 -5
- package/lib/protocolTreeDocumentStorageService.d.mts.map +1 -0
- package/lib/{protocolTreeDocumentStorageService.js → protocolTreeDocumentStorageService.mjs} +8 -5
- package/lib/protocolTreeDocumentStorageService.mjs.map +1 -0
- package/lib/quorum.d.mts +4 -0
- package/lib/quorum.d.mts.map +1 -0
- package/lib/quorum.mjs +12 -0
- package/lib/quorum.mjs.map +1 -0
- package/lib/{retriableDocumentStorageService.d.ts → retriableDocumentStorageService.d.mts} +8 -6
- package/lib/retriableDocumentStorageService.d.mts.map +1 -0
- package/lib/{retriableDocumentStorageService.js → retriableDocumentStorageService.mjs} +35 -20
- package/lib/retriableDocumentStorageService.mjs.map +1 -0
- package/lib/utils.d.mts +67 -0
- package/lib/utils.d.mts.map +1 -0
- package/lib/{utils.js → utils.mjs} +47 -11
- package/lib/utils.mjs.map +1 -0
- package/package.json +189 -69
- package/prettier.config.cjs +8 -0
- package/src/audience.ts +59 -49
- package/src/catchUpMonitor.ts +61 -0
- package/src/connectionManager.ts +1154 -910
- package/src/connectionState.ts +22 -25
- package/src/connectionStateHandler.ts +689 -319
- package/src/container.ts +2476 -1792
- package/src/containerContext.ts +98 -330
- package/src/containerStorageAdapter.ts +301 -105
- package/src/contracts.ts +184 -146
- package/src/debugLogger.ts +123 -0
- package/src/deltaManager.ts +1165 -900
- package/src/deltaQueue.ts +156 -152
- package/src/disposal.ts +25 -0
- package/src/error.ts +44 -0
- package/src/index.ts +14 -15
- package/src/loader.ts +356 -427
- package/src/location-redirection-utilities/index.ts +9 -0
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +61 -0
- package/src/noopHeuristic.ts +107 -0
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +150 -0
- package/src/protocolTreeDocumentStorageService.ts +35 -35
- package/src/quorum.ts +11 -50
- package/src/retriableDocumentStorageService.ts +135 -95
- package/src/utils.ts +159 -86
- package/tsc-multi.test.json +4 -0
- package/tsconfig.json +10 -12
- package/dist/audience.js.map +0 -1
- package/dist/collabWindowTracker.d.ts +0 -19
- package/dist/collabWindowTracker.d.ts.map +0 -1
- package/dist/collabWindowTracker.js.map +0 -1
- package/dist/connectionManager.js.map +0 -1
- package/dist/connectionState.js.map +0 -1
- package/dist/connectionStateHandler.js +0 -280
- package/dist/connectionStateHandler.js.map +0 -1
- package/dist/container.js +0 -1284
- package/dist/container.js.map +0 -1
- package/dist/containerContext.js +0 -217
- package/dist/containerContext.js.map +0 -1
- package/dist/containerStorageAdapter.js +0 -104
- package/dist/containerStorageAdapter.js.map +0 -1
- package/dist/contracts.js.map +0 -1
- package/dist/deltaManager.js.map +0 -1
- package/dist/deltaManagerProxy.d.ts +0 -54
- package/dist/deltaManagerProxy.d.ts.map +0 -1
- package/dist/deltaManagerProxy.js +0 -115
- package/dist/deltaManagerProxy.js.map +0 -1
- package/dist/deltaQueue.js.map +0 -1
- package/dist/index.js +0 -16
- package/dist/index.js.map +0 -1
- package/dist/loader.js +0 -241
- package/dist/loader.js.map +0 -1
- package/dist/packageVersion.js.map +0 -1
- package/dist/protocolTreeDocumentStorageService.js.map +0 -1
- package/dist/quorum.js +0 -44
- package/dist/quorum.js.map +0 -1
- package/dist/retriableDocumentStorageService.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/lib/audience.d.ts.map +0 -1
- package/lib/audience.js.map +0 -1
- package/lib/collabWindowTracker.d.ts +0 -19
- package/lib/collabWindowTracker.d.ts.map +0 -1
- package/lib/collabWindowTracker.js.map +0 -1
- package/lib/connectionManager.d.ts.map +0 -1
- package/lib/connectionManager.js.map +0 -1
- package/lib/connectionState.d.ts.map +0 -1
- package/lib/connectionState.js.map +0 -1
- package/lib/connectionStateHandler.d.ts +0 -81
- package/lib/connectionStateHandler.d.ts.map +0 -1
- package/lib/connectionStateHandler.js +0 -276
- package/lib/connectionStateHandler.js.map +0 -1
- package/lib/container.d.ts +0 -238
- package/lib/container.d.ts.map +0 -1
- package/lib/container.js +0 -1276
- package/lib/container.js.map +0 -1
- package/lib/containerContext.d.ts +0 -84
- package/lib/containerContext.d.ts.map +0 -1
- package/lib/containerContext.js +0 -213
- package/lib/containerContext.js.map +0 -1
- package/lib/containerStorageAdapter.d.ts +0 -48
- package/lib/containerStorageAdapter.d.ts.map +0 -1
- package/lib/containerStorageAdapter.js +0 -99
- package/lib/containerStorageAdapter.js.map +0 -1
- package/lib/contracts.d.ts.map +0 -1
- package/lib/contracts.js.map +0 -1
- package/lib/deltaManager.d.ts.map +0 -1
- package/lib/deltaManager.js.map +0 -1
- package/lib/deltaManagerProxy.d.ts +0 -54
- package/lib/deltaManagerProxy.d.ts.map +0 -1
- package/lib/deltaManagerProxy.js +0 -110
- package/lib/deltaManagerProxy.js.map +0 -1
- package/lib/deltaQueue.d.ts.map +0 -1
- package/lib/deltaQueue.js.map +0 -1
- package/lib/index.d.ts +0 -8
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -8
- package/lib/index.js.map +0 -1
- package/lib/loader.d.ts.map +0 -1
- package/lib/loader.js +0 -236
- package/lib/loader.js.map +0 -1
- package/lib/packageVersion.d.ts.map +0 -1
- package/lib/packageVersion.js.map +0 -1
- package/lib/protocolTreeDocumentStorageService.d.ts.map +0 -1
- package/lib/protocolTreeDocumentStorageService.js.map +0 -1
- package/lib/quorum.d.ts +0 -21
- package/lib/quorum.d.ts.map +0 -1
- package/lib/quorum.js +0 -38
- package/lib/quorum.js.map +0 -1
- package/lib/retriableDocumentStorageService.d.ts.map +0 -1
- package/lib/retriableDocumentStorageService.js.map +0 -1
- package/lib/utils.d.ts +0 -34
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js.map +0 -1
- package/src/collabWindowTracker.ts +0 -102
- package/src/deltaManagerProxy.ts +0 -158
- package/tsconfig.esnext.json +0 -7
package/README.md
CHANGED
|
@@ -1,30 +1,55 @@
|
|
|
1
1
|
# @fluidframework/container-loader
|
|
2
2
|
|
|
3
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_DEPENDENCY_GUIDELINES_SECTION:includeHeading=TRUE) -->
|
|
4
|
+
|
|
5
|
+
<!-- prettier-ignore-start -->
|
|
6
|
+
<!-- NOTE: This section is automatically generated using @fluid-tools/markdown-magic. Do not update these generated contents directly. -->
|
|
7
|
+
|
|
8
|
+
## Using Fluid Framework libraries
|
|
9
|
+
|
|
10
|
+
When taking a dependency on a Fluid Framework library, we recommend using a `^` (caret) version range, such as `^1.3.4`.
|
|
11
|
+
While Fluid Framework libraries may use different ranges with interdependencies between other Fluid Framework libraries,
|
|
12
|
+
library consumers should always prefer `^`.
|
|
13
|
+
|
|
14
|
+
Note that when depending on a library version of the form `2.0.0-internal.x.y.z`, called the Fluid internal version scheme,
|
|
15
|
+
you must use a `>= <` dependency range (such as `>=2.0.0-internal.x.y.z <2.0.0-internal.w.0.0` where `w` is `x+1`).
|
|
16
|
+
Standard `^` and `~` ranges will not work as expected.
|
|
17
|
+
See the [@fluid-tools/version-tools](https://github.com/microsoft/FluidFramework/blob/main/build-tools/packages/version-tools/README.md)
|
|
18
|
+
package for more information including tools to convert between version schemes.
|
|
19
|
+
|
|
20
|
+
<!-- prettier-ignore-end -->
|
|
21
|
+
|
|
22
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
|
23
|
+
|
|
3
24
|
**Topics covered below:**
|
|
4
25
|
|
|
5
|
-
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
|
|
26
|
+
- [@fluidframework/container-loader](#fluidframeworkcontainer-loader)
|
|
27
|
+
- [Using Fluid Framework libraries](#using-fluid-framework-libraries)
|
|
28
|
+
- [Fluid Loader](#fluid-loader)
|
|
29
|
+
- [Expectations from host implementers](#expectations-from-host-implementers)
|
|
30
|
+
- [Expectations from container runtime and data store implementers](#expectations-from-container-runtime-and-data-store-implementers)
|
|
31
|
+
- [Container Lifetime](#container-lifetime)
|
|
32
|
+
- [Loading](#loading)
|
|
33
|
+
- [Connectivity](#connectivity)
|
|
34
|
+
- [Closure](#closure)
|
|
35
|
+
- [`Container.close()`](#containerclose)
|
|
36
|
+
- [`Container.dispose()`](#containerdispose)
|
|
37
|
+
- [Audience](#audience)
|
|
38
|
+
- [ClientID and client identification](#clientid-and-client-identification)
|
|
39
|
+
- [Error handling](#error-handling)
|
|
40
|
+
- [Connectivity events](#connectivity-events)
|
|
41
|
+
- [Connection State Transitions Flow Chart](#connection-state-transitions-flow-chart)
|
|
42
|
+
- [Readonly states](#readonly-states)
|
|
43
|
+
- [`readonly`](#readonly)
|
|
44
|
+
- [`permissions`](#permissions)
|
|
45
|
+
- [`forced`](#forced)
|
|
46
|
+
- [`storageOnly`](#storageonly)
|
|
47
|
+
- [Dirty events](#dirty-events)
|
|
48
|
+
- [Trademark](#trademark)
|
|
23
49
|
|
|
24
50
|
**Related topics covered elsewhere:**
|
|
25
51
|
|
|
26
|
-
-
|
|
27
|
-
|
|
52
|
+
- [Quorum and Proposals](../../../server/routerlicious/packages/protocol-base/README.md)
|
|
28
53
|
|
|
29
54
|
## Fluid Loader
|
|
30
55
|
|
|
@@ -45,6 +70,7 @@ Please see specific sections for more details on these states and events - this
|
|
|
45
70
|
2. ["closed"](#Closure) event: If raised with error, host is responsible for conveying error in some form to the user. Container is left in disconnected & readonly state when it is closed (because of error or not).
|
|
46
71
|
3. ["readonly"](#Readonly-states) event: Host should have some indication to user that container is not editable. User permissions can change over lifetime of Container, but they can't change per connection session (in other words, change in permissions causes disconnect and reconnect). Hosts are advised to recheck this property on every reconnect.
|
|
47
72
|
4. [Dirty events](#Dirty-events): Host should have some reasonable UX / workflows to ensure user does not lose edits unexpectedly. I.e. there is enough signals (potentially including blocking user from closing container) ensuring that all user edits make it to storage, unless user explicitly choses to lose such edits.
|
|
73
|
+
5. [Closing or disposing containers](#containerclose): For most cases, you should use the `IContainer.dispose(...)` API to free up resources. If you intend on using the container after closure, or need to pass some critical error to the container, use the `IContainer.close(...)` API.
|
|
48
74
|
|
|
49
75
|
## Expectations from container runtime and data store implementers
|
|
50
76
|
|
|
@@ -60,42 +86,63 @@ Please see specific sections for more details on these states and events - this
|
|
|
60
86
|
|
|
61
87
|
Container is returned as result of Loader.resolve() call. Loader can cache containers, so if same URI is requested from same loader instance, earlier created container might be returned. This is important, as some of the headers (like `pause`) might be ignored because of Container reuse.
|
|
62
88
|
|
|
63
|
-
`ILoaderHeader` in [loader.ts](
|
|
89
|
+
`ILoaderHeader` in [loader.ts](../../common/container-definitions/src/loader.ts) describes properties controlling container loading.
|
|
64
90
|
|
|
65
91
|
### Connectivity
|
|
66
92
|
|
|
67
|
-
Usually container is returned when state of container (and data stores) is rehydrated from snapshot. Unless `IRequest.headers.pause` is specified, connection to ordering service will be established at some point (asynchronously) and latest Ops would be processed, allowing local changes to flow form client to server. `Container.connectionState` indicates whether connection to ordering service is established, and
|
|
93
|
+
Usually container is returned when state of container (and data stores) is rehydrated from snapshot. Unless `IRequest.headers.pause` is specified, connection to ordering service will be established at some point (asynchronously) and latest Ops would be processed, allowing local changes to flow form client to server. `Container.connectionState` indicates whether connection to ordering service is established, and [Connectivity events](#Connectivity-events) are notifying about connectivity changes. While it's highly recommended for listeners to check initial state at the moment they register for connectivity events, new listeners are called on registration to propagate current state. That is, if a container is disconnected when both "connected" and "disconnected" listeners are installed, newly installed listeners for "disconnected" event will be called on registration.
|
|
68
94
|
|
|
69
95
|
### Closure
|
|
70
96
|
|
|
71
|
-
Container can be closed directly by host by calling `Container.close()`.
|
|
97
|
+
Container can be closed directly by host by calling `Container.close()` and/or `Container.dispose()`. If the container is expected to be used upon closure, or you need to pass your own critical error to the container, use the `close()` API. Otherwise, use the `dispose()` API. The differences between these methods are detailed in the sections below.
|
|
98
|
+
|
|
99
|
+
#### `Container.close()`
|
|
72
100
|
|
|
73
|
-
|
|
101
|
+
Once closed, container terminates connection to ordering service, and any local changes (former or future) do not propagate to storage. This method is to be used when the container **IS** still expected to be used and the container needs to be switched to a "safe" state for viewing. For example, allowing a user to copy the content out of a container.
|
|
102
|
+
|
|
103
|
+
The "closed" state effectively means the container is disconnected forever and cannot be reconnected.
|
|
104
|
+
|
|
105
|
+
If after some time a closed container is no longer needed, calling `Container.dispose()` will dispose the runtime resources.
|
|
106
|
+
|
|
107
|
+
Container can also be closed and/or disposed by runtime itself as result of some critical error. Critical errors can be internal (like violation in op ordering invariants), or external (file was deleted). Please see [Error Handling](#Error-handling) for more details.
|
|
74
108
|
|
|
75
109
|
When container is closed, the following is true (in no particular order):
|
|
76
110
|
|
|
77
111
|
1. Container.closed property is set to true
|
|
78
112
|
2. "closed" event fires on container with optional error object (indicating reason for closure; if missing - closure was due to host closing container)
|
|
79
|
-
3. "readonly" event fires on DeltaManager & Container (and Container.readonly property is set to true)
|
|
113
|
+
3. "readonly" event fires on DeltaManager & Container (and Container.readonly property is set to true) indicating to all data stores that container is read-only, and data stores should not allow local edits, as they are not going to make it.
|
|
80
114
|
4. "disconnected" event fires, if connection was active at the moment of container closure.
|
|
81
115
|
|
|
82
|
-
`"closed"` event is available on Container for hosts.
|
|
116
|
+
`"closed"` event is available on Container for hosts.
|
|
117
|
+
|
|
118
|
+
#### `Container.dispose()`
|
|
119
|
+
|
|
120
|
+
Once disposed, container terminates connection to ordering service, and any local changes (former or future) do not propagate to storage. This method is to be used when the container is **NOT** expected to be used anymore.
|
|
121
|
+
|
|
122
|
+
When container is disposed, the following is true (in no particular order):
|
|
123
|
+
|
|
124
|
+
1. Container.closed property is set to true
|
|
125
|
+
2. "disposed" event fires on container
|
|
126
|
+
3. "disconnected" event fires, if connection was active at the moment of container disposal.
|
|
127
|
+
4. "dispose" event fires on container runtime
|
|
128
|
+
|
|
129
|
+
`"disposed"` event is available on Container for hosts. `"dispose"` event is delivered to container runtime when container is disposed, but container runtime can be also disposed when new code proposal is made and new version of the code (and container runtime) is loaded in accordance with it.
|
|
83
130
|
|
|
84
131
|
## Audience
|
|
85
132
|
|
|
86
133
|
`Container.audience` exposes an object that tracks all connected clients to same container.
|
|
87
134
|
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
135
|
+
- `getMembers()` can be used to retrieve current set of users
|
|
136
|
+
- `getMember()` can be used to get IClient information about particular client (returns undefined if such client is not connected)
|
|
137
|
+
- `"addMember"` event is raised when new member joins
|
|
138
|
+
- `"removeMember"` event is raised when an earlier connected member leaves (disconnects from container)
|
|
92
139
|
|
|
93
140
|
`getMembers()` and `"addMember"` event provide _IClient_ interface that describes type of connection, permissions and user information:
|
|
94
141
|
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
|
|
98
|
-
|
|
142
|
+
- clientId is the key - it is unique ID for a session. Please see [ClientID and client identification](#ClientId-and-client-identification) for more details on it, as well as how to properly differentiate human vs. agent clients and difference between client ID & user ID.
|
|
143
|
+
- IClient.mode in particular describes connectivity mode of a client:
|
|
144
|
+
- "write" means client has read/write connection, can change container contents, and participates in Quorum
|
|
145
|
+
- "read" indicates client as read connection. Such clients can't modify container and do not participate in quorum. That said, "read" does not indicate client permissions, i.e. client might have read-only permissions to a file, or maybe connected temporarily as read-only, to reduce COGS on server and not "modify" container (any read-write connection generates join & leave messages that modify container and change "last edited by" property)
|
|
99
146
|
|
|
100
147
|
Please note that if this client losses connection to ordering server, then audience information is not reset at that moment. It will become stale while client is disconnected, and will refresh the moment client connects back to container. For more details, please see [Connectivity events](#Connectivity-events) section
|
|
101
148
|
|
|
@@ -117,19 +164,20 @@ There are two ways errors are exposed:
|
|
|
117
164
|
|
|
118
165
|
Critical errors can show up in #1 & #2 workflows. For example, data store URI may point to a deleted file, which will result in errors on container open. But file can also be deleted while container is opened, resulting in same error type being raised through "error" handler.
|
|
119
166
|
|
|
120
|
-
Errors are of [ICriticalContainerError](
|
|
167
|
+
Errors are of [ICriticalContainerError](../../common/container-definitions/src/error.ts) type, and warnings are of [ContainerWarning](../../common/container-definitions/src/error.ts) type. Both have `errorType` property, describing type of an error (and appropriate interface of error object):
|
|
121
168
|
|
|
122
169
|
```ts
|
|
123
170
|
readonly errorType: string;
|
|
124
171
|
```
|
|
125
172
|
|
|
126
|
-
There are
|
|
173
|
+
There are 4 sources of errors:
|
|
127
174
|
|
|
128
|
-
1. [ContainerErrorType](
|
|
129
|
-
2. [
|
|
130
|
-
3.
|
|
175
|
+
1. [ContainerErrorType](../../common/container-definitions/src/error.ts) - errors & warnings raised at loader level
|
|
176
|
+
2. [DriverErrorType](../../common/driver-definitions/src/driverError.ts) - errors that are likely to be raised from the driver level
|
|
177
|
+
3. [OdspErrorType](../../drivers/odsp-driver/src/odspError.ts) and [RouterliciousErrorType](../../drivers/routerlicious-driver/src/documentDeltaConnection.ts) - errors raised by ODSP and R11S drivers.
|
|
178
|
+
4. Runtime errors, like `"summarizingError"`, `"dataCorruptionError"`. This class of errors is not pre-determined and depends on type of container loaded.
|
|
131
179
|
|
|
132
|
-
`ICriticalContainerError.errorType` is a string, which represents a union of
|
|
180
|
+
`ICriticalContainerError.errorType` is a string, which represents a union of 4 error types described above. Hosting application may package different drivers and open different types of containers, and only hosting application may have enough information to enumerate all possible error codes in such scenarios.
|
|
133
181
|
|
|
134
182
|
Hosts must listen to `"closed"` event. If error object is present there, container was closed due to error and this information needs to be communicated to user in some way. If there is no error object, it was closed due to host application calling Container.close() (without specifying error).
|
|
135
183
|
When container is closed, it is no longer connected to ordering service. It is also in read-only state, communicating to data stores not to allow user to make changes to container.
|
|
@@ -138,53 +186,101 @@ When container is closed, it is no longer connected to ordering service. It is a
|
|
|
138
186
|
|
|
139
187
|
Container raises two events to notify hosting application about connectivity issues and connectivity status.
|
|
140
188
|
|
|
141
|
-
-
|
|
142
|
-
-
|
|
189
|
+
- `"connected"` event is raised when container is connected and is up-to-date, i.e. changes are flowing between client and server.
|
|
190
|
+
- `"disconnected"` event is raised when container lost connectivity (for any reason).
|
|
143
191
|
|
|
144
192
|
Container also exposes `Container.connectionState` property to indicate current state.
|
|
145
193
|
|
|
146
|
-
In normal circumstances, container will attempt to reconnect back to ordering service as quickly as possible. But it will scale down retries if computer is offline.
|
|
194
|
+
In normal circumstances, container will attempt to reconnect back to ordering service as quickly as possible. But it will scale down retries if computer is offline. That said, if IThrottlingWarning is raised through `"warning"` handler, then container is following storage throttling policy and will attempt to reconnect after some amount of time (`IThrottlingWarning.retryAfterSeconds`).
|
|
147
195
|
|
|
148
196
|
Container will also not attempt to reconnect on lost connection if `Container.disconnect()` was called prior to loss of connection. This can be useful if the hosting application implements "user away" type of experience to reduce cost on both client and server of maintaining connection while user is away. Calling `Container.connect()` will reenable automatic reconnections, but the host might need to allow extra time for reconnection as it likely involves token fetch and processing of a lot of Ops generated by other clients while it was not connected.
|
|
149
197
|
|
|
150
|
-
Data stores should almost never listen to these events (see more on [Readonly states](#Readonly-states), and should use consensus DDSes if they need to synchronize activity across clients. DDSes listen for these events to know when to resubmit pending Ops.
|
|
198
|
+
Data stores should almost never listen to these events (see more on [Readonly states](#Readonly-states)), and should use consensus DDSes if they need to synchronize activity across clients. DDSes listen for these events to know when to resubmit pending Ops.
|
|
151
199
|
|
|
152
|
-
Hosting application can use these events in order to indicate to user when user changes are not propagating through the system, and thus can be lost (on browser tab being closed). It's advised to use some delay (like 5 seconds) before showing such UI, as network connectivity might be intermittent.
|
|
200
|
+
Hosting application can use these events in order to indicate to user when user changes are not propagating through the system, and thus can be lost (on browser tab being closed). It's advised to use some delay (like 5 seconds) before showing such UI, as network connectivity might be intermittent. Also if container was offline for very long period of time due to `Container.disconnect()` being called, it might take a while to get connected and current.
|
|
153
201
|
|
|
154
202
|
Please note that hosts can implement various strategies on how to handle disconnections. Some may decide to show some UX letting user know about potential loss of data if container is closed while disconnected. Others can force container to disallow user edits while offline (see [Readonly states](#Readonly-states)).
|
|
155
203
|
|
|
156
204
|
It's worth pointing out that being connected does not mean all user edits are preserved on container closure. There is latency in the system, and loader layer does not provide any guarantees here. Not every implementation needs a solution here (games likely do not care), and thus solving this problem is pushed to framework level (i.e. having a data store that can expose `'dirtyDocument'` signal from ContainerRuntime and request route that can return such data store).
|
|
157
205
|
|
|
206
|
+
## Connection State Transitions Flow Chart
|
|
207
|
+
|
|
208
|
+
```mermaid
|
|
209
|
+
flowchart TD;
|
|
210
|
+
A(Disconnected)-->B{Reconnect on error if \n AutoReconnect Enabled?};
|
|
211
|
+
B--Yes-->C(Establishing Connection);
|
|
212
|
+
B--No-->D[Connection during Container \n connect call];
|
|
213
|
+
D-->C
|
|
214
|
+
C-->E{Connection Success \n including any Retry?};
|
|
215
|
+
E--No-->F[Error or container.close or container.disconnect];
|
|
216
|
+
A-->F;
|
|
217
|
+
F-->A;
|
|
218
|
+
E--Yes-->G(Catching Up);
|
|
219
|
+
G-->F;
|
|
220
|
+
G-->H{Which Connection Mode?};
|
|
221
|
+
H--Read-->I(Connected);
|
|
222
|
+
H--Write-->J[Wait for Join Op];
|
|
223
|
+
J-->I;
|
|
224
|
+
I-->F;
|
|
225
|
+
```
|
|
226
|
+
|
|
158
227
|
## Readonly states
|
|
228
|
+
|
|
159
229
|
User permissions can change over lifetime of Container. They can't change during single connection session (in other words, change in permissions causes disconnect and reconnect). Hosts are advised to recheck this property on every reconnect.
|
|
160
230
|
|
|
161
231
|
DeltaManager will emit a `"readonly"` event when transitioning to a read-only state. Readonly events are accessible by data stores and DDSes (through ContainerRuntime.deltaManager). It's expected that data stores adhere to requirements and expose read-only (or rather 'no edit') experiences.
|
|
162
232
|
|
|
163
|
-
`Container.readOnlyInfo` (and `DeltaManager.readOnlyInfo`) indicates to host if file is writable or not.
|
|
233
|
+
`Container.readOnlyInfo` (and `DeltaManager.readOnlyInfo`) indicates to the host if the file is writable or not.
|
|
234
|
+
It contains the following properties:
|
|
235
|
+
|
|
164
236
|
### `readonly`
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
-
|
|
237
|
+
|
|
238
|
+
One of the following:
|
|
239
|
+
|
|
240
|
+
- `true`: Container is read-only. One or more of the additional properties listed below will be `true`.
|
|
241
|
+
- `undefined`: Runtime does not know yet if file is writable or not. Currently we get a signal here only when websocket connection is made to the server.
|
|
242
|
+
- `false`: Container.forceReadonly() was never called or last call was with false, plus it's known that user has write permissions to a file.
|
|
169
243
|
|
|
170
244
|
### `permissions`
|
|
171
|
-
There are two cases when it's true:
|
|
172
245
|
|
|
173
|
-
|
|
246
|
+
There are two cases when it's `true`:
|
|
247
|
+
|
|
248
|
+
1. User has no write permissions to modify this container (which usually maps to file in storage, and lack of write permissions by a given user)
|
|
174
249
|
2. Container was closed, either due to critical error, or due to host closing container. See [Container Lifetime](#Container-lifetime) and [Error Handling](#Error-handling) for more details.
|
|
175
250
|
|
|
176
251
|
### `forced`
|
|
177
|
-
Hosts can also force readonly-mode for a container via calling `Container.forceReadonly(true)`. This can be useful in scenarios like:
|
|
178
252
|
|
|
179
|
-
|
|
180
|
-
|
|
253
|
+
`true` if the Container is in read-only mode due to the host calling `Container.forceReadonly(true)`.
|
|
254
|
+
This can be useful in scenarios like:
|
|
255
|
+
|
|
256
|
+
- Loss of connectivity, in scenarios where host chooses method of preventing user edits over (or in addition to) showing disconnected UX and warning user of potential data loss on closure of container.
|
|
257
|
+
- Special view-only mode in host. For example can be used by hosts for previewing container content in-place with other host content, and leveraging full-screen / separate window experience for editing.
|
|
181
258
|
|
|
182
259
|
### `storageOnly`
|
|
183
|
-
|
|
260
|
+
|
|
261
|
+
Storage-only mode is a read-only mode in which the container does not connect to the delta stream and is unable to submit or receive ops. This is useful for viewing a specific version of a document.
|
|
184
262
|
|
|
185
263
|
## Dirty events
|
|
264
|
+
|
|
186
265
|
The Container runtime can communicate with the container to get the container's current state. In response, the container will raise two events - `"dirty"` and `"saved"` events. Transitions between these two events signify presence (or lack of) user changes that were not saved to storage. In other words, if container is dirty, closing it at that moment will result in data loss from user perspective, because not all user changes made it to storage.
|
|
187
266
|
This information can be used by a host to build appropriate UX that allows user to be confident in the platform. For example, a host may chose to show a dialog asking the user if they want to save their changes before closing. Instead of, or in addition to this, the host may choose to show "Saving..." and "Saved" text somewhere in UX. Coupled with lack of connectivity to ordering service (and appropriate notification to the user) that may create enough continuous notification to user not to require a blocking dialog on closing.
|
|
188
267
|
Note that when an active connection is in place, it's just a matter of time before changes will be flushed to storage unless there is some source of continuous local changes being generated that prevents container from ever being fully saved. But if there is no active connection, because the user is offline, for example, then a document may stay in a dirty state for very long time.
|
|
189
268
|
|
|
190
269
|
`Container.isDirty` can be used to get current state of container.
|
|
270
|
+
|
|
271
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_TRADEMARK_SECTION:includeHeading=TRUE) -->
|
|
272
|
+
|
|
273
|
+
<!-- prettier-ignore-start -->
|
|
274
|
+
<!-- NOTE: This section is automatically generated using @fluid-tools/markdown-magic. Do not update these generated contents directly. -->
|
|
275
|
+
|
|
276
|
+
## Trademark
|
|
277
|
+
|
|
278
|
+
This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services.
|
|
279
|
+
|
|
280
|
+
Use of these trademarks or logos must follow Microsoft's [Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
|
|
281
|
+
|
|
282
|
+
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
|
|
283
|
+
|
|
284
|
+
<!-- prettier-ignore-end -->
|
|
285
|
+
|
|
286
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
package/api-extractor.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
+
"extends": "../../../common/build/build-common/api-extractor-base.json"
|
|
4
4
|
}
|
|
@@ -0,0 +1,143 @@
|
|
|
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/core-interfaces';
|
|
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 { IHostLoader } from '@fluidframework/container-definitions';
|
|
18
|
+
import { ILoaderOptions as ILoaderOptions_2 } from '@fluidframework/container-definitions';
|
|
19
|
+
import { ILocationRedirectionError } from '@fluidframework/driver-definitions';
|
|
20
|
+
import { IProtocolHandler as IProtocolHandler_2 } from '@fluidframework/protocol-base';
|
|
21
|
+
import { IProvideFluidCodeDetailsComparer } from '@fluidframework/container-definitions';
|
|
22
|
+
import { IQuorumSnapshot } from '@fluidframework/protocol-base';
|
|
23
|
+
import { IRequest } from '@fluidframework/core-interfaces';
|
|
24
|
+
import { ISignalMessage } from '@fluidframework/protocol-definitions';
|
|
25
|
+
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
26
|
+
import { ITelemetryLoggerExt } from '@fluidframework/telemetry-utils';
|
|
27
|
+
import { IUrlResolver } from '@fluidframework/driver-definitions';
|
|
28
|
+
|
|
29
|
+
// @alpha (undocumented)
|
|
30
|
+
export enum ConnectionState {
|
|
31
|
+
CatchingUp = 1,
|
|
32
|
+
Connected = 2,
|
|
33
|
+
Disconnected = 0,
|
|
34
|
+
EstablishingConnection = 3
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// @alpha @deprecated (undocumented)
|
|
38
|
+
export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComparer> {
|
|
39
|
+
load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// @internal
|
|
43
|
+
export interface IContainerExperimental extends IContainer {
|
|
44
|
+
closeAndGetPendingLocalState?(stopBlobAttachingSignal?: AbortSignal): Promise<string>;
|
|
45
|
+
getPendingLocalState?(): Promise<string>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// @alpha
|
|
49
|
+
export type IDetachedBlobStorage = Pick<IDocumentStorageService, "createBlob" | "readBlob"> & {
|
|
50
|
+
size: number;
|
|
51
|
+
getBlobIds(): string[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// @alpha @deprecated (undocumented)
|
|
55
|
+
export interface IFluidModuleWithDetails {
|
|
56
|
+
details: IFluidCodeDetails;
|
|
57
|
+
module: IFluidModule;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// @alpha (undocumented)
|
|
61
|
+
export interface ILoaderOptions extends ILoaderOptions_2 {
|
|
62
|
+
// (undocumented)
|
|
63
|
+
summarizeProtocolTree?: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// @alpha
|
|
67
|
+
export interface ILoaderProps {
|
|
68
|
+
readonly codeLoader: ICodeDetailsLoader;
|
|
69
|
+
readonly configProvider?: IConfigProviderBase;
|
|
70
|
+
readonly detachedBlobStorage?: IDetachedBlobStorage;
|
|
71
|
+
readonly documentServiceFactory: IDocumentServiceFactory;
|
|
72
|
+
readonly logger?: ITelemetryBaseLogger;
|
|
73
|
+
readonly options?: ILoaderOptions;
|
|
74
|
+
readonly protocolHandlerBuilder?: ProtocolHandlerBuilder;
|
|
75
|
+
readonly scope?: FluidObject;
|
|
76
|
+
readonly urlResolver: IUrlResolver;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// @alpha
|
|
80
|
+
export interface ILoaderServices {
|
|
81
|
+
readonly codeLoader: ICodeDetailsLoader;
|
|
82
|
+
readonly detachedBlobStorage?: IDetachedBlobStorage;
|
|
83
|
+
readonly documentServiceFactory: IDocumentServiceFactory;
|
|
84
|
+
readonly options: ILoaderOptions;
|
|
85
|
+
readonly protocolHandlerBuilder?: ProtocolHandlerBuilder;
|
|
86
|
+
readonly scope: FluidObject;
|
|
87
|
+
readonly subLogger: ITelemetryLoggerExt;
|
|
88
|
+
readonly urlResolver: IUrlResolver;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// @internal
|
|
92
|
+
export interface IParsedUrl {
|
|
93
|
+
id: string;
|
|
94
|
+
path: string;
|
|
95
|
+
query: string;
|
|
96
|
+
version: string | null | undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// @alpha (undocumented)
|
|
100
|
+
export interface IProtocolHandler extends IProtocolHandler_2 {
|
|
101
|
+
// (undocumented)
|
|
102
|
+
readonly audience: IAudienceOwner;
|
|
103
|
+
// (undocumented)
|
|
104
|
+
processSignal(message: ISignalMessage): any;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// @internal
|
|
108
|
+
export function isLocationRedirectionError(error: any): error is ILocationRedirectionError;
|
|
109
|
+
|
|
110
|
+
// @alpha
|
|
111
|
+
export class Loader implements IHostLoader {
|
|
112
|
+
constructor(loaderProps: ILoaderProps);
|
|
113
|
+
// (undocumented)
|
|
114
|
+
createDetachedContainer(codeDetails: IFluidCodeDetails, createDetachedProps?: {
|
|
115
|
+
canReconnect?: boolean;
|
|
116
|
+
clientDetailsOverride?: IClientDetails;
|
|
117
|
+
}): Promise<IContainer>;
|
|
118
|
+
// (undocumented)
|
|
119
|
+
rehydrateDetachedContainerFromSnapshot(snapshot: string, createDetachedProps?: {
|
|
120
|
+
canReconnect?: boolean;
|
|
121
|
+
clientDetailsOverride?: IClientDetails;
|
|
122
|
+
}): Promise<IContainer>;
|
|
123
|
+
// (undocumented)
|
|
124
|
+
resolve(request: IRequest, pendingLocalState?: string): Promise<IContainer>;
|
|
125
|
+
// (undocumented)
|
|
126
|
+
readonly services: ILoaderServices;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// @alpha
|
|
130
|
+
export type ProtocolHandlerBuilder = (attributes: IDocumentAttributes, snapshot: IQuorumSnapshot, sendProposal: (key: string, value: any) => number) => IProtocolHandler;
|
|
131
|
+
|
|
132
|
+
// @alpha
|
|
133
|
+
export function resolveWithLocationRedirectionHandling<T>(api: (request: IRequest) => Promise<T>, request: IRequest, urlResolver: IUrlResolver, logger?: ITelemetryBaseLogger): Promise<T>;
|
|
134
|
+
|
|
135
|
+
// @internal
|
|
136
|
+
export function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined;
|
|
137
|
+
|
|
138
|
+
// @alpha
|
|
139
|
+
export function waitContainerToCatchUp(container: IContainer): Promise<boolean>;
|
|
140
|
+
|
|
141
|
+
// (No @packageDocumentation comment for this package)
|
|
142
|
+
|
|
143
|
+
```
|
|
@@ -6,13 +6,16 @@ exports.Audience = void 0;
|
|
|
6
6
|
* Licensed under the MIT License.
|
|
7
7
|
*/
|
|
8
8
|
const events_1 = require("events");
|
|
9
|
+
const core_utils_1 = require("@fluidframework/core-utils");
|
|
9
10
|
/**
|
|
10
11
|
* Audience represents all clients connected to the op stream.
|
|
11
12
|
*/
|
|
12
13
|
class Audience extends events_1.EventEmitter {
|
|
13
14
|
constructor() {
|
|
14
|
-
super(
|
|
15
|
+
super();
|
|
15
16
|
this.members = new Map();
|
|
17
|
+
// We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging.
|
|
18
|
+
super.setMaxListeners(0);
|
|
16
19
|
}
|
|
17
20
|
on(event, listener) {
|
|
18
21
|
return super.on(event, listener);
|
|
@@ -21,8 +24,16 @@ class Audience extends events_1.EventEmitter {
|
|
|
21
24
|
* Adds a new client to the audience
|
|
22
25
|
*/
|
|
23
26
|
addMember(clientId, details) {
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
// Given that signal delivery is unreliable process, we might observe same client being added twice
|
|
28
|
+
// In such case we should see exactly same payload (IClient), and should not raise event twice!
|
|
29
|
+
if (this.members.has(clientId)) {
|
|
30
|
+
const client = this.members.get(clientId);
|
|
31
|
+
(0, core_utils_1.assert)(JSON.stringify(client) === JSON.stringify(details), 0x4b2 /* new client has different payload from existing one */);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.members.set(clientId, details);
|
|
35
|
+
this.emit("addMember", clientId, details);
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
38
|
/**
|
|
28
39
|
* Removes a client from the audience. Only emits an event if a client is actually removed
|
|
@@ -51,15 +62,6 @@ class Audience extends events_1.EventEmitter {
|
|
|
51
62
|
getMember(clientId) {
|
|
52
63
|
return this.members.get(clientId);
|
|
53
64
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Clears the audience
|
|
56
|
-
*/
|
|
57
|
-
clear() {
|
|
58
|
-
const clientIds = this.members.keys();
|
|
59
|
-
for (const clientId of clientIds) {
|
|
60
|
-
this.removeMember(clientId);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
65
|
}
|
|
64
66
|
exports.Audience = Audience;
|
|
65
|
-
//# sourceMappingURL=audience.
|
|
67
|
+
//# sourceMappingURL=audience.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audience.cjs","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,mCAAsC;AACtC,2DAAoD;AAIpD;;GAEG;AACH,MAAa,QAAS,SAAQ,qBAAY;IAGzC;QACC,KAAK,EAAE,CAAC;QAHQ,YAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QAIrD,kHAAkH;QAClH,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAMM,EAAE,CAAC,KAAa,EAAE,QAAkC;QAC1D,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAClC,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,mBAAM,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;;OAEG;IACI,UAAU;QAChB,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,QAAgB;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;CACD;AA/DD,4BA+DC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { EventEmitter } from \"events\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { IAudienceOwner } from \"@fluidframework/container-definitions\";\nimport { IClient } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Audience represents all clients connected to the op stream.\n */\nexport class Audience extends EventEmitter implements IAudienceOwner {\n\tprivate readonly members = new Map<string, IClient>();\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 on(\n\t\tevent: \"addMember\" | \"removeMember\",\n\t\tlistener: (clientId: string, client: IClient) => void,\n\t): this;\n\tpublic on(event: string, listener: (...args: any[]) => void): this {\n\t\treturn super.on(event, listener);\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\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\tpublic getMember(clientId: string): IClient | undefined {\n\t\treturn this.members.get(clientId);\n\t}\n}\n"]}
|
package/dist/audience.d.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
/*!
|
|
2
3
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
4
|
* Licensed under the MIT License.
|
|
4
5
|
*/
|
|
5
6
|
import { EventEmitter } from "events";
|
|
6
|
-
import {
|
|
7
|
+
import { IAudienceOwner } from "@fluidframework/container-definitions";
|
|
7
8
|
import { IClient } from "@fluidframework/protocol-definitions";
|
|
8
9
|
/**
|
|
9
10
|
* Audience represents all clients connected to the op stream.
|
|
10
11
|
*/
|
|
11
|
-
export declare class Audience extends EventEmitter implements
|
|
12
|
+
export declare class Audience extends EventEmitter implements IAudienceOwner {
|
|
12
13
|
private readonly members;
|
|
14
|
+
constructor();
|
|
13
15
|
on(event: "addMember" | "removeMember", listener: (clientId: string, client: IClient) => void): this;
|
|
14
16
|
/**
|
|
15
17
|
* Adds a new client to the audience
|
|
@@ -28,9 +30,5 @@ export declare class Audience extends EventEmitter implements IAudience {
|
|
|
28
30
|
* Retrieves a specific member of the audience
|
|
29
31
|
*/
|
|
30
32
|
getMember(clientId: string): IClient | undefined;
|
|
31
|
-
/**
|
|
32
|
-
* Clears the audience
|
|
33
|
-
*/
|
|
34
|
-
clear(): void;
|
|
35
33
|
}
|
|
36
34
|
//# sourceMappingURL=audience.d.ts.map
|
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;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAE/D;;GAEG;AACH,qBAAa,QAAS,SAAQ,YAAa,YAAW,cAAc;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;;IAQ/C,EAAE,CACR,KAAK,EAAE,WAAW,GAAG,cAAc,EACnC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,GACnD,IAAI;IAKP;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAenD;;;OAGG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAW9C;;OAEG;IACI,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAIzC;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;CAGvD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.CatchUpMonitor = void 0;
|
|
8
|
+
const core_utils_1 = require("@fluidframework/core-utils");
|
|
9
|
+
/**
|
|
10
|
+
* Monitors a Container's DeltaManager, notifying listeners when all ops have been processed
|
|
11
|
+
* that were known at the time the monitor was created.
|
|
12
|
+
*/
|
|
13
|
+
class CatchUpMonitor {
|
|
14
|
+
/**
|
|
15
|
+
* Create the CatchUpMonitor, setting the target sequence number to wait for based on DeltaManager's current state.
|
|
16
|
+
*/
|
|
17
|
+
constructor(deltaManager, listener) {
|
|
18
|
+
this.deltaManager = deltaManager;
|
|
19
|
+
this.listener = listener;
|
|
20
|
+
this.caughtUp = false;
|
|
21
|
+
this.opHandler = (message) => {
|
|
22
|
+
if (!this.caughtUp && message.sequenceNumber >= this.targetSeqNumber) {
|
|
23
|
+
this.caughtUp = true;
|
|
24
|
+
this.listener();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
this.disposed = false;
|
|
28
|
+
this.targetSeqNumber = this.deltaManager.lastKnownSeqNumber;
|
|
29
|
+
(0, core_utils_1.assert)(this.targetSeqNumber >= this.deltaManager.lastSequenceNumber, 0x37c /* Cannot wait for seqNumber below last processed sequence number */);
|
|
30
|
+
this.deltaManager.on("op", this.opHandler);
|
|
31
|
+
// Simulate the last processed op to set caughtUp in case we already are
|
|
32
|
+
this.opHandler({ sequenceNumber: this.deltaManager.lastSequenceNumber });
|
|
33
|
+
}
|
|
34
|
+
dispose() {
|
|
35
|
+
if (this.disposed) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.disposed = true;
|
|
39
|
+
this.deltaManager.off("op", this.opHandler);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.CatchUpMonitor = CatchUpMonitor;
|
|
43
|
+
//# sourceMappingURL=catchUpMonitor.cjs.map
|