@fluidframework/id-compressor 2.0.0-internal.8.0.1 → 2.0.0-rc.1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +0 -6
- package/api-extractor-esm.json +4 -0
- package/api-extractor-lint.json +1 -10
- package/api-extractor.json +1 -9
- package/api-report/id-compressor.api.md +7 -5
- package/dist/id-compressor-alpha.d.ts +32 -5
- package/dist/id-compressor-beta.d.ts +142 -9
- package/dist/id-compressor-public.d.ts +142 -9
- package/dist/id-compressor-untrimmed.d.ts +32 -5
- package/dist/idCompressor.d.ts +6 -0
- package/dist/idCompressor.d.ts.map +1 -1
- package/dist/idCompressor.js +58 -20
- package/dist/idCompressor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/sessions.js +3 -6
- package/dist/sessions.js.map +1 -1
- package/dist/types/idCompressor.d.ts +22 -1
- package/dist/types/idCompressor.d.ts.map +1 -1
- package/dist/types/idCompressor.js.map +1 -1
- package/dist/types/identifiers.d.ts +4 -4
- package/dist/types/identifiers.js.map +1 -1
- package/lib/{appendOnlySortedMap.d.ts → appendOnlySortedMap.d.mts} +1 -1
- package/lib/appendOnlySortedMap.d.mts.map +1 -0
- package/lib/{appendOnlySortedMap.js → appendOnlySortedMap.mjs} +1 -3
- package/lib/appendOnlySortedMap.mjs.map +1 -0
- package/lib/{finalSpace.d.ts → finalSpace.d.mts} +3 -3
- package/lib/finalSpace.d.mts.map +1 -0
- package/lib/{finalSpace.js → finalSpace.mjs} +2 -2
- package/lib/finalSpace.mjs.map +1 -0
- package/lib/{id-compressor-alpha.d.ts → id-compressor-alpha.d.mts} +32 -5
- package/lib/id-compressor-beta.d.mts +172 -0
- package/lib/id-compressor-public.d.mts +172 -0
- package/lib/{id-compressor-untrimmed.d.ts → id-compressor-untrimmed.d.mts} +32 -5
- package/lib/{idCompressor.d.ts → idCompressor.d.mts} +8 -2
- package/lib/idCompressor.d.mts.map +1 -0
- package/lib/{idCompressor.js → idCompressor.mjs} +65 -27
- package/lib/idCompressor.mjs.map +1 -0
- package/lib/{identifiers.d.ts → identifiers.d.mts} +2 -2
- package/lib/identifiers.d.mts.map +1 -0
- package/lib/{identifiers.js → identifiers.mjs} +1 -1
- package/lib/identifiers.mjs.map +1 -0
- package/lib/{index.d.ts → index.d.mts} +4 -7
- package/lib/index.d.mts.map +1 -0
- package/lib/{index.js → index.mjs} +3 -6
- package/lib/index.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/{persistanceUtilities.d.ts → persistanceUtilities.d.mts} +2 -2
- package/lib/persistanceUtilities.d.mts.map +1 -0
- package/lib/{persistanceUtilities.js → persistanceUtilities.mjs} +1 -1
- package/lib/persistanceUtilities.mjs.map +1 -0
- package/lib/{sessionSpaceNormalizer.d.ts → sessionSpaceNormalizer.d.mts} +3 -3
- package/lib/sessionSpaceNormalizer.d.mts.map +1 -0
- package/lib/{sessionSpaceNormalizer.js → sessionSpaceNormalizer.mjs} +3 -3
- package/lib/sessionSpaceNormalizer.mjs.map +1 -0
- package/lib/{sessions.d.ts → sessions.d.mts} +3 -3
- package/lib/sessions.d.mts.map +1 -0
- package/lib/{sessions.js → sessions.mjs} +3 -3
- package/lib/sessions.mjs.map +1 -0
- package/lib/types/{idCompressor.d.ts → idCompressor.d.mts} +25 -4
- package/lib/types/idCompressor.d.mts.map +1 -0
- package/lib/types/{identifiers.js → idCompressor.mjs} +1 -1
- package/lib/types/idCompressor.mjs.map +1 -0
- package/lib/types/{identifiers.d.ts → identifiers.d.mts} +5 -5
- package/lib/types/identifiers.d.mts.map +1 -0
- package/lib/types/{idCompressor.js → identifiers.mjs} +1 -1
- package/lib/types/identifiers.mjs.map +1 -0
- package/lib/types/{index.d.ts → index.d.mts} +4 -4
- package/lib/types/index.d.mts.map +1 -0
- package/lib/types/{persisted-types/0.0.1.js → index.mjs} +1 -1
- package/lib/types/index.mjs.map +1 -0
- package/lib/types/persisted-types/{0.0.1.d.ts → 0.0.1.d.mts} +2 -2
- package/lib/types/persisted-types/0.0.1.d.mts.map +1 -0
- package/lib/types/persisted-types/{index.js → 0.0.1.mjs} +1 -1
- package/lib/types/persisted-types/0.0.1.mjs.map +1 -0
- package/lib/types/persisted-types/{index.d.ts → index.d.mts} +2 -2
- package/lib/types/persisted-types/index.d.mts.map +1 -0
- package/lib/types/{index.js → persisted-types/index.mjs} +1 -1
- package/lib/types/persisted-types/index.mjs.map +1 -0
- package/lib/{utilities.d.ts → utilities.d.mts} +3 -3
- package/lib/utilities.d.mts.map +1 -0
- package/lib/{utilities.js → utilities.mjs} +1 -2
- package/lib/utilities.mjs.map +1 -0
- package/package.json +26 -20
- package/src/idCompressor.ts +76 -19
- package/src/packageVersion.ts +1 -1
- package/src/sessions.ts +1 -1
- package/src/types/idCompressor.ts +23 -1
- package/src/types/identifiers.ts +4 -4
- package/tsconfig.json +4 -2
- package/lib/appendOnlySortedMap.d.ts.map +0 -1
- package/lib/appendOnlySortedMap.js.map +0 -1
- package/lib/finalSpace.d.ts.map +0 -1
- package/lib/finalSpace.js.map +0 -1
- package/lib/id-compressor-beta.d.ts +0 -39
- package/lib/id-compressor-public.d.ts +0 -39
- package/lib/idCompressor.d.ts.map +0 -1
- package/lib/idCompressor.js.map +0 -1
- package/lib/identifiers.d.ts.map +0 -1
- package/lib/identifiers.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/packageVersion.d.ts.map +0 -1
- package/lib/packageVersion.js.map +0 -1
- package/lib/persistanceUtilities.d.ts.map +0 -1
- package/lib/persistanceUtilities.js.map +0 -1
- package/lib/sessionSpaceNormalizer.d.ts.map +0 -1
- package/lib/sessionSpaceNormalizer.js.map +0 -1
- package/lib/sessions.d.ts.map +0 -1
- package/lib/sessions.js.map +0 -1
- package/lib/types/idCompressor.d.ts.map +0 -1
- package/lib/types/idCompressor.js.map +0 -1
- package/lib/types/identifiers.d.ts.map +0 -1
- package/lib/types/identifiers.js.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/index.js.map +0 -1
- package/lib/types/persisted-types/0.0.1.d.ts.map +0 -1
- package/lib/types/persisted-types/0.0.1.js.map +0 -1
- package/lib/types/persisted-types/index.d.ts.map +0 -1
- package/lib/types/persisted-types/index.js.map +0 -1
- package/lib/utilities.d.ts.map +0 -1
- package/lib/utilities.js.map +0 -1
- package/tsconfig.esnext.json +0 -7
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
2
|
+
|
|
3
|
+
/* Excluded from this release type: assertIsStableId */
|
|
4
|
+
|
|
5
|
+
/* Excluded from this release type: createIdCompressor */
|
|
6
|
+
|
|
7
|
+
/* Excluded from this release type: createSessionId */
|
|
8
|
+
|
|
9
|
+
/* Excluded from this release type: deserializeIdCompressor */
|
|
10
|
+
|
|
11
|
+
/* Excluded from this release type: generateStableId */
|
|
12
|
+
|
|
13
|
+
/* Excluded from this release type: IdCompressor */
|
|
14
|
+
|
|
15
|
+
/* Excluded from this release type: IdCreationRange */
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A distributed UUID generator and compressor.
|
|
19
|
+
*
|
|
20
|
+
* Generates arbitrary non-colliding v4 UUIDs, called stable IDs, for multiple "sessions" (which can be distributed across the network),
|
|
21
|
+
* providing each session with the ability to map these UUIDs to `numbers`.
|
|
22
|
+
*
|
|
23
|
+
* A session is a unique identifier that denotes a single compressor. New IDs are created through a single compressor API
|
|
24
|
+
* which should then sent in ranges to the server for total ordering (and are subsequently relayed to other clients). When a new ID is
|
|
25
|
+
* created it is said to be created by the compressor's "local" session.
|
|
26
|
+
*
|
|
27
|
+
* For each stable ID created, two numeric IDs are provided by the compressor:
|
|
28
|
+
*
|
|
29
|
+
* 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
|
|
30
|
+
* be serialized for offline usage). Available as soon as the stable ID is allocated. These IDs are session-unique and are thus only
|
|
31
|
+
* safely usable within the scope of the compressor that created it.
|
|
32
|
+
*
|
|
33
|
+
* 2. A final ID, which is stable across serialization and deserialization of an IdCompressor. Available as soon as the range containing
|
|
34
|
+
* the corresponding session-local ID is totally ordered (via consensus) with respect to other sessions' allocations.
|
|
35
|
+
* Final IDs are known to and publicly usable by any compressor that has received them.
|
|
36
|
+
*
|
|
37
|
+
* Compressors will allocate UUIDs in non-random ways to reduce entropy allowing for optimized storage of the data needed
|
|
38
|
+
* to map the UUIDs to the numbers.
|
|
39
|
+
*
|
|
40
|
+
* The following invariants are upheld by IdCompressor:
|
|
41
|
+
*
|
|
42
|
+
* 1. Session-local IDs will always decompress to the same UUIDs for the lifetime of the session.
|
|
43
|
+
*
|
|
44
|
+
* 2. Final IDs will always decompress to the same UUIDs.
|
|
45
|
+
*
|
|
46
|
+
* 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
|
|
47
|
+
* translated by the compressor into the corresponding final ID. For any given session-local ID, this translation will always yield the
|
|
48
|
+
* same final ID.
|
|
49
|
+
*
|
|
50
|
+
* 4. A UUID will always compress into the same session-local ID for the lifetime of the session.
|
|
51
|
+
*
|
|
52
|
+
* Session-local IDs are sent across the wire in efficiently-represented ranges. These ranges are created by querying the compressor, and *must*
|
|
53
|
+
* be ordered (i.e. sent to the server) in the order they are created in order to preserve the above invariants.
|
|
54
|
+
*
|
|
55
|
+
* Session-local IDs can be used immediately after creation, but will eventually (after being sequenced) have a corresponding final ID. This
|
|
56
|
+
* could make reasoning about equality of those two forms difficult. For example, if a cache is keyed off of a
|
|
57
|
+
* 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
|
|
58
|
+
* produce a cache miss. In order to make using collections of both remotely created and locally created IDs easy, regardless of whether the
|
|
59
|
+
* session-local IDs have been finalized, the compressor defines two "spaces" of IDs:
|
|
60
|
+
*
|
|
61
|
+
* 1. Session space: in this space, all IDs are normalized to their "most local form". This means that all IDs created by the local session
|
|
62
|
+
* will be in local form, regardless of if they have been finalized. Remotely created IDs, which could only have been received after
|
|
63
|
+
* finalizing and will never have a local form for the compressor, will of course be final IDs. This space should be used with consumer APIs
|
|
64
|
+
* and data structures, as the lifetime of the IDs is guaranteed to be the same as the compressor object. Care must be taken to not use
|
|
65
|
+
* these IDs across compressor objects, as the local IDs are specific to the compressor that created them.
|
|
66
|
+
*
|
|
67
|
+
* 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
|
|
68
|
+
* 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
|
|
69
|
+
* 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
|
|
70
|
+
* out of Op space over time, namely, when a session-local ID in this space becomes finalized, and thereafter has a "more final form".
|
|
71
|
+
* Consequentially, it may be useful to restrict parameters of a persisted type to this space (to optimize perf), but it is potentially
|
|
72
|
+
* 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
|
|
73
|
+
* "local as possible".
|
|
74
|
+
*
|
|
75
|
+
* These two spaces naturally define a rule: consumers of compressed IDs should use session-space IDs, but serialized forms such as ops
|
|
76
|
+
* should use op-space IDs.
|
|
77
|
+
* @public
|
|
78
|
+
*/
|
|
79
|
+
export declare interface IIdCompressor {
|
|
80
|
+
localSessionId: SessionId;
|
|
81
|
+
/**
|
|
82
|
+
* Generates a new compressed ID or returns an existing one.
|
|
83
|
+
* This should ONLY be called to generate IDs for local operations.
|
|
84
|
+
* @returns A new local ID in session space.
|
|
85
|
+
*/
|
|
86
|
+
generateCompressedId(): SessionSpaceCompressedId;
|
|
87
|
+
/**
|
|
88
|
+
* Normalizes a session space ID into op space.
|
|
89
|
+
* @param id - the local ID to normalize.
|
|
90
|
+
* @returns the ID in op space.
|
|
91
|
+
*/
|
|
92
|
+
normalizeToOpSpace(id: SessionSpaceCompressedId): OpSpaceCompressedId;
|
|
93
|
+
/**
|
|
94
|
+
* Normalizes an ID into session space.
|
|
95
|
+
* @param id - the ID to normalize. If it is a local ID, it is assumed to have been created by the session corresponding
|
|
96
|
+
* to `sessionId`.
|
|
97
|
+
* @param originSessionId - the session from which `id` originated
|
|
98
|
+
* @returns the session-space ID corresponding to `id`, which might not have been a final ID if the client that created it had not yet
|
|
99
|
+
* finalized it. This can occur when a client references an ID during the window of time in which it is waiting to receive the ordered
|
|
100
|
+
* range that contained it from the server.
|
|
101
|
+
*/
|
|
102
|
+
normalizeToSessionSpace(id: OpSpaceCompressedId, originSessionId: SessionId): SessionSpaceCompressedId;
|
|
103
|
+
/**
|
|
104
|
+
* Decompresses a previously compressed ID into a UUID.
|
|
105
|
+
* @param id - the compressed ID to be decompressed.
|
|
106
|
+
* @returns the UUID associated with the compressed ID. Fails if the ID was not generated by this compressor.
|
|
107
|
+
*/
|
|
108
|
+
decompress(id: SessionSpaceCompressedId): StableId;
|
|
109
|
+
/**
|
|
110
|
+
* Recompresses a UUID.
|
|
111
|
+
* @param uncompressed - the UUID to recompress.
|
|
112
|
+
* @returns the `CompressedId` associated with `uncompressed`. Fails if it has not been previously compressed by this compressor.
|
|
113
|
+
*/
|
|
114
|
+
recompress(uncompressed: StableId): SessionSpaceCompressedId;
|
|
115
|
+
/**
|
|
116
|
+
* Attempts to recompresses a UUID.
|
|
117
|
+
* @param uncompressed - the UUID to recompress,
|
|
118
|
+
* @returns the `CompressedId` associated with `uncompressed` or undefined if it has not been previously compressed by this compressor.
|
|
119
|
+
*/
|
|
120
|
+
tryRecompress(uncompressed: StableId): SessionSpaceCompressedId | undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Excluded from this release type: IIdCompressorCore */
|
|
124
|
+
|
|
125
|
+
/* Excluded from this release type: isStableId */
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* A compressed ID that has been normalized into "op space".
|
|
129
|
+
* Serialized/persisted structures (e.g. ops) should use op-space IDs as a performance optimization, as they require less normalizing when
|
|
130
|
+
* received by a remote client due to the fact that op space for a given compressor is session space for all other compressors.
|
|
131
|
+
* @public
|
|
132
|
+
*/
|
|
133
|
+
export declare type OpSpaceCompressedId = number & {
|
|
134
|
+
readonly OpNormalized: "9209432d-a959-4df7-b2ad-767ead4dbcae";
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/* Excluded from this release type: SerializedIdCompressor */
|
|
138
|
+
|
|
139
|
+
/* Excluded from this release type: SerializedIdCompressorWithNoSession */
|
|
140
|
+
|
|
141
|
+
/* Excluded from this release type: SerializedIdCompressorWithOngoingSession */
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* A StableId which is suitable for use as a session identifier
|
|
145
|
+
* @public
|
|
146
|
+
*/
|
|
147
|
+
export declare type SessionId = StableId & {
|
|
148
|
+
readonly SessionId: "4498f850-e14e-4be9-8db0-89ec00997e58";
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* A compressed ID that has been normalized into "session space" (see `IdCompressor` for more).
|
|
153
|
+
* Consumer-facing APIs and data structures should use session-space IDs as their lifetime and equality is stable and tied to
|
|
154
|
+
* the scope of the session (i.e. compressor) that produced them.
|
|
155
|
+
* @public
|
|
156
|
+
*/
|
|
157
|
+
export declare type SessionSpaceCompressedId = number & {
|
|
158
|
+
readonly SessionUnique: "cea55054-6b82-4cbf-ad19-1fa645ea3b3e";
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* A version 4, variant 1 uuid (https://datatracker.ietf.org/doc/html/rfc4122).
|
|
163
|
+
* A 128-bit Universally Unique IDentifier. Represented here
|
|
164
|
+
* with a string of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
|
|
165
|
+
* where x is a lowercase hex digit.
|
|
166
|
+
* @public
|
|
167
|
+
*/
|
|
168
|
+
export declare type StableId = string & {
|
|
169
|
+
readonly StableId: "53172b0d-a3d5-41ea-bd75-b43839c97f5a";
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export { }
|
|
@@ -73,6 +73,7 @@ export declare class IdCompressor implements IIdCompressor, IIdCompressorCore {
|
|
|
73
73
|
private nextRequestedClusterSize;
|
|
74
74
|
private telemetryLocalIdCount;
|
|
75
75
|
private telemetryEagerFinalIdCount;
|
|
76
|
+
private ongoingGhostSession?;
|
|
76
77
|
private constructor();
|
|
77
78
|
/**
|
|
78
79
|
* @deprecated Use `createIdCompressor` instead.
|
|
@@ -83,6 +84,10 @@ export declare class IdCompressor implements IIdCompressor, IIdCompressorCore {
|
|
|
83
84
|
*/
|
|
84
85
|
static create(sessionId: SessionId, logger?: ITelemetryBaseLogger): IIdCompressor & IIdCompressorCore;
|
|
85
86
|
generateCompressedId(): SessionSpaceCompressedId;
|
|
87
|
+
/**
|
|
88
|
+
* {@inheritdoc IIdCompressorCore.beginGhostSession}
|
|
89
|
+
*/
|
|
90
|
+
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): void;
|
|
86
91
|
private generateNextLocalId;
|
|
87
92
|
takeNextCreationRange(): IdCreationRange;
|
|
88
93
|
private static assertValidRange;
|
|
@@ -97,6 +102,7 @@ export declare class IdCompressor implements IIdCompressor, IIdCompressorCore {
|
|
|
97
102
|
serialize(withSession: false): SerializedIdCompressorWithNoSession;
|
|
98
103
|
static deserialize(serialized: SerializedIdCompressorWithOngoingSession): IdCompressor;
|
|
99
104
|
static deserialize(serialized: SerializedIdCompressorWithNoSession, newSessionId: SessionId): IdCompressor;
|
|
105
|
+
private static deserialize2_0;
|
|
100
106
|
equals(other: IdCompressor, includeLocalState: boolean): boolean;
|
|
101
107
|
}
|
|
102
108
|
|
|
@@ -186,7 +192,7 @@ export declare interface IdCreationRange {
|
|
|
186
192
|
*
|
|
187
193
|
* These two spaces naturally define a rule: consumers of compressed IDs should use session-space IDs, but serialized forms such as ops
|
|
188
194
|
* should use op-space IDs.
|
|
189
|
-
* @
|
|
195
|
+
* @public
|
|
190
196
|
*/
|
|
191
197
|
export declare interface IIdCompressor {
|
|
192
198
|
localSessionId: SessionId;
|
|
@@ -248,6 +254,27 @@ export declare interface IIdCompressorCore {
|
|
|
248
254
|
* @param range - the range of session-local IDs to finalize.
|
|
249
255
|
*/
|
|
250
256
|
finalizeCreationRange(range: IdCreationRange): void;
|
|
257
|
+
/**
|
|
258
|
+
* Run a callback that is performed from the perspective of a special "ghost" session.
|
|
259
|
+
* Any ids generated by this session will be immediately finalized on the local client as if
|
|
260
|
+
* they were created by a remote client with `ghostSessionId`.
|
|
261
|
+
*
|
|
262
|
+
* *WARNING:* This API requires an external consensus mechanism to safely use:
|
|
263
|
+
* In an attached container (i.e. multiple clients may have the document loaded), all clients must guarantee that:
|
|
264
|
+
* - They invoke this API starting from the same finalized creation ranges
|
|
265
|
+
* - This API is invoked with the same ghost session id
|
|
266
|
+
* - `ghostSessionCallback` deterministically mints the same number of ids on each client within the ghost session
|
|
267
|
+
* Failure to meet these requirement will result in divergence across clients and eventual consistency errors.
|
|
268
|
+
* While the ghost sesion callback is running, IdCompressor does not support serialization.
|
|
269
|
+
* @remarks This API is primarily intended for data migration scenarios which are able to deterministically transform
|
|
270
|
+
* data in some format into data in a new format.
|
|
271
|
+
* The first requirement (that all clients must invoke the API with the same finalized creation ranges) is guaranteed
|
|
272
|
+
* for this scenario because the data transformation callback occurs at a specific ack within the op stream on all
|
|
273
|
+
* clients, and clients don't finalize creation ranges for local changes they might have at this point in time.
|
|
274
|
+
* @param ghostSessionId - The session id that minted ids generated within `ghostSessionCallback` should be attributed to.
|
|
275
|
+
* @param ghostSessionCallback - Callback which mints ids attributed to the ghost session.
|
|
276
|
+
*/
|
|
277
|
+
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): any;
|
|
251
278
|
/**
|
|
252
279
|
* Returns a persistable form of the current state of this `IdCompressor` which can be rehydrated via `IdCompressor.deserialize()`.
|
|
253
280
|
* This includes finalized state as well as un-finalized state and is therefore suitable for use in offline scenarios.
|
|
@@ -271,7 +298,7 @@ export declare function isStableId(str: string): str is StableId;
|
|
|
271
298
|
* A compressed ID that has been normalized into "op space".
|
|
272
299
|
* Serialized/persisted structures (e.g. ops) should use op-space IDs as a performance optimization, as they require less normalizing when
|
|
273
300
|
* received by a remote client due to the fact that op space for a given compressor is session space for all other compressors.
|
|
274
|
-
* @
|
|
301
|
+
* @public
|
|
275
302
|
*/
|
|
276
303
|
export declare type OpSpaceCompressedId = number & {
|
|
277
304
|
readonly OpNormalized: "9209432d-a959-4df7-b2ad-767ead4dbcae";
|
|
@@ -303,7 +330,7 @@ export declare type SerializedIdCompressorWithOngoingSession = SerializedIdCompr
|
|
|
303
330
|
|
|
304
331
|
/**
|
|
305
332
|
* A StableId which is suitable for use as a session identifier
|
|
306
|
-
* @
|
|
333
|
+
* @public
|
|
307
334
|
*/
|
|
308
335
|
export declare type SessionId = StableId & {
|
|
309
336
|
readonly SessionId: "4498f850-e14e-4be9-8db0-89ec00997e58";
|
|
@@ -313,7 +340,7 @@ export declare type SessionId = StableId & {
|
|
|
313
340
|
* A compressed ID that has been normalized into "session space" (see `IdCompressor` for more).
|
|
314
341
|
* Consumer-facing APIs and data structures should use session-space IDs as their lifetime and equality is stable and tied to
|
|
315
342
|
* the scope of the session (i.e. compressor) that produced them.
|
|
316
|
-
* @
|
|
343
|
+
* @public
|
|
317
344
|
*/
|
|
318
345
|
export declare type SessionSpaceCompressedId = number & {
|
|
319
346
|
readonly SessionUnique: "cea55054-6b82-4cbf-ad19-1fa645ea3b3e";
|
|
@@ -324,7 +351,7 @@ export declare type SessionSpaceCompressedId = number & {
|
|
|
324
351
|
* A 128-bit Universally Unique IDentifier. Represented here
|
|
325
352
|
* with a string of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
|
|
326
353
|
* where x is a lowercase hex digit.
|
|
327
|
-
* @
|
|
354
|
+
* @public
|
|
328
355
|
*/
|
|
329
356
|
export declare type StableId = string & {
|
|
330
357
|
readonly StableId: "53172b0d-a3d5-41ea-bd75-b43839c97f5a";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
6
|
-
import { IdCreationRange, IIdCompressor, IIdCompressorCore, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, StableId } from "./types";
|
|
6
|
+
import { IdCreationRange, IIdCompressor, IIdCompressorCore, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, StableId } from "./types/index.mjs";
|
|
7
7
|
/**
|
|
8
8
|
* See {@link IIdCompressor} and {@link IIdCompressorCore}
|
|
9
9
|
*
|
|
@@ -34,6 +34,7 @@ export declare class IdCompressor implements IIdCompressor, IIdCompressorCore {
|
|
|
34
34
|
private nextRequestedClusterSize;
|
|
35
35
|
private telemetryLocalIdCount;
|
|
36
36
|
private telemetryEagerFinalIdCount;
|
|
37
|
+
private ongoingGhostSession?;
|
|
37
38
|
private constructor();
|
|
38
39
|
/**
|
|
39
40
|
* @deprecated Use `createIdCompressor` instead.
|
|
@@ -44,6 +45,10 @@ export declare class IdCompressor implements IIdCompressor, IIdCompressorCore {
|
|
|
44
45
|
*/
|
|
45
46
|
static create(sessionId: SessionId, logger?: ITelemetryBaseLogger): IIdCompressor & IIdCompressorCore;
|
|
46
47
|
generateCompressedId(): SessionSpaceCompressedId;
|
|
48
|
+
/**
|
|
49
|
+
* {@inheritdoc IIdCompressorCore.beginGhostSession}
|
|
50
|
+
*/
|
|
51
|
+
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): void;
|
|
47
52
|
private generateNextLocalId;
|
|
48
53
|
takeNextCreationRange(): IdCreationRange;
|
|
49
54
|
private static assertValidRange;
|
|
@@ -58,6 +63,7 @@ export declare class IdCompressor implements IIdCompressor, IIdCompressorCore {
|
|
|
58
63
|
serialize(withSession: false): SerializedIdCompressorWithNoSession;
|
|
59
64
|
static deserialize(serialized: SerializedIdCompressorWithOngoingSession): IdCompressor;
|
|
60
65
|
static deserialize(serialized: SerializedIdCompressorWithNoSession, newSessionId: SessionId): IdCompressor;
|
|
66
|
+
private static deserialize2_0;
|
|
61
67
|
equals(other: IdCompressor, includeLocalState: boolean): boolean;
|
|
62
68
|
}
|
|
63
69
|
/**
|
|
@@ -81,4 +87,4 @@ export declare function deserializeIdCompressor(serialized: SerializedIdCompress
|
|
|
81
87
|
* @alpha
|
|
82
88
|
*/
|
|
83
89
|
export declare function deserializeIdCompressor(serialized: SerializedIdCompressorWithNoSession, newSessionId: SessionId): IIdCompressor & IIdCompressorCore;
|
|
84
|
-
//# sourceMappingURL=idCompressor.d.
|
|
90
|
+
//# sourceMappingURL=idCompressor.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idCompressor.d.mts","sourceRoot":"","sources":["../src/idCompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAII,EAAE,oBAAoB,EAAE,MAAM,iCAAiC;OAE/D,EACN,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EAEnB,mCAAmC,EACnC,wCAAwC,EACxC,SAAS,EACT,wBAAwB,EACxB,QAAQ,EACR;AAsCD;;;;;;;GAOG;AACH,qBAAa,YAAa,YAAW,aAAa,EAAE,iBAAiB;IA+CnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IA9CzB;;OAEG;IACH,gBAAuB,cAAc,SAAW;IAIhD,SAAgB,cAAc,EAAE,SAAS,CAAC;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgC;IAE3D,OAAO,CAAC,aAAa,CAAK;IAQ1B,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAM/C;;;;;OAKG;IAEH,OAAO,CAAC,wBAAwB,CAAe;IAE/C,OAAO,CAAC,qBAAqB,CAAK;IAElC,OAAO,CAAC,0BAA0B,CAAK;IAEvC,OAAO,CAAC,mBAAmB,CAAC,CAAqD;IAIjF,OAAO;IAqBP;;OAEG;WACW,MAAM,CAAC,MAAM,CAAC,EAAE,oBAAoB,GAAG,aAAa,GAAG,iBAAiB;IACtF;;OAEG;WACW,MAAM,CACnB,SAAS,EAAE,SAAS,EACpB,MAAM,CAAC,EAAE,oBAAoB,GAC3B,aAAa,GAAG,iBAAiB;IAyB7B,oBAAoB,IAAI,wBAAwB;IAyCvD;;OAEG;IACI,iBAAiB,CAAC,cAAc,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,IAAI;IASpF,OAAO,CAAC,mBAAmB;IAMpB,qBAAqB,IAAI,eAAe;IAwB/C,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAaxB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAuF1D,OAAO,CAAC,eAAe;IAehB,kBAAkB,CAAC,EAAE,EAAE,wBAAwB,GAAG,mBAAmB;IAerE,uBAAuB,CAC7B,EAAE,EAAE,mBAAmB,EACvB,eAAe,EAAE,SAAS,GACxB,wBAAwB;IA4CpB,UAAU,CAAC,EAAE,EAAE,wBAAwB,GAAG,QAAQ;IAwClD,UAAU,CAAC,YAAY,EAAE,QAAQ,GAAG,wBAAwB;IAQ5D,aAAa,CAAC,YAAY,EAAE,QAAQ,GAAG,wBAAwB,GAAG,SAAS;IAwC3E,SAAS,CAAC,WAAW,EAAE,IAAI,GAAG,wCAAwC;IACtE,SAAS,CAAC,WAAW,EAAE,KAAK,GAAG,mCAAmC;WA2E3D,WAAW,CAAC,UAAU,EAAE,wCAAwC,GAAG,YAAY;WAC/E,WAAW,CACxB,UAAU,EAAE,mCAAmC,EAC/C,YAAY,EAAE,SAAS,GACrB,YAAY;IAsBf,OAAO,CAAC,MAAM,CAAC,cAAc;IA6DtB,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,GAAG,OAAO;CAgBvE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CACjC,MAAM,CAAC,EAAE,oBAAoB,GAC3B,aAAa,GAAG,iBAAiB,CAAC;AACrC;;;;GAIG;AACH,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,SAAS,EACpB,MAAM,CAAC,EAAE,oBAAoB,GAC3B,aAAa,GAAG,iBAAiB,CAAC;AAQrC;;;GAGG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,wCAAwC,GAClD,aAAa,GAAG,iBAAiB,CAAC;AACrC;;;GAGG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,mCAAmC,EAC/C,YAAY,EAAE,SAAS,GACrB,aAAa,GAAG,iBAAiB,CAAC"}
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
import { assert } from "@fluidframework/core-utils";
|
|
6
6
|
import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
7
7
|
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
8
|
-
import { isFinalId } from "./identifiers";
|
|
9
|
-
import { createSessionId, localIdFromGenCount, genCountFromLocalId, numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, subtractNumericUuids, } from "./utilities";
|
|
10
|
-
import { readBoolean, readNumber, readNumericUuid, writeBoolean, writeNumber, writeNumericUuid, } from "./persistanceUtilities";
|
|
11
|
-
import { getAlignedLocal, getAlignedFinal, lastFinalizedLocal, Session, Sessions, } from "./sessions";
|
|
12
|
-
import { SessionSpaceNormalizer } from "./sessionSpaceNormalizer";
|
|
13
|
-
import { FinalSpace } from "./finalSpace";
|
|
8
|
+
import { isFinalId } from "./identifiers.mjs";
|
|
9
|
+
import { createSessionId, localIdFromGenCount, genCountFromLocalId, numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, subtractNumericUuids, } from "./utilities.mjs";
|
|
10
|
+
import { readBoolean, readNumber, readNumericUuid, writeBoolean, writeNumber, writeNumericUuid, } from "./persistanceUtilities.mjs";
|
|
11
|
+
import { getAlignedLocal, getAlignedFinal, lastFinalizedLocal, Session, Sessions, lastFinalizedFinal, } from "./sessions.mjs";
|
|
12
|
+
import { SessionSpaceNormalizer } from "./sessionSpaceNormalizer.mjs";
|
|
13
|
+
import { FinalSpace } from "./finalSpace.mjs";
|
|
14
14
|
/**
|
|
15
15
|
* The version of IdCompressor that is currently persisted.
|
|
16
16
|
* This should not be changed without careful consideration to compatibility.
|
|
17
17
|
*/
|
|
18
|
-
const currentWrittenVersion =
|
|
18
|
+
const currentWrittenVersion = 2.0;
|
|
19
19
|
/**
|
|
20
20
|
* See {@link IIdCompressor} and {@link IIdCompressorCore}
|
|
21
21
|
*
|
|
@@ -87,27 +87,52 @@ export class IdCompressor {
|
|
|
87
87
|
return compressor;
|
|
88
88
|
}
|
|
89
89
|
generateCompressedId() {
|
|
90
|
-
this
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
// This ghost session code inside this block should not be changed without a version bump (it is performed at a consensus point)
|
|
91
|
+
if (this.ongoingGhostSession) {
|
|
92
|
+
if (this.ongoingGhostSession.cluster === undefined) {
|
|
93
|
+
this.ongoingGhostSession.cluster = this.addEmptyCluster(this.sessions.getOrCreate(this.ongoingGhostSession.ghostSessionId), 1);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
this.ongoingGhostSession.cluster.capacity++;
|
|
97
|
+
}
|
|
98
|
+
this.ongoingGhostSession.cluster.count++;
|
|
99
|
+
return lastFinalizedFinal(this.ongoingGhostSession.cluster);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
this.localGenCount++;
|
|
103
|
+
const lastCluster = this.localSession.getLastCluster();
|
|
104
|
+
if (lastCluster === undefined) {
|
|
105
|
+
this.telemetryLocalIdCount++;
|
|
106
|
+
return this.generateNextLocalId();
|
|
107
|
+
}
|
|
108
|
+
// If there exists a cluster of final IDs already claimed by the local session that still has room in it,
|
|
109
|
+
// it is known prior to range sequencing what a local ID's corresponding final ID will be.
|
|
110
|
+
// In this case, it is safe to return the final ID immediately. This is guaranteed to be safe because
|
|
111
|
+
// any op that the local session sends that contains one of those final IDs are guaranteed to arrive to
|
|
112
|
+
// collaborators *after* the one containing the creation range.
|
|
113
|
+
const clusterOffset = this.localGenCount - genCountFromLocalId(lastCluster.baseLocalId);
|
|
114
|
+
if (lastCluster.capacity > clusterOffset) {
|
|
115
|
+
this.telemetryEagerFinalIdCount++;
|
|
116
|
+
// Space in the cluster: eager final
|
|
117
|
+
return (lastCluster.baseFinalId +
|
|
118
|
+
clusterOffset);
|
|
119
|
+
}
|
|
120
|
+
// No space in the cluster, return next local
|
|
93
121
|
this.telemetryLocalIdCount++;
|
|
94
122
|
return this.generateNextLocalId();
|
|
95
123
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
// No space in the cluster, return next local
|
|
109
|
-
this.telemetryLocalIdCount++;
|
|
110
|
-
return this.generateNextLocalId();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* {@inheritdoc IIdCompressorCore.beginGhostSession}
|
|
127
|
+
*/
|
|
128
|
+
beginGhostSession(ghostSessionId, ghostSessionCallback) {
|
|
129
|
+
this.ongoingGhostSession = { ghostSessionId };
|
|
130
|
+
try {
|
|
131
|
+
ghostSessionCallback();
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
this.ongoingGhostSession = undefined;
|
|
135
|
+
}
|
|
111
136
|
}
|
|
112
137
|
generateNextLocalId() {
|
|
113
138
|
// Must tell the normalizer that we generated a local ID
|
|
@@ -115,6 +140,7 @@ export class IdCompressor {
|
|
|
115
140
|
return localIdFromGenCount(this.localGenCount);
|
|
116
141
|
}
|
|
117
142
|
takeNextCreationRange() {
|
|
143
|
+
assert(!this.ongoingGhostSession, 0x8a6 /* IdCompressor should not be operated normally when in a ghost session */);
|
|
118
144
|
const count = this.localGenCount - (this.nextRangeBaseGenCount - 1);
|
|
119
145
|
if (count === 0) {
|
|
120
146
|
return {
|
|
@@ -143,6 +169,7 @@ export class IdCompressor {
|
|
|
143
169
|
assert(requestedClusterSize <= IdCompressor.maxClusterSize, 0x877 /* Clusters must not exceed max cluster size. */);
|
|
144
170
|
}
|
|
145
171
|
finalizeCreationRange(range) {
|
|
172
|
+
assert(!this.ongoingGhostSession, 0x8a7 /* IdCompressor should not be operated normally when in a ghost session */);
|
|
146
173
|
// Check if the range has IDs
|
|
147
174
|
if (range.ids === undefined) {
|
|
148
175
|
return;
|
|
@@ -219,6 +246,7 @@ export class IdCompressor {
|
|
|
219
246
|
assert(!session.isEmpty(), 0x757 /* Empty sessions should not be created. */);
|
|
220
247
|
}
|
|
221
248
|
addEmptyCluster(session, capacity) {
|
|
249
|
+
assert(!this.ongoingGhostSession?.cluster, 0x8a8 /* IdCompressor should not be operated normally when in a ghost session */);
|
|
222
250
|
const newCluster = session.addNewCluster(this.finalSpace.getAllocatedIdLimit(), capacity, 0);
|
|
223
251
|
assert(!this.sessions.clusterCollides(newCluster), 0x758 /* Cluster collision detected. */);
|
|
224
252
|
this.finalSpace.addCluster(newCluster);
|
|
@@ -358,6 +386,7 @@ export class IdCompressor {
|
|
|
358
386
|
}
|
|
359
387
|
}
|
|
360
388
|
serialize(hasLocalState) {
|
|
389
|
+
assert(!this.ongoingGhostSession, 0x8a9 /* IdCompressor should not be operated normally when in a ghost session */);
|
|
361
390
|
const { normalizer, finalSpace, sessions } = this;
|
|
362
391
|
const sessionIndexMap = new Map();
|
|
363
392
|
let sessionIndex = 0;
|
|
@@ -423,7 +452,16 @@ export class IdCompressor {
|
|
|
423
452
|
bufferUint: new BigUint64Array(buffer),
|
|
424
453
|
};
|
|
425
454
|
const version = readNumber(index);
|
|
426
|
-
|
|
455
|
+
switch (version) {
|
|
456
|
+
case 1.0:
|
|
457
|
+
throw new Error("IdCompressor version 1.0 is no longer supported.");
|
|
458
|
+
case 2.0:
|
|
459
|
+
return IdCompressor.deserialize2_0(index, sessionId);
|
|
460
|
+
default:
|
|
461
|
+
throw new Error("Unknown IdCompressor serialized version.");
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
static deserialize2_0(index, sessionId) {
|
|
427
465
|
const hasLocalState = readBoolean(index);
|
|
428
466
|
const sessionCount = readNumber(index);
|
|
429
467
|
const clusterCount = readNumber(index);
|
|
@@ -493,4 +531,4 @@ export function deserializeIdCompressor(serialized, sessionId) {
|
|
|
493
531
|
? IdCompressor.deserialize(serialized)
|
|
494
532
|
: IdCompressor.deserialize(serialized, sessionId);
|
|
495
533
|
}
|
|
496
|
-
//# sourceMappingURL=idCompressor.
|
|
534
|
+
//# sourceMappingURL=idCompressor.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idCompressor.mjs","sourceRoot":"","sources":["../src/idCompressor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport { bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ITelemetryLoggerExt, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport {\n\tIdCreationRange,\n\tIIdCompressor,\n\tIIdCompressorCore,\n\tOpSpaceCompressedId,\n\tSerializedIdCompressor,\n\tSerializedIdCompressorWithNoSession,\n\tSerializedIdCompressorWithOngoingSession,\n\tSessionId,\n\tSessionSpaceCompressedId,\n\tStableId,\n} from \"./types\";\nimport { FinalCompressedId, isFinalId, LocalCompressedId, NumericUuid } from \"./identifiers\";\nimport {\n\tcreateSessionId,\n\tlocalIdFromGenCount,\n\tgenCountFromLocalId,\n\tnumericUuidFromStableId,\n\toffsetNumericUuid,\n\tstableIdFromNumericUuid,\n\tsubtractNumericUuids,\n} from \"./utilities\";\nimport {\n\tIndex,\n\treadBoolean,\n\treadNumber,\n\treadNumericUuid,\n\twriteBoolean,\n\twriteNumber,\n\twriteNumericUuid,\n} from \"./persistanceUtilities\";\nimport {\n\tgetAlignedLocal,\n\tgetAlignedFinal,\n\tIdCluster,\n\tlastFinalizedLocal,\n\tSession,\n\tSessions,\n\tlastFinalizedFinal,\n} from \"./sessions\";\nimport { SessionSpaceNormalizer } from \"./sessionSpaceNormalizer\";\nimport { FinalSpace } from \"./finalSpace\";\n\n/**\n * The version of IdCompressor that is currently persisted.\n * This should not be changed without careful consideration to compatibility.\n */\nconst currentWrittenVersion = 2.0;\n\n/**\n * See {@link IIdCompressor} and {@link IIdCompressorCore}\n *\n * @alpha\n *\n * @deprecated Not intended for public use and will be removed from the public API in the future.\n * Use `createIdCompressor` instead.\n */\nexport class IdCompressor implements IIdCompressor, IIdCompressorCore {\n\t/**\n\t * Max allowed initial cluster size.\n\t */\n\tpublic static readonly maxClusterSize = 2 ** 20;\n\n\t// #region Local state\n\n\tpublic readonly localSessionId: SessionId;\n\tprivate readonly localSession: Session;\n\tprivate readonly normalizer = new SessionSpaceNormalizer();\n\t// The number of IDs generated by the local session\n\tprivate localGenCount = 0;\n\n\t// #endregion\n\n\t// #region Final state\n\n\t// The gen count to be annotated on the range returned by the next call to `takeNextCreationRange`.\n\t// This is updated to be equal to `generatedIdCount` + 1 each time it is called.\n\tprivate nextRangeBaseGenCount = 1;\n\tprivate readonly sessions = new Sessions();\n\tprivate readonly finalSpace = new FinalSpace();\n\n\t// #endregion\n\n\t// #region Ephemeral state\n\n\t/**\n\t * Roughly equates to a minimum of 1M sessions before we start allocating 64 bit IDs.\n\t * Eventually, this can be adjusted dynamically to have cluster reservation policies that\n\t * optimize the number of eager finals.\n\t * It is not readonly as it is accessed by tests for clear-box testing.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/prefer-readonly\n\tprivate nextRequestedClusterSize: number = 512;\n\t// The number of local IDs generated since the last telemetry was sent.\n\tprivate telemetryLocalIdCount = 0;\n\t// The number of eager final IDs generated since the last telemetry was sent.\n\tprivate telemetryEagerFinalIdCount = 0;\n\t// The ongoing ghost session, if one exists.\n\tprivate ongoingGhostSession?: { cluster?: IdCluster; ghostSessionId: SessionId };\n\n\t// #endregion\n\n\tprivate constructor(\n\t\tlocalSessionIdOrDeserialized: SessionId | Sessions,\n\t\tprivate readonly logger?: ITelemetryLoggerExt,\n\t) {\n\t\tif (typeof localSessionIdOrDeserialized === \"string\") {\n\t\t\tthis.localSessionId = localSessionIdOrDeserialized;\n\t\t\tthis.localSession = this.sessions.getOrCreate(localSessionIdOrDeserialized);\n\t\t} else {\n\t\t\t// Deserialize case\n\t\t\tthis.sessions = localSessionIdOrDeserialized;\n\t\t\t// As policy, the first session is always the local session. Preserve this invariant\n\t\t\t// during deserialization.\n\t\t\tconst firstSession = localSessionIdOrDeserialized.sessions().next();\n\t\t\tassert(!firstSession.done, 0x754 /* First session must be present. */);\n\t\t\tthis.localSession = firstSession.value;\n\t\t\tthis.localSessionId = stableIdFromNumericUuid(\n\t\t\t\tthis.localSession.sessionUuid,\n\t\t\t) as SessionId;\n\t\t}\n\t}\n\n\t/**\n\t * @deprecated Use `createIdCompressor` instead.\n\t */\n\tpublic static create(logger?: ITelemetryBaseLogger): IIdCompressor & IIdCompressorCore;\n\t/**\n\t * @deprecated Use `createIdCompressor` instead.\n\t */\n\tpublic static create(\n\t\tsessionId: SessionId,\n\t\tlogger?: ITelemetryBaseLogger,\n\t): IIdCompressor & IIdCompressorCore;\n\tpublic static create(\n\t\tsessionIdOrLogger?: SessionId | ITelemetryBaseLogger,\n\t\tloggerOrUndefined?: ITelemetryBaseLogger,\n\t): IIdCompressor & IIdCompressorCore {\n\t\tlet localSessionId: SessionId;\n\t\tlet logger: ITelemetryBaseLogger | undefined;\n\t\tif (sessionIdOrLogger === undefined) {\n\t\t\tlocalSessionId = createSessionId();\n\t\t} else {\n\t\t\tif (typeof sessionIdOrLogger === \"string\") {\n\t\t\t\tlocalSessionId = sessionIdOrLogger;\n\t\t\t\tlogger = loggerOrUndefined;\n\t\t\t} else {\n\t\t\t\tlocalSessionId = createSessionId();\n\t\t\t\tlogger = loggerOrUndefined;\n\t\t\t}\n\t\t}\n\t\tconst compressor = new IdCompressor(\n\t\t\tlocalSessionId,\n\t\t\tlogger === undefined ? undefined : createChildLogger({ logger }),\n\t\t);\n\t\treturn compressor;\n\t}\n\n\tpublic generateCompressedId(): SessionSpaceCompressedId {\n\t\t// This ghost session code inside this block should not be changed without a version bump (it is performed at a consensus point)\n\t\tif (this.ongoingGhostSession) {\n\t\t\tif (this.ongoingGhostSession.cluster === undefined) {\n\t\t\t\tthis.ongoingGhostSession.cluster = this.addEmptyCluster(\n\t\t\t\t\tthis.sessions.getOrCreate(this.ongoingGhostSession.ghostSessionId),\n\t\t\t\t\t1,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.ongoingGhostSession.cluster.capacity++;\n\t\t\t}\n\t\t\tthis.ongoingGhostSession.cluster.count++;\n\t\t\treturn lastFinalizedFinal(\n\t\t\t\tthis.ongoingGhostSession.cluster,\n\t\t\t) as unknown as SessionSpaceCompressedId;\n\t\t} else {\n\t\t\tthis.localGenCount++;\n\t\t\tconst lastCluster = this.localSession.getLastCluster();\n\t\t\tif (lastCluster === undefined) {\n\t\t\t\tthis.telemetryLocalIdCount++;\n\t\t\t\treturn this.generateNextLocalId();\n\t\t\t}\n\n\t\t\t// If there exists a cluster of final IDs already claimed by the local session that still has room in it,\n\t\t\t// it is known prior to range sequencing what a local ID's corresponding final ID will be.\n\t\t\t// In this case, it is safe to return the final ID immediately. This is guaranteed to be safe because\n\t\t\t// any op that the local session sends that contains one of those final IDs are guaranteed to arrive to\n\t\t\t// collaborators *after* the one containing the creation range.\n\t\t\tconst clusterOffset = this.localGenCount - genCountFromLocalId(lastCluster.baseLocalId);\n\t\t\tif (lastCluster.capacity > clusterOffset) {\n\t\t\t\tthis.telemetryEagerFinalIdCount++;\n\t\t\t\t// Space in the cluster: eager final\n\t\t\t\treturn ((lastCluster.baseFinalId as number) +\n\t\t\t\t\tclusterOffset) as SessionSpaceCompressedId;\n\t\t\t}\n\t\t\t// No space in the cluster, return next local\n\t\t\tthis.telemetryLocalIdCount++;\n\t\t\treturn this.generateNextLocalId();\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritdoc IIdCompressorCore.beginGhostSession}\n\t */\n\tpublic beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void) {\n\t\tthis.ongoingGhostSession = { ghostSessionId };\n\t\ttry {\n\t\t\tghostSessionCallback();\n\t\t} finally {\n\t\t\tthis.ongoingGhostSession = undefined;\n\t\t}\n\t}\n\n\tprivate generateNextLocalId(): LocalCompressedId {\n\t\t// Must tell the normalizer that we generated a local ID\n\t\tthis.normalizer.addLocalRange(this.localGenCount, 1);\n\t\treturn localIdFromGenCount(this.localGenCount);\n\t}\n\n\tpublic takeNextCreationRange(): IdCreationRange {\n\t\tassert(\n\t\t\t!this.ongoingGhostSession,\n\t\t\t0x8a6 /* IdCompressor should not be operated normally when in a ghost session */,\n\t\t);\n\t\tconst count = this.localGenCount - (this.nextRangeBaseGenCount - 1);\n\t\tif (count === 0) {\n\t\t\treturn {\n\t\t\t\tsessionId: this.localSessionId,\n\t\t\t};\n\t\t}\n\t\tconst range: IdCreationRange = {\n\t\t\tsessionId: this.localSessionId,\n\t\t\tids: {\n\t\t\t\tfirstGenCount: this.nextRangeBaseGenCount,\n\t\t\t\tcount,\n\t\t\t\trequestedClusterSize: this.nextRequestedClusterSize,\n\t\t\t},\n\t\t};\n\t\tthis.nextRangeBaseGenCount = this.localGenCount + 1;\n\t\tIdCompressor.assertValidRange(range);\n\t\treturn range;\n\t}\n\n\tprivate static assertValidRange(range: IdCreationRange): void {\n\t\tif (range.ids === undefined) {\n\t\t\treturn;\n\t\t}\n\t\tconst { count, requestedClusterSize } = range.ids;\n\t\tassert(count > 0, 0x755 /* Malformed ID Range. */);\n\t\tassert(requestedClusterSize > 0, 0x876 /* Clusters must have a positive capacity. */);\n\t\tassert(\n\t\t\trequestedClusterSize <= IdCompressor.maxClusterSize,\n\t\t\t0x877 /* Clusters must not exceed max cluster size. */,\n\t\t);\n\t}\n\n\tpublic finalizeCreationRange(range: IdCreationRange): void {\n\t\tassert(\n\t\t\t!this.ongoingGhostSession,\n\t\t\t0x8a7 /* IdCompressor should not be operated normally when in a ghost session */,\n\t\t);\n\t\t// Check if the range has IDs\n\t\tif (range.ids === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tIdCompressor.assertValidRange(range);\n\t\tconst { sessionId, ids } = range;\n\t\tconst { count, firstGenCount, requestedClusterSize } = ids;\n\t\tconst session = this.sessions.getOrCreate(sessionId);\n\t\tconst isLocal = session === this.localSession;\n\t\tconst rangeBaseLocal = localIdFromGenCount(firstGenCount);\n\t\tlet lastCluster = session.getLastCluster();\n\t\tif (lastCluster === undefined) {\n\t\t\t// This is the first cluster in the session space\n\t\t\tif (rangeBaseLocal !== -1) {\n\t\t\t\tthrow new Error(\"Ranges finalized out of order.\");\n\t\t\t}\n\t\t\tlastCluster = this.addEmptyCluster(session, requestedClusterSize + count);\n\t\t\tif (isLocal) {\n\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\teventName: \"RuntimeIdCompressor:FirstCluster\",\n\t\t\t\t\tsessionId: this.localSessionId,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst remainingCapacity = lastCluster.capacity - lastCluster.count;\n\t\tif (lastCluster.baseLocalId - lastCluster.count !== rangeBaseLocal) {\n\t\t\tthrow new Error(\"Ranges finalized out of order.\");\n\t\t}\n\n\t\tif (remainingCapacity >= count) {\n\t\t\t// The current range fits in the existing cluster\n\t\t\tlastCluster.count += count;\n\t\t} else {\n\t\t\tconst overflow = count - remainingCapacity;\n\t\t\tconst newClaimedFinalCount = overflow + requestedClusterSize;\n\t\t\tif (lastCluster === this.finalSpace.getLastCluster()) {\n\t\t\t\t// The last cluster in the sessions chain is the last cluster globally, so it can be expanded.\n\t\t\t\tlastCluster.capacity += newClaimedFinalCount;\n\t\t\t\tlastCluster.count += count;\n\t\t\t\tassert(\n\t\t\t\t\t!this.sessions.clusterCollides(lastCluster),\n\t\t\t\t\t0x756 /* Cluster collision detected. */,\n\t\t\t\t);\n\t\t\t\tif (isLocal) {\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"RuntimeIdCompressor:ClusterExpansion\",\n\t\t\t\t\t\tsessionId: this.localSessionId,\n\t\t\t\t\t\tpreviousCapacity: lastCluster.capacity - newClaimedFinalCount,\n\t\t\t\t\t\tnewCapacity: lastCluster.capacity,\n\t\t\t\t\t\toverflow,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// The last cluster in the sessions chain is *not* the last cluster globally. Fill and overflow to new.\n\t\t\t\tlastCluster.count = lastCluster.capacity;\n\t\t\t\tconst newCluster = this.addEmptyCluster(session, newClaimedFinalCount);\n\t\t\t\tnewCluster.count += overflow;\n\t\t\t\tif (isLocal) {\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"RuntimeIdCompressor:NewCluster\",\n\t\t\t\t\t\tsessionId: this.localSessionId,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isLocal) {\n\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\teventName: \"RuntimeIdCompressor:IdCompressorStatus\",\n\t\t\t\teagerFinalIdCount: this.telemetryEagerFinalIdCount,\n\t\t\t\tlocalIdCount: this.telemetryLocalIdCount,\n\t\t\t\tsessionId: this.localSessionId,\n\t\t\t});\n\t\t\tthis.telemetryEagerFinalIdCount = 0;\n\t\t\tthis.telemetryLocalIdCount = 0;\n\t\t}\n\n\t\tassert(!session.isEmpty(), 0x757 /* Empty sessions should not be created. */);\n\t}\n\n\tprivate addEmptyCluster(session: Session, capacity: number): IdCluster {\n\t\tassert(\n\t\t\t!this.ongoingGhostSession?.cluster,\n\t\t\t0x8a8 /* IdCompressor should not be operated normally when in a ghost session */,\n\t\t);\n\t\tconst newCluster = session.addNewCluster(\n\t\t\tthis.finalSpace.getAllocatedIdLimit(),\n\t\t\tcapacity,\n\t\t\t0,\n\t\t);\n\t\tassert(!this.sessions.clusterCollides(newCluster), 0x758 /* Cluster collision detected. */);\n\t\tthis.finalSpace.addCluster(newCluster);\n\t\treturn newCluster;\n\t}\n\n\tpublic normalizeToOpSpace(id: SessionSpaceCompressedId): OpSpaceCompressedId {\n\t\tif (isFinalId(id)) {\n\t\t\treturn id;\n\t\t} else {\n\t\t\tconst local = id as unknown as LocalCompressedId;\n\t\t\tif (!this.normalizer.contains(local)) {\n\t\t\t\tthrow new Error(\"Invalid ID to normalize.\");\n\t\t\t}\n\t\t\tconst finalForm = this.localSession.tryConvertToFinal(local, true);\n\t\t\treturn finalForm === undefined\n\t\t\t\t? (local as unknown as OpSpaceCompressedId)\n\t\t\t\t: (finalForm as OpSpaceCompressedId);\n\t\t}\n\t}\n\n\tpublic normalizeToSessionSpace(\n\t\tid: OpSpaceCompressedId,\n\t\toriginSessionId: SessionId,\n\t): SessionSpaceCompressedId {\n\t\tif (isFinalId(id)) {\n\t\t\tconst containingCluster = this.localSession.getClusterByAllocatedFinal(id);\n\t\t\tif (containingCluster === undefined) {\n\t\t\t\t// Does not exist in local cluster chain\n\t\t\t\tif (id >= this.finalSpace.getFinalizedIdLimit()) {\n\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t}\n\t\t\t\treturn id as unknown as SessionSpaceCompressedId;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = getAlignedLocal(containingCluster, id);\n\t\t\t\tif (this.normalizer.contains(alignedLocal)) {\n\t\t\t\t\treturn alignedLocal;\n\t\t\t\t} else {\n\t\t\t\t\tif (genCountFromLocalId(alignedLocal) > this.localGenCount) {\n\t\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t\t}\n\t\t\t\t\treturn id as unknown as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst localToNormalize = id as unknown as LocalCompressedId;\n\t\t\tif (originSessionId === this.localSessionId) {\n\t\t\t\tif (this.normalizer.contains(localToNormalize)) {\n\t\t\t\t\treturn localToNormalize;\n\t\t\t\t} else {\n\t\t\t\t\t// We never generated this local ID, so fail\n\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// LocalId from a remote session\n\t\t\t\tconst remoteSession = this.sessions.get(originSessionId);\n\t\t\t\tif (remoteSession === undefined) {\n\t\t\t\t\tthrow new Error(\"No IDs have ever been finalized by the supplied session.\");\n\t\t\t\t}\n\t\t\t\tconst correspondingFinal = remoteSession.tryConvertToFinal(localToNormalize, false);\n\t\t\t\tif (correspondingFinal === undefined) {\n\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t}\n\t\t\t\treturn correspondingFinal as unknown as SessionSpaceCompressedId;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic decompress(id: SessionSpaceCompressedId): StableId {\n\t\tif (isFinalId(id)) {\n\t\t\tconst containingCluster = Session.getContainingCluster(id, this.finalSpace.clusters);\n\t\t\tif (containingCluster === undefined) {\n\t\t\t\tthrow new Error(\"Unknown ID\");\n\t\t\t}\n\t\t\tconst alignedLocal = getAlignedLocal(containingCluster, id);\n\t\t\tconst alignedGenCount = genCountFromLocalId(alignedLocal);\n\t\t\tconst lastFinalizedGenCount = genCountFromLocalId(\n\t\t\t\tlastFinalizedLocal(containingCluster),\n\t\t\t);\n\t\t\tif (alignedGenCount > lastFinalizedGenCount) {\n\t\t\t\t// should be an eager final id generated by the local session\n\t\t\t\tif (containingCluster.session === this.localSession) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!this.normalizer.contains(alignedLocal),\n\t\t\t\t\t\t0x759 /* Normalizer out of sync. */,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(\"Unknown ID\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn stableIdFromNumericUuid(\n\t\t\t\toffsetNumericUuid(containingCluster.session.sessionUuid, alignedGenCount - 1),\n\t\t\t);\n\t\t} else {\n\t\t\tconst localToDecompress = id as unknown as LocalCompressedId;\n\t\t\tif (!this.normalizer.contains(localToDecompress)) {\n\t\t\t\tthrow new Error(\"Unknown ID\");\n\t\t\t}\n\t\t\treturn stableIdFromNumericUuid(\n\t\t\t\toffsetNumericUuid(\n\t\t\t\t\tthis.localSession.sessionUuid,\n\t\t\t\t\tgenCountFromLocalId(localToDecompress) - 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic recompress(uncompressed: StableId): SessionSpaceCompressedId {\n\t\tconst recompressed = this.tryRecompress(uncompressed);\n\t\tif (recompressed === undefined) {\n\t\t\tthrow new Error(\"Could not recompress.\");\n\t\t}\n\t\treturn recompressed;\n\t}\n\n\tpublic tryRecompress(uncompressed: StableId): SessionSpaceCompressedId | undefined {\n\t\tconst match = this.sessions.getContainingCluster(uncompressed);\n\t\tif (match === undefined) {\n\t\t\tconst numericUncompressed = numericUuidFromStableId(uncompressed);\n\t\t\tconst offset = subtractNumericUuids(numericUncompressed, this.localSession.sessionUuid);\n\t\t\tif (offset < Number.MAX_SAFE_INTEGER) {\n\t\t\t\tconst genCountEquivalent = Number(offset) + 1;\n\t\t\t\tconst localEquivalent = localIdFromGenCount(genCountEquivalent);\n\t\t\t\tif (this.normalizer.contains(localEquivalent)) {\n\t\t\t\t\treturn localEquivalent;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t} else {\n\t\t\tconst [containingCluster, alignedLocal] = match;\n\t\t\tif (containingCluster.session === this.localSession) {\n\t\t\t\t// Local session\n\t\t\t\tif (this.normalizer.contains(alignedLocal)) {\n\t\t\t\t\treturn alignedLocal;\n\t\t\t\t} else {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tgenCountFromLocalId(alignedLocal) <= this.localGenCount,\n\t\t\t\t\t\t0x75a /* Clusters out of sync. */,\n\t\t\t\t\t);\n\t\t\t\t\t// Id is an eager final\n\t\t\t\t\treturn getAlignedFinal(containingCluster, alignedLocal) as\n\t\t\t\t\t\t| SessionSpaceCompressedId\n\t\t\t\t\t\t| undefined;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Not the local session\n\t\t\t\treturn genCountFromLocalId(alignedLocal) >= lastFinalizedLocal(containingCluster)\n\t\t\t\t\t? (getAlignedFinal(containingCluster, alignedLocal) as\n\t\t\t\t\t\t\t| SessionSpaceCompressedId\n\t\t\t\t\t\t\t| undefined)\n\t\t\t\t\t: undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(withSession: true): SerializedIdCompressorWithOngoingSession;\n\tpublic serialize(withSession: false): SerializedIdCompressorWithNoSession;\n\tpublic serialize(hasLocalState: boolean): SerializedIdCompressor {\n\t\tassert(\n\t\t\t!this.ongoingGhostSession,\n\t\t\t0x8a9 /* IdCompressor should not be operated normally when in a ghost session */,\n\t\t);\n\t\tconst { normalizer, finalSpace, sessions } = this;\n\t\tconst sessionIndexMap = new Map<Session, number>();\n\t\tlet sessionIndex = 0;\n\t\tfor (const session of sessions.sessions()) {\n\t\t\t// Filter empty sessions to prevent them accumulating in the serialized state\n\t\t\tif (!session.isEmpty() || hasLocalState) {\n\t\t\t\tsessionIndexMap.set(session, sessionIndex);\n\t\t\t\tsessionIndex++;\n\t\t\t}\n\t\t}\n\t\tconst localStateSize = hasLocalState\n\t\t\t? 1 + // generated ID count\n\t\t\t 1 + // next range base genCount\n\t\t\t 1 + // count of normalizer pairs\n\t\t\t this.normalizer.idRanges.size * 2 // pairs\n\t\t\t: 0;\n\t\t// Layout size, in 8 byte increments\n\t\tconst totalSize =\n\t\t\t1 + // version\n\t\t\t1 + // hasLocalState\n\t\t\t1 + // session count\n\t\t\t1 + // cluster count\n\t\t\tsessionIndexMap.size * 2 + // session IDs\n\t\t\tfinalSpace.clusters.length * 3 + // clusters: (sessionIndex, capacity, count)[]\n\t\t\tlocalStateSize; // local state, if present\n\n\t\tconst serializedFloat = new Float64Array(totalSize);\n\t\tconst serializedUint = new BigUint64Array(serializedFloat.buffer);\n\t\tlet index = 0;\n\t\tindex = writeNumber(serializedFloat, index, currentWrittenVersion);\n\t\tindex = writeBoolean(serializedFloat, index, hasLocalState);\n\t\tindex = writeNumber(serializedFloat, index, sessionIndexMap.size);\n\t\tindex = writeNumber(serializedFloat, index, finalSpace.clusters.length);\n\n\t\tfor (const [session] of sessionIndexMap.entries()) {\n\t\t\tindex = writeNumericUuid(serializedUint, index, session.sessionUuid);\n\t\t}\n\n\t\tfinalSpace.clusters.forEach((cluster) => {\n\t\t\tindex = writeNumber(\n\t\t\t\tserializedFloat,\n\t\t\t\tindex,\n\t\t\t\tsessionIndexMap.get(cluster.session) as number,\n\t\t\t);\n\t\t\tindex = writeNumber(serializedFloat, index, cluster.capacity);\n\t\t\tindex = writeNumber(serializedFloat, index, cluster.count);\n\t\t});\n\n\t\tif (hasLocalState) {\n\t\t\tindex = writeNumber(serializedFloat, index, this.localGenCount);\n\t\t\tindex = writeNumber(serializedFloat, index, this.nextRangeBaseGenCount);\n\t\t\tindex = writeNumber(serializedFloat, index, normalizer.idRanges.size);\n\t\t\tfor (const [leadingGenCount, count] of normalizer.idRanges.entries()) {\n\t\t\t\tindex = writeNumber(serializedFloat, index, leadingGenCount);\n\t\t\t\tindex = writeNumber(serializedFloat, index, count);\n\t\t\t}\n\t\t}\n\n\t\tassert(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);\n\t\tthis.logger?.sendTelemetryEvent({\n\t\t\teventName: \"RuntimeIdCompressor:SerializedIdCompressorSize\",\n\t\t\tsize: serializedFloat.byteLength,\n\t\t\tclusterCount: finalSpace.clusters.length,\n\t\t\tsessionCount: sessionIndexMap.size,\n\t\t});\n\n\t\treturn bufferToString(serializedFloat.buffer, \"base64\") as SerializedIdCompressor;\n\t}\n\n\tpublic static deserialize(serialized: SerializedIdCompressorWithOngoingSession): IdCompressor;\n\tpublic static deserialize(\n\t\tserialized: SerializedIdCompressorWithNoSession,\n\t\tnewSessionId: SessionId,\n\t): IdCompressor;\n\tpublic static deserialize(\n\t\tserialized: SerializedIdCompressor,\n\t\tsessionId?: SessionId,\n\t): IdCompressor {\n\t\tconst buffer = stringToBuffer(serialized, \"base64\");\n\t\tconst index: Index = {\n\t\t\tindex: 0,\n\t\t\tbufferFloat: new Float64Array(buffer),\n\t\t\tbufferUint: new BigUint64Array(buffer),\n\t\t};\n\t\tconst version = readNumber(index);\n\t\tswitch (version) {\n\t\t\tcase 1.0:\n\t\t\t\tthrow new Error(\"IdCompressor version 1.0 is no longer supported.\");\n\t\t\tcase 2.0:\n\t\t\t\treturn IdCompressor.deserialize2_0(index, sessionId);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\"Unknown IdCompressor serialized version.\");\n\t\t}\n\t}\n\n\tprivate static deserialize2_0(index: Index, sessionId?: SessionId): IdCompressor {\n\t\tconst hasLocalState = readBoolean(index);\n\t\tconst sessionCount = readNumber(index);\n\t\tconst clusterCount = readNumber(index);\n\n\t\t// Sessions\n\t\tlet sessionOffset = 0;\n\t\tconst sessions: [NumericUuid, Session][] = [];\n\t\tif (!hasLocalState) {\n\t\t\t// If !hasLocalState, there won't be a serialized local session ID so insert one at the beginning\n\t\t\tassert(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);\n\t\t\tconst localSessionNumeric = numericUuidFromStableId(sessionId);\n\t\t\tsessions.push([localSessionNumeric, new Session(localSessionNumeric)]);\n\t\t\tsessionOffset = 1;\n\t\t} else {\n\t\t\tassert(\n\t\t\t\tsessionId === undefined,\n\t\t\t\t0x75e /* Local state should not exist in serialized form. */,\n\t\t\t);\n\t\t}\n\n\t\tfor (let i = 0; i < sessionCount; i++) {\n\t\t\tconst numeric = readNumericUuid(index);\n\t\t\tsessions.push([numeric, new Session(numeric)]);\n\t\t}\n\n\t\tconst compressor = new IdCompressor(new Sessions(sessions));\n\n\t\t// Clusters\n\t\tlet baseFinalId = 0;\n\t\tfor (let i = 0; i < clusterCount; i++) {\n\t\t\tconst sessionIndex = readNumber(index);\n\t\t\tconst session = sessions[sessionIndex + sessionOffset][1];\n\t\t\tconst capacity = readNumber(index);\n\t\t\tconst count = readNumber(index);\n\t\t\tconst cluster = session.addNewCluster(\n\t\t\t\tbaseFinalId as FinalCompressedId,\n\t\t\t\tcapacity,\n\t\t\t\tcount,\n\t\t\t);\n\t\t\tcompressor.finalSpace.addCluster(cluster);\n\t\t\tbaseFinalId += capacity;\n\t\t}\n\n\t\t// Local state\n\t\tif (hasLocalState) {\n\t\t\tcompressor.localGenCount = readNumber(index);\n\t\t\tcompressor.nextRangeBaseGenCount = readNumber(index);\n\t\t\tconst normalizerCount = readNumber(index);\n\t\t\tfor (let i = 0; i < normalizerCount; i++) {\n\t\t\t\tcompressor.normalizer.addLocalRange(readNumber(index), readNumber(index));\n\t\t\t}\n\t\t}\n\n\t\tassert(\n\t\t\tindex.index === index.bufferFloat.length,\n\t\t\t0x75f /* Failed to read entire serialized compressor. */,\n\t\t);\n\t\treturn compressor;\n\t}\n\n\tpublic equals(other: IdCompressor, includeLocalState: boolean): boolean {\n\t\tif (\n\t\t\tincludeLocalState &&\n\t\t\t(this.localSessionId !== other.localSessionId ||\n\t\t\t\t!this.localSession.equals(other.localSession) ||\n\t\t\t\t!this.normalizer.equals(other.normalizer) ||\n\t\t\t\tthis.nextRangeBaseGenCount !== other.nextRangeBaseGenCount ||\n\t\t\t\tthis.localGenCount !== other.localGenCount)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (\n\t\t\tthis.sessions.equals(other.sessions, includeLocalState) &&\n\t\t\tthis.finalSpace.equals(other.finalSpace)\n\t\t);\n\t}\n}\n\n/**\n * Create a new {@link IIdCompressor}.\n * @alpha\n */\nexport function createIdCompressor(\n\tlogger?: ITelemetryBaseLogger,\n): IIdCompressor & IIdCompressorCore;\n/**\n * Create a new {@link IIdCompressor}.\n * @param sessionId - The seed ID for the compressor.\n * @alpha\n */\nexport function createIdCompressor(\n\tsessionId: SessionId,\n\tlogger?: ITelemetryBaseLogger,\n): IIdCompressor & IIdCompressorCore;\nexport function createIdCompressor(\n\tsessionIdOrLogger?: SessionId | ITelemetryBaseLogger,\n\tloggerOrUndefined?: ITelemetryBaseLogger,\n): IIdCompressor & IIdCompressorCore {\n\treturn IdCompressor.create(sessionIdOrLogger as SessionId, loggerOrUndefined);\n}\n\n/**\n * Deserializes the supplied state into an ID compressor.\n * @alpha\n */\nexport function deserializeIdCompressor(\n\tserialized: SerializedIdCompressorWithOngoingSession,\n): IIdCompressor & IIdCompressorCore;\n/**\n * Deserializes the supplied state into an ID compressor.\n * @alpha\n */\nexport function deserializeIdCompressor(\n\tserialized: SerializedIdCompressorWithNoSession,\n\tnewSessionId: SessionId,\n): IIdCompressor & IIdCompressorCore;\nexport function deserializeIdCompressor(\n\tserialized: SerializedIdCompressor | SerializedIdCompressorWithNoSession,\n\tsessionId?: SessionId,\n): IIdCompressor & IIdCompressorCore {\n\treturn sessionId === undefined\n\t\t? IdCompressor.deserialize(serialized as SerializedIdCompressorWithOngoingSession)\n\t\t: IdCompressor.deserialize(serialized as SerializedIdCompressorWithNoSession, sessionId);\n}\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { OpSpaceCompressedId, SessionSpaceCompressedId } from "./types";
|
|
5
|
+
import { OpSpaceCompressedId, SessionSpaceCompressedId } from "./types/index.mjs";
|
|
6
6
|
/**
|
|
7
7
|
* A compressed ID that is stable and unique within the scope of network of compressors (i.e. a document).
|
|
8
8
|
* It can only be used/decompressed in the context of the originating document.
|
|
@@ -29,4 +29,4 @@ export declare function isFinalId(id: SessionSpaceCompressedId | OpSpaceCompress
|
|
|
29
29
|
export type NumericUuid = bigint & {
|
|
30
30
|
readonly NumericUuid: "be04dd4d-9d7e-4337-a833-eec64c61aa46";
|
|
31
31
|
};
|
|
32
|
-
//# sourceMappingURL=identifiers.d.
|
|
32
|
+
//# sourceMappingURL=identifiers.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identifiers.d.mts","sourceRoot":"","sources":["../src/identifiers.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAEI,EAAE,mBAAmB,EAAE,wBAAwB,EAAE;AAExD;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG;IACxC,QAAQ,CAAC,iBAAiB,EAAE,sCAAsC,CAAC;IAGnE,QAAQ,CAAC,YAAY,EAAE,sCAAsC,CAAC;CAC9D,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG;IACxC,QAAQ,CAAC,iBAAiB,EAAE,sCAAsC,CAAC;CACnE,GAAG,wBAAwB,CAAC;AAE7B;;GAEG;AACH,wBAAgB,SAAS,CACxB,EAAE,EAAE,wBAAwB,GAAG,mBAAmB,GAChD,EAAE,IAAI,iBAAiB,CAEzB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG;IAClC,QAAQ,CAAC,WAAW,EAAE,sCAAsC,CAAC;CAC7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identifiers.mjs","sourceRoot":"","sources":["../src/identifiers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwBH;;GAEG;AACH,MAAM,UAAU,SAAS,CACxB,EAAkD;IAElD,OAAO,EAAE,IAAI,CAAC,CAAC;AAChB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { OpSpaceCompressedId, SessionSpaceCompressedId } from \"./types\";\n\n/**\n * A compressed ID that is stable and unique within the scope of network of compressors (i.e. a document).\n * It can only be used/decompressed in the context of the originating document.\n */\nexport type FinalCompressedId = number & {\n\treadonly FinalCompressedId: \"5d83d1e2-98b7-4e4e-a889-54c855cfa73d\";\n\n\t// Same brand as OpNormalizedCompressedId, as final IDs are always finally normalized\n\treadonly OpNormalized: \"9209432d-a959-4df7-b2ad-767ead4dbcae\";\n};\n\n/**\n * A compressed ID that is local to a session (can only be decompressed when paired with a SessionId).\n * Internally, it should not be persisted outside a scope annotated with the originating SessionId in order to be unambiguous.\n * If external persistence is needed (e.g. by a client), a StableId should be used instead.\n */\nexport type LocalCompressedId = number & {\n\treadonly LocalCompressedId: \"6fccb42f-e2a4-4243-bd29-f13d12b9c6d1\";\n} & SessionSpaceCompressedId; // Same brand as CompressedId, as local IDs are always locally normalized\n\n/**\n * @returns true if the supplied ID is a final ID.\n */\nexport function isFinalId(\n\tid: SessionSpaceCompressedId | OpSpaceCompressedId,\n): id is FinalCompressedId {\n\treturn id >= 0;\n}\n\n/**\n * A StableId which is suitable for use as a session identifier\n */\nexport type NumericUuid = bigint & {\n\treadonly NumericUuid: \"be04dd4d-9d7e-4337-a833-eec64c61aa46\";\n};\n"]}
|
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export { createSessionId, assertIsStableId, generateStableId, isStableId } from "./utilities";
|
|
10
|
-
export { IIdCompressorCore, IIdCompressor, SerializedIdCompressor, SerializedIdCompressorWithOngoingSession, SerializedIdCompressorWithNoSession, SessionSpaceCompressedId, OpSpaceCompressedId, SessionId, StableId, IdCreationRange, } from "./types";
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
|
5
|
+
export { createIdCompressor, deserializeIdCompressor, IdCompressor } from "./idCompressor.mjs";
|
|
6
|
+
export { createSessionId, assertIsStableId, generateStableId, isStableId } from "./utilities.mjs";
|
|
7
|
+
export { IIdCompressorCore, IIdCompressor, SerializedIdCompressor, SerializedIdCompressorWithOngoingSession, SerializedIdCompressorWithNoSession, SessionSpaceCompressedId, OpSpaceCompressedId, SessionId, StableId, IdCreationRange, } from "./types/index.mjs";
|
|
8
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAMI,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE;OAC7D,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE;OACnE,EACN,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,wCAAwC,EACxC,mCAAmC,EACnC,wBAAwB,EACxB,mBAAmB,EACnB,SAAS,EACT,QAAQ,EACR,eAAe,GACf"}
|