@fluid-experimental/tree 1.3.3 → 1.3.4
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/dist/id-compressor/IdCompressor.d.ts.map +1 -1
- package/dist/id-compressor/IdCompressor.js +26 -18
- package/dist/id-compressor/IdCompressor.js.map +1 -1
- package/dist/id-compressor/SessionIdNormalizer.d.ts +31 -4
- package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
- package/dist/id-compressor/SessionIdNormalizer.js +64 -18
- package/dist/id-compressor/SessionIdNormalizer.js.map +1 -1
- package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
- package/lib/id-compressor/IdCompressor.js +26 -18
- package/lib/id-compressor/IdCompressor.js.map +1 -1
- package/lib/id-compressor/SessionIdNormalizer.d.ts +31 -4
- package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
- package/lib/id-compressor/SessionIdNormalizer.js +64 -18
- package/lib/id-compressor/SessionIdNormalizer.js.map +1 -1
- package/lib/test/IdCompressor.tests.js +210 -87
- package/lib/test/IdCompressor.tests.js.map +1 -1
- package/lib/test/SessionIdNormalizer.tests.js +124 -46
- package/lib/test/SessionIdNormalizer.tests.js.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts +17 -5
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.js +60 -14
- package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -1
- package/package.json +17 -17
- package/src/id-compressor/IdCompressor.ts +28 -17
- package/src/id-compressor/SessionIdNormalizer.ts +72 -17
|
@@ -75,16 +75,17 @@ export declare class SessionIdNormalizer<TRangeObject> {
|
|
|
75
75
|
*/
|
|
76
76
|
addLocalId(): LocalCompressedId;
|
|
77
77
|
/**
|
|
78
|
-
* Registers
|
|
79
|
-
* If there are any local IDs at the tip of session-space that do not have a corresponding final,
|
|
80
|
-
* the first of those. Otherwise, will be registered as the next ID in session space in creation order.
|
|
78
|
+
* Registers one or more final IDs with this normalizer.
|
|
79
|
+
* If there are any local IDs at the tip of session-space that do not have a corresponding final, they will be registered (aligned)
|
|
80
|
+
* starting with the first of those. Otherwise, will be registered as the next ID in session space in creation order.
|
|
81
81
|
*
|
|
82
|
+
* An example:
|
|
82
83
|
* Locals: [-1, -2, X, -4]
|
|
83
84
|
* Finals: [ 0, 1, 2, X]
|
|
84
85
|
* Calling `addFinalIds` with first === last === 5 results in the following:
|
|
85
86
|
* Locals: [-1, -2, X, -4]
|
|
86
87
|
* Finals: [ 0, 1, 2, 5]
|
|
87
|
-
*
|
|
88
|
+
* Subsequently calling `addFinalIds` with first === last === 6 results in the following:
|
|
88
89
|
* Locals: [-1, -2, X, -4, X]
|
|
89
90
|
* Finals: [ 0, 1, 2, 5, 6]
|
|
90
91
|
*
|
|
@@ -96,6 +97,32 @@ export declare class SessionIdNormalizer<TRangeObject> {
|
|
|
96
97
|
* ^final ID 9 is not contiguous and does not have a corresponding local ID
|
|
97
98
|
*/
|
|
98
99
|
addFinalIds(firstFinal: FinalCompressedId, lastFinal: FinalCompressedId, rangeObject: TRangeObject): void;
|
|
100
|
+
/**
|
|
101
|
+
* Alerts the normalizer to the existence of a block of final IDs that are *allocated* (but may not be entirely used).
|
|
102
|
+
*
|
|
103
|
+
* The normalizer may have unaligned (unfinalized) local IDs; any such outstanding locals will be eagerly aligned with
|
|
104
|
+
* as many finals from the registered block as possible.
|
|
105
|
+
*
|
|
106
|
+
* It is important to register blocks via this method as soon as they are created for future eager final generations to be utilized, as such
|
|
107
|
+
* generation is dependant on the normalizer being up-to-date with which local IDs have been aligned with finals. If, for instance,
|
|
108
|
+
* a block of finals is not immediately registered with the normalizer and there are outstanding locals that would have aligned with them,
|
|
109
|
+
* those locals will not be finalized until their creation range is finalized, which could be later if the block was created by an earlier
|
|
110
|
+
* creation range's finalization but is large enough to span them both. In this scenario, no eager finals can be generated until the second
|
|
111
|
+
* creation range is finalized.
|
|
112
|
+
*
|
|
113
|
+
* A usage example:
|
|
114
|
+
* Locals: [-1, -2, X, -4, -5, -6]
|
|
115
|
+
* Finals: [ 0, 1, 2, X, X, X]
|
|
116
|
+
* Calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 10 results in the following:
|
|
117
|
+
* Locals: [-1, -2, X, -4, -5, -6]
|
|
118
|
+
* Finals: [ 0, 1, 2, 5, 6, 7]
|
|
119
|
+
* Instead calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 2 results in the following:
|
|
120
|
+
* Locals: [-1, -2, X, -4, -5, -6]
|
|
121
|
+
* Finals: [ 0, 1, 2, 5, 6, X]
|
|
122
|
+
*
|
|
123
|
+
*/
|
|
124
|
+
registerFinalIdBlock(firstFinalInBlock: FinalCompressedId, count: number, rangeObject: TRangeObject): void;
|
|
125
|
+
private getAlignmentOfLastRange;
|
|
99
126
|
/**
|
|
100
127
|
* Returns an enumerable of all session-space IDs known to this normalizer, in creation order.
|
|
101
128
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionIdNormalizer.d.ts","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAEhG,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,mBAAmB,CAAC,YAAY;IAkBzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAjBpD,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAcvB;gBAEkC,gBAAgB,UAAQ;IAE5D;;;OAGG;IACI,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,wBAAwB,GAAG,SAAS;IAqB1F;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,CAAC,iBAAiB,EAAE,YAAY,CAAC,GAAG,SAAS;IAoB5F;;;OAGG;IACI,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS;IAgBvE;;OAEG;IACI,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS;IAwBhF,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAQjC;;OAEG;IACI,cAAc,IAAI,iBAAiB,GAAG,SAAS;IAetD;;;;;;OAMG;IACI,UAAU,IAAI,iBAAiB;IA6BtC
|
|
1
|
+
{"version":3,"file":"SessionIdNormalizer.d.ts","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAEhG,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,mBAAmB,CAAC,YAAY;IAkBzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAjBpD,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAcvB;gBAEkC,gBAAgB,UAAQ;IAE5D;;;OAGG;IACI,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,wBAAwB,GAAG,SAAS;IAqB1F;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,CAAC,iBAAiB,EAAE,YAAY,CAAC,GAAG,SAAS;IAoB5F;;;OAGG;IACI,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS;IAgBvE;;OAEG;IACI,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS;IAwBhF,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAQjC;;OAEG;IACI,cAAc,IAAI,iBAAiB,GAAG,SAAS;IAetD;;;;;;OAMG;IACI,UAAU,IAAI,iBAAiB;IA6BtC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,WAAW,CAAC,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,GAAG,IAAI;IAwChH;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACI,oBAAoB,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,GAAG,IAAI;IAgBjH,OAAO,CAAC,uBAAuB;IAwB/B;;OAEG;IACK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,wBAAwB,CAAC;IAwBhE,SAAS,IAAI,6BAA6B;WAkBnC,WAAW,CAAC,YAAY,EACrC,UAAU,EAAE,6BAA6B,EACzC,cAAc,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,YAAY,GAC1D,mBAAmB,CAAC,YAAY,CAAC;IAuB7B,MAAM,CACZ,KAAK,EAAE,mBAAmB,CAAC,YAAY,CAAC,EACxC,mBAAmB,GAAE,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,OAA2B,GACpF,OAAO;CA+BV"}
|
|
@@ -198,16 +198,17 @@ class SessionIdNormalizer {
|
|
|
198
198
|
return localId;
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
|
-
* Registers
|
|
202
|
-
* If there are any local IDs at the tip of session-space that do not have a corresponding final,
|
|
203
|
-
* the first of those. Otherwise, will be registered as the next ID in session space in creation order.
|
|
201
|
+
* Registers one or more final IDs with this normalizer.
|
|
202
|
+
* If there are any local IDs at the tip of session-space that do not have a corresponding final, they will be registered (aligned)
|
|
203
|
+
* starting with the first of those. Otherwise, will be registered as the next ID in session space in creation order.
|
|
204
204
|
*
|
|
205
|
+
* An example:
|
|
205
206
|
* Locals: [-1, -2, X, -4]
|
|
206
207
|
* Finals: [ 0, 1, 2, X]
|
|
207
208
|
* Calling `addFinalIds` with first === last === 5 results in the following:
|
|
208
209
|
* Locals: [-1, -2, X, -4]
|
|
209
210
|
* Finals: [ 0, 1, 2, 5]
|
|
210
|
-
*
|
|
211
|
+
* Subsequently calling `addFinalIds` with first === last === 6 results in the following:
|
|
211
212
|
* Locals: [-1, -2, X, -4, X]
|
|
212
213
|
* Finals: [ 0, 1, 2, 5, 6]
|
|
213
214
|
*
|
|
@@ -219,7 +220,7 @@ class SessionIdNormalizer {
|
|
|
219
220
|
* ^final ID 9 is not contiguous and does not have a corresponding local ID
|
|
220
221
|
*/
|
|
221
222
|
addFinalIds(firstFinal, lastFinal, rangeObject) {
|
|
222
|
-
var _a
|
|
223
|
+
var _a;
|
|
223
224
|
(0, Common_1.assert)(lastFinal >= firstFinal, 'Malformed normalization range.');
|
|
224
225
|
const [firstLocal, finalRangesObj] = (_a = this.idRanges.last()) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Final IDs must be added to an existing local range.');
|
|
225
226
|
const [lastLocal, finalRanges] = finalRangesObj;
|
|
@@ -229,18 +230,7 @@ class SessionIdNormalizer {
|
|
|
229
230
|
nextLocal = Math.min(this.nextLocalId, firstLocal - (lastFinal - firstFinal) - 1);
|
|
230
231
|
}
|
|
231
232
|
else {
|
|
232
|
-
const
|
|
233
|
-
let lastFinalRange;
|
|
234
|
-
let firstAlignedLocal;
|
|
235
|
-
if (isSingle) {
|
|
236
|
-
firstAlignedLocal = firstLocal;
|
|
237
|
-
lastFinalRange = finalRanges;
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
[firstAlignedLocal, lastFinalRange] = (_b = finalRanges.last()) !== null && _b !== void 0 ? _b : (0, Common_1.fail)('Map should be non-empty.');
|
|
241
|
-
}
|
|
242
|
-
const [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;
|
|
243
|
-
const lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);
|
|
233
|
+
const [firstAlignedLocal, lastAlignedLocal, lastAlignedFinal, lastFinalRange] = this.getAlignmentOfLastRange(firstLocal, finalRanges);
|
|
244
234
|
nextLocal = Math.min(this.nextLocalId, lastAlignedLocal - (lastFinal - firstFinal) - 2);
|
|
245
235
|
if (firstFinal === lastAlignedFinal + 1) {
|
|
246
236
|
lastFinalRange[1] = lastFinal;
|
|
@@ -248,7 +238,7 @@ class SessionIdNormalizer {
|
|
|
248
238
|
else {
|
|
249
239
|
const alignedLocal = (lastAlignedLocal - 1);
|
|
250
240
|
let rangeMap;
|
|
251
|
-
if (
|
|
241
|
+
if (isSingleRange(finalRanges)) {
|
|
252
242
|
// Convert the single range to a range collection
|
|
253
243
|
rangeMap = SessionIdNormalizer.makeFinalRangesMap();
|
|
254
244
|
rangeMap.append(firstAlignedLocal, lastFinalRange);
|
|
@@ -266,6 +256,62 @@ class SessionIdNormalizer {
|
|
|
266
256
|
}
|
|
267
257
|
this.nextLocalId = nextLocal;
|
|
268
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Alerts the normalizer to the existence of a block of final IDs that are *allocated* (but may not be entirely used).
|
|
261
|
+
*
|
|
262
|
+
* The normalizer may have unaligned (unfinalized) local IDs; any such outstanding locals will be eagerly aligned with
|
|
263
|
+
* as many finals from the registered block as possible.
|
|
264
|
+
*
|
|
265
|
+
* It is important to register blocks via this method as soon as they are created for future eager final generations to be utilized, as such
|
|
266
|
+
* generation is dependant on the normalizer being up-to-date with which local IDs have been aligned with finals. If, for instance,
|
|
267
|
+
* a block of finals is not immediately registered with the normalizer and there are outstanding locals that would have aligned with them,
|
|
268
|
+
* those locals will not be finalized until their creation range is finalized, which could be later if the block was created by an earlier
|
|
269
|
+
* creation range's finalization but is large enough to span them both. In this scenario, no eager finals can be generated until the second
|
|
270
|
+
* creation range is finalized.
|
|
271
|
+
*
|
|
272
|
+
* A usage example:
|
|
273
|
+
* Locals: [-1, -2, X, -4, -5, -6]
|
|
274
|
+
* Finals: [ 0, 1, 2, X, X, X]
|
|
275
|
+
* Calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 10 results in the following:
|
|
276
|
+
* Locals: [-1, -2, X, -4, -5, -6]
|
|
277
|
+
* Finals: [ 0, 1, 2, 5, 6, 7]
|
|
278
|
+
* Instead calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 2 results in the following:
|
|
279
|
+
* Locals: [-1, -2, X, -4, -5, -6]
|
|
280
|
+
* Finals: [ 0, 1, 2, 5, 6, X]
|
|
281
|
+
*
|
|
282
|
+
*/
|
|
283
|
+
registerFinalIdBlock(firstFinalInBlock, count, rangeObject) {
|
|
284
|
+
var _a;
|
|
285
|
+
(0, Common_1.assert)(count >= 1, 'Malformed normalization block.');
|
|
286
|
+
const [firstLocal, [lastLocal, finalRanges]] = (_a = this.idRanges.last()) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Final ID block should not be registered before any locals.');
|
|
287
|
+
let unalignedLocalCount;
|
|
288
|
+
if (finalRanges === undefined) {
|
|
289
|
+
unalignedLocalCount = firstLocal - lastLocal + 1;
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
const [_, lastAlignedLocal] = this.getAlignmentOfLastRange(firstLocal, finalRanges);
|
|
293
|
+
unalignedLocalCount = lastAlignedLocal - lastLocal;
|
|
294
|
+
}
|
|
295
|
+
(0, Common_1.assert)(unalignedLocalCount > 0, 'Final ID block should not be registered without an existing local range.');
|
|
296
|
+
const lastFinal = (firstFinalInBlock + Math.min(unalignedLocalCount, count) - 1);
|
|
297
|
+
this.addFinalIds(firstFinalInBlock, lastFinal, rangeObject);
|
|
298
|
+
}
|
|
299
|
+
getAlignmentOfLastRange(firstLocal, finalRanges) {
|
|
300
|
+
var _a;
|
|
301
|
+
const isSingle = isSingleRange(finalRanges);
|
|
302
|
+
let lastFinalRange;
|
|
303
|
+
let firstAlignedLocal;
|
|
304
|
+
if (isSingle) {
|
|
305
|
+
firstAlignedLocal = firstLocal;
|
|
306
|
+
lastFinalRange = finalRanges;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
[firstAlignedLocal, lastFinalRange] = (_a = finalRanges.last()) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Map should be non-empty.');
|
|
310
|
+
}
|
|
311
|
+
const [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;
|
|
312
|
+
const lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);
|
|
313
|
+
return [firstAlignedLocal, lastAlignedLocal, lastAlignedFinal, lastFinalRange];
|
|
314
|
+
}
|
|
269
315
|
/**
|
|
270
316
|
* Returns an enumerable of all session-space IDs known to this normalizer, in creation order.
|
|
271
317
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionIdNormalizer.js","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.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\n/* eslint-disable @typescript-eslint/restrict-plus-operands */\n\nimport { assert, compareFiniteNumbers, compareFiniteNumbersReversed, fail, Mutable } from '../Common';\nimport { FinalCompressedId, LocalCompressedId, SessionSpaceCompressedId } from '../Identifiers';\nimport { AppendOnlyDoublySortedMap } from './AppendOnlySortedMap';\nimport { SerializedSessionIdNormalizer } from './persisted-types';\n\n/**\n * Maps IDs created by a session between their local and final forms (i.e. normalization). These IDs are in a contiguous range.\n * The local and final forms of IDs made by a session can be thought of as two equal-length sparse arrays, aligned such\n * that normalizeLocalToFinal(locals[i]) === finals[i] and vice versa.\n * Below is an example to illustrate how various mappings can arise:\n *\n * +- Creation Index\n * / +- Locals\n * / / +- Finals\n * / / /\n * ---+-----+----\n * 0 | -1 | 0 -|___ Two IDs are allocated as locals since no cluster exists. A new cluster is created when acked.\n * 1 | -2 | 1 -|\n * 2 | | 2 -|\n * 3 | | 3 --|-- Three more IDs are allocated as finals eagerly since a cluster exists with available capacity.\n * 4 | | 4 -|\n * 5 | -6 | 10 ----- One ID is allocated as a local (it overflows the existing cluster) and a new cluster is created after ack.\n * 6 | | 11 ----- One ID is allocated as a final eagerly into the existing cluster.\n * 7 | -8 | 12 ----- A local ID with an override is allocated. The override forces it to be a local ID.\n * 8 | | 13\n * 9 | | 14\n * 10 | -11 | ----- A local ID is allocated. It has no corresponding final ID since it has not been acked.\n *\n * Note that in this example, some IDs (those at indices 2, 3, 4, 6, 8, and 9) have no local form. The ID at index 10 has no final form.\n * These kinds of \"gaps\" occur due to the timing of allocation calls on the client and how they relate to finalization/cluster creation,\n * which depends on receiving an ack/sequence number from the server. Given this context, \"session space\" can be thought of as:\n *\n * \t\tfor each index in the range of IDs created by a session:\n * \t\t\tthe local form if it exists, otherwise the final form\n *\n * This class is designed to efficiently build and query these mappings by leveraging the facts that much of the range (in both local and\n * final space) is uninterrupted by \"gaps\" and can be compactly represented by a (first, last) pair and is easily binary searched for\n * normalization between local and final space.\n */\nexport class SessionIdNormalizer<TRangeObject> {\n\tprivate nextLocalId: LocalCompressedId = -1 as LocalCompressedId;\n\tprivate readonly idRanges: AppendOnlyDoublySortedMap<\n\t\tLocalCompressedId,\n\t\t[lastLocal: LocalCompressedId, finalRanges: FinalRanges<TRangeObject> | undefined],\n\t\tFinalCompressedId\n\t> = new AppendOnlyDoublySortedMap(\n\t\tcompareFiniteNumbersReversed,\n\t\t([_, finalRanges]) => {\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\tconst first = getFirstRange(finalRanges);\n\t\t\t\treturn extractFirstFinalFromRange(first);\n\t\t\t}\n\t\t\treturn Number.POSITIVE_INFINITY as FinalCompressedId;\n\t\t},\n\t\tcompareFiniteNumbers\n\t);\n\n\tpublic constructor(private readonly expensiveAsserts = false) {}\n\n\t/**\n\t * Converts the final ID to its session-space representation.\n\t * This will be the corresponding local if a local form exists, and `finalId` otherwise.\n\t */\n\tpublic getSessionSpaceId(finalId: FinalCompressedId): SessionSpaceCompressedId | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\tif (finalDelta <= localRangeDelta) {\n\t\t\t\t\t\treturn (alignedLocal - finalDelta) as LocalCompressedId;\n\t\t\t\t\t}\n\t\t\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Converts the local ID to its corresponding final ID, if one exists.\n\t */\n\tpublic getFinalId(localId: LocalCompressedId): [FinalCompressedId, TRangeObject] | undefined {\n\t\tconst localRange =\n\t\t\tthis.idRanges.getPairOrNextLower(localId) ?? fail('Local ID was never recorded with this normalizer.');\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localId < lastLocal) {\n\t\t\tfail('Local ID was never recorded with this normalizer.');\n\t\t}\n\t\tconst finalRange = getPairOrNextLower(firstLocal, finalRanges, localId);\n\t\tif (finalRange !== undefined) {\n\t\t\tconst [alignedLocal, [firstFinal, lastFinal, rangeObject]] = finalRange;\n\t\t\tconst rangeDelta = lastFinal - firstFinal;\n\t\t\tconst localDelta = alignedLocal - localId;\n\t\t\tif (localDelta <= rangeDelta) {\n\t\t\t\t// Local is within a range segment that has a corresponding final\n\t\t\t\treturn [(firstFinal + localDelta) as FinalCompressedId, rangeObject];\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the index of the supplied session-space ID in the total range of IDs created by the session, if the ID was created\n\t * by the session for this `SessionIdNormalizer`.\n\t */\n\tpublic getCreationIndex(finalId: FinalCompressedId): number | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [_, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\treturn -alignedLocal - 1 + finalDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the session-space ID at the supplied creation index, if one exists.\n\t */\n\tpublic getIdByCreationIndex(index: number): SessionSpaceCompressedId | undefined {\n\t\tconst localByIndex = -(index + 1) as LocalCompressedId;\n\t\tconst localRange = this.idRanges.getPairOrNextLower(localByIndex);\n\t\tif (localRange === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localByIndex >= lastLocal) {\n\t\t\treturn localByIndex;\n\t\t}\n\t\tconst finalRange =\n\t\t\tgetPairOrNextLower(firstLocal, finalRanges, localByIndex) ??\n\t\t\tfail('Final ranges not aligned with owning local range.');\n\n\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\tconst localDelta = alignedLocal - localByIndex;\n\t\tconst finalId = firstFinal + localDelta;\n\t\tif (finalId <= lastFinal) {\n\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate static makeFinalRangesMap<TRangeObject>(): FinalRangesMap<TRangeObject> {\n\t\treturn new AppendOnlyDoublySortedMap(\n\t\t\tcompareFiniteNumbersReversed,\n\t\t\textractFirstFinalFromRange,\n\t\t\tcompareFiniteNumbers\n\t\t);\n\t}\n\n\t/**\n\t * Returns the last final ID known to this normalizer.\n\t */\n\tpublic getLastFinalId(): FinalCompressedId | undefined {\n\t\tconst lastIndex = this.idRanges.size - 1;\n\t\tconst secondToLast = Math.max(0, lastIndex - 1);\n\t\tfor (let i = lastIndex; i >= secondToLast; i--) {\n\t\t\tconst localRange = this.idRanges.getAtIndex(i);\n\t\t\tif (localRange !== undefined) {\n\t\t\t\tconst finalRanges = localRange[1][1];\n\t\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t\treturn getLastRange(finalRanges)[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Registers and returns the next ID in local space with this normalizer. An example:\n\t *\n\t * Locals: [-1, -2, X, X]\n\t * Finals: [ 0, 1, 2, 3]\n\t * In this scenario, a call to this method would generate and return -5.\n\t */\n\tpublic addLocalId(): LocalCompressedId {\n\t\tconst localId = this.nextLocalId-- as LocalCompressedId;\n\t\tconst lastLocalRange = this.idRanges.last();\n\t\tif (lastLocalRange !== undefined) {\n\t\t\tconst lastLocal = lastLocalRange[1][0];\n\t\t\tif (localId === lastLocal - 1) {\n\t\t\t\t// New local simply expands the last local range tracked\n\t\t\t\tlastLocalRange[1][0] = localId;\n\t\t\t\treturn localId;\n\t\t\t}\n\t\t}\n\n\t\tif (this.expensiveAsserts) {\n\t\t\tif (lastLocalRange === undefined) {\n\t\t\t\tassert(localId === -1, 'Local ID space must start at -1.');\n\t\t\t} else {\n\t\t\t\tconst [firstLocal, [_, finalRanges]] = lastLocalRange;\n\t\t\t\tlet finalDelta = 0;\n\t\t\t\tfor (const [_, [firstFinal, lastFinal]] of entries(firstLocal, finalRanges)) {\n\t\t\t\t\tfinalDelta += lastFinal - firstFinal + 1;\n\t\t\t\t}\n\t\t\t\tassert(localId === firstLocal - finalDelta, 'Local ID space must be contiguous.');\n\t\t\t}\n\t\t}\n\n\t\tthis.idRanges.append(localId, [localId, undefined]);\n\t\treturn localId;\n\t}\n\n\t/**\n\t * Registers a final ID with this normalizer.\n\t * If there are any local IDs at the tip of session-space that do not have a corresponding final, it will be registered (aligned) with\n\t * the first of those. Otherwise, will be registered as the next ID in session space in creation order. An example:\n\t *\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, X]\n\t * Calling `addFinalIds` with first === last === 5 results in the following:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, 5]\n\t * Calling `addFinalIds` with first === last === 6 results in the following:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 6]\n\t *\n\t * Non-contiguous final IDs (i.e. the first final after a \"gap\" in final space) must always correspond to a local ID. For example,\n\t * in the final call to `addFinalIds` above would fail if first === last === 9, because the resulting state would have a\n\t * non-contiguous final ID without a local form:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 9]\n\t * ^final ID 9 is not contiguous and does not have a corresponding local ID\n\t */\n\tpublic addFinalIds(firstFinal: FinalCompressedId, lastFinal: FinalCompressedId, rangeObject: TRangeObject): void {\n\t\tassert(lastFinal >= firstFinal, 'Malformed normalization range.');\n\t\tconst [firstLocal, finalRangesObj] =\n\t\t\tthis.idRanges.last() ?? fail('Final IDs must be added to an existing local range.');\n\t\tconst [lastLocal, finalRanges] = finalRangesObj;\n\t\tlet nextLocal: LocalCompressedId;\n\t\tif (finalRanges === undefined) {\n\t\t\tfinalRangesObj[1] = [firstFinal, lastFinal, rangeObject];\n\t\t\tnextLocal = Math.min(this.nextLocalId, firstLocal - (lastFinal - firstFinal) - 1) as LocalCompressedId;\n\t\t} else {\n\t\t\tconst isSingle = isSingleRange(finalRanges);\n\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\tlet firstAlignedLocal: LocalCompressedId;\n\t\t\tif (isSingle) {\n\t\t\t\tfirstAlignedLocal = firstLocal;\n\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t} else {\n\t\t\t\t[firstAlignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t\t}\n\n\t\t\tconst [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;\n\t\t\tconst lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tlastAlignedLocal - (lastFinal - firstFinal) - 2\n\t\t\t) as LocalCompressedId;\n\t\t\tif (firstFinal === lastAlignedFinal + 1) {\n\t\t\t\tlastFinalRange[1] = lastFinal;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = (lastAlignedLocal - 1) as LocalCompressedId;\n\t\t\t\tlet rangeMap: FinalRangesMap<TRangeObject>;\n\t\t\t\tif (isSingle) {\n\t\t\t\t\t// Convert the single range to a range collection\n\t\t\t\t\trangeMap = SessionIdNormalizer.makeFinalRangesMap();\n\t\t\t\t\trangeMap.append(firstAlignedLocal, lastFinalRange);\n\t\t\t\t\tfinalRangesObj[1] = rangeMap;\n\t\t\t\t} else {\n\t\t\t\t\trangeMap = finalRanges;\n\t\t\t\t}\n\t\t\t\trangeMap.append(alignedLocal, [firstFinal, lastFinal, rangeObject]);\n\t\t\t\tassert(alignedLocal >= lastLocal, 'Gaps in final space must align to a local.');\n\t\t\t}\n\t\t\tif (this.expensiveAsserts) {\n\t\t\t\tthis.idRanges.assertValid();\n\t\t\t}\n\t\t}\n\n\t\tthis.nextLocalId = nextLocal;\n\t}\n\n\t/**\n\t * Returns an enumerable of all session-space IDs known to this normalizer, in creation order.\n\t */\n\tpublic *[Symbol.iterator](): IterableIterator<SessionSpaceCompressedId> {\n\t\tfor (const [firstLocal, [lastLocal, finalRanges]] of this.idRanges.entries()) {\n\t\t\tfor (let i = firstLocal; i >= lastLocal; i--) {\n\t\t\t\tyield i;\n\t\t\t}\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t// Safe to get only the last final range, as all others must have corresponding locals (see `addFinalIds` docs)\n\t\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\t\tlet alignedLocal: LocalCompressedId;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\talignedLocal = firstLocal;\n\t\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t\t} else {\n\t\t\t\t\t[alignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t\t\t}\n\t\t\t\tconst [firstFinal, lastFinal] = lastFinalRange;\n\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\tfor (let i = firstFinal + localRangeDelta + 1; i <= lastFinal; i++) {\n\t\t\t\t\tyield i as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(): SerializedSessionIdNormalizer {\n\t\tconst serialized: Mutable<SerializedSessionIdNormalizer> = { localRanges: [], nextLocalId: this.nextLocalId };\n\t\tconst localRanges = serialized.localRanges as Mutable<typeof serialized.localRanges>;\n\t\tfor (const [firstLocal, finalRanges] of this.idRanges.entries()) {\n\t\t\tconst [lastLocal, finalRangesTable] = finalRanges;\n\t\t\tif (finalRangesTable !== undefined) {\n\t\t\t\tconst serializedFinalRanges: [LocalCompressedId, FinalCompressedId, FinalCompressedId][] = [];\n\t\t\t\tfor (const [alignedLocal, [firstFinal, lastFinal]] of entries(firstLocal, finalRangesTable)) {\n\t\t\t\t\tserializedFinalRanges.push([alignedLocal, firstFinal, lastFinal]);\n\t\t\t\t}\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal, serializedFinalRanges]);\n\t\t\t} else {\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal]);\n\t\t\t}\n\t\t}\n\t\treturn serialized;\n\t}\n\n\tpublic static deserialize<TRangeObject>(\n\t\tserialized: SerializedSessionIdNormalizer,\n\t\tgetRangeObject: (finalId: FinalCompressedId) => TRangeObject\n\t): SessionIdNormalizer<TRangeObject> {\n\t\tconst normalizer = new SessionIdNormalizer<TRangeObject>();\n\t\tconst { idRanges } = normalizer;\n\t\tfor (const [firstLocal, lastLocal, serializedFinalRanges] of serialized.localRanges) {\n\t\t\tlet finalRanges: FinalRanges<TRangeObject> | undefined;\n\t\t\tif (serializedFinalRanges !== undefined) {\n\t\t\t\tassert(serializedFinalRanges.length !== 0, 'Empty range should not be reified.');\n\t\t\t\tif (serializedFinalRanges.length === 1) {\n\t\t\t\t\tconst [_, firstFinal, lastFinal] = serializedFinalRanges[0];\n\t\t\t\t\tfinalRanges = [firstFinal, lastFinal, getRangeObject(firstFinal)];\n\t\t\t\t} else {\n\t\t\t\t\tfinalRanges = SessionIdNormalizer.makeFinalRangesMap<TRangeObject>();\n\t\t\t\t\tfor (const [alignedLocal, firstFinal, lastFinal] of serializedFinalRanges) {\n\t\t\t\t\t\tfinalRanges.append(alignedLocal, [firstFinal, lastFinal, getRangeObject(firstFinal)]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tidRanges.append(firstLocal, [lastLocal, finalRanges]);\n\t\t}\n\t\tnormalizer.nextLocalId = serialized.nextLocalId;\n\t\treturn normalizer;\n\t}\n\n\tpublic equals(\n\t\tother: SessionIdNormalizer<TRangeObject>,\n\t\tcompareRangeObjects: (a: TRangeObject, b: TRangeObject) => boolean = (a, b) => a === b\n\t): boolean {\n\t\treturn (\n\t\t\tthis.nextLocalId === other.nextLocalId &&\n\t\t\tthis.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {\n\t\t\t\tconst [lastLocalA, finalRangesA] = localRangeA;\n\t\t\t\tconst [lastLocalB, finalRangesB] = localRangeB;\n\t\t\t\tif (finalRangesA === undefined || finalRangesB === undefined) {\n\t\t\t\t\treturn finalRangesA === finalRangesB;\n\t\t\t\t}\n\n\t\t\t\tconst rangeEquals = (finalRangeA: FinalRange<TRangeObject>, finalRangeB: FinalRange<TRangeObject>) => {\n\t\t\t\t\tconst [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;\n\t\t\t\t\tconst [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;\n\t\t\t\t\treturn (\n\t\t\t\t\t\tfirstFinalA === firstFinalB &&\n\t\t\t\t\t\tlastFinalA === lastFinalB &&\n\t\t\t\t\t\tcompareRangeObjects(rangeObjectA, rangeObjectB)\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\tif (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {\n\t\t\t\t\tif (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn rangeEquals(finalRangesA, finalRangesB);\n\t\t\t\t}\n\n\t\t\t\treturn lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);\n\t\t\t})\n\t\t);\n\t}\n}\n\ntype FinalRange<TRangeObject> = [\n\tfirstFinal: FinalCompressedId,\n\tlastFinal: FinalCompressedId,\n\trangeObject: TRangeObject\n];\n\ntype FinalRangesMap<TRangeObject> = AppendOnlyDoublySortedMap<\n\tLocalCompressedId,\n\tFinalRange<TRangeObject>,\n\tFinalCompressedId\n>;\n\ntype FinalRanges<TRangeObject> = FinalRange<TRangeObject> | FinalRangesMap<TRangeObject>;\n\nfunction isSingleRange<TRangeObject>(ranges: FinalRanges<TRangeObject>): ranges is FinalRange<TRangeObject> {\n\treturn Array.isArray(ranges);\n}\n\nfunction getLastRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.last() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction getFirstRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.first() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction extractFirstFinalFromRange<TRangeObject>(finalRange: FinalRange<TRangeObject>): FinalCompressedId {\n\treturn finalRange[0];\n}\n\nfunction getPairOrNextLowerByValue<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tfinalId: FinalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (finalId < finalRanges[0]) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLowerByValue(finalId);\n}\n\nfunction getPairOrNextLower<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tlocalId: LocalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (localId > firstLocal) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLower(localId);\n}\n\nfunction* entries<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined\n): IterableIterator<readonly [LocalCompressedId, FinalRange<TRangeObject>]> {\n\tif (finalRanges !== undefined) {\n\t\tif (isSingleRange(finalRanges)) {\n\t\t\tyield [firstLocal, finalRanges];\n\t\t} else {\n\t\t\tfor (const range of finalRanges.entries()) {\n\t\t\t\tyield range;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SessionIdNormalizer.js","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.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\n/* eslint-disable @typescript-eslint/restrict-plus-operands */\n\nimport { assert, compareFiniteNumbers, compareFiniteNumbersReversed, fail, Mutable } from '../Common';\nimport { FinalCompressedId, LocalCompressedId, SessionSpaceCompressedId } from '../Identifiers';\nimport { AppendOnlyDoublySortedMap } from './AppendOnlySortedMap';\nimport { SerializedSessionIdNormalizer } from './persisted-types';\n\n/**\n * Maps IDs created by a session between their local and final forms (i.e. normalization). These IDs are in a contiguous range.\n * The local and final forms of IDs made by a session can be thought of as two equal-length sparse arrays, aligned such\n * that normalizeLocalToFinal(locals[i]) === finals[i] and vice versa.\n * Below is an example to illustrate how various mappings can arise:\n *\n * +- Creation Index\n * / +- Locals\n * / / +- Finals\n * / / /\n * ---+-----+----\n * 0 | -1 | 0 -|___ Two IDs are allocated as locals since no cluster exists. A new cluster is created when acked.\n * 1 | -2 | 1 -|\n * 2 | | 2 -|\n * 3 | | 3 --|-- Three more IDs are allocated as finals eagerly since a cluster exists with available capacity.\n * 4 | | 4 -|\n * 5 | -6 | 10 ----- One ID is allocated as a local (it overflows the existing cluster) and a new cluster is created after ack.\n * 6 | | 11 ----- One ID is allocated as a final eagerly into the existing cluster.\n * 7 | -8 | 12 ----- A local ID with an override is allocated. The override forces it to be a local ID.\n * 8 | | 13\n * 9 | | 14\n * 10 | -11 | ----- A local ID is allocated. It has no corresponding final ID since it has not been acked.\n *\n * Note that in this example, some IDs (those at indices 2, 3, 4, 6, 8, and 9) have no local form. The ID at index 10 has no final form.\n * These kinds of \"gaps\" occur due to the timing of allocation calls on the client and how they relate to finalization/cluster creation,\n * which depends on receiving an ack/sequence number from the server. Given this context, \"session space\" can be thought of as:\n *\n * \t\tfor each index in the range of IDs created by a session:\n * \t\t\tthe local form if it exists, otherwise the final form\n *\n * This class is designed to efficiently build and query these mappings by leveraging the facts that much of the range (in both local and\n * final space) is uninterrupted by \"gaps\" and can be compactly represented by a (first, last) pair and is easily binary searched for\n * normalization between local and final space.\n */\nexport class SessionIdNormalizer<TRangeObject> {\n\tprivate nextLocalId: LocalCompressedId = -1 as LocalCompressedId;\n\tprivate readonly idRanges: AppendOnlyDoublySortedMap<\n\t\tLocalCompressedId,\n\t\t[lastLocal: LocalCompressedId, finalRanges: FinalRanges<TRangeObject> | undefined],\n\t\tFinalCompressedId\n\t> = new AppendOnlyDoublySortedMap(\n\t\tcompareFiniteNumbersReversed,\n\t\t([_, finalRanges]) => {\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\tconst first = getFirstRange(finalRanges);\n\t\t\t\treturn extractFirstFinalFromRange(first);\n\t\t\t}\n\t\t\treturn Number.POSITIVE_INFINITY as FinalCompressedId;\n\t\t},\n\t\tcompareFiniteNumbers\n\t);\n\n\tpublic constructor(private readonly expensiveAsserts = false) {}\n\n\t/**\n\t * Converts the final ID to its session-space representation.\n\t * This will be the corresponding local if a local form exists, and `finalId` otherwise.\n\t */\n\tpublic getSessionSpaceId(finalId: FinalCompressedId): SessionSpaceCompressedId | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\tif (finalDelta <= localRangeDelta) {\n\t\t\t\t\t\treturn (alignedLocal - finalDelta) as LocalCompressedId;\n\t\t\t\t\t}\n\t\t\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Converts the local ID to its corresponding final ID, if one exists.\n\t */\n\tpublic getFinalId(localId: LocalCompressedId): [FinalCompressedId, TRangeObject] | undefined {\n\t\tconst localRange =\n\t\t\tthis.idRanges.getPairOrNextLower(localId) ?? fail('Local ID was never recorded with this normalizer.');\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localId < lastLocal) {\n\t\t\tfail('Local ID was never recorded with this normalizer.');\n\t\t}\n\t\tconst finalRange = getPairOrNextLower(firstLocal, finalRanges, localId);\n\t\tif (finalRange !== undefined) {\n\t\t\tconst [alignedLocal, [firstFinal, lastFinal, rangeObject]] = finalRange;\n\t\t\tconst rangeDelta = lastFinal - firstFinal;\n\t\t\tconst localDelta = alignedLocal - localId;\n\t\t\tif (localDelta <= rangeDelta) {\n\t\t\t\t// Local is within a range segment that has a corresponding final\n\t\t\t\treturn [(firstFinal + localDelta) as FinalCompressedId, rangeObject];\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the index of the supplied session-space ID in the total range of IDs created by the session, if the ID was created\n\t * by the session for this `SessionIdNormalizer`.\n\t */\n\tpublic getCreationIndex(finalId: FinalCompressedId): number | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [_, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\treturn -alignedLocal - 1 + finalDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the session-space ID at the supplied creation index, if one exists.\n\t */\n\tpublic getIdByCreationIndex(index: number): SessionSpaceCompressedId | undefined {\n\t\tconst localByIndex = -(index + 1) as LocalCompressedId;\n\t\tconst localRange = this.idRanges.getPairOrNextLower(localByIndex);\n\t\tif (localRange === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localByIndex >= lastLocal) {\n\t\t\treturn localByIndex;\n\t\t}\n\t\tconst finalRange =\n\t\t\tgetPairOrNextLower(firstLocal, finalRanges, localByIndex) ??\n\t\t\tfail('Final ranges not aligned with owning local range.');\n\n\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\tconst localDelta = alignedLocal - localByIndex;\n\t\tconst finalId = firstFinal + localDelta;\n\t\tif (finalId <= lastFinal) {\n\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate static makeFinalRangesMap<TRangeObject>(): FinalRangesMap<TRangeObject> {\n\t\treturn new AppendOnlyDoublySortedMap(\n\t\t\tcompareFiniteNumbersReversed,\n\t\t\textractFirstFinalFromRange,\n\t\t\tcompareFiniteNumbers\n\t\t);\n\t}\n\n\t/**\n\t * Returns the last final ID known to this normalizer.\n\t */\n\tpublic getLastFinalId(): FinalCompressedId | undefined {\n\t\tconst lastIndex = this.idRanges.size - 1;\n\t\tconst secondToLast = Math.max(0, lastIndex - 1);\n\t\tfor (let i = lastIndex; i >= secondToLast; i--) {\n\t\t\tconst localRange = this.idRanges.getAtIndex(i);\n\t\t\tif (localRange !== undefined) {\n\t\t\t\tconst finalRanges = localRange[1][1];\n\t\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t\treturn getLastRange(finalRanges)[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Registers and returns the next ID in local space with this normalizer. An example:\n\t *\n\t * Locals: [-1, -2, X, X]\n\t * Finals: [ 0, 1, 2, 3]\n\t * In this scenario, a call to this method would generate and return -5.\n\t */\n\tpublic addLocalId(): LocalCompressedId {\n\t\tconst localId = this.nextLocalId-- as LocalCompressedId;\n\t\tconst lastLocalRange = this.idRanges.last();\n\t\tif (lastLocalRange !== undefined) {\n\t\t\tconst lastLocal = lastLocalRange[1][0];\n\t\t\tif (localId === lastLocal - 1) {\n\t\t\t\t// New local simply expands the last local range tracked\n\t\t\t\tlastLocalRange[1][0] = localId;\n\t\t\t\treturn localId;\n\t\t\t}\n\t\t}\n\n\t\tif (this.expensiveAsserts) {\n\t\t\tif (lastLocalRange === undefined) {\n\t\t\t\tassert(localId === -1, 'Local ID space must start at -1.');\n\t\t\t} else {\n\t\t\t\tconst [firstLocal, [_, finalRanges]] = lastLocalRange;\n\t\t\t\tlet finalDelta = 0;\n\t\t\t\tfor (const [_, [firstFinal, lastFinal]] of entries(firstLocal, finalRanges)) {\n\t\t\t\t\tfinalDelta += lastFinal - firstFinal + 1;\n\t\t\t\t}\n\t\t\t\tassert(localId === firstLocal - finalDelta, 'Local ID space must be contiguous.');\n\t\t\t}\n\t\t}\n\n\t\tthis.idRanges.append(localId, [localId, undefined]);\n\t\treturn localId;\n\t}\n\n\t/**\n\t * Registers one or more final IDs with this normalizer.\n\t * If there are any local IDs at the tip of session-space that do not have a corresponding final, they will be registered (aligned)\n\t * starting with the first of those. Otherwise, will be registered as the next ID in session space in creation order.\n\t *\n\t * An example:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, X]\n\t * Calling `addFinalIds` with first === last === 5 results in the following:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, 5]\n\t * Subsequently calling `addFinalIds` with first === last === 6 results in the following:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 6]\n\t *\n\t * Non-contiguous final IDs (i.e. the first final after a \"gap\" in final space) must always correspond to a local ID. For example,\n\t * in the final call to `addFinalIds` above would fail if first === last === 9, because the resulting state would have a\n\t * non-contiguous final ID without a local form:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 9]\n\t * ^final ID 9 is not contiguous and does not have a corresponding local ID\n\t */\n\tpublic addFinalIds(firstFinal: FinalCompressedId, lastFinal: FinalCompressedId, rangeObject: TRangeObject): void {\n\t\tassert(lastFinal >= firstFinal, 'Malformed normalization range.');\n\t\tconst [firstLocal, finalRangesObj] =\n\t\t\tthis.idRanges.last() ?? fail('Final IDs must be added to an existing local range.');\n\t\tconst [lastLocal, finalRanges] = finalRangesObj;\n\t\tlet nextLocal: LocalCompressedId;\n\t\tif (finalRanges === undefined) {\n\t\t\tfinalRangesObj[1] = [firstFinal, lastFinal, rangeObject];\n\t\t\tnextLocal = Math.min(this.nextLocalId, firstLocal - (lastFinal - firstFinal) - 1) as LocalCompressedId;\n\t\t} else {\n\t\t\tconst [firstAlignedLocal, lastAlignedLocal, lastAlignedFinal, lastFinalRange] =\n\t\t\t\tthis.getAlignmentOfLastRange(firstLocal, finalRanges);\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tlastAlignedLocal - (lastFinal - firstFinal) - 2\n\t\t\t) as LocalCompressedId;\n\t\t\tif (firstFinal === lastAlignedFinal + 1) {\n\t\t\t\tlastFinalRange[1] = lastFinal;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = (lastAlignedLocal - 1) as LocalCompressedId;\n\t\t\t\tlet rangeMap: FinalRangesMap<TRangeObject>;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\t// Convert the single range to a range collection\n\t\t\t\t\trangeMap = SessionIdNormalizer.makeFinalRangesMap();\n\t\t\t\t\trangeMap.append(firstAlignedLocal, lastFinalRange);\n\t\t\t\t\tfinalRangesObj[1] = rangeMap;\n\t\t\t\t} else {\n\t\t\t\t\trangeMap = finalRanges;\n\t\t\t\t}\n\t\t\t\trangeMap.append(alignedLocal, [firstFinal, lastFinal, rangeObject]);\n\t\t\t\tassert(alignedLocal >= lastLocal, 'Gaps in final space must align to a local.');\n\t\t\t}\n\t\t\tif (this.expensiveAsserts) {\n\t\t\t\tthis.idRanges.assertValid();\n\t\t\t}\n\t\t}\n\n\t\tthis.nextLocalId = nextLocal;\n\t}\n\n\t/**\n\t * Alerts the normalizer to the existence of a block of final IDs that are *allocated* (but may not be entirely used).\n\t *\n\t * The normalizer may have unaligned (unfinalized) local IDs; any such outstanding locals will be eagerly aligned with\n\t * as many finals from the registered block as possible.\n\t *\n\t * It is important to register blocks via this method as soon as they are created for future eager final generations to be utilized, as such\n\t * generation is dependant on the normalizer being up-to-date with which local IDs have been aligned with finals. If, for instance,\n\t * a block of finals is not immediately registered with the normalizer and there are outstanding locals that would have aligned with them,\n\t * those locals will not be finalized until their creation range is finalized, which could be later if the block was created by an earlier\n\t * creation range's finalization but is large enough to span them both. In this scenario, no eager finals can be generated until the second\n\t * creation range is finalized.\n\t *\n\t * A usage example:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, X, X, X]\n\t * Calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 10 results in the following:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, 5, 6, 7]\n\t * Instead calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 2 results in the following:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, 5, 6, X]\n\t *\n\t */\n\tpublic registerFinalIdBlock(firstFinalInBlock: FinalCompressedId, count: number, rangeObject: TRangeObject): void {\n\t\tassert(count >= 1, 'Malformed normalization block.');\n\t\tconst [firstLocal, [lastLocal, finalRanges]] =\n\t\t\tthis.idRanges.last() ?? fail('Final ID block should not be registered before any locals.');\n\t\tlet unalignedLocalCount: number;\n\t\tif (finalRanges === undefined) {\n\t\t\tunalignedLocalCount = firstLocal - lastLocal + 1;\n\t\t} else {\n\t\t\tconst [_, lastAlignedLocal] = this.getAlignmentOfLastRange(firstLocal, finalRanges);\n\t\t\tunalignedLocalCount = lastAlignedLocal - lastLocal;\n\t\t}\n\t\tassert(unalignedLocalCount > 0, 'Final ID block should not be registered without an existing local range.');\n\t\tconst lastFinal = (firstFinalInBlock + Math.min(unalignedLocalCount, count) - 1) as FinalCompressedId;\n\t\tthis.addFinalIds(firstFinalInBlock, lastFinal, rangeObject);\n\t}\n\n\tprivate getAlignmentOfLastRange(\n\t\tfirstLocal: LocalCompressedId,\n\t\tfinalRanges: FinalRanges<TRangeObject>\n\t): [\n\t\tfirstAlignedLocal: LocalCompressedId,\n\t\tlastAlignedLocal: LocalCompressedId,\n\t\tlastAlignedFinal: FinalCompressedId,\n\t\tlastFinalRange: FinalRange<TRangeObject>\n\t] {\n\t\tconst isSingle = isSingleRange(finalRanges);\n\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\tlet firstAlignedLocal: LocalCompressedId;\n\t\tif (isSingle) {\n\t\t\tfirstAlignedLocal = firstLocal;\n\t\t\tlastFinalRange = finalRanges;\n\t\t} else {\n\t\t\t[firstAlignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t}\n\n\t\tconst [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;\n\t\tconst lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);\n\t\treturn [firstAlignedLocal, lastAlignedLocal as LocalCompressedId, lastAlignedFinal, lastFinalRange];\n\t}\n\n\t/**\n\t * Returns an enumerable of all session-space IDs known to this normalizer, in creation order.\n\t */\n\tpublic *[Symbol.iterator](): IterableIterator<SessionSpaceCompressedId> {\n\t\tfor (const [firstLocal, [lastLocal, finalRanges]] of this.idRanges.entries()) {\n\t\t\tfor (let i = firstLocal; i >= lastLocal; i--) {\n\t\t\t\tyield i;\n\t\t\t}\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t// Safe to get only the last final range, as all others must have corresponding locals (see `addFinalIds` docs)\n\t\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\t\tlet alignedLocal: LocalCompressedId;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\talignedLocal = firstLocal;\n\t\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t\t} else {\n\t\t\t\t\t[alignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t\t\t}\n\t\t\t\tconst [firstFinal, lastFinal] = lastFinalRange;\n\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\tfor (let i = firstFinal + localRangeDelta + 1; i <= lastFinal; i++) {\n\t\t\t\t\tyield i as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(): SerializedSessionIdNormalizer {\n\t\tconst serialized: Mutable<SerializedSessionIdNormalizer> = { localRanges: [], nextLocalId: this.nextLocalId };\n\t\tconst localRanges = serialized.localRanges as Mutable<typeof serialized.localRanges>;\n\t\tfor (const [firstLocal, finalRanges] of this.idRanges.entries()) {\n\t\t\tconst [lastLocal, finalRangesTable] = finalRanges;\n\t\t\tif (finalRangesTable !== undefined) {\n\t\t\t\tconst serializedFinalRanges: [LocalCompressedId, FinalCompressedId, FinalCompressedId][] = [];\n\t\t\t\tfor (const [alignedLocal, [firstFinal, lastFinal]] of entries(firstLocal, finalRangesTable)) {\n\t\t\t\t\tserializedFinalRanges.push([alignedLocal, firstFinal, lastFinal]);\n\t\t\t\t}\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal, serializedFinalRanges]);\n\t\t\t} else {\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal]);\n\t\t\t}\n\t\t}\n\t\treturn serialized;\n\t}\n\n\tpublic static deserialize<TRangeObject>(\n\t\tserialized: SerializedSessionIdNormalizer,\n\t\tgetRangeObject: (finalId: FinalCompressedId) => TRangeObject\n\t): SessionIdNormalizer<TRangeObject> {\n\t\tconst normalizer = new SessionIdNormalizer<TRangeObject>();\n\t\tconst { idRanges } = normalizer;\n\t\tfor (const [firstLocal, lastLocal, serializedFinalRanges] of serialized.localRanges) {\n\t\t\tlet finalRanges: FinalRanges<TRangeObject> | undefined;\n\t\t\tif (serializedFinalRanges !== undefined) {\n\t\t\t\tassert(serializedFinalRanges.length !== 0, 'Empty range should not be reified.');\n\t\t\t\tif (serializedFinalRanges.length === 1) {\n\t\t\t\t\tconst [_, firstFinal, lastFinal] = serializedFinalRanges[0];\n\t\t\t\t\tfinalRanges = [firstFinal, lastFinal, getRangeObject(firstFinal)];\n\t\t\t\t} else {\n\t\t\t\t\tfinalRanges = SessionIdNormalizer.makeFinalRangesMap<TRangeObject>();\n\t\t\t\t\tfor (const [alignedLocal, firstFinal, lastFinal] of serializedFinalRanges) {\n\t\t\t\t\t\tfinalRanges.append(alignedLocal, [firstFinal, lastFinal, getRangeObject(firstFinal)]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tidRanges.append(firstLocal, [lastLocal, finalRanges]);\n\t\t}\n\t\tnormalizer.nextLocalId = serialized.nextLocalId;\n\t\treturn normalizer;\n\t}\n\n\tpublic equals(\n\t\tother: SessionIdNormalizer<TRangeObject>,\n\t\tcompareRangeObjects: (a: TRangeObject, b: TRangeObject) => boolean = (a, b) => a === b\n\t): boolean {\n\t\treturn (\n\t\t\tthis.nextLocalId === other.nextLocalId &&\n\t\t\tthis.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {\n\t\t\t\tconst [lastLocalA, finalRangesA] = localRangeA;\n\t\t\t\tconst [lastLocalB, finalRangesB] = localRangeB;\n\t\t\t\tif (finalRangesA === undefined || finalRangesB === undefined) {\n\t\t\t\t\treturn finalRangesA === finalRangesB;\n\t\t\t\t}\n\n\t\t\t\tconst rangeEquals = (finalRangeA: FinalRange<TRangeObject>, finalRangeB: FinalRange<TRangeObject>) => {\n\t\t\t\t\tconst [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;\n\t\t\t\t\tconst [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;\n\t\t\t\t\treturn (\n\t\t\t\t\t\tfirstFinalA === firstFinalB &&\n\t\t\t\t\t\tlastFinalA === lastFinalB &&\n\t\t\t\t\t\tcompareRangeObjects(rangeObjectA, rangeObjectB)\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\tif (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {\n\t\t\t\t\tif (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn rangeEquals(finalRangesA, finalRangesB);\n\t\t\t\t}\n\n\t\t\t\treturn lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);\n\t\t\t})\n\t\t);\n\t}\n}\n\ntype FinalRange<TRangeObject> = [\n\tfirstFinal: FinalCompressedId,\n\tlastFinal: FinalCompressedId,\n\trangeObject: TRangeObject\n];\n\ntype FinalRangesMap<TRangeObject> = AppendOnlyDoublySortedMap<\n\tLocalCompressedId,\n\tFinalRange<TRangeObject>,\n\tFinalCompressedId\n>;\n\ntype FinalRanges<TRangeObject> = FinalRange<TRangeObject> | FinalRangesMap<TRangeObject>;\n\nfunction isSingleRange<TRangeObject>(ranges: FinalRanges<TRangeObject>): ranges is FinalRange<TRangeObject> {\n\treturn Array.isArray(ranges);\n}\n\nfunction getLastRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.last() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction getFirstRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.first() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction extractFirstFinalFromRange<TRangeObject>(finalRange: FinalRange<TRangeObject>): FinalCompressedId {\n\treturn finalRange[0];\n}\n\nfunction getPairOrNextLowerByValue<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tfinalId: FinalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (finalId < finalRanges[0]) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLowerByValue(finalId);\n}\n\nfunction getPairOrNextLower<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tlocalId: LocalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (localId > firstLocal) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLower(localId);\n}\n\nfunction* entries<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined\n): IterableIterator<readonly [LocalCompressedId, FinalRange<TRangeObject>]> {\n\tif (finalRanges !== undefined) {\n\t\tif (isSingleRange(finalRanges)) {\n\t\t\tyield [firstLocal, finalRanges];\n\t\t} else {\n\t\t\tfor (const range of finalRanges.entries()) {\n\t\t\t\tyield range;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IdCompressor.d.ts","sourceRoot":"","sources":["../../src/id-compressor/IdCompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAetE,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,QAAQ,EACR,mBAAmB,EACnB,SAAS,EACT,YAAY,EAEZ,aAAa,EACb,MAAM,gBAAgB,CAAC;AAaxB,OAAO,KAAK,EACX,eAAe,EAIf,mCAAmC,EACnC,wCAAwC,EAIxC,+BAA+B,EAC/B,MAAM,mBAAmB,CAAC;AA2E3B;;;GAGG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAQ1C;;;GAGG;AACH,eAAO,MAAM,6BAA6B,0CAA0C,CAAC;AAErF;;GAEG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,YAAY,GAAG,EAAE,IAAI,iBAAiB,CAEnE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,YAAY,GAAG,EAAE,IAAI,iBAAiB,CAEnE;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,qBAAa,YAAY;aAuHP,cAAc,EAAE,SAAS;aACzB,eAAe,EAAE,MAAM;IAEvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAzHzB;;OAEG;IACH,OAAc,cAAc,SAAW;IAEvC;;;OAGG;IACH,OAAO,CAAC,kBAAkB,CAA0B;IAEpD;;OAEG;IACH,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED;;;OAGG;IACH,IAAW,eAAe,CAAC,KAAK,EAAE,MAAM,EAIvC;IAED;;OAEG;IACH,IAAW,aAAa,IAAI,aAAa,CAExC;IAED;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAE1D;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IAEvC;;OAEG;IACH,OAAO,CAAC,sBAAsB,CAA6C;IAE3E;;OAEG;IACH,OAAO,CAAC,YAAY,CAAK;IAEzB;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAAgC;IAExD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoF;IAEnH;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,mBAAmB,CAAwC;IAEnE;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAG5C;IAEF;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAE/B;IAEF;;;;;;;;;;OAUG;gBAEc,cAAc,EAAE,SAAS,EACzB,eAAe,EAAE,MAAM,EACvC,aAAa,CAAC,EAAE,aAAa,EACZ,MAAM,CAAC,8BAAkB;IAuB3C;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAiBrB;;;OAGG;IACI,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,wBAAwB,GAAG,iBAAiB;IAUjF;;OAEG;IACI,yBAAyB,IAAI,gBAAgB,CAAC,wBAAwB,CAAC;IAI9E;;OAEG;IACI,WAAW,CAAC,EAAE,EAAE,wBAAwB,GAAG,aAAa;IAiB/D;;;;;OAKG;IACI,qBAAqB,IAAI,eAAe;IAsD/C;;;OAGG;IACI,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"IdCompressor.d.ts","sourceRoot":"","sources":["../../src/id-compressor/IdCompressor.ts"],"names":[],"mappings":"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"}
|
|
@@ -349,12 +349,12 @@ export class IdCompressor {
|
|
|
349
349
|
if (currentClusterExists) {
|
|
350
350
|
if (isLocal) {
|
|
351
351
|
const lastKnownFinal = (_c = this.sessionIdNormalizer.getLastFinalId()) !== null && _c !== void 0 ? _c : fail('Cluster exists but normalizer does not have an entry for it.');
|
|
352
|
-
const
|
|
352
|
+
const lastAlignedFinalInCluster = (currentBaseFinalId +
|
|
353
353
|
Math.min(currentCluster.count + finalizeCount, currentCluster.capacity) -
|
|
354
354
|
1);
|
|
355
|
-
if (
|
|
356
|
-
eagerFinalIdCount =
|
|
357
|
-
this.sessionIdNormalizer.addFinalIds((lastKnownFinal + 1),
|
|
355
|
+
if (lastAlignedFinalInCluster > lastKnownFinal) {
|
|
356
|
+
eagerFinalIdCount = lastAlignedFinalInCluster - (lastKnownFinal + 1);
|
|
357
|
+
this.sessionIdNormalizer.addFinalIds((lastKnownFinal + 1), lastAlignedFinalInCluster, currentCluster);
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
360
|
initialClusterCount = currentCluster.count;
|
|
@@ -385,9 +385,17 @@ export class IdCompressor {
|
|
|
385
385
|
// overflow = 2: ----
|
|
386
386
|
// localIdPivot^
|
|
387
387
|
// lastFinalizedFinal^
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
388
|
+
const newLastFinalizedFinal = (currentBaseFinalId +
|
|
389
|
+
currentCluster.count -
|
|
390
|
+
1);
|
|
391
|
+
assert(session.lastFinalizedLocalId !== undefined, 'Cluster already exists for session but there is no finalized local ID');
|
|
392
|
+
const finalPivot = (newLastFinalizedFinal - overflow + 1);
|
|
393
|
+
// Inform the normalizer of all IDs that we now know will end up being finalized into this cluster, including the ones
|
|
394
|
+
// that were given out as locals (non-eager) because they exceeded the bounds of the current cluster before it was expanded.
|
|
395
|
+
// It is safe to associate the unfinalized locals with their future final IDs even before the ranges for those locals are
|
|
396
|
+
// actually finalized, because total order broadcast guarantees that any usage of those final IDs will be observed after
|
|
397
|
+
// the finalization of the ranges.
|
|
398
|
+
this.sessionIdNormalizer.registerFinalIdBlock(finalPivot, expansionAmount, currentCluster);
|
|
391
399
|
(_d = this.logger) === null || _d === void 0 ? void 0 : _d.sendTelemetryEvent({
|
|
392
400
|
eventName: 'IdCompressor:ClusterExpansion',
|
|
393
401
|
sessionId: this.localSessionId,
|
|
@@ -453,8 +461,7 @@ export class IdCompressor {
|
|
|
453
461
|
clusterCapacity: newCapacity,
|
|
454
462
|
clusterCount: remainingCount,
|
|
455
463
|
});
|
|
456
|
-
|
|
457
|
-
this.sessionIdNormalizer.addFinalIds(newBaseFinalId, lastFinalizedFinal, newCluster);
|
|
464
|
+
this.sessionIdNormalizer.registerFinalIdBlock(newBaseFinalId, newCluster.capacity, newCluster);
|
|
458
465
|
}
|
|
459
466
|
this.checkClusterForCollision(newCluster);
|
|
460
467
|
this.clustersAndOverridesInversion.set(stableIdFromNumericUuid(newCluster.baseUuid), {
|
|
@@ -704,10 +711,10 @@ export class IdCompressor {
|
|
|
704
711
|
let eagerFinalId;
|
|
705
712
|
let cluster;
|
|
706
713
|
if (currentClusterDetails !== undefined) {
|
|
707
|
-
const { clusterBase } = currentClusterDetails;
|
|
708
714
|
cluster = currentClusterDetails.cluster;
|
|
709
715
|
const lastFinalKnown = sessionIdNormalizer.getLastFinalId();
|
|
710
|
-
if (lastFinalKnown !== undefined &&
|
|
716
|
+
if (lastFinalKnown !== undefined &&
|
|
717
|
+
lastFinalKnown - currentClusterDetails.clusterBase + 1 < cluster.capacity) {
|
|
711
718
|
eagerFinalId = (lastFinalKnown + 1);
|
|
712
719
|
}
|
|
713
720
|
}
|
|
@@ -858,7 +865,7 @@ export class IdCompressor {
|
|
|
858
865
|
* @returns the ID in op space.
|
|
859
866
|
*/
|
|
860
867
|
normalizeToOpSpace(id) {
|
|
861
|
-
var _a, _b;
|
|
868
|
+
var _a, _b, _c;
|
|
862
869
|
if (isFinalId(id)) {
|
|
863
870
|
return id;
|
|
864
871
|
}
|
|
@@ -878,15 +885,16 @@ export class IdCompressor {
|
|
|
878
885
|
if (override !== undefined) {
|
|
879
886
|
const inversionKey = IdCompressor.createInversionKey(override);
|
|
880
887
|
const compressionMapping = (_a = this.clustersAndOverridesInversion.get(inversionKey)) !== null && _a !== void 0 ? _a : fail('Bimap is malformed.');
|
|
881
|
-
|
|
888
|
+
return !IdCompressor.isClusterInfo(compressionMapping) &&
|
|
882
889
|
!IdCompressor.isUnfinalizedOverride(compressionMapping) &&
|
|
883
|
-
compressionMapping.associatedLocalId === id
|
|
884
|
-
|
|
885
|
-
|
|
890
|
+
compressionMapping.associatedLocalId === id
|
|
891
|
+
? compressionMapping.originalOverridingFinal
|
|
892
|
+
: id;
|
|
886
893
|
}
|
|
887
|
-
|
|
894
|
+
const possibleFinal = this.sessionIdNormalizer.getFinalId(id);
|
|
895
|
+
return (_b = possibleFinal === null || possibleFinal === void 0 ? void 0 : possibleFinal[0]) !== null && _b !== void 0 ? _b : id;
|
|
888
896
|
}
|
|
889
|
-
const [correspondingFinal, cluster] = (
|
|
897
|
+
const [correspondingFinal, cluster] = (_c = this.sessionIdNormalizer.getFinalId(id)) !== null && _c !== void 0 ? _c : fail('Locally created cluster should be added to the map when allocated');
|
|
890
898
|
if (cluster.overrides) {
|
|
891
899
|
const override = cluster.overrides.get(correspondingFinal);
|
|
892
900
|
if (typeof override === 'object' && override.originalOverridingFinal !== undefined) {
|