@fluid-experimental/tree 0.59.3003 → 0.59.4000

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.
Files changed (54) hide show
  1. package/dist/Forest.js +1 -1
  2. package/dist/Forest.js.map +1 -1
  3. package/dist/id-compressor/IdCompressor.d.ts +19 -45
  4. package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
  5. package/dist/id-compressor/IdCompressor.js +151 -151
  6. package/dist/id-compressor/IdCompressor.js.map +1 -1
  7. package/dist/id-compressor/SessionIdNormalizer.d.ts +1 -16
  8. package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
  9. package/dist/id-compressor/SessionIdNormalizer.js +23 -21
  10. package/dist/id-compressor/SessionIdNormalizer.js.map +1 -1
  11. package/dist/id-compressor/persisted-types/0.0.1.d.ts +23 -4
  12. package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  13. package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
  14. package/lib/Forest.js +1 -1
  15. package/lib/Forest.js.map +1 -1
  16. package/lib/id-compressor/IdCompressor.d.ts +19 -45
  17. package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
  18. package/lib/id-compressor/IdCompressor.js +152 -152
  19. package/lib/id-compressor/IdCompressor.js.map +1 -1
  20. package/lib/id-compressor/SessionIdNormalizer.d.ts +1 -16
  21. package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
  22. package/lib/id-compressor/SessionIdNormalizer.js +23 -21
  23. package/lib/id-compressor/SessionIdNormalizer.js.map +1 -1
  24. package/lib/id-compressor/persisted-types/0.0.1.d.ts +23 -4
  25. package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  26. package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -1
  27. package/lib/test/IdCompressor.perf.tests.js +47 -67
  28. package/lib/test/IdCompressor.perf.tests.js.map +1 -1
  29. package/lib/test/IdCompressor.tests.js +196 -101
  30. package/lib/test/IdCompressor.tests.js.map +1 -1
  31. package/lib/test/Summary.tests.d.ts +0 -1
  32. package/lib/test/Summary.tests.d.ts.map +1 -1
  33. package/lib/test/Summary.tests.js +0 -3
  34. package/lib/test/Summary.tests.js.map +1 -1
  35. package/lib/test/Virtualization.tests.js +0 -4
  36. package/lib/test/Virtualization.tests.js.map +1 -1
  37. package/lib/test/utilities/IdCompressorTestUtilities.d.ts +14 -7
  38. package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -1
  39. package/lib/test/utilities/IdCompressorTestUtilities.js +40 -20
  40. package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -1
  41. package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
  42. package/lib/test/utilities/SharedTreeTests.js +0 -1
  43. package/lib/test/utilities/SharedTreeTests.js.map +1 -1
  44. package/lib/test/utilities/SummaryLoadPerfTests.js +1 -1
  45. package/lib/test/utilities/SummaryLoadPerfTests.js.map +1 -1
  46. package/lib/test/utilities/TestCommon.d.ts +4 -0
  47. package/lib/test/utilities/TestCommon.d.ts.map +1 -1
  48. package/lib/test/utilities/TestCommon.js +6 -0
  49. package/lib/test/utilities/TestCommon.js.map +1 -1
  50. package/package.json +24 -19
  51. package/src/Forest.ts +1 -1
  52. package/src/id-compressor/IdCompressor.ts +171 -198
  53. package/src/id-compressor/SessionIdNormalizer.ts +29 -41
  54. package/src/id-compressor/persisted-types/0.0.1.ts +25 -4
@@ -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;AAGhG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,WAAW,CAAC,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,GAAG,IAAI;IAkDhH;;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;IAsB7B,MAAM,CACZ,KAAK,EAAE,mBAAmB,CAAC,YAAY,CAAC,EACxC,mBAAmB,GAAE,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,OAA2B,GACpF,OAAO;CA4BV;AAED;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC7C,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,SAAS;QACxC,UAAU,EAAE,iBAAiB;QAC7B,SAAS,EAAE,iBAAiB;QAC5B,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS;YAChC,YAAY,EAAE,iBAAiB;YAC/B,UAAU,EAAE,iBAAiB;YAC7B,SAAS,EAAE,iBAAiB;SAC5B,CAAC,EAAE;KACJ,CAAC,EAAE,CAAC;CACL"}
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;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,WAAW,CAAC,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,GAAG,IAAI;IAkDhH;;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"}
@@ -292,7 +292,7 @@ export class SessionIdNormalizer {
292
292
  }
