@fluid-experimental/tree 0.59.2001 → 0.59.3000
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +2 -0
- package/.vscode/SharedTree.code-workspace +15 -0
- package/.vscode/settings.json +6 -0
- package/dist/ChangeCompression.js +9 -9
- package/dist/ChangeCompression.js.map +1 -1
- package/dist/ChangeTypes.d.ts +1 -6
- package/dist/ChangeTypes.d.ts.map +1 -1
- package/dist/ChangeTypes.js +5 -5
- package/dist/ChangeTypes.js.map +1 -1
- package/dist/Checkout.js +14 -14
- package/dist/Checkout.js.map +1 -1
- package/dist/Common.d.ts +21 -3
- package/dist/Common.d.ts.map +1 -1
- package/dist/Common.js +29 -4
- package/dist/Common.js.map +1 -1
- package/dist/EditLog.js +26 -25
- package/dist/EditLog.js.map +1 -1
- package/dist/EditUtilities.js +17 -17
- package/dist/EditUtilities.js.map +1 -1
- package/dist/Forest.js +31 -31
- package/dist/Forest.js.map +1 -1
- package/dist/HistoryEditFactory.js +9 -9
- package/dist/HistoryEditFactory.js.map +1 -1
- package/dist/IdConversion.js +9 -9
- package/dist/IdConversion.js.map +1 -1
- package/dist/Identifiers.d.ts +4 -0
- package/dist/Identifiers.d.ts.map +1 -1
- package/dist/Identifiers.js.map +1 -1
- package/dist/LogViewer.d.ts +1 -5
- package/dist/LogViewer.d.ts.map +1 -1
- package/dist/LogViewer.js +11 -19
- package/dist/LogViewer.js.map +1 -1
- package/dist/MergeHealth.js +2 -2
- package/dist/MergeHealth.js.map +1 -1
- package/dist/NodeIdUtilities.js +2 -2
- package/dist/NodeIdUtilities.js.map +1 -1
- package/dist/PayloadUtilities.js +1 -1
- package/dist/PayloadUtilities.js.map +1 -1
- package/dist/RevisionValueCache.d.ts +13 -10
- package/dist/RevisionValueCache.d.ts.map +1 -1
- package/dist/RevisionValueCache.js +14 -11
- package/dist/RevisionValueCache.js.map +1 -1
- package/dist/RevisionView.js +4 -4
- package/dist/RevisionView.js.map +1 -1
- package/dist/SerializationUtilities.js +4 -4
- package/dist/SerializationUtilities.js.map +1 -1
- package/dist/SharedTree.d.ts +93 -31
- package/dist/SharedTree.d.ts.map +1 -1
- package/dist/SharedTree.js +160 -131
- package/dist/SharedTree.js.map +1 -1
- package/dist/SharedTreeEncoder.d.ts +3 -3
- package/dist/SharedTreeEncoder.d.ts.map +1 -1
- package/dist/SharedTreeEncoder.js +36 -36
- package/dist/SharedTreeEncoder.js.map +1 -1
- package/dist/StringInterner.js +1 -1
- package/dist/StringInterner.js.map +1 -1
- package/dist/Summary.js +1 -1
- package/dist/Summary.js.map +1 -1
- package/dist/SummaryBackCompatibility.js +8 -8
- package/dist/SummaryBackCompatibility.js.map +1 -1
- package/dist/Transaction.js +1 -1
- package/dist/Transaction.js.map +1 -1
- package/dist/TransactionInternal.js +17 -17
- package/dist/TransactionInternal.js.map +1 -1
- package/dist/TreeCompressor.d.ts.map +1 -1
- package/dist/TreeCompressor.js +6 -8
- package/dist/TreeCompressor.js.map +1 -1
- package/dist/TreeNodeHandle.js +4 -4
- package/dist/TreeNodeHandle.js.map +1 -1
- package/dist/TreeView.js +7 -7
- package/dist/TreeView.js.map +1 -1
- package/dist/TreeViewUtilities.js +2 -2
- package/dist/TreeViewUtilities.js.map +1 -1
- package/dist/UndoRedoHandler.js +1 -1
- package/dist/UndoRedoHandler.js.map +1 -1
- package/dist/UuidUtilities.d.ts +30 -0
- package/dist/UuidUtilities.d.ts.map +1 -0
- package/dist/UuidUtilities.js +106 -0
- package/dist/UuidUtilities.js.map +1 -0
- package/dist/id-compressor/AppendOnlySortedMap.d.ts +52 -28
- package/dist/id-compressor/AppendOnlySortedMap.d.ts.map +1 -1
- package/dist/id-compressor/AppendOnlySortedMap.js +167 -90
- package/dist/id-compressor/AppendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/IdCompressor.d.ts +43 -42
- package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
- package/dist/id-compressor/IdCompressor.js +179 -177
- package/dist/id-compressor/IdCompressor.js.map +1 -1
- package/dist/id-compressor/IdRange.js +1 -1
- package/dist/id-compressor/IdRange.js.map +1 -1
- package/dist/id-compressor/NumericUuid.d.ts +6 -14
- package/dist/id-compressor/NumericUuid.d.ts.map +1 -1
- package/dist/id-compressor/NumericUuid.js +15 -76
- package/dist/id-compressor/NumericUuid.js.map +1 -1
- package/dist/id-compressor/SessionIdNormalizer.d.ts +122 -0
- package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -0
- package/dist/id-compressor/SessionIdNormalizer.js +418 -0
- package/dist/id-compressor/SessionIdNormalizer.js.map +1 -0
- package/dist/id-compressor/persisted-types/0.0.1.d.ts +6 -13
- package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
- package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/persisted-types/0.1.1.d.ts +1 -6
- package/dist/persisted-types/0.1.1.d.ts.map +1 -1
- package/dist/persisted-types/0.1.1.js +3 -3
- package/dist/persisted-types/0.1.1.js.map +1 -1
- package/lib/ChangeTypes.d.ts +1 -6
- package/lib/ChangeTypes.d.ts.map +1 -1
- package/lib/Checkout.js.map +1 -1
- package/lib/Common.d.ts +21 -3
- package/lib/Common.d.ts.map +1 -1
- package/lib/Common.js +25 -3
- package/lib/Common.js.map +1 -1
- package/lib/EditLog.js +2 -1
- package/lib/EditLog.js.map +1 -1
- package/lib/EditUtilities.js.map +1 -1
- package/lib/Forest.js.map +1 -1
- package/lib/HistoryEditFactory.js.map +1 -1
- package/lib/Identifiers.d.ts +4 -0
- package/lib/Identifiers.d.ts.map +1 -1
- package/lib/Identifiers.js.map +1 -1
- package/lib/LogViewer.d.ts +1 -5
- package/lib/LogViewer.d.ts.map +1 -1
- package/lib/LogViewer.js +5 -13
- package/lib/LogViewer.js.map +1 -1
- package/lib/MergeHealth.js.map +1 -1
- package/lib/NodeIdUtilities.js.map +1 -1
- package/lib/RevisionValueCache.d.ts +13 -10
- package/lib/RevisionValueCache.d.ts.map +1 -1
- package/lib/RevisionValueCache.js +10 -7
- package/lib/RevisionValueCache.js.map +1 -1
- package/lib/RevisionView.js.map +1 -1
- package/lib/SharedTree.d.ts +93 -31
- package/lib/SharedTree.d.ts.map +1 -1
- package/lib/SharedTree.js +107 -78
- package/lib/SharedTree.js.map +1 -1
- package/lib/SharedTreeEncoder.d.ts +3 -3
- package/lib/SharedTreeEncoder.d.ts.map +1 -1
- package/lib/SharedTreeEncoder.js +4 -4
- package/lib/SharedTreeEncoder.js.map +1 -1
- package/lib/StringInterner.js.map +1 -1
- package/lib/Summary.js.map +1 -1
- package/lib/TreeCompressor.d.ts.map +1 -1
- package/lib/TreeCompressor.js +1 -3
- package/lib/TreeCompressor.js.map +1 -1
- package/lib/TreeNodeHandle.js.map +1 -1
- package/lib/TreeView.js.map +1 -1
- package/lib/TreeViewUtilities.js.map +1 -1
- package/lib/UuidUtilities.d.ts +30 -0
- package/lib/UuidUtilities.d.ts.map +1 -0
- package/lib/UuidUtilities.js +98 -0
- package/lib/UuidUtilities.js.map +1 -0
- package/lib/id-compressor/AppendOnlySortedMap.d.ts +52 -28
- package/lib/id-compressor/AppendOnlySortedMap.d.ts.map +1 -1
- package/lib/id-compressor/AppendOnlySortedMap.js +165 -88
- package/lib/id-compressor/AppendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/IdCompressor.d.ts +43 -42
- package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
- package/lib/id-compressor/IdCompressor.js +97 -95
- package/lib/id-compressor/IdCompressor.js.map +1 -1
- package/lib/id-compressor/NumericUuid.d.ts +6 -14
- package/lib/id-compressor/NumericUuid.d.ts.map +1 -1
- package/lib/id-compressor/NumericUuid.js +11 -70
- package/lib/id-compressor/NumericUuid.js.map +1 -1
- package/lib/id-compressor/SessionIdNormalizer.d.ts +122 -0
- package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -0
- package/lib/id-compressor/SessionIdNormalizer.js +414 -0
- package/lib/id-compressor/SessionIdNormalizer.js.map +1 -0
- package/lib/id-compressor/persisted-types/0.0.1.d.ts +6 -13
- package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
- package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/persisted-types/0.1.1.d.ts +1 -6
- package/lib/persisted-types/0.1.1.d.ts.map +1 -1
- package/lib/persisted-types/0.1.1.js.map +1 -1
- package/lib/test/AppendOnlySortedMap.perf.tests.d.ts +6 -0
- package/lib/test/AppendOnlySortedMap.perf.tests.d.ts.map +1 -0
- package/lib/test/AppendOnlySortedMap.perf.tests.js +49 -0
- package/lib/test/AppendOnlySortedMap.perf.tests.js.map +1 -0
- package/lib/test/AppendOnlySortedMap.tests.js +56 -14
- package/lib/test/AppendOnlySortedMap.tests.js.map +1 -1
- package/lib/test/Checkout.tests.js +2 -2
- package/lib/test/Checkout.tests.js.map +1 -1
- package/lib/test/Forest.tests.js.map +1 -1
- package/lib/test/IdCompressor.perf.tests.js +8 -2
- package/lib/test/IdCompressor.perf.tests.js.map +1 -1
- package/lib/test/IdCompressor.tests.js +75 -24
- package/lib/test/IdCompressor.tests.js.map +1 -1
- package/lib/test/LogViewer.tests.js +3 -5
- package/lib/test/LogViewer.tests.js.map +1 -1
- package/lib/test/NumericUuid.perf.tests.js +4 -4
- package/lib/test/NumericUuid.perf.tests.js.map +1 -1
- package/lib/test/NumericUuid.tests.js +5 -4
- package/lib/test/NumericUuid.tests.js.map +1 -1
- package/lib/test/RevisionValueCache.tests.js.map +1 -1
- package/lib/test/RevisionView.tests.js.map +1 -1
- package/lib/test/SessionIdNormalizer.tests.d.ts +6 -0
- package/lib/test/SessionIdNormalizer.tests.d.ts.map +1 -0
- package/lib/test/SessionIdNormalizer.tests.js +299 -0
- package/lib/test/SessionIdNormalizer.tests.js.map +1 -0
- package/lib/test/Summary.tests.js +1 -1
- package/lib/test/Summary.tests.js.map +1 -1
- package/lib/test/TreeCompression.tests.js +1 -1
- package/lib/test/TreeCompression.tests.js.map +1 -1
- package/lib/test/Virtualization.tests.js +1 -1
- package/lib/test/Virtualization.tests.js.map +1 -1
- package/lib/test/fuzz/Generators.d.ts +3 -14
- package/lib/test/fuzz/Generators.d.ts.map +1 -1
- package/lib/test/fuzz/Generators.js +60 -151
- package/lib/test/fuzz/Generators.js.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.d.ts +10 -7
- package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.js +94 -104
- package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
- package/lib/test/fuzz/Types.d.ts +2 -9
- package/lib/test/fuzz/Types.d.ts.map +1 -1
- package/lib/test/fuzz/Types.js +1 -1
- package/lib/test/fuzz/Types.js.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts +57 -11
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.js +112 -98
- package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -1
- package/lib/test/utilities/PendingLocalStateTests.d.ts.map +1 -1
- package/lib/test/utilities/PendingLocalStateTests.js +2 -1
- package/lib/test/utilities/PendingLocalStateTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeTests.js +30 -1
- package/lib/test/utilities/SharedTreeTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.js +20 -0
- package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
- package/lib/test/utilities/SummaryLoadPerfTests.d.ts.map +1 -1
- package/lib/test/utilities/SummaryLoadPerfTests.js +6 -3
- package/lib/test/utilities/SummaryLoadPerfTests.js.map +1 -1
- package/lib/test/utilities/TestNode.js.map +1 -1
- package/lib/test/utilities/TestUtilities.d.ts +9 -1
- package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/TestUtilities.js +27 -13
- package/lib/test/utilities/TestUtilities.js.map +1 -1
- package/package.json +19 -17
- package/src/Common.ts +42 -4
- package/src/EditLog.ts +1 -1
- package/src/Identifiers.ts +5 -0
- package/src/LogViewer.ts +4 -20
- package/src/RevisionValueCache.ts +11 -8
- package/src/SharedTree.ts +222 -75
- package/src/SharedTreeEncoder.ts +17 -11
- package/src/TreeCompressor.ts +2 -4
- package/src/UuidUtilities.ts +123 -0
- package/src/id-compressor/AppendOnlySortedMap.ts +183 -94
- package/src/id-compressor/IdCompressor.ts +144 -132
- package/src/id-compressor/NumericUuid.ts +11 -80
- package/src/id-compressor/SessionIdNormalizer.ts +497 -0
- package/src/id-compressor/persisted-types/0.0.1.ts +12 -15
- package/src/index.ts +5 -0
|
@@ -11,6 +11,7 @@ exports.hasOngoingSession = exports.IdCompressor = exports.isLocalId = exports.i
|
|
|
11
11
|
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
|
12
12
|
const sorted_btree_1 = __importDefault(require("sorted-btree"));
|
|
13
13
|
const Common_1 = require("../Common");
|
|
14
|
+
const UuidUtilities_1 = require("../UuidUtilities");
|
|
14
15
|
const AppendOnlySortedMap_1 = require("./AppendOnlySortedMap");
|
|
15
16
|
const IdRange_1 = require("./IdRange");
|
|
16
17
|
const NumericUuid_1 = require("./NumericUuid");
|
|
@@ -23,7 +24,7 @@ exports.defaultClusterCapacity = 512;
|
|
|
23
24
|
* The base UUID for the reserved id cluster.
|
|
24
25
|
* This should not be changed without consideration to compatibility.
|
|
25
26
|
*/
|
|
26
|
-
const reservedSessionId = NumericUuid_1.ensureSessionUuid(
|
|
27
|
+
const reservedSessionId = (0, NumericUuid_1.ensureSessionUuid)((0, UuidUtilities_1.assertIsStableId)('decaf40b-3c1a-47f8-a7a1-e8461ddb69ce'));
|
|
27
28
|
/**
|
|
28
29
|
* The ID override for the initial tree of a SharedTree. An artifact of an unfortunate typo which included an extraneous '6' on the UUID
|
|
29
30
|
* which must be forever preserved for backwards compatibility.
|
|
@@ -106,14 +107,17 @@ const nonStableOverridePrefix = '\ue15e'; // A character in the Private Use Area
|
|
|
106
107
|
*/
|
|
107
108
|
class IdCompressor {
|
|
108
109
|
/**
|
|
109
|
-
* @param localSessionId the `IdCompressor`'s current local session ID.
|
|
110
|
-
* @param reservedIdCount the number of IDs that will be known by this compressor without relying on consensus.
|
|
111
|
-
* for a given session must be constant for any compressor that contains IDs from that session
|
|
112
|
-
* compressor must have the same reservedIdCount forever). Compressors with different
|
|
113
|
-
* IDs.
|
|
114
|
-
* @param
|
|
110
|
+
* @param localSessionId - the `IdCompressor`'s current local session ID.
|
|
111
|
+
* @param reservedIdCount - the number of IDs that will be known by this compressor without relying on consensus.
|
|
112
|
+
* The reserved ID count for a given session must be constant for any compressor that contains IDs from that session
|
|
113
|
+
* (i.e. any DDS that uses the ID compressor must have the same reservedIdCount forever). Compressors with different
|
|
114
|
+
* reserved ID counts will fail to synchronize their IDs.
|
|
115
|
+
* @param attributionId - a UUID that identifies the user of this instance of the compressor. IDs created by this
|
|
116
|
+
* compressor will be associated with this UUID and can be queried later via `attributeID`. If no UUID is provided,
|
|
117
|
+
* this compressor will generate its own. An `AttributionId` is an `UuidString` which may be validated via
|
|
118
|
+
* {@link isUuidString} or generated via {@link generateStableId}.
|
|
115
119
|
*/
|
|
116
|
-
constructor(localSessionId, reservedIdCount,
|
|
120
|
+
constructor(localSessionId, reservedIdCount, attributionId) {
|
|
117
121
|
this.localSessionId = localSessionId;
|
|
118
122
|
this.reservedIdCount = reservedIdCount;
|
|
119
123
|
/**
|
|
@@ -122,14 +126,10 @@ class IdCompressor {
|
|
|
122
126
|
*/
|
|
123
127
|
this.newClusterCapacity = exports.defaultClusterCapacity;
|
|
124
128
|
/**
|
|
125
|
-
* Session ID
|
|
129
|
+
* Session ID -\> data about the session's current cluster.
|
|
126
130
|
* Sessions are mutable, and thus should only be created via `createSession`.
|
|
127
131
|
*/
|
|
128
132
|
this.sessions = new Map();
|
|
129
|
-
/**
|
|
130
|
-
* Boolean to track whether attribution has been sent with an ID range yet. Prevents unnecessary bloat of ranges.
|
|
131
|
-
*/
|
|
132
|
-
this.sentAttributionInfo = false;
|
|
133
133
|
/**
|
|
134
134
|
* The base final ID of the next cluster to be created.
|
|
135
135
|
*/
|
|
@@ -142,13 +142,13 @@ class IdCompressor {
|
|
|
142
142
|
* Maps local IDs to override strings. This will contain an entry for every override assigned to a local ID generated during
|
|
143
143
|
* the current session, and retains entries for the lifetime of this compressor.
|
|
144
144
|
*/
|
|
145
|
-
this.localOverrides = new AppendOnlySortedMap_1.AppendOnlySortedMap(compareFiniteNumbersReversed);
|
|
145
|
+
this.localOverrides = new AppendOnlySortedMap_1.AppendOnlySortedMap(Common_1.compareFiniteNumbersReversed);
|
|
146
146
|
/**
|
|
147
147
|
* Maps local IDs to the cluster they belong to (if any). This can be used to efficiently convert a local ID to a
|
|
148
|
-
* final ID by finding an entry
|
|
148
|
+
* final ID by finding an entry \<= a given local ID (to find the cluster it is associated with) and checking
|
|
149
149
|
* it against `numFinalizedLocalIds`.
|
|
150
150
|
*/
|
|
151
|
-
this.localIdToCluster = new AppendOnlySortedMap_1.AppendOnlyDoublySortedMap(compareFiniteNumbersReversed, (value) => value[0],
|
|
151
|
+
this.localIdToCluster = new AppendOnlySortedMap_1.AppendOnlyDoublySortedMap(Common_1.compareFiniteNumbersReversed, (value) => value[0], Common_1.compareFiniteNumbers);
|
|
152
152
|
/**
|
|
153
153
|
* Contains entries for cluster base UUIDs and override strings (both local and final).
|
|
154
154
|
* As a performance optimization, entries for finalized strings also include the containing cluster object.
|
|
@@ -163,8 +163,11 @@ class IdCompressor {
|
|
|
163
163
|
* Can be searched in O(log n) to determine clusters for any final ID.
|
|
164
164
|
*/
|
|
165
165
|
this.finalIdToCluster = new AppendOnlySortedMap_1.AppendOnlySortedMap(Common_1.compareFiniteNumbers);
|
|
166
|
-
Common_1.assert(reservedIdCount >= 0, 'reservedIdCount must be non-negative');
|
|
167
|
-
|
|
166
|
+
(0, Common_1.assert)(reservedIdCount >= 0, 'reservedIdCount must be non-negative');
|
|
167
|
+
if (attributionId !== undefined) {
|
|
168
|
+
(0, UuidUtilities_1.assertIsUuidString)(attributionId);
|
|
169
|
+
}
|
|
170
|
+
this.localSession = this.createSession(localSessionId, attributionId);
|
|
168
171
|
if (reservedIdCount > 0) {
|
|
169
172
|
const clusterCapacity = this.clusterCapacity;
|
|
170
173
|
this.clusterCapacity = reservedIdCount;
|
|
@@ -172,7 +175,7 @@ class IdCompressor {
|
|
|
172
175
|
sessionId: reservedSessionId,
|
|
173
176
|
ids: {
|
|
174
177
|
last: -reservedIdCount,
|
|
175
|
-
overrides: [[-1, exports.legacySharedTreeInitialTreeId]],
|
|
178
|
+
overrides: [[-1, exports.legacySharedTreeInitialTreeId]], // Kludge: see `initialTreeId`
|
|
176
179
|
},
|
|
177
180
|
};
|
|
178
181
|
// Reserved final IDs are implicitly finalized and no one locally created them, so finalizing immediately is safe.
|
|
@@ -191,48 +194,51 @@ class IdCompressor {
|
|
|
191
194
|
* `IdCompressor.maxClusterSize`.
|
|
192
195
|
*/
|
|
193
196
|
set clusterCapacity(value) {
|
|
194
|
-
Common_1.assert(value > 0, 'Clusters must have a positive capacity');
|
|
195
|
-
Common_1.assert(value <= IdCompressor.maxClusterSize, 'Clusters must not exceed max cluster size');
|
|
197
|
+
(0, Common_1.assert)(value > 0, 'Clusters must have a positive capacity');
|
|
198
|
+
(0, Common_1.assert)(value <= IdCompressor.maxClusterSize, 'Clusters must not exceed max cluster size');
|
|
196
199
|
this.newClusterCapacity = value;
|
|
197
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* The UUID used for attribution of identities created by this compressor
|
|
203
|
+
*/
|
|
204
|
+
get attributionId() {
|
|
205
|
+
return this.localSession.attributionId;
|
|
206
|
+
}
|
|
198
207
|
/**
|
|
199
208
|
* Helper comparator for searching append-only sorted maps.
|
|
200
209
|
*/
|
|
201
210
|
static overrideComparator(search, element) {
|
|
202
|
-
return Common_1.compareFiniteNumbers(search, element[0]);
|
|
211
|
+
return (0, Common_1.compareFiniteNumbers)(search, element[0]);
|
|
203
212
|
}
|
|
204
213
|
/**
|
|
205
214
|
* Creates a session object for the supplied ID.
|
|
206
215
|
* Must only be called once per ID.
|
|
207
|
-
* @param sessionId the ID for the session
|
|
216
|
+
* @param sessionId - the ID for the session
|
|
208
217
|
* @returns the session object for the supplied ID
|
|
209
218
|
*/
|
|
210
|
-
createSession(sessionId,
|
|
219
|
+
createSession(sessionId, attributionId) {
|
|
220
|
+
(0, Common_1.assert)(!this.clustersAndOverridesInversion.has(sessionId));
|
|
211
221
|
const existingSession = this.sessions.get(sessionId);
|
|
212
222
|
if (existingSession !== undefined) {
|
|
213
|
-
Common_1.fail('createSession must only be called once for each session ID.');
|
|
223
|
+
(0, Common_1.fail)('createSession must only be called once for each session ID.');
|
|
214
224
|
}
|
|
215
|
-
const sessionUuid = NumericUuid_1.numericUuidFromStableId(sessionId);
|
|
216
|
-
Common_1.assert(!this.clustersAndOverridesInversion.has(sessionId));
|
|
225
|
+
const sessionUuid = (0, NumericUuid_1.numericUuidFromStableId)(sessionId);
|
|
217
226
|
const session = {
|
|
218
227
|
sessionUuid,
|
|
219
228
|
currentClusterDetails: undefined,
|
|
220
229
|
lastFinalizedLocalId: undefined,
|
|
230
|
+
attributionId: attributionId !== null && attributionId !== void 0 ? attributionId : sessionId,
|
|
221
231
|
};
|
|
222
|
-
Common_1.setPropertyIfDefined(attributionInfo, session, 'attributionInfo');
|
|
223
232
|
this.sessions.set(sessionId, session);
|
|
224
233
|
return session;
|
|
225
234
|
}
|
|
226
|
-
tryGetSession(sessionId) {
|
|
227
|
-
return this.sessions.get(sessionId);
|
|
228
|
-
}
|
|
229
235
|
/**
|
|
230
236
|
* Return the nth reserved ID.
|
|
231
|
-
* @param index the index of the ID to return
|
|
237
|
+
* @param index - the index of the ID to return
|
|
232
238
|
*/
|
|
233
239
|
getReservedId(index) {
|
|
234
240
|
if (index < 0 || index >= this.reservedIdCount) {
|
|
235
|
-
Common_1.fail('Reserved Id index out of bounds');
|
|
241
|
+
(0, Common_1.fail)('Reserved Id index out of bounds');
|
|
236
242
|
}
|
|
237
243
|
// All reserved IDs are contiguous and finalized during the Compressor's construction, therefore they are always the lowest
|
|
238
244
|
// final IDs, beginning at 0
|
|
@@ -248,16 +254,16 @@ class IdCompressor {
|
|
|
248
254
|
}
|
|
249
255
|
}
|
|
250
256
|
/**
|
|
251
|
-
* Returns the attribution
|
|
257
|
+
* Returns the attribution ID associated with the compressor that created the ID
|
|
252
258
|
*/
|
|
253
259
|
attributeId(id) {
|
|
254
260
|
var _a;
|
|
255
261
|
const opSpaceNormalizedId = this.normalizeToOpSpace(id);
|
|
256
262
|
if (isLocalId(opSpaceNormalizedId)) {
|
|
257
|
-
return this.
|
|
263
|
+
return this.attributionId;
|
|
258
264
|
}
|
|
259
|
-
const [_, cluster] = (_a = this.getClusterForFinalId(opSpaceNormalizedId)) !== null && _a !== void 0 ? _a : Common_1.fail('Cluster does not exist for final ID');
|
|
260
|
-
return cluster.session.
|
|
265
|
+
const [_, cluster] = (_a = this.getClusterForFinalId(opSpaceNormalizedId)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Cluster does not exist for final ID');
|
|
266
|
+
return cluster.session.attributionId;
|
|
261
267
|
}
|
|
262
268
|
/**
|
|
263
269
|
* Provides the session-space IDs corresponding to a range of IDs.
|
|
@@ -271,26 +277,26 @@ class IdCompressor {
|
|
|
271
277
|
length: count,
|
|
272
278
|
get: (index) => {
|
|
273
279
|
if (index < 0 || index >= count) {
|
|
274
|
-
Common_1.fail('Index out of bounds of range.');
|
|
280
|
+
(0, Common_1.fail)('Index out of bounds of range.');
|
|
275
281
|
}
|
|
276
282
|
return (first - index);
|
|
277
283
|
},
|
|
278
284
|
};
|
|
279
285
|
}
|
|
280
286
|
else {
|
|
281
|
-
const session = (_a = this.
|
|
282
|
-
const firstNumericUuid = NumericUuid_1.incrementUuid(session.sessionUuid, -first - 1);
|
|
283
|
-
const firstFinal = (_b = this.compressNumericUuid(firstNumericUuid)) !== null && _b !== void 0 ? _b : Common_1.fail('Remote range must be finalized before getting IDs.');
|
|
284
|
-
Common_1.assert(isFinalId(firstFinal), 'ID from a remote session ID must have final form, as overrides are impossible by definition.');
|
|
285
|
-
const [baseFinalId, cluster] = (_c = this.getClusterForFinalId(firstFinal)) !== null && _c !== void 0 ? _c : Common_1.fail();
|
|
287
|
+
const session = (_a = this.sessions.get(sessionId)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Unknown session, range may not be finalized.');
|
|
288
|
+
const firstNumericUuid = (0, NumericUuid_1.incrementUuid)(session.sessionUuid, -first - 1);
|
|
289
|
+
const firstFinal = (_b = this.compressNumericUuid(firstNumericUuid)) !== null && _b !== void 0 ? _b : (0, Common_1.fail)('Remote range must be finalized before getting IDs.');
|
|
290
|
+
(0, Common_1.assert)(isFinalId(firstFinal), 'ID from a remote session ID must have final form, as overrides are impossible by definition.');
|
|
291
|
+
const [baseFinalId, cluster] = (_c = this.getClusterForFinalId(firstFinal)) !== null && _c !== void 0 ? _c : (0, Common_1.fail)();
|
|
286
292
|
const numIdsRemainingInFirstCluster = cluster.capacity - (firstFinal - baseFinalId);
|
|
287
293
|
let pivotFinal;
|
|
288
294
|
if (count > numIdsRemainingInFirstCluster) {
|
|
289
|
-
const compressedPivot = this.compressNumericUuid(NumericUuid_1.incrementUuid(firstNumericUuid, numIdsRemainingInFirstCluster));
|
|
295
|
+
const compressedPivot = this.compressNumericUuid((0, NumericUuid_1.incrementUuid)(firstNumericUuid, numIdsRemainingInFirstCluster));
|
|
290
296
|
// Looking up the actual cluster can be avoided, as it is guaranteed that at most one new cluster will be
|
|
291
297
|
// created when finalizing a range (regardless of size) due to the expansion optimization.
|
|
292
298
|
if (compressedPivot === undefined || isLocalId(compressedPivot)) {
|
|
293
|
-
Common_1.fail('ID from a remote session ID must have final form, as overrides are impossible by definition.');
|
|
299
|
+
(0, Common_1.fail)('ID from a remote session ID must have final form, as overrides are impossible by definition.');
|
|
294
300
|
}
|
|
295
301
|
else {
|
|
296
302
|
pivotFinal = compressedPivot;
|
|
@@ -300,13 +306,13 @@ class IdCompressor {
|
|
|
300
306
|
length: count,
|
|
301
307
|
get: (index) => {
|
|
302
308
|
if (index < 0 || index >= count) {
|
|
303
|
-
Common_1.fail('Index out of bounds of range.');
|
|
309
|
+
(0, Common_1.fail)('Index out of bounds of range.');
|
|
304
310
|
}
|
|
305
311
|
if (index < numIdsRemainingInFirstCluster) {
|
|
306
312
|
return (firstFinal + index);
|
|
307
313
|
}
|
|
308
314
|
else {
|
|
309
|
-
return ((pivotFinal !== null && pivotFinal !== void 0 ? pivotFinal : Common_1.fail('Pivot must exist if range spans clusters.')) +
|
|
315
|
+
return ((pivotFinal !== null && pivotFinal !== void 0 ? pivotFinal : (0, Common_1.fail)('Pivot must exist if range spans clusters.')) +
|
|
310
316
|
(index - numIdsRemainingInFirstCluster));
|
|
311
317
|
}
|
|
312
318
|
},
|
|
@@ -323,25 +329,25 @@ class IdCompressor {
|
|
|
323
329
|
var _a;
|
|
324
330
|
const lastLocalInRange = -this.localIdCount;
|
|
325
331
|
const lastTakenNormalized = (_a = this.lastTakenLocalId) !== null && _a !== void 0 ? _a : 0;
|
|
326
|
-
Common_1.assert(lastLocalInRange <= lastTakenNormalized);
|
|
332
|
+
(0, Common_1.assert)(lastLocalInRange <= lastTakenNormalized);
|
|
333
|
+
// The attribution ID is sent with each range, but it can be elided after the first IDs are allocated.
|
|
334
|
+
const sendAttributionId = this.lastTakenLocalId === undefined;
|
|
327
335
|
let ids;
|
|
328
336
|
if (lastLocalInRange !== lastTakenNormalized) {
|
|
329
337
|
const firstLocalInRange = (lastTakenNormalized - 1);
|
|
330
|
-
const
|
|
338
|
+
const overrides = [
|
|
331
339
|
...this.localOverrides.getRange((lastTakenNormalized - 1), lastLocalInRange),
|
|
332
340
|
];
|
|
333
|
-
if (
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
Common_1.assert(overrides[0][0] <= firstLocalInRange);
|
|
337
|
-
Common_1.assert(overrides[overrides.length - 1][0] >= lastLocalInRange);
|
|
341
|
+
if ((0, Common_1.hasLength)(overrides, 1)) {
|
|
342
|
+
(0, Common_1.assert)(overrides[0][0] <= firstLocalInRange);
|
|
343
|
+
(0, Common_1.assert)(overrides[overrides.length - 1][0] >= lastLocalInRange);
|
|
338
344
|
ids = {
|
|
339
345
|
overrides,
|
|
340
346
|
};
|
|
341
347
|
const first = firstLocalInRange === overrides[0][0] ? undefined : firstLocalInRange;
|
|
342
348
|
const last = lastLocalInRange === overrides[overrides.length - 1][0] ? undefined : lastLocalInRange;
|
|
343
|
-
Common_1.setPropertyIfDefined(first, ids, 'first');
|
|
344
|
-
Common_1.setPropertyIfDefined(last, ids, 'last');
|
|
349
|
+
(0, Common_1.setPropertyIfDefined)(first, ids, 'first');
|
|
350
|
+
(0, Common_1.setPropertyIfDefined)(last, ids, 'last');
|
|
345
351
|
}
|
|
346
352
|
else {
|
|
347
353
|
ids = {
|
|
@@ -352,29 +358,27 @@ class IdCompressor {
|
|
|
352
358
|
this.lastTakenLocalId = lastLocalInRange;
|
|
353
359
|
}
|
|
354
360
|
const range = { sessionId: this.localSessionId };
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
this.sentAttributionInfo = true;
|
|
361
|
+
if (this.attributionId !== this.localSessionId && sendAttributionId) {
|
|
362
|
+
range.attributionId = this.attributionId;
|
|
358
363
|
}
|
|
359
364
|
if (ids === undefined) {
|
|
360
365
|
return range;
|
|
361
366
|
}
|
|
362
|
-
Common_1.assert(this.lastTakenLocalId === -this.localIdCount && this.lastTakenLocalId !== lastTakenNormalized, 'Non-empty range must properly consume local IDs');
|
|
367
|
+
(0, Common_1.assert)(this.lastTakenLocalId === -this.localIdCount && this.lastTakenLocalId !== lastTakenNormalized, 'Non-empty range must properly consume local IDs');
|
|
363
368
|
range.ids = ids;
|
|
364
369
|
return range;
|
|
365
370
|
}
|
|
366
371
|
/**
|
|
367
372
|
* Finalizes the supplied range of IDs (which may be from either a remote or local session).
|
|
368
|
-
* @param range the range of session-local IDs to finalize.
|
|
373
|
+
* @param range - the range of session-local IDs to finalize.
|
|
369
374
|
*/
|
|
370
375
|
finalizeCreationRange(range) {
|
|
371
|
-
var _a, _b;
|
|
372
|
-
const { sessionId,
|
|
376
|
+
var _a, _b, _c;
|
|
377
|
+
const { sessionId, attributionId } = range;
|
|
373
378
|
const isLocal = sessionId === this.localSessionId;
|
|
374
|
-
|
|
375
|
-
Common_1.assert(range.
|
|
376
|
-
|
|
377
|
-
const ids = IdRange_1.getIds(range);
|
|
379
|
+
const session = (_a = this.sessions.get(sessionId)) !== null && _a !== void 0 ? _a : this.createSession(sessionId, attributionId);
|
|
380
|
+
(0, Common_1.assert)(range.attributionId === undefined || range.attributionId === session.attributionId, "A session's attribution ID may never be modified.");
|
|
381
|
+
const ids = (0, IdRange_1.getIds)(range);
|
|
378
382
|
if (ids === undefined) {
|
|
379
383
|
return;
|
|
380
384
|
}
|
|
@@ -383,12 +387,12 @@ class IdCompressor {
|
|
|
383
387
|
cluster: undefined,
|
|
384
388
|
clusterBase: undefined,
|
|
385
389
|
};
|
|
386
|
-
const normalizedLastFinalized = (
|
|
390
|
+
const normalizedLastFinalized = (_b = session.lastFinalizedLocalId) !== null && _b !== void 0 ? _b : 0;
|
|
387
391
|
const { first: newFirstFinalizedLocalId, last: newLastFinalizedLocalId } = ids;
|
|
388
|
-
Common_1.assert(newFirstFinalizedLocalId === normalizedLastFinalized - 1, 'Ranges finalized out of order.');
|
|
392
|
+
(0, Common_1.assert)(newFirstFinalizedLocalId === normalizedLastFinalized - 1, 'Ranges finalized out of order.');
|
|
389
393
|
// The total number of session-local IDs to finalize
|
|
390
394
|
const finalizeCount = normalizedLastFinalized - newLastFinalizedLocalId;
|
|
391
|
-
Common_1.assert(finalizeCount >= 1, 'Cannot finalize an empty range.');
|
|
395
|
+
(0, Common_1.assert)(finalizeCount >= 1, 'Cannot finalize an empty range.');
|
|
392
396
|
let initialClusterCount = 0;
|
|
393
397
|
let remainingCount = finalizeCount;
|
|
394
398
|
let newBaseUuid;
|
|
@@ -407,14 +411,14 @@ class IdCompressor {
|
|
|
407
411
|
const expansionAmount = this.newClusterCapacity + overflow;
|
|
408
412
|
currentCluster.capacity += expansionAmount;
|
|
409
413
|
this.nextClusterBaseFinalId = (this.nextClusterBaseFinalId + expansionAmount);
|
|
410
|
-
Common_1.assert(this.nextClusterBaseFinalId < Number.MAX_SAFE_INTEGER, 'The number of allocated final IDs must not exceed the JS maximum safe integer.');
|
|
414
|
+
(0, Common_1.assert)(this.nextClusterBaseFinalId < Number.MAX_SAFE_INTEGER, 'The number of allocated final IDs must not exceed the JS maximum safe integer.');
|
|
411
415
|
this.checkClusterForCollision(currentCluster);
|
|
412
416
|
}
|
|
413
417
|
}
|
|
414
418
|
else {
|
|
415
419
|
// The range cannot be fully allocated in the existing cluster, so allocate any space left in it and
|
|
416
420
|
// form a new one by incrementing the previous baseUuid
|
|
417
|
-
newBaseUuid = NumericUuid_1.incrementUuid(currentCluster.baseUuid, currentCluster.capacity);
|
|
421
|
+
newBaseUuid = (0, NumericUuid_1.incrementUuid)(currentCluster.baseUuid, currentCluster.capacity);
|
|
418
422
|
currentCluster.count += remainingCapacity;
|
|
419
423
|
remainingCount -= remainingCapacity;
|
|
420
424
|
}
|
|
@@ -436,10 +440,10 @@ class IdCompressor {
|
|
|
436
440
|
// Need to make a new cluster
|
|
437
441
|
if (newBaseUuid !== undefined) {
|
|
438
442
|
if (remainingCount <= 0) {
|
|
439
|
-
Common_1.fail('Should not create an empty cluster.');
|
|
443
|
+
(0, Common_1.fail)('Should not create an empty cluster.');
|
|
440
444
|
}
|
|
441
445
|
if (currentCluster !== undefined && currentCluster.capacity !== currentCluster.count) {
|
|
442
|
-
Common_1.fail('Cluster must be filled before another is allocated.');
|
|
446
|
+
(0, Common_1.fail)('Cluster must be filled before another is allocated.');
|
|
443
447
|
}
|
|
444
448
|
newBaseFinalId = this.nextClusterBaseFinalId;
|
|
445
449
|
newCluster = {
|
|
@@ -454,13 +458,13 @@ class IdCompressor {
|
|
|
454
458
|
this.localIdToCluster.append(localIdPivot, [newBaseFinalId, newCluster]);
|
|
455
459
|
}
|
|
456
460
|
this.checkClusterForCollision(newCluster);
|
|
457
|
-
this.clustersAndOverridesInversion.set(NumericUuid_1.stableIdFromNumericUuid(newCluster.baseUuid), {
|
|
461
|
+
this.clustersAndOverridesInversion.set((0, NumericUuid_1.stableIdFromNumericUuid)(newCluster.baseUuid), {
|
|
458
462
|
clusterBase: newBaseFinalId,
|
|
459
463
|
cluster: newCluster,
|
|
460
464
|
});
|
|
461
465
|
session.currentClusterDetails = { cluster: newCluster, clusterBase: newBaseFinalId };
|
|
462
466
|
this.nextClusterBaseFinalId = (this.nextClusterBaseFinalId + newCluster.capacity);
|
|
463
|
-
Common_1.assert(this.nextClusterBaseFinalId < Number.MAX_SAFE_INTEGER, 'The number of allocated final IDs must not exceed the JS maximum safe integer.');
|
|
467
|
+
(0, Common_1.assert)(this.nextClusterBaseFinalId < Number.MAX_SAFE_INTEGER, 'The number of allocated final IDs must not exceed the JS maximum safe integer.');
|
|
464
468
|
this.finalIdToCluster.append(newBaseFinalId, newCluster);
|
|
465
469
|
}
|
|
466
470
|
// If there are overrides, we must determine which cluster object (current or overflow) each belongs to and add it.
|
|
@@ -469,29 +473,28 @@ class IdCompressor {
|
|
|
469
473
|
for (let i = 0; i < overrides.length; i++) {
|
|
470
474
|
const [overriddenLocal, override] = overrides[i];
|
|
471
475
|
// Note: recall that local IDs are negative
|
|
472
|
-
Common_1.assert(i === 0 || overriddenLocal < overrides[i - 1][0], 'Override IDs must be in sorted order.');
|
|
473
|
-
Common_1.assert(overriddenLocal < normalizedLastFinalized, 'Ranges finalized out of order.');
|
|
474
|
-
Common_1.assert(overriddenLocal >= newLastFinalizedLocalId, 'Malformed range: override ID ahead of range start.');
|
|
476
|
+
(0, Common_1.assert)(i === 0 || overriddenLocal < overrides[i - 1][0], 'Override IDs must be in sorted order.');
|
|
477
|
+
(0, Common_1.assert)(overriddenLocal < normalizedLastFinalized, 'Ranges finalized out of order.');
|
|
478
|
+
(0, Common_1.assert)(overriddenLocal >= newLastFinalizedLocalId, 'Malformed range: override ID ahead of range start.');
|
|
475
479
|
let cluster;
|
|
476
480
|
let overriddenFinal;
|
|
477
481
|
if (localIdPivot !== undefined && overriddenLocal <= localIdPivot) {
|
|
478
482
|
// Override is at or past the pivot, so it is in a new cluster.
|
|
479
|
-
Common_1.assert(newCluster !== undefined && newBaseFinalId !== undefined, 'No cluster was created when overflow occurred.');
|
|
483
|
+
(0, Common_1.assert)(newCluster !== undefined && newBaseFinalId !== undefined, 'No cluster was created when overflow occurred.');
|
|
480
484
|
cluster = newCluster;
|
|
481
485
|
overriddenFinal = (newBaseFinalId + (localIdPivot - overriddenLocal));
|
|
482
486
|
}
|
|
483
487
|
else {
|
|
484
488
|
// Override was finalized into an existing cluster
|
|
485
|
-
Common_1.assert(currentCluster !== undefined && currentBaseFinalId !== undefined, 'No cluster exists but IDs were finalized.');
|
|
489
|
+
(0, Common_1.assert)(currentCluster !== undefined && currentBaseFinalId !== undefined, 'No cluster exists but IDs were finalized.');
|
|
486
490
|
cluster = currentCluster;
|
|
487
491
|
overriddenFinal = (currentBaseFinalId +
|
|
488
492
|
initialClusterCount +
|
|
489
493
|
(normalizedLastFinalized - overriddenLocal) -
|
|
490
494
|
1);
|
|
491
495
|
}
|
|
492
|
-
(
|
|
496
|
+
(_c = cluster.overrides) !== null && _c !== void 0 ? _c : (cluster.overrides = new Map());
|
|
493
497
|
const inversionKey = IdCompressor.createInversionKey(override);
|
|
494
|
-
// TODO: This cast can be removed on typescript 4.6
|
|
495
498
|
const existingIds = this.getExistingIdsForNewOverride(inversionKey, true);
|
|
496
499
|
let overrideForCluster;
|
|
497
500
|
let associatedLocal;
|
|
@@ -511,7 +514,7 @@ class IdCompressor {
|
|
|
511
514
|
overrideForCluster = mostFinalExistingOverride;
|
|
512
515
|
}
|
|
513
516
|
else {
|
|
514
|
-
Common_1.assert(!isLocal || mostFinalExistingOverride === overriddenLocal, 'Cannot have multiple local IDs with identical overrides.');
|
|
517
|
+
(0, Common_1.assert)(!isLocal || mostFinalExistingOverride === overriddenLocal, 'Cannot have multiple local IDs with identical overrides.');
|
|
515
518
|
// This session has created an ID with this override before, but has not finalized it yet. The incoming
|
|
516
519
|
// range "wins" and will contain the final ID associated with that override, regardless of if that range was
|
|
517
520
|
// made by this session or not.
|
|
@@ -522,7 +525,7 @@ class IdCompressor {
|
|
|
522
525
|
// This is the first time this override has been associated with any ID
|
|
523
526
|
overrideForCluster = override;
|
|
524
527
|
}
|
|
525
|
-
Common_1.assert(!cluster.overrides.has(overriddenFinal), 'Cannot add a second override for final id');
|
|
528
|
+
(0, Common_1.assert)(!cluster.overrides.has(overriddenFinal), 'Cannot add a second override for final id');
|
|
526
529
|
if (typeof overrideForCluster === 'string') {
|
|
527
530
|
if (isLocal || associatedLocal === undefined) {
|
|
528
531
|
cluster.overrides.set(overriddenFinal, override);
|
|
@@ -540,14 +543,14 @@ class IdCompressor {
|
|
|
540
543
|
override,
|
|
541
544
|
originalOverridingFinal: overrideForCluster,
|
|
542
545
|
};
|
|
543
|
-
Common_1.setPropertyIfDefined(associatedLocal, unifiedOverride, 'associatedLocalId');
|
|
546
|
+
(0, Common_1.setPropertyIfDefined)(associatedLocal, unifiedOverride, 'associatedLocalId');
|
|
544
547
|
cluster.overrides.set(overriddenFinal, unifiedOverride);
|
|
545
548
|
}
|
|
546
549
|
const finalizedOverride = {
|
|
547
550
|
cluster,
|
|
548
551
|
originalOverridingFinal: overriddenFinal,
|
|
549
552
|
};
|
|
550
|
-
Common_1.setPropertyIfDefined(associatedLocal, finalizedOverride, 'associatedLocalId');
|
|
553
|
+
(0, Common_1.setPropertyIfDefined)(associatedLocal, finalizedOverride, 'associatedLocalId');
|
|
551
554
|
const currentOverride = this.clustersAndOverridesInversion.get(inversionKey);
|
|
552
555
|
if (currentOverride === undefined || IdCompressor.isUnfinalizedOverride(currentOverride)) {
|
|
553
556
|
// Update the map to contain a finalized override, but never update it with future finalized overrides with
|
|
@@ -559,16 +562,16 @@ class IdCompressor {
|
|
|
559
562
|
session.lastFinalizedLocalId = newLastFinalizedLocalId;
|
|
560
563
|
}
|
|
561
564
|
checkClusterForCollision(cluster) {
|
|
562
|
-
const maxClusterUuid = NumericUuid_1.incrementUuid(cluster.baseUuid, cluster.capacity - 1);
|
|
563
|
-
const maxClusterStableId = NumericUuid_1.stableIdFromNumericUuid(maxClusterUuid);
|
|
565
|
+
const maxClusterUuid = (0, NumericUuid_1.incrementUuid)(cluster.baseUuid, cluster.capacity - 1);
|
|
566
|
+
const maxClusterStableId = (0, NumericUuid_1.stableIdFromNumericUuid)(maxClusterUuid);
|
|
564
567
|
const closestMatch = this.clustersAndOverridesInversion.getPairOrNextLower(maxClusterStableId);
|
|
565
568
|
if (closestMatch !== undefined) {
|
|
566
569
|
const [inversionKey, compressionMapping] = closestMatch;
|
|
567
570
|
if (!IdCompressor.isClusterInfo(compressionMapping)) {
|
|
568
|
-
if (
|
|
571
|
+
if ((0, UuidUtilities_1.isStableId)(inversionKey) &&
|
|
569
572
|
IdCompressor.uuidsMightCollide(inversionKey, maxClusterStableId, cluster.capacity)) {
|
|
570
|
-
const numericOverride = NumericUuid_1.numericUuidFromStableId(inversionKey);
|
|
571
|
-
const delta = NumericUuid_1.getPositiveDelta(maxClusterUuid, numericOverride, cluster.capacity - 1);
|
|
573
|
+
const numericOverride = (0, NumericUuid_1.numericUuidFromStableId)(inversionKey);
|
|
574
|
+
const delta = (0, NumericUuid_1.getPositiveDelta)(maxClusterUuid, numericOverride, cluster.capacity - 1);
|
|
572
575
|
if (delta !== undefined) {
|
|
573
576
|
IdCompressor.failWithCollidingOverride(inversionKey);
|
|
574
577
|
}
|
|
@@ -577,7 +580,7 @@ class IdCompressor {
|
|
|
577
580
|
}
|
|
578
581
|
}
|
|
579
582
|
static failWithCollidingOverride(override) {
|
|
580
|
-
Common_1.fail(`Override '${override}' collides with another allocated UUID.`);
|
|
583
|
+
(0, Common_1.fail)(`Override '${override}' collides with another allocated UUID.`);
|
|
581
584
|
}
|
|
582
585
|
static isClusterInfo(compressionMapping) {
|
|
583
586
|
return compressionMapping.clusterBase !== undefined;
|
|
@@ -586,8 +589,7 @@ class IdCompressor {
|
|
|
586
589
|
return typeof compressionMapping === 'number';
|
|
587
590
|
}
|
|
588
591
|
static createInversionKey(inversionKey) {
|
|
589
|
-
|
|
590
|
-
return NumericUuid_1.isStableId(inversionKey) ? inversionKey : `${nonStableOverridePrefix}${inversionKey}`;
|
|
592
|
+
return (0, UuidUtilities_1.isStableId)(inversionKey) ? inversionKey : `${nonStableOverridePrefix}${inversionKey}`;
|
|
591
593
|
}
|
|
592
594
|
static isStableInversionKey(inversionKey) {
|
|
593
595
|
return inversionKey.charAt(0) !== nonStableOverridePrefix;
|
|
@@ -617,8 +619,8 @@ class IdCompressor {
|
|
|
617
619
|
stableOverride = inversionKey;
|
|
618
620
|
const cluster = compressionMapping.cluster;
|
|
619
621
|
if (IdCompressor.uuidsMightCollide(inversionKey, key, cluster.capacity)) {
|
|
620
|
-
numericOverride = NumericUuid_1.numericUuidFromStableId(stableOverride);
|
|
621
|
-
const delta = NumericUuid_1.getPositiveDelta(numericOverride, cluster.baseUuid, cluster.capacity - 1);
|
|
622
|
+
numericOverride = (0, NumericUuid_1.numericUuidFromStableId)(stableOverride);
|
|
623
|
+
const delta = (0, NumericUuid_1.getPositiveDelta)(numericOverride, cluster.baseUuid, cluster.capacity - 1);
|
|
622
624
|
if (delta !== undefined) {
|
|
623
625
|
if (isFinalOverride) {
|
|
624
626
|
IdCompressor.failWithCollidingOverride(inversionKey);
|
|
@@ -646,7 +648,7 @@ class IdCompressor {
|
|
|
646
648
|
}
|
|
647
649
|
/**
|
|
648
650
|
* Check if `a` might be within `range` of `b`, where both are treated as hex numbers.
|
|
649
|
-
* @param range an integer
|
|
651
|
+
* @param range - an integer
|
|
650
652
|
*/
|
|
651
653
|
static uuidsMightCollide(a, b, range) {
|
|
652
654
|
// Check if any of the UUIDs in the cluster collide (i.e. any in [base, base + capacity)).
|
|
@@ -676,7 +678,7 @@ class IdCompressor {
|
|
|
676
678
|
/**
|
|
677
679
|
* Generates a new compressed ID or returns an existing one.
|
|
678
680
|
* This should ONLY be called to generate IDs for local operations.
|
|
679
|
-
* @param override Specifies a specific string to be associated with the returned compressed ID.
|
|
681
|
+
* @param override - Specifies a specific string to be associated with the returned compressed ID.
|
|
680
682
|
* Performance note: assigning override strings incurs a performance overhead.
|
|
681
683
|
* @returns an existing ID if one already exists for `override`, and a new local ID otherwise. The returned ID is in session space.
|
|
682
684
|
*/
|
|
@@ -704,12 +706,12 @@ class IdCompressor {
|
|
|
704
706
|
/**
|
|
705
707
|
* Generates a range of compressed IDs.
|
|
706
708
|
* This should ONLY be called to generate IDs for local operations.
|
|
707
|
-
* @param count the number of IDs to generate, must be
|
|
709
|
+
* @param count - the number of IDs to generate, must be \> 0.
|
|
708
710
|
* @returns a persistable descriptor of the ID range.
|
|
709
711
|
*/
|
|
710
712
|
generateCompressedIdRange(count) {
|
|
711
|
-
Common_1.assert(count > 0, 'Must generate a nonzero number of IDs.');
|
|
712
|
-
Common_1.assert(count <= Number.MAX_SAFE_INTEGER, 'The number of allocated local IDs must not exceed the JS maximum safe integer.');
|
|
713
|
+
(0, Common_1.assert)(count > 0, 'Must generate a nonzero number of IDs.');
|
|
714
|
+
(0, Common_1.assert)(count <= Number.MAX_SAFE_INTEGER, 'The number of allocated local IDs must not exceed the JS maximum safe integer.');
|
|
713
715
|
const first = this.generateNextLocalId();
|
|
714
716
|
this.localIdCount += count - 1;
|
|
715
717
|
return { first, count };
|
|
@@ -719,16 +721,16 @@ class IdCompressor {
|
|
|
719
721
|
}
|
|
720
722
|
/**
|
|
721
723
|
* Decompresses a previously compressed ID into a UUID or override string.
|
|
722
|
-
* @param id the compressed ID to be decompressed.
|
|
724
|
+
* @param id - the compressed ID to be decompressed.
|
|
723
725
|
* @returns the UUID or override string associated with the compressed ID. Fails if the ID was not generated by this compressor.
|
|
724
726
|
*/
|
|
725
727
|
decompress(id) {
|
|
726
728
|
var _a;
|
|
727
|
-
return (_a = this.tryDecompress(id)) !== null && _a !== void 0 ? _a : Common_1.fail('Compressed ID was not generated by this compressor');
|
|
729
|
+
return (_a = this.tryDecompress(id)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Compressed ID was not generated by this compressor');
|
|
728
730
|
}
|
|
729
731
|
/**
|
|
730
732
|
* Attempts to decompress a previously compressed ID into a UUID or override string.
|
|
731
|
-
* @param id the compressed ID to be decompressed.
|
|
733
|
+
* @param id - the compressed ID to be decompressed.
|
|
732
734
|
* @returns the UUID or override string associated with the compressed ID, or undefined if the ID was not generated by this compressor.
|
|
733
735
|
*/
|
|
734
736
|
tryDecompress(id) {
|
|
@@ -746,7 +748,7 @@ class IdCompressor {
|
|
|
746
748
|
}
|
|
747
749
|
else {
|
|
748
750
|
const offsetInCluster = id - baseFinalId;
|
|
749
|
-
return NumericUuid_1.stableIdFromNumericUuid(cluster.baseUuid, offsetInCluster);
|
|
751
|
+
return (0, NumericUuid_1.stableIdFromNumericUuid)(cluster.baseUuid, offsetInCluster);
|
|
750
752
|
}
|
|
751
753
|
}
|
|
752
754
|
}
|
|
@@ -764,22 +766,22 @@ class IdCompressor {
|
|
|
764
766
|
return localOverride;
|
|
765
767
|
}
|
|
766
768
|
else {
|
|
767
|
-
return NumericUuid_1.stableIdFromNumericUuid(this.localSession.sessionUuid, idOffset - 1);
|
|
769
|
+
return (0, NumericUuid_1.stableIdFromNumericUuid)(this.localSession.sessionUuid, idOffset - 1);
|
|
768
770
|
}
|
|
769
771
|
}
|
|
770
772
|
}
|
|
771
773
|
/**
|
|
772
774
|
* Recompresses a decompressed ID, which could be a UUID or an override string.
|
|
773
|
-
* @param uncompressed the UUID or override string to recompress.
|
|
775
|
+
* @param uncompressed - the UUID or override string to recompress.
|
|
774
776
|
* @returns the `CompressedId` associated with `uncompressed`. Fails if it has not been previously compressed by this compressor.
|
|
775
777
|
*/
|
|
776
778
|
recompress(uncompressed) {
|
|
777
779
|
var _a;
|
|
778
|
-
return (_a = this.tryRecompress(uncompressed)) !== null && _a !== void 0 ? _a : Common_1.fail('No such string has ever been compressed');
|
|
780
|
+
return (_a = this.tryRecompress(uncompressed)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('No such string has ever been compressed');
|
|
779
781
|
}
|
|
780
782
|
/**
|
|
781
783
|
* Attempts to recompresses a decompressed ID, which could be a UUID or an override string.
|
|
782
|
-
* @param uncompressed the UUID or override string to recompress,
|
|
784
|
+
* @param uncompressed - the UUID or override string to recompress,
|
|
783
785
|
* @returns the `CompressedId` associated with `uncompressed` or undefined if it has not been previously compressed by this compressor.
|
|
784
786
|
*/
|
|
785
787
|
tryRecompress(uncompressed) {
|
|
@@ -792,7 +794,6 @@ class IdCompressor {
|
|
|
792
794
|
recompressInternal(uncompressed, uncompressedUuidNumeric) {
|
|
793
795
|
var _a, _b;
|
|
794
796
|
let numericUuid = uncompressedUuidNumeric;
|
|
795
|
-
// TODO: This cast can be removed on typescript 4.6, and should give improved typesafety.
|
|
796
797
|
const inversionKey = IdCompressor.createInversionKey(uncompressed);
|
|
797
798
|
const isStable = IdCompressor.isStableInversionKey(inversionKey);
|
|
798
799
|
const closestMatch = this.clustersAndOverridesInversion.getPairOrNextLower(inversionKey, reusedArray);
|
|
@@ -805,7 +806,7 @@ class IdCompressor {
|
|
|
805
806
|
}
|
|
806
807
|
else {
|
|
807
808
|
const cluster = compressionMapping.cluster;
|
|
808
|
-
Common_1.assert(IdCompressor.tryGetOverride(cluster, compressionMapping.originalOverridingFinal) !==
|
|
809
|
+
(0, Common_1.assert)(IdCompressor.tryGetOverride(cluster, compressionMapping.originalOverridingFinal) !==
|
|
809
810
|
undefined, 'No override for cluster marked as having one.');
|
|
810
811
|
return ((_a = compressionMapping.associatedLocalId) !== null && _a !== void 0 ? _a : compressionMapping.originalOverridingFinal);
|
|
811
812
|
}
|
|
@@ -816,8 +817,8 @@ class IdCompressor {
|
|
|
816
817
|
return undefined;
|
|
817
818
|
}
|
|
818
819
|
const { clusterBase: closestBaseFinalId, cluster: closestCluster } = compressionMapping;
|
|
819
|
-
numericUuid !== null && numericUuid !== void 0 ? numericUuid : (numericUuid = NumericUuid_1.numericUuidFromStableId(inversionKey));
|
|
820
|
-
const uuidOffset = NumericUuid_1.getPositiveDelta(numericUuid, closestCluster.baseUuid, closestCluster.count - 1);
|
|
820
|
+
numericUuid !== null && numericUuid !== void 0 ? numericUuid : (numericUuid = (0, NumericUuid_1.numericUuidFromStableId)(inversionKey));
|
|
821
|
+
const uuidOffset = (0, NumericUuid_1.getPositiveDelta)(numericUuid, closestCluster.baseUuid, closestCluster.count - 1);
|
|
821
822
|
if (uuidOffset !== undefined) {
|
|
822
823
|
let targetFinalId = (closestBaseFinalId + uuidOffset);
|
|
823
824
|
const override = (_b = closestCluster.overrides) === null || _b === void 0 ? void 0 : _b.get(targetFinalId);
|
|
@@ -835,7 +836,6 @@ class IdCompressor {
|
|
|
835
836
|
}
|
|
836
837
|
if (isStable) {
|
|
837
838
|
// May have already computed the numeric UUID, so avoid recomputing if possible
|
|
838
|
-
// TODO: This cast can be removed on typescript 4.6
|
|
839
839
|
const localId = this.getLocalIdForStableId(numericUuid !== null && numericUuid !== void 0 ? numericUuid : inversionKey);
|
|
840
840
|
if (localId !== undefined) {
|
|
841
841
|
return localId;
|
|
@@ -845,7 +845,7 @@ class IdCompressor {
|
|
|
845
845
|
}
|
|
846
846
|
/**
|
|
847
847
|
* Normalizes a session space ID into op space.
|
|
848
|
-
* @param id the local ID to normalize.
|
|
848
|
+
* @param id - the local ID to normalize.
|
|
849
849
|
* @returns the ID in op space.
|
|
850
850
|
*/
|
|
851
851
|
normalizeToOpSpace(id) {
|
|
@@ -855,7 +855,7 @@ class IdCompressor {
|
|
|
855
855
|
}
|
|
856
856
|
// Check if this local ID has not been allocated yet
|
|
857
857
|
if (-id > this.localIdCount) {
|
|
858
|
-
Common_1.fail('Supplied local ID was not created by this compressor.');
|
|
858
|
+
(0, Common_1.fail)('Supplied local ID was not created by this compressor.');
|
|
859
859
|
}
|
|
860
860
|
// Check if this local ID has not been finalized yet
|
|
861
861
|
const { lastFinalizedLocalId } = this.localSession;
|
|
@@ -863,7 +863,7 @@ class IdCompressor {
|
|
|
863
863
|
const override = this.localOverrides.get(id);
|
|
864
864
|
if (override !== undefined) {
|
|
865
865
|
const inversionKey = IdCompressor.createInversionKey(override);
|
|
866
|
-
const compressionMapping = (_a = this.clustersAndOverridesInversion.get(inversionKey)) !== null && _a !== void 0 ? _a : Common_1.fail('Bimap is malformed.');
|
|
866
|
+
const compressionMapping = (_a = this.clustersAndOverridesInversion.get(inversionKey)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Bimap is malformed.');
|
|
867
867
|
if (!IdCompressor.isClusterInfo(compressionMapping) &&
|
|
868
868
|
!IdCompressor.isUnfinalizedOverride(compressionMapping) &&
|
|
869
869
|
compressionMapping.associatedLocalId === id) {
|
|
@@ -872,7 +872,7 @@ class IdCompressor {
|
|
|
872
872
|
}
|
|
873
873
|
return id;
|
|
874
874
|
}
|
|
875
|
-
const [localBase, [finalBase, cluster]] = (_b = this.localIdToCluster.getPairOrNextLower(id)) !== null && _b !== void 0 ? _b : Common_1.fail('Locally created cluster should be added to the map when allocated');
|
|
875
|
+
const [localBase, [finalBase, cluster]] = (_b = this.localIdToCluster.getPairOrNextLower(id)) !== null && _b !== void 0 ? _b : (0, Common_1.fail)('Locally created cluster should be added to the map when allocated');
|
|
876
876
|
const correspondingFinal = (finalBase + (localBase - id));
|
|
877
877
|
if (cluster.overrides) {
|
|
878
878
|
const override = cluster.overrides.get(correspondingFinal);
|
|
@@ -890,18 +890,18 @@ class IdCompressor {
|
|
|
890
890
|
if (isLocalSession) {
|
|
891
891
|
const localIndex = -id;
|
|
892
892
|
if (localIndex > this.localIdCount) {
|
|
893
|
-
Common_1.fail('Supplied local ID was not created by this compressor.');
|
|
893
|
+
(0, Common_1.fail)('Supplied local ID was not created by this compressor.');
|
|
894
894
|
}
|
|
895
895
|
return id;
|
|
896
896
|
}
|
|
897
897
|
else {
|
|
898
|
-
const session = this.
|
|
898
|
+
const session = this.sessions.get(originSessionId !== null && originSessionId !== void 0 ? originSessionId : (0, Common_1.fail)());
|
|
899
899
|
if (session === undefined) {
|
|
900
|
-
Common_1.fail('No IDs have ever been finalized by the supplied session.');
|
|
900
|
+
(0, Common_1.fail)('No IDs have ever been finalized by the supplied session.');
|
|
901
901
|
}
|
|
902
902
|
const localCount = -id;
|
|
903
|
-
const numericUuid = NumericUuid_1.incrementUuid(session.sessionUuid, localCount - 1);
|
|
904
|
-
return (_a = this.compressNumericUuid(numericUuid)) !== null && _a !== void 0 ? _a : Common_1.fail('ID is not known to this compressor.');
|
|
903
|
+
const numericUuid = (0, NumericUuid_1.incrementUuid)(session.sessionUuid, localCount - 1);
|
|
904
|
+
return (_a = this.compressNumericUuid(numericUuid)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('ID is not known to this compressor.');
|
|
905
905
|
}
|
|
906
906
|
}
|
|
907
907
|
const closestResult = this.localIdToCluster.getPairOrNextLowerByValue(id);
|
|
@@ -914,7 +914,7 @@ class IdCompressor {
|
|
|
914
914
|
}
|
|
915
915
|
// Check for a unified override finalized first by another session but to which the local session
|
|
916
916
|
// still has an associated local ID.
|
|
917
|
-
const [_, cluster] = (_b = this.getClusterForFinalId(id)) !== null && _b !== void 0 ? _b : Common_1.fail('Supplied final ID was not finalized by this compressor.');
|
|
917
|
+
const [_, cluster] = (_b = this.getClusterForFinalId(id)) !== null && _b !== void 0 ? _b : (0, Common_1.fail)('Supplied final ID was not finalized by this compressor.');
|
|
918
918
|
const override = (_c = cluster.overrides) === null || _c === void 0 ? void 0 : _c.get(id);
|
|
919
919
|
if (typeof override === 'object' && override.associatedLocalId !== undefined) {
|
|
920
920
|
return override.associatedLocalId;
|
|
@@ -942,7 +942,7 @@ class IdCompressor {
|
|
|
942
942
|
* session-space ID corresponding to A0000000-0000-0000-0000-000000000000 (with override X0000000-0000-0000-0000-000000000000).
|
|
943
943
|
*/
|
|
944
944
|
compressNumericUuid(numericUuid) {
|
|
945
|
-
const stableId = NumericUuid_1.stableIdFromNumericUuid(numericUuid);
|
|
945
|
+
const stableId = (0, NumericUuid_1.stableIdFromNumericUuid)(numericUuid);
|
|
946
946
|
const sessionSpaceId = this.recompressInternal(stableId, numericUuid);
|
|
947
947
|
if (sessionSpaceId === undefined) {
|
|
948
948
|
return undefined;
|
|
@@ -950,9 +950,8 @@ class IdCompressor {
|
|
|
950
950
|
return sessionSpaceId;
|
|
951
951
|
}
|
|
952
952
|
getLocalIdForStableId(stableId) {
|
|
953
|
-
|
|
954
|
-
const
|
|
955
|
-
const offset = NumericUuid_1.getPositiveDelta(numericUuid, this.localSession.sessionUuid, this.localIdCount - 1);
|
|
953
|
+
const numericUuid = typeof stableId === 'string' ? (0, NumericUuid_1.numericUuidFromStableId)(stableId) : stableId;
|
|
954
|
+
const offset = (0, NumericUuid_1.getPositiveDelta)(numericUuid, this.localSession.sessionUuid, this.localIdCount - 1);
|
|
956
955
|
if (offset === undefined) {
|
|
957
956
|
return undefined;
|
|
958
957
|
}
|
|
@@ -970,21 +969,21 @@ class IdCompressor {
|
|
|
970
969
|
return possibleCluster;
|
|
971
970
|
}
|
|
972
971
|
/**
|
|
973
|
-
* @returns if `other` is equal to this `IdCompressor`. The equality check includes local session state.
|
|
974
|
-
*
|
|
972
|
+
* @returns if `other` is equal to this `IdCompressor`. The equality check includes local session state only if specified.
|
|
973
|
+
* \@testOnly
|
|
975
974
|
*/
|
|
976
975
|
equals(other, compareLocalState) {
|
|
977
976
|
if (compareLocalState) {
|
|
978
977
|
if (this.localIdCount !== other.localIdCount ||
|
|
979
978
|
this.localSessionId !== other.localSessionId ||
|
|
980
979
|
this.lastTakenLocalId !== other.lastTakenLocalId ||
|
|
981
|
-
this.
|
|
980
|
+
this.attributionId !== other.attributionId) {
|
|
982
981
|
return false;
|
|
983
982
|
}
|
|
984
983
|
if (!this.localOverrides.equals(other.localOverrides, (a, b) => a === b)) {
|
|
985
984
|
return false;
|
|
986
985
|
}
|
|
987
|
-
if (!Common_1.compareMaps(this.sessions, other.sessions, (a, b) => IdCompressor.sessionDataEqual(a, b, true, compareLocalState))) {
|
|
986
|
+
if (!(0, Common_1.compareMaps)(this.sessions, other.sessions, (a, b) => IdCompressor.sessionDataEqual(a, b, true, compareLocalState))) {
|
|
988
987
|
return false;
|
|
989
988
|
}
|
|
990
989
|
}
|
|
@@ -1060,8 +1059,8 @@ class IdCompressor {
|
|
|
1060
1059
|
return diff === undefined;
|
|
1061
1060
|
}
|
|
1062
1061
|
static sessionDataEqual(a, b, checkCluster = true, compareLocalState = true) {
|
|
1063
|
-
if (a.
|
|
1064
|
-
!NumericUuid_1.numericUuidEquals(a.sessionUuid, b.sessionUuid) ||
|
|
1062
|
+
if (a.attributionId !== b.attributionId ||
|
|
1063
|
+
!(0, NumericUuid_1.numericUuidEquals)(a.sessionUuid, b.sessionUuid) ||
|
|
1065
1064
|
a.lastFinalizedLocalId !== b.lastFinalizedLocalId) {
|
|
1066
1065
|
return false;
|
|
1067
1066
|
}
|
|
@@ -1078,13 +1077,13 @@ class IdCompressor {
|
|
|
1078
1077
|
return true;
|
|
1079
1078
|
}
|
|
1080
1079
|
static idClustersEqual(a, b, checkSessionData = true, compareLocalState = true) {
|
|
1081
|
-
const areEqual = NumericUuid_1.numericUuidEquals(a.baseUuid, b.baseUuid) &&
|
|
1080
|
+
const areEqual = (0, NumericUuid_1.numericUuidEquals)(a.baseUuid, b.baseUuid) &&
|
|
1082
1081
|
a.capacity === b.capacity &&
|
|
1083
1082
|
a.count === b.count &&
|
|
1084
1083
|
(!checkSessionData || IdCompressor.sessionDataEqual(a.session, b.session, false, compareLocalState)) &&
|
|
1085
1084
|
(a.overrides === undefined) === (b.overrides === undefined) &&
|
|
1086
1085
|
(a.overrides === undefined ||
|
|
1087
|
-
Common_1.compareMaps(Common_1.assertNotUndefined(a.overrides), Common_1.assertNotUndefined(b.overrides), (a, b) => {
|
|
1086
|
+
(0, Common_1.compareMaps)((0, Common_1.assertNotUndefined)(a.overrides), (0, Common_1.assertNotUndefined)(b.overrides), (a, b) => {
|
|
1088
1087
|
if (compareLocalState) {
|
|
1089
1088
|
if (typeof a === 'string' || typeof b === 'string') {
|
|
1090
1089
|
return a === b;
|
|
@@ -1109,6 +1108,8 @@ class IdCompressor {
|
|
|
1109
1108
|
var _a;
|
|
1110
1109
|
const serializedSessions = [];
|
|
1111
1110
|
const sessionIdToSessionIndex = new Map();
|
|
1111
|
+
const attributionIdToAttributionIndex = new Map();
|
|
1112
|
+
let serializedAttributionIds;
|
|
1112
1113
|
for (const [sessionId, session] of this.sessions) {
|
|
1113
1114
|
const isLocalSession = sessionId === this.localSessionId;
|
|
1114
1115
|
const includeSession = sessionId !== reservedSessionId && // Ignore reserved clusters, but
|
|
@@ -1116,8 +1117,10 @@ class IdCompressor {
|
|
|
1116
1117
|
(isLocalSession && withSession)); // include the un-acked local session if requested
|
|
1117
1118
|
if (includeSession) {
|
|
1118
1119
|
const sessionData = [sessionId];
|
|
1119
|
-
if (session.
|
|
1120
|
-
|
|
1120
|
+
if (session.attributionId !== sessionId) {
|
|
1121
|
+
// As an optimization, don't include the attributionId if it is its default (the sessionId)
|
|
1122
|
+
// Get the index into the array for the given attribution ID. If it doesn't exist, push it onto the array and update the map.
|
|
1123
|
+
sessionData.push((0, Common_1.getOrCreate)(attributionIdToAttributionIndex, session.attributionId, (id) => (serializedAttributionIds !== null && serializedAttributionIds !== void 0 ? serializedAttributionIds : (serializedAttributionIds = [])).push(id) - 1));
|
|
1121
1124
|
}
|
|
1122
1125
|
sessionIdToSessionIndex.set(sessionId, serializedSessions.length);
|
|
1123
1126
|
serializedSessions.push(sessionData);
|
|
@@ -1125,9 +1128,9 @@ class IdCompressor {
|
|
|
1125
1128
|
}
|
|
1126
1129
|
const serializedClusters = [];
|
|
1127
1130
|
for (const [baseFinalId, cluster] of this.finalIdToCluster.entries()) {
|
|
1128
|
-
const sessionId = NumericUuid_1.stableIdFromNumericUuid(cluster.session.sessionUuid);
|
|
1131
|
+
const sessionId = (0, NumericUuid_1.stableIdFromNumericUuid)(cluster.session.sessionUuid);
|
|
1129
1132
|
if (sessionId !== reservedSessionId) {
|
|
1130
|
-
const sessionIndex = (_a = sessionIdToSessionIndex.get(sessionId)) !== null && _a !== void 0 ? _a : Common_1.fail('Session object contains wrong session numeric UUID');
|
|
1133
|
+
const sessionIndex = (_a = sessionIdToSessionIndex.get(sessionId)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Session object contains wrong session numeric UUID');
|
|
1131
1134
|
const serializedCluster = [sessionIndex, cluster.capacity];
|
|
1132
1135
|
if (cluster.count !== cluster.capacity) {
|
|
1133
1136
|
serializedCluster.push(cluster.count);
|
|
@@ -1156,7 +1159,7 @@ class IdCompressor {
|
|
|
1156
1159
|
}
|
|
1157
1160
|
}
|
|
1158
1161
|
// Reserved session not serialized, and local session is present but may not make IDs
|
|
1159
|
-
Common_1.assert(serializedSessions.length - this.sessions.size <= 2, 'session not serialized');
|
|
1162
|
+
(0, Common_1.assert)(serializedSessions.length - this.sessions.size <= 2, 'session not serialized');
|
|
1160
1163
|
const serializedIdCompressor = {
|
|
1161
1164
|
version: currentWrittenVersion,
|
|
1162
1165
|
reservedIdCount: this.reservedIdCount,
|
|
@@ -1164,6 +1167,7 @@ class IdCompressor {
|
|
|
1164
1167
|
sessions: serializedSessions,
|
|
1165
1168
|
clusters: serializedClusters,
|
|
1166
1169
|
};
|
|
1170
|
+
(0, Common_1.setPropertyIfDefined)(serializedAttributionIds, serializedIdCompressor, 'attributionIds');
|
|
1167
1171
|
if (withSession) {
|
|
1168
1172
|
const serializedWithSession = serializedIdCompressor;
|
|
1169
1173
|
serializedWithSession.localSessionIndex = serializedWithSession.sessions.findIndex(([sessionId]) => sessionId === this.localSessionId);
|
|
@@ -1172,40 +1176,41 @@ class IdCompressor {
|
|
|
1172
1176
|
localIdCount: this.localIdCount,
|
|
1173
1177
|
overrides: [...this.localOverrides.entries()].map((entry) => [...entry]),
|
|
1174
1178
|
lastTakenLocalId: this.lastTakenLocalId,
|
|
1175
|
-
sentAttributionInfo: this.sentAttributionInfo,
|
|
1176
1179
|
};
|
|
1177
1180
|
}
|
|
1178
1181
|
return serializedWithSession;
|
|
1179
1182
|
}
|
|
1180
1183
|
return serializedIdCompressor;
|
|
1181
1184
|
}
|
|
1182
|
-
static deserialize(
|
|
1183
|
-
const
|
|
1185
|
+
static deserialize(...args) {
|
|
1186
|
+
const [serialized, newSessionIdMaybe, attributionIdMaybe] = args;
|
|
1187
|
+
const { clusterCapacity, reservedIdCount, sessions: serializedSessions, clusters: serializedClusters, attributionIds: serializedAttributionIds, } = serialized;
|
|
1184
1188
|
let localSessionId;
|
|
1185
|
-
let
|
|
1189
|
+
let attributionId;
|
|
1186
1190
|
let serializedLocalState;
|
|
1187
|
-
if (
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1191
|
+
if (newSessionIdMaybe === undefined) {
|
|
1192
|
+
// Alias of serialized, but known to be a SerializedIdCompressorWithOngoingSession
|
|
1193
|
+
const [serializedWithSession] = args;
|
|
1194
|
+
const serializedSessionData = serializedSessions[serializedWithSession.localSessionIndex];
|
|
1195
|
+
localSessionId = serializedSessionData[0];
|
|
1196
|
+
const attributionIndex = serializedSessionData[1];
|
|
1197
|
+
if (attributionIndex !== undefined) {
|
|
1198
|
+
(0, Common_1.assert)(serializedAttributionIds !== undefined && serializedAttributionIds.length > attributionIndex);
|
|
1199
|
+
attributionId = serializedAttributionIds[attributionIndex];
|
|
1200
|
+
}
|
|
1201
|
+
serializedLocalState = serializedWithSession.localState;
|
|
1194
1202
|
}
|
|
1195
1203
|
else {
|
|
1196
|
-
Common_1.assert(newSessionIdMaybe !== undefined);
|
|
1197
1204
|
localSessionId = newSessionIdMaybe;
|
|
1198
|
-
|
|
1205
|
+
attributionId = attributionIdMaybe;
|
|
1199
1206
|
}
|
|
1200
|
-
const
|
|
1201
|
-
const compressor = new IdCompressor(localSessionId, reservedIdCount, attributionInfo);
|
|
1207
|
+
const compressor = new IdCompressor(localSessionId, reservedIdCount, attributionId);
|
|
1202
1208
|
compressor.clusterCapacity = clusterCapacity;
|
|
1203
1209
|
const localOverridesInverse = new Map();
|
|
1204
1210
|
if (serializedLocalState !== undefined) {
|
|
1205
1211
|
// Do this part of local rehydration first since the cluster map population needs to query to local overrides
|
|
1206
1212
|
compressor.localIdCount = serializedLocalState.localIdCount;
|
|
1207
1213
|
compressor.lastTakenLocalId = serializedLocalState.lastTakenLocalId;
|
|
1208
|
-
compressor.sentAttributionInfo = serializedLocalState.sentAttributionInfo;
|
|
1209
1214
|
if (serializedLocalState.overrides !== undefined) {
|
|
1210
1215
|
for (const [localId, override] of serializedLocalState.overrides) {
|
|
1211
1216
|
compressor.localOverrides.append(localId, override);
|
|
@@ -1216,13 +1221,18 @@ class IdCompressor {
|
|
|
1216
1221
|
}
|
|
1217
1222
|
const sessionInfos = [];
|
|
1218
1223
|
for (const serializedSession of serializedSessions) {
|
|
1219
|
-
const [sessionId,
|
|
1224
|
+
const [sessionId, attributionIndex] = serializedSession;
|
|
1220
1225
|
if (sessionId === localSessionId) {
|
|
1221
|
-
Common_1.assert(
|
|
1226
|
+
(0, Common_1.assert)(hasOngoingSession(serialized), 'Cannot resume existing session.');
|
|
1222
1227
|
sessionInfos.push({ session: compressor.localSession, sessionId });
|
|
1223
1228
|
}
|
|
1224
1229
|
else {
|
|
1225
|
-
|
|
1230
|
+
let attributionId;
|
|
1231
|
+
if (attributionIndex !== undefined) {
|
|
1232
|
+
(0, Common_1.assert)(serializedAttributionIds !== undefined && serializedAttributionIds.length > attributionIndex, 'AttributionId index out of bounds');
|
|
1233
|
+
attributionId = serializedAttributionIds[attributionIndex];
|
|
1234
|
+
}
|
|
1235
|
+
const session = compressor.createSession(sessionId, attributionId);
|
|
1226
1236
|
sessionInfos.push({ session, sessionId });
|
|
1227
1237
|
}
|
|
1228
1238
|
}
|
|
@@ -1234,7 +1244,7 @@ class IdCompressor {
|
|
|
1234
1244
|
const cluster = {
|
|
1235
1245
|
capacity,
|
|
1236
1246
|
count,
|
|
1237
|
-
baseUuid: NumericUuid_1.incrementUuid(sessionUuid, currentIdCount),
|
|
1247
|
+
baseUuid: (0, NumericUuid_1.incrementUuid)(sessionUuid, currentIdCount),
|
|
1238
1248
|
session,
|
|
1239
1249
|
};
|
|
1240
1250
|
const lastFinalizedNormalized = lastFinalizedLocalId !== null && lastFinalizedLocalId !== void 0 ? lastFinalizedLocalId : 0;
|
|
@@ -1249,7 +1259,7 @@ class IdCompressor {
|
|
|
1249
1259
|
session.currentClusterDetails = { clusterBase, cluster };
|
|
1250
1260
|
compressor.nextClusterBaseFinalId = (compressor.nextClusterBaseFinalId + capacity);
|
|
1251
1261
|
compressor.finalIdToCluster.append(clusterBase, cluster);
|
|
1252
|
-
compressor.clustersAndOverridesInversion.set(NumericUuid_1.stableIdFromNumericUuid(cluster.baseUuid), {
|
|
1262
|
+
compressor.clustersAndOverridesInversion.set((0, NumericUuid_1.stableIdFromNumericUuid)(cluster.baseUuid), {
|
|
1253
1263
|
clusterBase,
|
|
1254
1264
|
cluster,
|
|
1255
1265
|
});
|
|
@@ -1263,7 +1273,7 @@ class IdCompressor {
|
|
|
1263
1273
|
originalOverridingFinal,
|
|
1264
1274
|
};
|
|
1265
1275
|
if (serializedLocalState !== undefined) {
|
|
1266
|
-
Common_1.setPropertyIfDefined(localOverridesInverse.get(override), unifiedOverride, 'associatedLocalId');
|
|
1276
|
+
(0, Common_1.setPropertyIfDefined)(localOverridesInverse.get(override), unifiedOverride, 'associatedLocalId');
|
|
1267
1277
|
}
|
|
1268
1278
|
cluster.overrides.set(finalId, unifiedOverride);
|
|
1269
1279
|
}
|
|
@@ -1287,20 +1297,20 @@ class IdCompressor {
|
|
|
1287
1297
|
originalOverridingFinal: finalId,
|
|
1288
1298
|
};
|
|
1289
1299
|
if (serializedLocalState !== undefined) {
|
|
1290
|
-
Common_1.setPropertyIfDefined(associatedLocal, finalizedOverride, 'associatedLocalId');
|
|
1300
|
+
(0, Common_1.setPropertyIfDefined)(associatedLocal, finalizedOverride, 'associatedLocalId');
|
|
1291
1301
|
}
|
|
1292
1302
|
compressor.clustersAndOverridesInversion.set(IdCompressor.createInversionKey(override), finalizedOverride);
|
|
1293
1303
|
}
|
|
1294
1304
|
}
|
|
1295
1305
|
}
|
|
1296
1306
|
}
|
|
1297
|
-
Common_1.assert(compressor.localSession.lastFinalizedLocalId === undefined ||
|
|
1307
|
+
(0, Common_1.assert)(compressor.localSession.lastFinalizedLocalId === undefined ||
|
|
1298
1308
|
compressor.localIdCount >= -compressor.localSession.lastFinalizedLocalId);
|
|
1299
1309
|
return compressor;
|
|
1300
1310
|
}
|
|
1301
1311
|
static convertToCurrentVersion(serializedCompressor, hasSession) {
|
|
1302
1312
|
if (serializedCompressor.version !== currentWrittenVersion) {
|
|
1303
|
-
Common_1.fail('Unknown SerializedIdCompressor version number');
|
|
1313
|
+
(0, Common_1.fail)('Unknown SerializedIdCompressor version number');
|
|
1304
1314
|
}
|
|
1305
1315
|
const serialized = serializedCompressor;
|
|
1306
1316
|
if (hasSession !== hasOngoingSession(serialized)) {
|
|
@@ -1331,10 +1341,8 @@ function deserializeCluster(serializedCluster) {
|
|
|
1331
1341
|
return {
|
|
1332
1342
|
sessionIndex,
|
|
1333
1343
|
capacity,
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
// TODO: This cast can be removed on typescript 4.6
|
|
1337
|
-
overrides: (hasCount ? overrides : countOrOverrides),
|
|
1344
|
+
count: hasCount ? countOrOverrides : capacity,
|
|
1345
|
+
overrides: hasCount ? overrides : countOrOverrides,
|
|
1338
1346
|
};
|
|
1339
1347
|
}
|
|
1340
1348
|
/**
|
|
@@ -1344,10 +1352,4 @@ function deserializeCluster(serializedCluster) {
|
|
|
1344
1352
|
* lookup results should be extracted from the tuple immediately after invocation.
|
|
1345
1353
|
*/
|
|
1346
1354
|
const reusedArray = [];
|
|
1347
|
-
/**
|
|
1348
|
-
* A numeric comparator used for sorting in descending order.
|
|
1349
|
-
*/
|
|
1350
|
-
function compareFiniteNumbersReversed(a, b) {
|
|
1351
|
-
return b - a;
|
|
1352
|
-
}
|
|
1353
1355
|
//# sourceMappingURL=IdCompressor.js.map
|