@fluidframework/runtime-definitions 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.6.4.0.191258
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 +1 -0
- package/CHANGELOG.md +139 -0
- package/README.md +4 -3
- package/dist/attribution.d.ts +2 -2
- package/dist/attribution.js.map +1 -1
- package/dist/dataStoreContext.d.ts +47 -8
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/id-compressor/idCompressor.d.ts +32 -50
- package/dist/id-compressor/idCompressor.d.ts.map +1 -1
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/identifiers.d.ts +10 -51
- package/dist/id-compressor/identifiers.d.ts.map +1 -1
- package/dist/id-compressor/identifiers.js.map +1 -1
- package/dist/id-compressor/index.d.ts +2 -2
- package/dist/id-compressor/index.d.ts.map +1 -1
- package/dist/id-compressor/index.js +3 -0
- package/dist/id-compressor/index.js.map +1 -1
- package/dist/id-compressor/persisted-types/0.0.1.d.ts +18 -136
- package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
- package/dist/id-compressor/persisted-types/0.0.1.js +6 -0
- package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
- package/dist/id-compressor/persisted-types/index.d.ts +1 -1
- package/dist/id-compressor/persisted-types/index.d.ts.map +1 -1
- package/dist/id-compressor/persisted-types/index.js +3 -0
- package/dist/id-compressor/persisted-types/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/summary.d.ts +3 -2
- package/dist/summary.d.ts.map +1 -1
- package/dist/summary.js.map +1 -1
- package/package.json +12 -14
- package/src/aliasing.md +42 -0
- package/src/attribution.ts +2 -2
- package/src/dataStoreContext.ts +50 -10
- package/src/id-compressor/idCompressor.ts +32 -59
- package/src/id-compressor/identifiers.ts +10 -58
- package/src/id-compressor/index.ts +2 -19
- package/src/id-compressor/persisted-types/0.0.1.ts +18 -159
- package/src/id-compressor/persisted-types/index.ts +1 -8
- package/src/index.ts +1 -13
- package/src/summary.ts +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/runtime-definitions",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.6.4.0.191258",
|
|
4
4
|
"description": "Fluid Runtime definitions",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -14,23 +14,21 @@
|
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"types": "dist/index.d.ts",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@fluidframework/
|
|
18
|
-
"@fluidframework/
|
|
19
|
-
"@fluidframework/
|
|
20
|
-
"@fluidframework/core-interfaces": "2.0.0-dev.5.2.0.169897",
|
|
21
|
-
"@fluidframework/driver-definitions": "2.0.0-dev.5.2.0.169897",
|
|
17
|
+
"@fluidframework/container-definitions": "2.0.0-dev.6.4.0.191258",
|
|
18
|
+
"@fluidframework/core-interfaces": "2.0.0-dev.6.4.0.191258",
|
|
19
|
+
"@fluidframework/driver-definitions": "2.0.0-dev.6.4.0.191258",
|
|
22
20
|
"@fluidframework/protocol-definitions": "^1.1.0"
|
|
23
21
|
},
|
|
24
22
|
"devDependencies": {
|
|
25
|
-
"@fluid-tools/build-cli": "^0.
|
|
26
|
-
"@fluidframework/build-common": "^
|
|
27
|
-
"@fluidframework/build-tools": "^0.
|
|
28
|
-
"@fluidframework/eslint-config-fluid": "^2.
|
|
29
|
-
"@fluidframework/runtime-definitions-previous": "npm:@fluidframework/runtime-definitions@2.0.0-internal.
|
|
23
|
+
"@fluid-tools/build-cli": "^0.22.0",
|
|
24
|
+
"@fluidframework/build-common": "^2.0.0",
|
|
25
|
+
"@fluidframework/build-tools": "^0.22.0",
|
|
26
|
+
"@fluidframework/eslint-config-fluid": "^2.1.0",
|
|
27
|
+
"@fluidframework/runtime-definitions-previous": "npm:@fluidframework/runtime-definitions@2.0.0-internal.6.3.0",
|
|
30
28
|
"@microsoft/api-extractor": "^7.34.4",
|
|
31
|
-
"concurrently": "^7.6.0",
|
|
32
29
|
"copyfiles": "^2.4.1",
|
|
33
30
|
"eslint": "~8.6.0",
|
|
31
|
+
"eslint-plugin-deprecation": "~1.5.0",
|
|
34
32
|
"prettier": "~2.6.2",
|
|
35
33
|
"rimraf": "^4.4.0",
|
|
36
34
|
"typescript": "~4.5.5"
|
|
@@ -44,7 +42,7 @@
|
|
|
44
42
|
"build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
|
|
45
43
|
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
46
44
|
"ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
|
|
47
|
-
"clean": "rimraf dist *.tsbuildinfo *.build.log",
|
|
45
|
+
"clean": "rimraf --glob 'dist' '*.tsbuildinfo' '*.build.log' '_api-extractor-temp'",
|
|
48
46
|
"eslint": "eslint --format stylish src",
|
|
49
47
|
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
50
48
|
"format": "npm run prettier:fix",
|
|
@@ -54,6 +52,6 @@
|
|
|
54
52
|
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
55
53
|
"tsc": "tsc",
|
|
56
54
|
"typetests:gen": "fluid-type-test-generator",
|
|
57
|
-
"typetests:prepare": "flub
|
|
55
|
+
"typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
|
|
58
56
|
}
|
|
59
57
|
}
|
package/src/aliasing.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Aliasing and root datastores
|
|
2
|
+
|
|
3
|
+
## What is a root datastore? What is an aliased datastore?
|
|
4
|
+
|
|
5
|
+
A root datastore is a datastore which is addressable by a custom identifier (client supplied) and is a direct child of the container runtime. A root datastore will never be garbage collected and it is a singleton with regards to the runtime it belongs to. The concept of a root datastore is considered legacy, mainly due to the previous (deprecated and removed) APIs which referred to such datastores as root. 'Aliased datastore' is the preferred current term to refer to such datastores.
|
|
6
|
+
|
|
7
|
+
## When to alias datastores?
|
|
8
|
+
|
|
9
|
+
Alias needs to happen for datastores which:
|
|
10
|
+
|
|
11
|
+
- must be referenced by a custom id
|
|
12
|
+
- must never be garbage collected (as they are bound to a custom id which may be stored by the client, they must always be available to be referenced)
|
|
13
|
+
- must be singletons in the container
|
|
14
|
+
|
|
15
|
+
Creating root datastores was vulnerable to name conflicts, as two clients attempting to create the same root datastore with the same id risks corrupting the document. Aliasing changed the way to achieve the same goal, by enabling an asynchronous 'aliasing' operation on any newly created datastore. So in order to create such a datastore, the client needs to create an anonymous datastore (which will receive a newly generated UUID) and then explicitly attempt to bind it to a custom id (the alias) within a different operation which is decoupled from its creation.
|
|
16
|
+
|
|
17
|
+
## Aliasing API
|
|
18
|
+
|
|
19
|
+
The process of aliasing a datastore is split in two parts:
|
|
20
|
+
|
|
21
|
+
- Creating a regular datastore using the `IContainerRuntimeBase.createDataStore(pkg: string | string[]): Promise<IDataStore>` function
|
|
22
|
+
- Aliasing the resulting datastore by using the `IDataStore.trySetAlias(alias: string): Promise<AliasResult>` function and specifying a string value to serve as the alias to which the datastore needs to be bound. If successful, `"Success"` will be returned, and a call to `getAliasedDataStoreEntryPoint` with the alias as parameter will return the same datastore's entry point.
|
|
23
|
+
|
|
24
|
+
The alias API can fail in the following situations, per the `AliasResult` type (see `@fluidframework/runtime-definitions`) type:
|
|
25
|
+
|
|
26
|
+
- `"Conflict"` - the alias has already been taken. In this case, the client can call `getAliasedDataStoreEntryPoint` to get the entry point of the datastore already aliased for that value. The current datastore can be left alone unreferenced so it can eventually be garbage collected.
|
|
27
|
+
- `"AlreadyAliased"` - the datastore has already been aliased to a different id.
|
|
28
|
+
|
|
29
|
+
The alias API is idempotent. Repeatedly calling the trySetAlias function on the same datastore will return Success when the datastore has already been aliased to the same value.
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
const dataStore = await dataObject.context.containerRuntime.createDataStore("packageName");
|
|
35
|
+
// One client will receive "Success", the other client will receive "Conflict".
|
|
36
|
+
const aliasResult = await dataStore.trySetAlias("alias");
|
|
37
|
+
// Both clients will get the actual aliased datastore. However, the client with the "Conflict" result must fetch the datastore by name
|
|
38
|
+
const finalDataStore =
|
|
39
|
+
aliasResult === "Success"
|
|
40
|
+
? dataStore
|
|
41
|
+
: await dataObject.context.containerRuntime.getAliasedDataStoreEntryPoint("alias");
|
|
42
|
+
```
|
package/src/attribution.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface OpAttributionKey {
|
|
|
29
29
|
/**
|
|
30
30
|
* AttributionKey associated with content that was inserted while the container was in a detached state.
|
|
31
31
|
*
|
|
32
|
-
* @remarks
|
|
32
|
+
* @remarks Retrieving an {@link AttributionInfo} from content associated with detached attribution keys
|
|
33
33
|
* is currently unsupported, as applications can effectively modify content anonymously while detached.
|
|
34
34
|
* The runtime has no mechanism for reliably obtaining the user. It would be reasonable to start supporting
|
|
35
35
|
* this functionality if the host provided additional context to their attributor or attach calls.
|
|
@@ -42,7 +42,7 @@ export interface DetachedAttributionKey {
|
|
|
42
42
|
/**
|
|
43
43
|
* Arbitrary discriminator associated with content inserted while detached.
|
|
44
44
|
*
|
|
45
|
-
* @remarks
|
|
45
|
+
* @remarks For now, the runtime assumes all content created while detached is associated
|
|
46
46
|
* with the same user/timestamp.
|
|
47
47
|
* We could weaken this assumption in the future with further API support and
|
|
48
48
|
* allow arbitrary strings or numbers as part of this key.
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -4,12 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
ITelemetryBaseLogger,
|
|
8
|
-
IDisposable,
|
|
9
7
|
IEvent,
|
|
10
8
|
IEventProvider,
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
ITelemetryBaseLogger,
|
|
10
|
+
IDisposable,
|
|
13
11
|
IFluidRouter,
|
|
14
12
|
IProvideFluidHandleContext,
|
|
15
13
|
IFluidHandle,
|
|
@@ -118,8 +116,8 @@ export interface IContainerRuntimeBaseEvents extends IEvent {
|
|
|
118
116
|
* Encapsulates the return codes of the aliasing API.
|
|
119
117
|
*
|
|
120
118
|
* 'Success' - the datastore has been successfully aliased. It can now be used.
|
|
121
|
-
* 'Conflict' - there is already a datastore bound to the provided alias. To acquire
|
|
122
|
-
*
|
|
119
|
+
* 'Conflict' - there is already a datastore bound to the provided alias. To acquire it's entry point, use
|
|
120
|
+
* the `IContainerRuntime.getAliasedDataStoreEntryPoint` function. The current datastore should be discarded
|
|
123
121
|
* and will be garbage collected. The current datastore cannot be aliased to a different value.
|
|
124
122
|
* 'AlreadyAliased' - the datastore has already been previously bound to another alias name.
|
|
125
123
|
*/
|
|
@@ -131,13 +129,14 @@ export type AliasResult = "Success" | "Conflict" | "AlreadyAliased";
|
|
|
131
129
|
* - Fluid router for the data store
|
|
132
130
|
* - Can be assigned an alias
|
|
133
131
|
*/
|
|
134
|
-
export interface IDataStore
|
|
132
|
+
export interface IDataStore {
|
|
135
133
|
/**
|
|
136
134
|
* Attempt to assign an alias to the datastore.
|
|
137
135
|
* If the operation succeeds, the datastore can be referenced
|
|
138
136
|
* by the supplied alias and will not be garbage collected.
|
|
139
137
|
*
|
|
140
138
|
* @param alias - Given alias for this datastore.
|
|
139
|
+
* @returns A promise with the {@link AliasResult}
|
|
141
140
|
*/
|
|
142
141
|
trySetAlias(alias: string): Promise<AliasResult>;
|
|
143
142
|
|
|
@@ -151,6 +150,37 @@ export interface IDataStore extends IFluidRouter {
|
|
|
151
150
|
* the data store's entryPoint.
|
|
152
151
|
*/
|
|
153
152
|
readonly entryPoint?: IFluidHandle<FluidObject>;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* IMPORTANT: This overload is provided for back-compat where IDataStore.request(\{ url: "/" \}) is already implemented and used.
|
|
156
|
+
* The functionality it can provide (if the DataStore implementation is built for it) is redundant with @see {@link IDataStore.entryPoint}.
|
|
157
|
+
* Once that API is mandatory on IDataStore, this overload will be deprecated.
|
|
158
|
+
*
|
|
159
|
+
* Refer to Removing-IFluidRouter.md for details on migrating from the request pattern to using entryPoint.
|
|
160
|
+
*
|
|
161
|
+
* @param request - Only requesting \{ url: "/" \} is supported, requesting arbitrary URLs is deprecated.
|
|
162
|
+
*/
|
|
163
|
+
request(request: { url: "/"; headers?: undefined }): Promise<IResponse>;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Issue a request against the DataStore for a resource within it.
|
|
167
|
+
* @param request - The request to be issued against the DataStore
|
|
168
|
+
*
|
|
169
|
+
* @deprecated - Requesting an arbitrary URL with headers will not be supported in a future major release.
|
|
170
|
+
* Instead, access the objects within the DataStore using entryPoint, and then navigate from there using
|
|
171
|
+
* app-specific logic (e.g. retrieving a handle from a DDS, or the entryPoint object could implement a request paradigm itself)
|
|
172
|
+
*
|
|
173
|
+
* NOTE: IDataStore.request(\{url: "/"\}) is not yet deprecated. If and only if the DataStore implementation supports it,
|
|
174
|
+
* that overload may be used as a proxy for getting the entryPoint until {@link IDataStore.entryPoint} is mandatory.
|
|
175
|
+
*
|
|
176
|
+
* Refer to Removing-IFluidRouter.md for details on migrating from the request pattern to using entryPoint.
|
|
177
|
+
*/
|
|
178
|
+
request(request: IRequest): Promise<IResponse>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
182
|
+
*/
|
|
183
|
+
readonly IFluidRouter: IFluidRouter;
|
|
154
184
|
}
|
|
155
185
|
|
|
156
186
|
/**
|
|
@@ -214,7 +244,7 @@ export interface IContainerRuntimeBase
|
|
|
214
244
|
*/
|
|
215
245
|
getAbsoluteUrl(relativeUrl: string): Promise<string | undefined>;
|
|
216
246
|
|
|
217
|
-
uploadBlob(blob: ArrayBufferLike): Promise<IFluidHandle<ArrayBufferLike>>;
|
|
247
|
+
uploadBlob(blob: ArrayBufferLike, signal?: AbortSignal): Promise<IFluidHandle<ArrayBufferLike>>;
|
|
218
248
|
|
|
219
249
|
/**
|
|
220
250
|
* Returns the current quorum.
|
|
@@ -233,7 +263,7 @@ export interface IContainerRuntimeBase
|
|
|
233
263
|
* Functionality include attach, snapshot, op/signal processing, request routes, expose an entryPoint,
|
|
234
264
|
* and connection state notifications
|
|
235
265
|
*/
|
|
236
|
-
export interface IFluidDataStoreChannel extends
|
|
266
|
+
export interface IFluidDataStoreChannel extends IDisposable {
|
|
237
267
|
readonly id: string;
|
|
238
268
|
|
|
239
269
|
/**
|
|
@@ -333,6 +363,16 @@ export interface IFluidDataStoreChannel extends IFluidRouter, IDisposable {
|
|
|
333
363
|
* the component's entryPoint.
|
|
334
364
|
*/
|
|
335
365
|
readonly entryPoint?: IFluidHandle<FluidObject>;
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
369
|
+
*/
|
|
370
|
+
request(request: IRequest): Promise<IResponse>;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
374
|
+
*/
|
|
375
|
+
readonly IFluidRouter: IFluidRouter;
|
|
336
376
|
}
|
|
337
377
|
|
|
338
378
|
export type CreateChildSummarizerNodeFn = (
|
|
@@ -472,7 +512,7 @@ export interface IFluidDataStoreContext
|
|
|
472
512
|
createParam: CreateChildSummarizerNodeParam,
|
|
473
513
|
): CreateChildSummarizerNodeFn;
|
|
474
514
|
|
|
475
|
-
uploadBlob(blob: ArrayBufferLike): Promise<IFluidHandle<ArrayBufferLike>>;
|
|
515
|
+
uploadBlob(blob: ArrayBufferLike, signal?: AbortSignal): Promise<IFluidHandle<ArrayBufferLike>>;
|
|
476
516
|
|
|
477
517
|
/**
|
|
478
518
|
* @deprecated - The functionality to get base GC details has been moved to summarizer node.
|
|
@@ -3,13 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
SessionSpaceCompressedId,
|
|
8
|
-
OpSpaceCompressedId,
|
|
9
|
-
SessionId,
|
|
10
|
-
FinalCompressedId,
|
|
11
|
-
StableId,
|
|
12
|
-
} from "./identifiers";
|
|
6
|
+
import { SessionSpaceCompressedId, OpSpaceCompressedId, SessionId, StableId } from "./identifiers";
|
|
13
7
|
import {
|
|
14
8
|
IdCreationRange,
|
|
15
9
|
SerializedIdCompressorWithNoSession,
|
|
@@ -17,7 +11,13 @@ import {
|
|
|
17
11
|
} from "./persisted-types";
|
|
18
12
|
|
|
19
13
|
export interface IIdCompressorCore {
|
|
20
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Returns a range of IDs created by this session in a format for sending to the server for finalizing.
|
|
16
|
+
* The range will include all IDs generated via calls to `generateCompressedId` since the last time this method was called.
|
|
17
|
+
* @returns the range of IDs, which may be empty. This range must be sent to the server for ordering before
|
|
18
|
+
* it is finalized. Ranges must be sent to the server in the order that they are taken via calls to this method.
|
|
19
|
+
*/
|
|
20
|
+
takeNextCreationRange(): IdCreationRange;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Finalizes the supplied range of IDs (which may be from either a remote or local session).
|
|
@@ -25,14 +25,6 @@ export interface IIdCompressorCore {
|
|
|
25
25
|
*/
|
|
26
26
|
finalizeCreationRange(range: IdCreationRange): void;
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
* Returns a range of local IDs created by this session in a format for sending to the server for finalizing.
|
|
30
|
-
* The range will include all local IDs generated via calls to `generateCompressedId` since the last time this method was called.
|
|
31
|
-
* @returns the range of session-local IDs, which may be empty. This range must be sent to the server for ordering before
|
|
32
|
-
* it is finalized. Ranges must be sent to the server in the order that they are taken via calls to this method.
|
|
33
|
-
*/
|
|
34
|
-
takeNextCreationRange(): IdCreationRange;
|
|
35
|
-
|
|
36
28
|
/**
|
|
37
29
|
* Returns a persistable form of the current state of this `IdCompressor` which can be rehydrated via `IdCompressor.deserialize()`.
|
|
38
30
|
* This includes finalized state as well as un-finalized state and is therefore suitable for use in offline scenarios.
|
|
@@ -58,38 +50,35 @@ export interface IIdCompressorCore {
|
|
|
58
50
|
*
|
|
59
51
|
* For each stable ID created, two numeric IDs are provided by the compressor:
|
|
60
52
|
*
|
|
61
|
-
* 1. A local ID, which is stable for the lifetime of the session (which could be longer than that of the compressor object, as it may
|
|
62
|
-
* be serialized for offline usage). Available as soon as the stable ID is allocated.
|
|
63
|
-
*
|
|
53
|
+
* 1. A session-local ID, which is stable for the lifetime of the session (which could be longer than that of the compressor object, as it may
|
|
54
|
+
* be serialized for offline usage). Available as soon as the stable ID is allocated. These IDs are session-unique and are thus only
|
|
55
|
+
* safely usable within the scope of the compressor that created it.
|
|
64
56
|
*
|
|
65
57
|
* 2. A final ID, which is stable across serialization and deserialization of an IdCompressor. Available as soon as the range containing
|
|
66
|
-
* the corresponding local ID is totally ordered (via consensus) with respect to other sessions' allocations.
|
|
58
|
+
* the corresponding session-local ID is totally ordered (via consensus) with respect to other sessions' allocations.
|
|
67
59
|
* Final IDs are known to and publicly usable by any compressor that has received them.
|
|
68
60
|
*
|
|
69
61
|
* Compressors will allocate UUIDs in non-random ways to reduce entropy allowing for optimized storage of the data needed
|
|
70
62
|
* to map the UUIDs to the numbers.
|
|
71
63
|
*
|
|
72
|
-
* A client may optionally supply an "override" for any generated ID, associating an arbitrary string with the local/final ID rather than
|
|
73
|
-
* the UUID that would otherwise be created.
|
|
74
|
-
*
|
|
75
64
|
* The following invariants are upheld by IdCompressor:
|
|
76
65
|
*
|
|
77
|
-
* 1.
|
|
66
|
+
* 1. Session-local IDs will always decompress to the same UUIDs for the lifetime of the session.
|
|
78
67
|
*
|
|
79
|
-
* 2. Final IDs will always decompress to the same UUIDs
|
|
68
|
+
* 2. Final IDs will always decompress to the same UUIDs.
|
|
80
69
|
*
|
|
81
|
-
* 3. After a server-processed range of local IDs (from any session) is received by a compressor, any of those local IDs may be
|
|
82
|
-
* translated by the compressor into the corresponding final ID. For any given local ID, this translation will always yield the
|
|
70
|
+
* 3. After a server-processed range of session-local IDs (from any session) is received by a compressor, any of those session-local IDs may be
|
|
71
|
+
* translated by the compressor into the corresponding final ID. For any given session-local ID, this translation will always yield the
|
|
83
72
|
* same final ID.
|
|
84
73
|
*
|
|
85
|
-
* 4. A UUID
|
|
74
|
+
* 4. A UUID will always compress into the same session-local ID for the lifetime of the session.
|
|
86
75
|
*
|
|
87
|
-
*
|
|
76
|
+
* Session-local IDs are sent across the wire in efficiently-represented ranges. These ranges are created by querying the compressor, and *must*
|
|
88
77
|
* be ordered (i.e. sent to the server) in the order they are created in order to preserve the above invariants.
|
|
89
78
|
*
|
|
90
79
|
* Session-local IDs can be used immediately after creation, but will eventually (after being sequenced) have a corresponding final ID. This
|
|
91
|
-
* could make reasoning about equality of those two forms
|
|
92
|
-
* local ID but is later queried using the final ID (which is semantically equal, as it decompresses to the same UUID/string) it will
|
|
80
|
+
* could make reasoning about equality of those two forms difficult. For example, if a cache is keyed off of a
|
|
81
|
+
* session-local ID but is later queried using the final ID (which is semantically equal, as it decompresses to the same UUID/string) it will
|
|
93
82
|
* produce a cache miss. In order to make using collections of both remotely created and locally created IDs easy, regardless of whether the
|
|
94
83
|
* session-local IDs have been finalized, the compressor defines two "spaces" of IDs:
|
|
95
84
|
*
|
|
@@ -102,7 +91,7 @@ export interface IIdCompressorCore {
|
|
|
102
91
|
* 2. Op space: in this space, all IDs are normalized to their "most final form". This means that all IDs except session-local IDs that
|
|
103
92
|
* have not yet been finalized will be in final ID form. This space is useful for serialization in ops (e.g. references), as other clients
|
|
104
93
|
* that receive them need not do any work to normalize them to *their* session-space in the common case. Note that IDs in op space may move
|
|
105
|
-
* out of Op space over time, namely, when a local ID in this space becomes finalized, and thereafter has a "more final form".
|
|
94
|
+
* out of Op space over time, namely, when a session-local ID in this space becomes finalized, and thereafter has a "more final form".
|
|
106
95
|
* Consequentially, it may be useful to restrict parameters of a persisted type to this space (to optimize perf), but it is potentially
|
|
107
96
|
* incorrect to use this type for a runtime variable. This is an asymmetry that does not affect session space, as local IDs are always as
|
|
108
97
|
* "local as possible".
|
|
@@ -117,11 +106,9 @@ export interface IIdCompressor {
|
|
|
117
106
|
/**
|
|
118
107
|
* Generates a new compressed ID or returns an existing one.
|
|
119
108
|
* This should ONLY be called to generate IDs for local operations.
|
|
120
|
-
* @
|
|
121
|
-
* Performance note: assigning override strings incurs a performance overhead.
|
|
122
|
-
* @returns an existing ID if one already exists for `override`, and a new local ID otherwise. The returned ID is in session space.
|
|
109
|
+
* @returns A new local ID in session space.
|
|
123
110
|
*/
|
|
124
|
-
generateCompressedId(
|
|
111
|
+
generateCompressedId(): SessionSpaceCompressedId;
|
|
125
112
|
/**
|
|
126
113
|
* Normalizes a session space ID into op space.
|
|
127
114
|
* @param id - the local ID to normalize.
|
|
@@ -143,37 +130,23 @@ export interface IIdCompressor {
|
|
|
143
130
|
): SessionSpaceCompressedId;
|
|
144
131
|
|
|
145
132
|
/**
|
|
146
|
-
*
|
|
147
|
-
* @param id - the final ID to normalize.
|
|
148
|
-
* @returns the session-space ID corresponding to `id`.
|
|
149
|
-
*/
|
|
150
|
-
normalizeToSessionSpace(id: FinalCompressedId): SessionSpaceCompressedId;
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Decompresses a previously compressed ID into a UUID or override string.
|
|
154
|
-
* @param id - the compressed ID to be decompressed.
|
|
155
|
-
* @returns the UUID or override string associated with the compressed ID. Fails if the ID was not generated by this compressor.
|
|
156
|
-
*/
|
|
157
|
-
decompress(id: SessionSpaceCompressedId | FinalCompressedId): StableId | string;
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Attempts to decompress a previously compressed ID into a UUID or override string.
|
|
133
|
+
* Decompresses a previously compressed ID into a UUID.
|
|
161
134
|
* @param id - the compressed ID to be decompressed.
|
|
162
|
-
* @returns the UUID
|
|
135
|
+
* @returns the UUID associated with the compressed ID. Fails if the ID was not generated by this compressor.
|
|
163
136
|
*/
|
|
164
|
-
|
|
137
|
+
decompress(id: SessionSpaceCompressedId): StableId;
|
|
165
138
|
|
|
166
139
|
/**
|
|
167
|
-
* Recompresses a
|
|
168
|
-
* @param uncompressed - the UUID
|
|
140
|
+
* Recompresses a UUID.
|
|
141
|
+
* @param uncompressed - the UUID to recompress.
|
|
169
142
|
* @returns the `CompressedId` associated with `uncompressed`. Fails if it has not been previously compressed by this compressor.
|
|
170
143
|
*/
|
|
171
|
-
recompress(uncompressed:
|
|
144
|
+
recompress(uncompressed: StableId): SessionSpaceCompressedId;
|
|
172
145
|
|
|
173
146
|
/**
|
|
174
|
-
* Attempts to recompresses a
|
|
175
|
-
* @param uncompressed - the UUID
|
|
147
|
+
* Attempts to recompresses a UUID.
|
|
148
|
+
* @param uncompressed - the UUID to recompress,
|
|
176
149
|
* @returns the `CompressedId` associated with `uncompressed` or undefined if it has not been previously compressed by this compressor.
|
|
177
150
|
*/
|
|
178
|
-
tryRecompress(uncompressed:
|
|
151
|
+
tryRecompress(uncompressed: StableId): SessionSpaceCompressedId | undefined;
|
|
179
152
|
}
|
|
@@ -3,79 +3,31 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* An identifier (UUID) that has been shortened by a distributed compression algorithm.
|
|
8
|
-
* @alpha
|
|
9
|
-
*/
|
|
10
|
-
export type CompressedId = FinalCompressedId | LocalCompressedId;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A brand for identity types that are unique within a particular session (SharedTree instance).
|
|
14
|
-
*/
|
|
15
|
-
export interface SessionUnique {
|
|
16
|
-
readonly SessionUnique: "cea55054-6b82-4cbf-ad19-1fa645ea3b3e";
|
|
17
|
-
}
|
|
18
|
-
|
|
19
6
|
/**
|
|
20
7
|
* A compressed ID that has been normalized into "session space" (see `IdCompressor` for more).
|
|
21
|
-
* Consumer-facing APIs and data structures should use session-space IDs as their lifetime and equality is stable and tied to
|
|
22
|
-
* compressor that produced them.
|
|
23
|
-
* @alpha
|
|
8
|
+
* Consumer-facing APIs and data structures should use session-space IDs as their lifetime and equality is stable and tied to
|
|
9
|
+
* the scope of the session (i.e. compressor) that produced them.
|
|
24
10
|
*/
|
|
25
|
-
export type SessionSpaceCompressedId =
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* A compressed ID that has been normalized into "op space" (see `IdCompressor` for more).
|
|
29
|
-
* Serialized/persisted structures (e.g. ops) should use op-space IDs as a performance optimization, as they require no normalizing when
|
|
30
|
-
* received by a remote client due to the fact that op space for a given compressor is session space for all other compressors.
|
|
31
|
-
*/
|
|
32
|
-
export type OpSpaceCompressedId = CompressedId & {
|
|
33
|
-
readonly OpNormalized: "9209432d-a959-4df7-b2ad-767ead4dbcae";
|
|
11
|
+
export type SessionSpaceCompressedId = number & {
|
|
12
|
+
readonly SessionUnique: "cea55054-6b82-4cbf-ad19-1fa645ea3b3e";
|
|
34
13
|
};
|
|
35
14
|
|
|
36
15
|
/**
|
|
37
|
-
* A compressed ID that
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* @alpha
|
|
16
|
+
* A compressed ID that has been normalized into "op space".
|
|
17
|
+
* Serialized/persisted structures (e.g. ops) should use op-space IDs as a performance optimization, as they require less normalizing when
|
|
18
|
+
* received by a remote client due to the fact that op space for a given compressor is session space for all other compressors.
|
|
41
19
|
*/
|
|
42
|
-
export type
|
|
43
|
-
readonly FinalCompressedId: "5d83d1e2-98b7-4e4e-a889-54c855cfa73d";
|
|
44
|
-
|
|
45
|
-
// Same brand as OpNormalizedCompressedId, as final IDs are always finally normalized
|
|
20
|
+
export type OpSpaceCompressedId = number & {
|
|
46
21
|
readonly OpNormalized: "9209432d-a959-4df7-b2ad-767ead4dbcae";
|
|
47
22
|
};
|
|
48
23
|
|
|
49
24
|
/**
|
|
50
|
-
* A
|
|
51
|
-
* It should not be persisted outside of the history as it can only be decompressed in the context of the originating session.
|
|
52
|
-
* If external persistence is needed (e.g. by a client), a StableId should be used instead.
|
|
53
|
-
* @alpha
|
|
54
|
-
*/
|
|
55
|
-
export type LocalCompressedId = number & {
|
|
56
|
-
readonly LocalCompressedId: "6fccb42f-e2a4-4243-bd29-f13d12b9c6d1";
|
|
57
|
-
} & SessionUnique; // Same brand as CompressedId, as local IDs are always locally normalized
|
|
58
|
-
|
|
59
|
-
export interface NodeIdBrand {
|
|
60
|
-
readonly NodeId: "e53e7d6b-c8b9-431a-8805-4843fc639342";
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Type-safe identifiers for specific use cases.
|
|
65
|
-
*/
|
|
66
|
-
|
|
67
|
-
/**
|
|
25
|
+
* A version 4, variant 1 uuid (https://datatracker.ietf.org/doc/html/rfc4122).
|
|
68
26
|
* A 128-bit Universally Unique IDentifier. Represented here
|
|
69
27
|
* with a string of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
|
|
70
28
|
* where x is a lowercase hex digit.
|
|
71
|
-
* @public
|
|
72
|
-
*/
|
|
73
|
-
export type UuidString = string & { readonly UuidString: "9d40d0ae-90d9-44b1-9482-9f55d59d5465" };
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* A version 4, variant 2 uuid (https://datatracker.ietf.org/doc/html/rfc4122).
|
|
77
29
|
*/
|
|
78
|
-
export type StableId =
|
|
30
|
+
export type StableId = string & { readonly StableId: "53172b0d-a3d5-41ea-bd75-b43839c97f5a" };
|
|
79
31
|
|
|
80
32
|
/**
|
|
81
33
|
* A StableId which is suitable for use as a session identifier
|
|
@@ -5,30 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
export {
|
|
7
7
|
IdCreationRange,
|
|
8
|
-
SerializedCluster,
|
|
9
|
-
SerializedClusterOverrides,
|
|
10
8
|
SerializedIdCompressor,
|
|
11
9
|
SerializedIdCompressorWithNoSession,
|
|
12
10
|
SerializedIdCompressorWithOngoingSession,
|
|
13
|
-
SerializedLocalOverrides,
|
|
14
|
-
SerializedLocalState,
|
|
15
|
-
SerializedSessionData,
|
|
16
|
-
SerializedSessionIdNormalizer,
|
|
17
|
-
UnackedLocalId,
|
|
18
|
-
VersionedSerializedIdCompressor,
|
|
19
11
|
IdCreationRangeWithStashedState,
|
|
12
|
+
initialClusterCapacity,
|
|
20
13
|
} from "./persisted-types";
|
|
21
14
|
|
|
22
15
|
export { IIdCompressorCore, IIdCompressor } from "./idCompressor";
|
|
23
16
|
|
|
24
|
-
export {
|
|
25
|
-
SessionSpaceCompressedId,
|
|
26
|
-
OpSpaceCompressedId,
|
|
27
|
-
SessionId,
|
|
28
|
-
FinalCompressedId,
|
|
29
|
-
StableId,
|
|
30
|
-
UuidString,
|
|
31
|
-
CompressedId,
|
|
32
|
-
SessionUnique,
|
|
33
|
-
LocalCompressedId,
|
|
34
|
-
} from "./identifiers";
|
|
17
|
+
export { SessionSpaceCompressedId, OpSpaceCompressedId, SessionId, StableId } from "./identifiers";
|