293
293
  }
294
294
  serialize() {
295
- const serialized = { localRanges: [] };
295
+ const serialized = { localRanges: [], nextLocalId: this.nextLocalId };
296
296
  const localRanges = serialized.localRanges;
297
297
  for (const [firstLocal, finalRanges] of this.idRanges.entries()) {
298
298
  const [lastLocal, finalRangesTable] = finalRanges;
@@ -329,30 +329,32 @@ export class SessionIdNormalizer {
329
329
  }
330
330
  idRanges.append(firstLocal, [lastLocal, finalRanges]);
331
331
  }
332
+ normalizer.nextLocalId = serialized.nextLocalId;
332
333
  return normalizer;
333
334
  }
334
335
  equals(other, compareRangeObjects = (a, b) => a === b) {
335
- return this.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {
336
- const [lastLocalA, finalRangesA] = localRangeA;
337
- const [lastLocalB, finalRangesB] = localRangeB;
338
- if (finalRangesA === undefined || finalRangesB === undefined) {
339
- return finalRangesA === finalRangesB;
340
- }
341
- const rangeEquals = (finalRangeA, finalRangeB) => {
342
- const [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;
343
- const [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;
344
- return (firstFinalA === firstFinalB &&
345
- lastFinalA === lastFinalB &&
346
- compareRangeObjects(rangeObjectA, rangeObjectB));
347
- };
348
- if (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {
349
- if (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {
350
- return false;
336
+ return (this.nextLocalId === other.nextLocalId &&
337
+ this.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {
338
+ const [lastLocalA, finalRangesA] = localRangeA;
339
+ const [lastLocalB, finalRangesB] = localRangeB;
340
+ if (finalRangesA === undefined || finalRangesB === undefined) {
341
+ return finalRangesA === finalRangesB;
351
342
  }
352
- return rangeEquals(finalRangesA, finalRangesB);
353
- }
354
- return lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);
355
- });
343
+ const rangeEquals = (finalRangeA, finalRangeB) => {
344
+ const [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;
345
+ const [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;
346
+ return (firstFinalA === firstFinalB &&
347
+ lastFinalA === lastFinalB &&
348
+ compareRangeObjects(rangeObjectA, rangeObjectB));
349
+ };
350
+ if (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {
351
+ if (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {
352
+ return false;
353
+ }
354
+ return rangeEquals(finalRangesA, finalRangesB);
355
+ }
356
+ return lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);
357
+ }));
356
358
  }
357
359
  }
358
360
  function isSingleRange(ranges) {
@@ -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';\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: [] };\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\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 this.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {\n\t\t\tconst [lastLocalA, finalRangesA] = localRangeA;\n\t\t\tconst [lastLocalB, finalRangesB] = localRangeB;\n\t\t\tif (finalRangesA === undefined || finalRangesB === undefined) {\n\t\t\t\treturn finalRangesA === finalRangesB;\n\t\t\t}\n\n\t\t\tconst rangeEquals = (finalRangeA: FinalRange<TRangeObject>, finalRangeB: FinalRange<TRangeObject>) => {\n\t\t\t\tconst [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;\n\t\t\t\tconst [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;\n\t\t\t\treturn (\n\t\t\t\t\tfirstFinalA === firstFinalB &&\n\t\t\t\t\tlastFinalA === lastFinalB &&\n\t\t\t\t\tcompareRangeObjects(rangeObjectA, rangeObjectB)\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tif (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {\n\t\t\t\tif (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn rangeEquals(finalRangesA, finalRangesB);\n\t\t\t}\n\n\t\t\treturn lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);\n\t\t});\n\t}\n}\n\n/**\n * Serialized table for normalizing IDs made by the local session.\n *\n * TODO: Move this into ID compressor persisted types when integrated.\n */\nexport interface SerializedSessionIdNormalizer {\n\treadonly localRanges: readonly (readonly [\n\t\tfirstLocal: LocalCompressedId,\n\t\tlastLocal: LocalCompressedId,\n\t\tfinalRanges?: readonly (readonly [\n\t\t\talignedLocal: LocalCompressedId,\n\t\t\tfirstFinal: FinalCompressedId,\n\t\t\tlastFinal: FinalCompressedId\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 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"]}
@@ -48,20 +48,39 @@ export declare type SerializedCluster = readonly [
48
48
  */
49
49
  overrides?: SerializedClusterOverrides
50
50
  ];
51
- export declare type SerializedLocalOverrides = readonly [LocalCompressedId, string][];
51
+ export declare type SerializedLocalOverrides = readonly (readonly [LocalCompressedId, string])[];
52
52
  export interface SerializedLocalState {
53
53
  /**
54
54
  * The total number of local IDs created by this session
55
55
  */
56
- localIdCount: number;
56
+ readonly localIdCount: number;
57
57
  /**
58
58
  * Overrides generated by this session. Omitted if no local overrides exist in the session.
59
59
  */
60
- overrides?: SerializedLocalOverrides;
60
+ readonly overrides?: SerializedLocalOverrides;
61
61
  /**
62
62
  * The most recent local ID in a range returned by `takeNextCreationRange`.
63
63
  */
64
- lastTakenLocalId: LocalCompressedId | undefined;
64
+ readonly lastTakenLocalId: LocalCompressedId | undefined;
65
+ /**
66
+ * Serialized table for normalizing IDs made by the local session.
67
+ */
68
+ readonly sessionNormalizer: SerializedSessionIdNormalizer;
69
+ }
70
+ /**
71
+ * Serialized table for normalizing IDs made by the local session.
72
+ */
73
+ export interface SerializedSessionIdNormalizer {
74
+ readonly nextLocalId: LocalCompressedId;
75
+ readonly localRanges: readonly (readonly [
76
+ firstLocal: LocalCompressedId,
77
+ lastLocal: LocalCompressedId,
78
+ finalRanges?: readonly (readonly [
79
+ alignedLocal: LocalCompressedId,
80
+ firstFinal: FinalCompressedId,
81
+ lastFinal: FinalCompressedId
82
+ ])[]
83
+ ])[];
65
84
  }
66
85
  /**
67
86
  * The minimal required contents of a serialized IdCompressor.
@@ -1 +1 @@
1
- {"version":3,"file":"0.0.1.d.ts","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"0.0.1.d.ts","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"0.0.1.js","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tAttributionId,\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tOpSpaceCompressedId,\n\tSessionId,\n} from '../../Identifiers';\n\n/**\n * A serialized ID allocation session for an `IdCompressor`.\n */\nexport type SerializedSessionData = readonly [\n\t/**\n\t * The ID of the session.\n\t */\n\tsessionId: SessionId,\n\n\t/**\n\t * Index into the serialized AttributionIDs array; points to the attribution ID provided for this session\n\t */\n\tattributionId?: number\n];\n\nexport type SerializedClusterOverrides = readonly [\n\t/** The overridden final ID, represented as an index into the cluster's ID range */\n\toverriddenFinalIndex: number, // A cluster with base UUID '...beef' and an `overriddenFinalIndex` of 3 would correspond to '...bef2'\n\t/** The override string */\n\toverride: string,\n\t/** The first ID that was finalized and associated with this override, set only if different than the `overriddenFinalIndex` */\n\toverriddenId?: FinalCompressedId\n][];\n\n/**\n * A serialized final ID cluster.\n */\nexport type SerializedCluster = readonly [\n\t/**\n\t * Index into the serialized sessions array. Can be converted into a baseUuid via its order in `clusters`.\n\t * If negative, then this cluster was created by the local session.\n\t */\n\tsessionIndex: number,\n\n\t/**\n\t * The capacity of the cluster.\n\t */\n\tcapacity: number,\n\n\t/**\n\t * The number of IDs in the cluster. Omitted if count === capacity.\n\t * --OR--\n\t * The overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\tcountOrOverrides?: number | SerializedClusterOverrides,\n\n\t/**\n\t * Overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\toverrides?: SerializedClusterOverrides\n];\n\nexport type SerializedLocalOverrides = readonly [LocalCompressedId, string][];\n\nexport interface SerializedLocalState {\n\t/**\n\t * The total number of local IDs created by this session\n\t */\n\tlocalIdCount: number;\n\t/**\n\t * Overrides generated by this session. Omitted if no local overrides exist in the session.\n\t */\n\toverrides?: SerializedLocalOverrides;\n\n\t/**\n\t * The most recent local ID in a range returned by `takeNextCreationRange`.\n\t */\n\tlastTakenLocalId: LocalCompressedId | undefined;\n}\n\n/**\n * The minimal required contents of a serialized IdCompressor.\n */\nexport interface VersionedSerializedIdCompressor {\n\treadonly _versionedSerializedIdCompressor: '8c73c57c-1cf4-4278-8915-6444cb4f6af5';\n\treadonly version: string;\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressor extends VersionedSerializedIdCompressor {\n\t/** The cluster capacity of this compressor */\n\treadonly clusterCapacity: number;\n\t/** The number of reserved IDs in this compressor */\n\treadonly reservedIdCount: number;\n\t/** All sessions except the local session. */\n\treadonly sessions: readonly SerializedSessionData[];\n\t/** All clusters in the compressor in the order they were created. */\n\treadonly clusters: readonly SerializedCluster[];\n\t/** All attribution IDs for all sessions */\n\treadonly attributionIds?: readonly AttributionId[];\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressorWithNoSession extends SerializedIdCompressor {\n\treadonly _noLocalState: '3aa2e1e8-cc28-4ea7-bc1a-a11dc3f26dfb';\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressorWithOngoingSession extends SerializedIdCompressor {\n\treadonly _hasLocalState: '1281acae-6d14-47e7-bc92-71c8ee0819cb';\n\t/** The session ID of the local session, by index into `sessions`. */\n\treadonly localSessionIndex: number;\n\t/** This is only present if the local session made any IDs. */\n\treadonly localState?: SerializedLocalState;\n}\n\n/**\n * Data describing a range of session-local IDs (from a remote or local session).\n *\n * A range is composed of local IDs that were generated. Some of these may have overrides.\n *\n * @example\n * Suppose an IdCompressor generated a sequence of local IDs as follows:\n * ```\n * compressor.generateLocalId()\n * compressor.generateLocalId('0093cf29-9454-4034-8940-33b1077b41c3')\n * compressor.generateLocalId()\n * compressor.generateLocalId('0ed545f8-e97e-4dc1-acf9-c4a783258bdf')\n * compressor.generateLocalId()\n * compressor.generateLocalId()\n * compressor.takeNextCreationRange()\n * ```\n * This would result in the following range:\n * ```\n * {\n * first: localId1,\n * last: localId6,\n * overrides: [[localId2, '0093cf29-9454-4034-8940-33b1077b41c3'], [localId4, '0ed545f8-e97e-4dc1-acf9-c4a783258bdf']]\n * }\n * ```\n */\nexport interface IdCreationRange {\n\treadonly sessionId: SessionId;\n\treadonly ids?: IdCreationRange.Ids;\n\treadonly attributionId?: AttributionId;\n}\n\nexport type UnackedLocalId = LocalCompressedId & OpSpaceCompressedId;\n\nexport namespace IdCreationRange {\n\texport type Ids =\n\t\t| {\n\t\t\t\treadonly first: UnackedLocalId;\n\t\t\t\treadonly last: UnackedLocalId;\n\t\t }\n\t\t| ({\n\t\t\t\treadonly first?: UnackedLocalId;\n\t\t\t\treadonly last?: UnackedLocalId;\n\t\t } & HasOverrides);\n\n\texport interface HasOverrides {\n\t\treadonly overrides: Overrides;\n\t}\n\n\texport type Override = readonly [id: UnackedLocalId, override: string];\n\texport type Overrides = readonly [Override, ...Override[]];\n}\n"]}
1
+ {"version":3,"file":"0.0.1.js","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tAttributionId,\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tOpSpaceCompressedId,\n\tSessionId,\n} from '../../Identifiers';\n\n/**\n * A serialized ID allocation session for an `IdCompressor`.\n */\nexport type SerializedSessionData = readonly [\n\t/**\n\t * The ID of the session.\n\t */\n\tsessionId: SessionId,\n\n\t/**\n\t * Index into the serialized AttributionIDs array; points to the attribution ID provided for this session\n\t */\n\tattributionId?: number\n];\n\nexport type SerializedClusterOverrides = readonly [\n\t/** The overridden final ID, represented as an index into the cluster's ID range */\n\toverriddenFinalIndex: number, // A cluster with base UUID '...beef' and an `overriddenFinalIndex` of 3 would correspond to '...bef2'\n\t/** The override string */\n\toverride: string,\n\t/** The first ID that was finalized and associated with this override, set only if different than the `overriddenFinalIndex` */\n\toverriddenId?: FinalCompressedId\n][];\n\n/**\n * A serialized final ID cluster.\n */\nexport type SerializedCluster = readonly [\n\t/**\n\t * Index into the serialized sessions array. Can be converted into a baseUuid via its order in `clusters`.\n\t * If negative, then this cluster was created by the local session.\n\t */\n\tsessionIndex: number,\n\n\t/**\n\t * The capacity of the cluster.\n\t */\n\tcapacity: number,\n\n\t/**\n\t * The number of IDs in the cluster. Omitted if count === capacity.\n\t * --OR--\n\t * The overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\tcountOrOverrides?: number | SerializedClusterOverrides,\n\n\t/**\n\t * Overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\toverrides?: SerializedClusterOverrides\n];\n\nexport type SerializedLocalOverrides = readonly (readonly [LocalCompressedId, string])[];\n\nexport interface SerializedLocalState {\n\t/**\n\t * The total number of local IDs created by this session\n\t */\n\treadonly localIdCount: number;\n\t/**\n\t * Overrides generated by this session. Omitted if no local overrides exist in the session.\n\t */\n\treadonly overrides?: SerializedLocalOverrides;\n\n\t/**\n\t * The most recent local ID in a range returned by `takeNextCreationRange`.\n\t */\n\treadonly lastTakenLocalId: LocalCompressedId | undefined;\n\n\t/**\n\t * Serialized table for normalizing IDs made by the local session.\n\t */\n\treadonly sessionNormalizer: SerializedSessionIdNormalizer;\n}\n\n/**\n * Serialized table for normalizing IDs made by the local session.\n */\nexport interface SerializedSessionIdNormalizer {\n\treadonly nextLocalId: LocalCompressedId;\n\treadonly localRanges: readonly (readonly [\n\t\tfirstLocal: LocalCompressedId,\n\t\tlastLocal: LocalCompressedId,\n\t\tfinalRanges?: readonly (readonly [\n\t\t\talignedLocal: LocalCompressedId,\n\t\t\tfirstFinal: FinalCompressedId,\n\t\t\tlastFinal: FinalCompressedId\n\t\t])[]\n\t])[];\n}\n\n/**\n * The minimal required contents of a serialized IdCompressor.\n */\nexport interface VersionedSerializedIdCompressor {\n\treadonly _versionedSerializedIdCompressor: '8c73c57c-1cf4-4278-8915-6444cb4f6af5';\n\treadonly version: string;\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressor extends VersionedSerializedIdCompressor {\n\t/** The cluster capacity of this compressor */\n\treadonly clusterCapacity: number;\n\t/** The number of reserved IDs in this compressor */\n\treadonly reservedIdCount: number;\n\t/** All sessions except the local session. */\n\treadonly sessions: readonly SerializedSessionData[];\n\t/** All clusters in the compressor in the order they were created. */\n\treadonly clusters: readonly SerializedCluster[];\n\t/** All attribution IDs for all sessions */\n\treadonly attributionIds?: readonly AttributionId[];\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressorWithNoSession extends SerializedIdCompressor {\n\treadonly _noLocalState: '3aa2e1e8-cc28-4ea7-bc1a-a11dc3f26dfb';\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressorWithOngoingSession extends SerializedIdCompressor {\n\treadonly _hasLocalState: '1281acae-6d14-47e7-bc92-71c8ee0819cb';\n\t/** The session ID of the local session, by index into `sessions`. */\n\treadonly localSessionIndex: number;\n\t/** This is only present if the local session made any IDs. */\n\treadonly localState?: SerializedLocalState;\n}\n\n/**\n * Data describing a range of session-local IDs (from a remote or local session).\n *\n * A range is composed of local IDs that were generated. Some of these may have overrides.\n *\n * @example\n * Suppose an IdCompressor generated a sequence of local IDs as follows:\n * ```\n * compressor.generateLocalId()\n * compressor.generateLocalId('0093cf29-9454-4034-8940-33b1077b41c3')\n * compressor.generateLocalId()\n * compressor.generateLocalId('0ed545f8-e97e-4dc1-acf9-c4a783258bdf')\n * compressor.generateLocalId()\n * compressor.generateLocalId()\n * compressor.takeNextCreationRange()\n * ```\n * This would result in the following range:\n * ```\n * {\n * first: localId1,\n * last: localId6,\n * overrides: [[localId2, '0093cf29-9454-4034-8940-33b1077b41c3'], [localId4, '0ed545f8-e97e-4dc1-acf9-c4a783258bdf']]\n * }\n * ```\n */\nexport interface IdCreationRange {\n\treadonly sessionId: SessionId;\n\treadonly ids?: IdCreationRange.Ids;\n\treadonly attributionId?: AttributionId;\n}\n\nexport type UnackedLocalId = LocalCompressedId & OpSpaceCompressedId;\n\nexport namespace IdCreationRange {\n\texport type Ids =\n\t\t| {\n\t\t\t\treadonly first: UnackedLocalId;\n\t\t\t\treadonly last: UnackedLocalId;\n\t\t }\n\t\t| ({\n\t\t\t\treadonly first?: UnackedLocalId;\n\t\t\t\treadonly last?: UnackedLocalId;\n\t\t } & HasOverrides);\n\n\texport interface HasOverrides {\n\t\treadonly overrides: Overrides;\n\t}\n\n\texport type Override = readonly [id: UnackedLocalId, override: string];\n\texport type Overrides = readonly [Override, ...Override[]];\n}\n"]}
@@ -2,23 +2,24 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
5
6
  import { benchmark, BenchmarkType } from '@fluid-tools/benchmark';
6
- import { v4 } from 'uuid';
7
7
  import { take } from '@fluid-internal/stochastic-test-utils';
8
8
  import { fail } from '../Common';
9
- import { defaultClusterCapacity, IdCompressor, isFinalId, isLocalId, } from '../id-compressor/IdCompressor';
9
+ import { defaultClusterCapacity, IdCompressor, isFinalId, isLocalId } from '../id-compressor/IdCompressor';
10
10
  import { createSessionId, numericUuidFromStableId, stableIdFromNumericUuid } from '../id-compressor/NumericUuid';
11
11
  import { Client, IdCompressorTestNetwork, makeOpGenerator, performFuzzActions, sessionIds, } from './utilities/IdCompressorTestUtilities';
12
12
  describe('IdCompressor Perf', () => {
13
13
  const type = BenchmarkType.Measurement;
14
14
  const localClient = Client.Client1;
15
15
  const remoteClient = Client.Client2;
16
+ let perfCompressor;
17
+ let network;
16
18
  let compressor;
17
- let remoteCompressor;
18
19
  function setupCompressors(clusterSize, allowLocal, includeOverrides) {
19
- const network = new IdCompressorTestNetwork(clusterSize);
20
+ network = new IdCompressorTestNetwork(clusterSize);
20
21
  [compressor] = createPerfCompressor(network, allowLocal, includeOverrides, localClient);
21
- [remoteCompressor] = createPerfCompressor(network, allowLocal, includeOverrides, remoteClient);
22
+ perfCompressor = undefined;
22
23
  return network;
23
24
  }
24
25
  function createPerfCompressor(network, allowLocal, includeOverrides, client) {
@@ -27,7 +28,7 @@ describe('IdCompressor Perf', () => {
27
28
  if (network.initialClusterSize > maxClusterSize) {
28
29
  network.enqueueCapacityChange(maxClusterSize);
29
30
  }
30
- performFuzzActions(generator, network, Math.E, client, allowLocal ? false : true);
31
+ performFuzzActions(generator, network, Math.E, allowLocal ? undefined : client, !allowLocal);
31
32
  return [network.getCompressorUnsafe(client), network.getIdLog(client)];
32
33
  }
33
34
  function setupCompressorWithId(local, override, clusterHasOtherOverrides) {
@@ -63,34 +64,6 @@ describe('IdCompressor Perf', () => {
63
64
  }
64
65
  }
65
66
  }
66
- [true, false].forEach((isLocal) => {
67
- let range;
68
- let sessionId;
69
- const numIds = 100;
70
- const clusterSize = Math.round(numIds / 2);
71
- const setupRange = (isLocal) => {
72
- setupCompressors(clusterSize, true, false);
73
- const originCompressor = isLocal ? compressor : remoteCompressor;
74
- sessionId = originCompressor.localSessionId;
75
- range = originCompressor.generateCompressedIdRange(numIds);
76
- const creationRange = originCompressor.takeNextCreationRange();
77
- compressor.finalizeCreationRange(creationRange);
78
- };
79
- const beforeLocal = () => setupRange(false);
80
- const beforeRemote = () => setupRange(true);
81
- benchmark({
82
- type,
83
- title: `get ${numIds} sequential IDs for a ${isLocal ? 'local' : 'remote'} range`,
84
- before: isLocal ? beforeLocal : beforeRemote,
85
- benchmarkFn: () => {
86
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
87
- const ids = compressor.getIdsFromRange(range, sessionId);
88
- for (let i = 0; i < numIds; i++) {
89
- ids.get(i); // get a sequential ID
90
- }
91
- },
92
- });
93
- });
94
67
  [true, false].forEach((override) => {
95
68
  const numericSource = numericUuidFromStableId(createSessionId());
96
69
  let overrideIndex = 0;
@@ -99,9 +72,10 @@ describe('IdCompressor Perf', () => {
99
72
  title: `allocate local ID (${override ? 'override' : 'sequential'})`,
100
73
  before: () => {
101
74
  setupCompressors(defaultClusterCapacity, true, false);
75
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
102
76
  },
103
77
  benchmarkFn: () => {
104
- compressor.generateCompressedId(override ? stableIdFromNumericUuid(numericSource, overrideIndex++) : undefined);
78
+ perfCompressor.generateCompressedId(override ? stableIdFromNumericUuid(numericSource, overrideIndex++) : undefined);
105
79
  },
106
80
  });
107
81
  });
@@ -120,6 +94,7 @@ describe('IdCompressor Perf', () => {
120
94
  title: `finalize a range of IDs (cluster size =${clusterSize}${override ? ', overrides present' : ''})`,
121
95
  before: () => {
122
96
  setupCompressors(clusterSize, false, false);
97
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
123
98
  },
124
99
  benchmarkFn: () => {
125
100
  // Create a range with as minimal overhead as possible, as we'd like for this code to not exist
@@ -146,7 +121,7 @@ describe('IdCompressor Perf', () => {
146
121
  overrides,
147
122
  },
148
123
  };
149
- compressor.finalizeCreationRange(range);
124
+ perfCompressor.finalizeCreationRange(range);
150
125
  if (isLocal) {
151
126
  lastFinalizedLocalId1 = last;
152
127
  }
@@ -159,30 +134,26 @@ describe('IdCompressor Perf', () => {
159
134
  });
160
135
  }
161
136
  });
162
- [true, false].forEach((override) => {
163
- const idCount = 5;
164
- benchmark({
165
- type,
166
- title: `creates an ID range (${override ? 'with overrides' : ''})`,
167
- before: () => {
168
- setupCompressors(defaultClusterCapacity, true, false);
169
- },
170
- benchmarkFn: () => {
171
- if (override) {
172
- compressor.generateCompressedId(v4());
173
- }
174
- compressor.generateCompressedIdRange(idCount);
175
- compressor.takeNextCreationRange();
176
- },
177
- });
137
+ benchmark({
138
+ type,
139
+ title: `takes a ID creation range'})`,
140
+ before: () => {
141
+ setupCompressors(defaultClusterCapacity, true, false);
142
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
143
+ },
144
+ benchmarkFn: () => {
145
+ perfCompressor.generateCompressedId();
146
+ perfCompressor.takeNextCreationRange();
147
+ },
178
148
  });
179
149
  benchmarkWithIdTypes((local, override, titleSuffix) => {
180
150
  let idToDecompress;
181
151
  const before = () => {
182
152
  idToDecompress = setupCompressorWithId(local, override, true);
153
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
183
154
  };
184
155
  const benchmarkFn = () => {
185
- compressor.decompress(idToDecompress);
156
+ perfCompressor.decompress(idToDecompress);
186
157
  };
187
158
  if (local) {
188
159
  benchmark({
@@ -209,6 +180,7 @@ describe('IdCompressor Perf', () => {
209
180
  title: `${titleBase} (sequential, overrides ${clusterHasOverride ? 'present' : 'not present'} in owning cluster)`,
210
181
  before: () => {
211
182
  idToDecompress = setupCompressorWithId(local, override, clusterHasOverride);
183
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
212
184
  },
213
185
  benchmarkFn,
214
186
  });
@@ -224,9 +196,10 @@ describe('IdCompressor Perf', () => {
224
196
  before: () => {
225
197
  const idAdded = setupCompressorWithId(local, override, true);
226
198
  stableToCompress = compressor.decompress(idAdded);
199
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
227
200
  },
228
201
  benchmarkFn: () => {
229
- compressor.recompress(stableToCompress);
202
+ perfCompressor.recompress(stableToCompress);
230
203
  },
231
204
  });
232
205
  });
@@ -241,25 +214,34 @@ describe('IdCompressor Perf', () => {
241
214
  const log = network.getSequencedIdLog(localClient);
242
215
  const id = compressor.normalizeToOpSpace(log[log.length - 1].id);
243
216
  final = isFinalId(id) ? id : fail('not a final ID');
217
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
244
218
  },
245
219
  benchmarkFn: () => {
246
- compressor.normalizeToSessionSpace(final, compressor.localSessionId);
220
+ perfCompressor.normalizeToSessionSpace(final, compressor.localSessionId);
247
221
  },
248
222
  });
223
+ function getLastLocalId(client, network) {
224
+ const log = network.getIdLog(client);
225
+ for (let i = log.length - 1; i > 0; i--) {
226
+ const cur = log[i].id;
227
+ if (isLocalId(cur)) {
228
+ return cur;
229
+ }
230
+ }
231
+ fail('no local ID found in log');
232
+ }
249
233
  let localId;
250
234
  benchmark({
251
235
  type,
252
236
  title: `normalize a local ID from the local session to session space`,
253
237
  before: () => {
254
238
  const network = setupCompressors(defaultClusterCapacity, true, true);
255
- network.allocateAndSendIds(localClient, 1);
256
239
  network.deliverOperations(localClient);
257
- const log = network.getIdLog(localClient);
258
- const id = log[log.length - 1].id;
259
- localId = isLocalId(id) ? id : fail('not a local ID');
240
+ localId = getLastLocalId(localClient, network);
241
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
260
242
  },
261
243
  benchmarkFn: () => {
262
- compressor.normalizeToOpSpace(localId);
244
+ perfCompressor.normalizeToOpSpace(localId);
263
245
  },
264
246
  });
265
247
  const remoteSessionId = sessionIds.get(remoteClient);
@@ -269,15 +251,12 @@ describe('IdCompressor Perf', () => {
269
251
  title: `normalize a local ID from a remote session to session space`,
270
252
  before: () => {
271
253
  const network = setupCompressors(defaultClusterCapacity, true, true);
272
- network.allocateAndSendIds(remoteClient, 1);
273
- const log = network.getIdLog(remoteClient);
274
- const id = remoteCompressor.normalizeToOpSpace(log[log.length - 1].id);
275
- opSpaceId = isLocalId(id) ? id : fail('not a local ID');
276
- // Ensure id is finalized on local compressor
277
254
  network.deliverOperations(localClient);
255
+ opSpaceId = getLastLocalId(remoteClient, network);
256
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
278
257
  },
279
258
  benchmarkFn: () => {
280
- compressor.normalizeToSessionSpace(opSpaceId !== null && opSpaceId !== void 0 ? opSpaceId : fail(), remoteSessionId);
259
+ perfCompressor.normalizeToSessionSpace(opSpaceId !== null && opSpaceId !== void 0 ? opSpaceId : fail(), remoteSessionId);
281
260
  },
282
261
  });
283
262
  for (const overrideInClusters of [true, false]) {
@@ -287,9 +266,10 @@ describe('IdCompressor Perf', () => {
287
266
  title: `serialize an IdCompressor${titleSuffix}`,
288
267
  before: () => {
289
268
  setupCompressors(defaultClusterCapacity, false, overrideInClusters);
269
+ perfCompressor = network.getCompressorUnsafeNoProxy(localClient);
290
270
  },
291
271
  benchmarkFn: () => {
292
- compressor.serialize(false);
272
+ perfCompressor.serialize(false);
293
273
  },
294
274
  });
295
275
  let serialized;