@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":"IdCompressor.perf.tests.js","sourceRoot":"","sources":["../../src/test/IdCompressor.perf.tests.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { benchmark, BenchmarkType } from '@fluid-tools/benchmark';\nimport { v4 } from 'uuid';\nimport { take } from '@fluid-internal/stochastic-test-utils';\nimport { fail, Mutable } from '../Common';\nimport {\n\tdefaultClusterCapacity,\n\tIdCompressor,\n\tIdRangeDescriptor,\n\tisFinalId,\n\tisLocalId,\n} from '../id-compressor/IdCompressor';\nimport { IdCreationRange, UnackedLocalId, SerializedIdCompressorWithNoSession } from '../id-compressor';\nimport { createSessionId, numericUuidFromStableId, stableIdFromNumericUuid } from '../id-compressor/NumericUuid';\nimport {\n\tCompressedId,\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tOpSpaceCompressedId,\n\tSessionId,\n\tSessionSpaceCompressedId,\n} from '../Identifiers';\nimport {\n\tClient,\n\tIdCompressorTestNetwork,\n\tmakeOpGenerator,\n\tperformFuzzActions,\n\tsessionIds,\n\tTestIdData,\n} from './utilities/IdCompressorTestUtilities';\n\ndescribe('IdCompressor Perf', () => {\n\tconst type = BenchmarkType.Measurement;\n\tconst localClient = Client.Client1;\n\tconst remoteClient = Client.Client2;\n\tlet compressor: IdCompressor;\n\tlet remoteCompressor: IdCompressor;\n\n\tfunction setupCompressors(\n\t\tclusterSize: number,\n\t\tallowLocal: boolean,\n\t\tincludeOverrides: boolean\n\t): IdCompressorTestNetwork {\n\t\tconst network = new IdCompressorTestNetwork(clusterSize);\n\t\t[compressor] = createPerfCompressor(network, allowLocal, includeOverrides, localClient);\n\t\t[remoteCompressor] = createPerfCompressor(network, allowLocal, includeOverrides, remoteClient);\n\t\treturn network;\n\t}\n\n\tfunction createPerfCompressor(\n\t\tnetwork: IdCompressorTestNetwork,\n\t\tallowLocal: boolean,\n\t\tincludeOverrides: boolean,\n\t\tclient: Client\n\t): [IdCompressor, readonly TestIdData[]] {\n\t\tconst maxClusterSize = 25;\n\t\tconst generator = take(1000, makeOpGenerator({ includeOverrides, validateInterval: 2000, maxClusterSize }));\n\t\tif (network.initialClusterSize > maxClusterSize) {\n\t\t\tnetwork.enqueueCapacityChange(maxClusterSize);\n\t\t}\n\t\tperformFuzzActions(generator, network, Math.E, client, allowLocal ? false : true);\n\t\treturn [network.getCompressorUnsafe(client), network.getIdLog(client)];\n\t}\n\n\tfunction setupCompressorWithId(local: boolean, override: boolean, clusterHasOtherOverrides: boolean): CompressedId {\n\t\tconst clusterCapacity = defaultClusterCapacity;\n\t\tconst network = setupCompressors(clusterCapacity, true, true);\n\t\tif (!clusterHasOtherOverrides) {\n\t\t\tnetwork.allocateAndSendIds(localClient, clusterCapacity);\n\t\t} else {\n\t\t\tnetwork.allocateAndSendIds(localClient, 2, {\n\t\t\t\t0: 'override1',\n\t\t\t\t1: 'override2',\n\t\t\t});\n\t\t}\n\t\tif (override) {\n\t\t\tnetwork.allocateAndSendIds(localClient, 1, { 0: 'override3' });\n\t\t} else {\n\t\t\tnetwork.allocateAndSendIds(localClient, 1);\n\t\t}\n\n\t\tif (!local) {\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t}\n\n\t\tconst ids = network.getIdLog(localClient);\n\t\tconst lastId = ids[ids.length - 1].id;\n\t\treturn lastId;\n\t}\n\n\tfunction benchmarkWithIdTypes(creator: (local: boolean, override: boolean, titleSuffix: string) => void) {\n\t\tfor (const local of [true, false]) {\n\t\t\tfor (const override of [true, false]) {\n\t\t\t\tconst titleSuffix = ` (${override ? 'override' : 'sequential'})`;\n\t\t\t\tcreator(local, override, titleSuffix);\n\t\t\t}\n\t\t}\n\t}\n\n\t[true, false].forEach((isLocal) => {\n\t\tlet range: IdRangeDescriptor<SessionSpaceCompressedId>;\n\t\tlet sessionId: SessionId;\n\t\tconst numIds = 100;\n\t\tconst clusterSize = Math.round(numIds / 2);\n\t\tconst setupRange = (isLocal: boolean) => {\n\t\t\tsetupCompressors(clusterSize, true, false);\n\t\t\tconst originCompressor = isLocal ? compressor : remoteCompressor;\n\t\t\tsessionId = originCompressor.localSessionId;\n\t\t\trange = originCompressor.generateCompressedIdRange(numIds);\n\t\t\tconst creationRange = originCompressor.takeNextCreationRange();\n\t\t\tcompressor.finalizeCreationRange(creationRange);\n\t\t};\n\t\tconst beforeLocal = () => setupRange(false);\n\t\tconst beforeRemote = () => setupRange(true);\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `get ${numIds} sequential IDs for a ${isLocal ? 'local' : 'remote'} range`,\n\t\t\tbefore: isLocal ? beforeLocal : beforeRemote,\n\t\t\tbenchmarkFn: () => {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst ids = compressor.getIdsFromRange(range!, sessionId!);\n\t\t\t\tfor (let i = 0; i < numIds; i++) {\n\t\t\t\t\tids.get(i); // get a sequential ID\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t});\n\n\t[true, false].forEach((override) => {\n\t\tconst numericSource = numericUuidFromStableId(createSessionId());\n\t\tlet overrideIndex = 0;\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `allocate local ID (${override ? 'override' : 'sequential'})`,\n\t\t\tbefore: () => {\n\t\t\t\tsetupCompressors(defaultClusterCapacity, true, false);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tcompressor.generateCompressedId(\n\t\t\t\t\toverride ? stableIdFromNumericUuid(numericSource, overrideIndex++) : undefined\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t});\n\n\t[true, false].forEach((override) => {\n\t\tfor (const clusterSize of [1, 10, 500, 1000]) {\n\t\t\tconst overrideCount = 3;\n\t\t\tconst numIds = 7;\n\t\t\tconst session1 = '8150a099-5302-4672-b5f3-7a4492b59418' as SessionId;\n\t\t\tconst session2 = 'f2ded886-92da-4248-967b-eb96ee04cf51' as SessionId;\n\t\t\tlet session: SessionId = session1;\n\t\t\tlet lastFinalizedLocalId1 = 0 as LocalCompressedId;\n\t\t\tlet lastFinalizedLocalId2 = 0 as LocalCompressedId;\n\t\t\tlet overrideIndex = 0;\n\t\t\tbenchmark({\n\t\t\t\ttype,\n\t\t\t\ttitle: `finalize a range of IDs (cluster size =${clusterSize}${override ? ', overrides present' : ''})`,\n\t\t\t\tbefore: () => {\n\t\t\t\t\tsetupCompressors(clusterSize, false, false);\n\t\t\t\t},\n\t\t\t\tbenchmarkFn: () => {\n\t\t\t\t\t// Create a range with as minimal overhead as possible, as we'd like for this code to not exist\n\t\t\t\t\t// in the timing loop at all (but benchmark forces us to do so)\n\t\t\t\t\tconst isLocal = session === session1;\n\t\t\t\t\tconst first = ((isLocal ? lastFinalizedLocalId1 : lastFinalizedLocalId2) - 1) as LocalCompressedId &\n\t\t\t\t\t\tOpSpaceCompressedId;\n\t\t\t\t\tlet overrides: Mutable<IdCreationRange.Overrides> | undefined;\n\t\t\t\t\tconst actualOverrideCount = override ? overrideCount : 0;\n\t\t\t\t\tif (actualOverrideCount > 0) {\n\t\t\t\t\t\toverrides = [] as unknown as Mutable<IdCreationRange.Overrides>;\n\t\t\t\t\t\tfor (let i = 0; i < actualOverrideCount; i++) {\n\t\t\t\t\t\t\toverrides.push([\n\t\t\t\t\t\t\t\t(first - i) as LocalCompressedId & OpSpaceCompressedId,\n\t\t\t\t\t\t\t\t`override${overrideIndex++}`,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst last = (first - numIds) as UnackedLocalId;\n\t\t\t\t\tconst range: IdCreationRange = {\n\t\t\t\t\t\tsessionId: session,\n\t\t\t\t\t\tids: {\n\t\t\t\t\t\t\tfirst,\n\t\t\t\t\t\t\tlast,\n\t\t\t\t\t\t\toverrides,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tcompressor.finalizeCreationRange(range);\n\n\t\t\t\t\tif (isLocal) {\n\t\t\t\t\t\tlastFinalizedLocalId1 = last;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlastFinalizedLocalId2 = last;\n\t\t\t\t\t}\n\t\t\t\t\t// Alternate clients to sidestep optimization that packs them all into last cluster\n\t\t\t\t\tsession = isLocal ? session1 : session2;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t});\n\n\t[true, false].forEach((override) => {\n\t\tconst idCount = 5;\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `creates an ID range (${override ? 'with overrides' : ''})`,\n\t\t\tbefore: () => {\n\t\t\t\tsetupCompressors(defaultClusterCapacity, true, false);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tif (override) {\n\t\t\t\t\tcompressor.generateCompressedId(v4());\n\t\t\t\t}\n\t\t\t\tcompressor.generateCompressedIdRange(idCount);\n\t\t\t\tcompressor.takeNextCreationRange();\n\t\t\t},\n\t\t});\n\t});\n\n\tbenchmarkWithIdTypes((local, override, titleSuffix) => {\n\t\tlet idToDecompress!: CompressedId;\n\t\tconst before = () => {\n\t\t\tidToDecompress = setupCompressorWithId(local, override, true);\n\t\t};\n\t\tconst benchmarkFn = () => {\n\t\t\tcompressor.decompress(idToDecompress);\n\t\t};\n\t\tif (local) {\n\t\t\tbenchmark({\n\t\t\t\ttype,\n\t\t\t\ttitle: `decompress local ID into stable IDs${titleSuffix}`,\n\t\t\t\tbefore,\n\t\t\t\tbenchmarkFn,\n\t\t\t});\n\t\t} else {\n\t\t\tconst titleBase = 'decompress final ID into stable IDs';\n\t\t\tif (override) {\n\t\t\t\tbenchmark({\n\t\t\t\t\ttype,\n\t\t\t\t\ttitle: titleBase + titleSuffix,\n\t\t\t\t\tbefore,\n\t\t\t\t\tbenchmarkFn,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tfor (const clusterHasOverride of [true, false]) {\n\t\t\t\t\tbenchmark({\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\ttitle: `${titleBase} (sequential, overrides ${\n\t\t\t\t\t\t\tclusterHasOverride ? 'present' : 'not present'\n\t\t\t\t\t\t} in owning cluster)`,\n\t\t\t\t\t\tbefore: () => {\n\t\t\t\t\t\t\tidToDecompress = setupCompressorWithId(local, override, clusterHasOverride);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbenchmarkFn,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tbenchmarkWithIdTypes((local, override, titleSuffix) => {\n\t\tlet stableToCompress!: string;\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `compress a stable ID to a ${local ? 'local' : 'final'} ID${titleSuffix}`,\n\t\t\tbefore: () => {\n\t\t\t\tconst idAdded = setupCompressorWithId(local, override, true);\n\t\t\t\tstableToCompress = compressor.decompress(idAdded);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tcompressor.recompress(stableToCompress);\n\t\t\t},\n\t\t});\n\t});\n\n\tlet final!: FinalCompressedId;\n\tbenchmark({\n\t\ttype,\n\t\ttitle: `normalize a final ID from the local session to session space`,\n\t\tbefore: () => {\n\t\t\tconst network = setupCompressors(defaultClusterCapacity, true, true);\n\t\t\tnetwork.allocateAndSendIds(localClient, 1);\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t\tconst log = network.getSequencedIdLog(localClient);\n\t\t\tconst id = compressor.normalizeToOpSpace(log[log.length - 1].id);\n\t\t\tfinal = isFinalId(id) ? id : fail('not a final ID');\n\t\t},\n\t\tbenchmarkFn: () => {\n\t\t\tcompressor.normalizeToSessionSpace(final, compressor.localSessionId);\n\t\t},\n\t});\n\n\tlet localId!: LocalCompressedId;\n\tbenchmark({\n\t\ttype,\n\t\ttitle: `normalize a local ID from the local session to session space`,\n\t\tbefore: () => {\n\t\t\tconst network = setupCompressors(defaultClusterCapacity, true, true);\n\t\t\tnetwork.allocateAndSendIds(localClient, 1);\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t\tconst log = network.getIdLog(localClient);\n\t\t\tconst id = log[log.length - 1].id;\n\t\t\tlocalId = isLocalId(id) ? id : fail('not a local ID');\n\t\t},\n\t\tbenchmarkFn: () => {\n\t\t\tcompressor.normalizeToOpSpace(localId);\n\t\t},\n\t});\n\n\tconst remoteSessionId = sessionIds.get(remoteClient);\n\tlet opSpaceId: OpSpaceCompressedId | undefined;\n\tbenchmark({\n\t\ttype,\n\t\ttitle: `normalize a local ID from a remote session to session space`,\n\t\tbefore: () => {\n\t\t\tconst network = setupCompressors(defaultClusterCapacity, true, true);\n\t\t\tnetwork.allocateAndSendIds(remoteClient, 1);\n\t\t\tconst log = network.getIdLog(remoteClient);\n\t\t\tconst id = remoteCompressor.normalizeToOpSpace(log[log.length - 1].id);\n\t\t\topSpaceId = isLocalId(id) ? id : fail('not a local ID');\n\t\t\t// Ensure id is finalized on local compressor\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t},\n\t\tbenchmarkFn: () => {\n\t\t\tcompressor.normalizeToSessionSpace(opSpaceId ?? fail(), remoteSessionId);\n\t\t},\n\t});\n\n\tfor (const overrideInClusters of [true, false]) {\n\t\tconst titleSuffix = ` (${overrideInClusters ? 'with' : 'without'} overrides)`;\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `serialize an IdCompressor${titleSuffix}`,\n\t\t\tbefore: () => {\n\t\t\t\tsetupCompressors(defaultClusterCapacity, false, overrideInClusters);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tcompressor.serialize(false);\n\t\t\t},\n\t\t});\n\n\t\tlet serialized!: SerializedIdCompressorWithNoSession;\n\t\tconst remoteSessionId = createSessionId();\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `deserialize an IdCompressor${titleSuffix}`,\n\t\t\tbefore: () => {\n\t\t\t\tsetupCompressors(defaultClusterCapacity, false, overrideInClusters);\n\t\t\t\tserialized = compressor.serialize(false);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tIdCompressor.deserialize(serialized, remoteSessionId);\n\t\t\t},\n\t\t});\n\t}\n});\n"]}
1
+ {"version":3,"file":"IdCompressor.perf.tests.js","sourceRoot":"","sources":["../../src/test/IdCompressor.perf.tests.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/no-non-null-assertion */\n\nimport { benchmark, BenchmarkType } from '@fluid-tools/benchmark';\nimport { take } from '@fluid-internal/stochastic-test-utils';\nimport { fail, Mutable } from '../Common';\nimport { defaultClusterCapacity, IdCompressor, isFinalId, isLocalId } from '../id-compressor/IdCompressor';\nimport { IdCreationRange, UnackedLocalId, SerializedIdCompressorWithNoSession } from '../id-compressor';\nimport { createSessionId, numericUuidFromStableId, stableIdFromNumericUuid } from '../id-compressor/NumericUuid';\nimport { CompressedId, FinalCompressedId, LocalCompressedId, OpSpaceCompressedId, SessionId } from '../Identifiers';\nimport {\n\tClient,\n\tIdCompressorTestNetwork,\n\tmakeOpGenerator,\n\tperformFuzzActions,\n\tsessionIds,\n\tTestIdData,\n} from './utilities/IdCompressorTestUtilities';\n\ndescribe('IdCompressor Perf', () => {\n\tconst type = BenchmarkType.Measurement;\n\tconst localClient = Client.Client1;\n\tconst remoteClient = Client.Client2;\n\tlet perfCompressor: IdCompressor | undefined;\n\tlet network: IdCompressorTestNetwork;\n\tlet compressor: IdCompressor;\n\n\tfunction setupCompressors(\n\t\tclusterSize: number,\n\t\tallowLocal: boolean,\n\t\tincludeOverrides: boolean\n\t): IdCompressorTestNetwork {\n\t\tnetwork = new IdCompressorTestNetwork(clusterSize);\n\t\t[compressor] = createPerfCompressor(network, allowLocal, includeOverrides, localClient);\n\t\tperfCompressor = undefined;\n\t\treturn network;\n\t}\n\n\tfunction createPerfCompressor(\n\t\tnetwork: IdCompressorTestNetwork,\n\t\tallowLocal: boolean,\n\t\tincludeOverrides: boolean,\n\t\tclient: Client\n\t): [IdCompressor, readonly TestIdData[]] {\n\t\tconst maxClusterSize = 25;\n\t\tconst generator = take(1000, makeOpGenerator({ includeOverrides, validateInterval: 2000, maxClusterSize }));\n\t\tif (network.initialClusterSize > maxClusterSize) {\n\t\t\tnetwork.enqueueCapacityChange(maxClusterSize);\n\t\t}\n\t\tperformFuzzActions(generator, network, Math.E, allowLocal ? undefined : client, !allowLocal);\n\t\treturn [network.getCompressorUnsafe(client), network.getIdLog(client)];\n\t}\n\n\tfunction setupCompressorWithId(local: boolean, override: boolean, clusterHasOtherOverrides: boolean): CompressedId {\n\t\tconst clusterCapacity = defaultClusterCapacity;\n\t\tconst network = setupCompressors(clusterCapacity, true, true);\n\t\tif (!clusterHasOtherOverrides) {\n\t\t\tnetwork.allocateAndSendIds(localClient, clusterCapacity);\n\t\t} else {\n\t\t\tnetwork.allocateAndSendIds(localClient, 2, {\n\t\t\t\t0: 'override1',\n\t\t\t\t1: 'override2',\n\t\t\t});\n\t\t}\n\t\tif (override) {\n\t\t\tnetwork.allocateAndSendIds(localClient, 1, { 0: 'override3' });\n\t\t} else {\n\t\t\tnetwork.allocateAndSendIds(localClient, 1);\n\t\t}\n\n\t\tif (!local) {\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t}\n\n\t\tconst ids = network.getIdLog(localClient);\n\t\tconst lastId = ids[ids.length - 1].id;\n\t\treturn lastId;\n\t}\n\n\tfunction benchmarkWithIdTypes(creator: (local: boolean, override: boolean, titleSuffix: string) => void) {\n\t\tfor (const local of [true, false]) {\n\t\t\tfor (const override of [true, false]) {\n\t\t\t\tconst titleSuffix = ` (${override ? 'override' : 'sequential'})`;\n\t\t\t\tcreator(local, override, titleSuffix);\n\t\t\t}\n\t\t}\n\t}\n\n\t[true, false].forEach((override) => {\n\t\tconst numericSource = numericUuidFromStableId(createSessionId());\n\t\tlet overrideIndex = 0;\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `allocate local ID (${override ? 'override' : 'sequential'})`,\n\t\t\tbefore: () => {\n\t\t\t\tsetupCompressors(defaultClusterCapacity, true, false);\n\t\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tperfCompressor!.generateCompressedId(\n\t\t\t\t\toverride ? stableIdFromNumericUuid(numericSource, overrideIndex++) : undefined\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t});\n\n\t[true, false].forEach((override) => {\n\t\tfor (const clusterSize of [1, 10, 500, 1000]) {\n\t\t\tconst overrideCount = 3;\n\t\t\tconst numIds = 7;\n\t\t\tconst session1 = '8150a099-5302-4672-b5f3-7a4492b59418' as SessionId;\n\t\t\tconst session2 = 'f2ded886-92da-4248-967b-eb96ee04cf51' as SessionId;\n\t\t\tlet session: SessionId = session1;\n\t\t\tlet lastFinalizedLocalId1 = 0 as LocalCompressedId;\n\t\t\tlet lastFinalizedLocalId2 = 0 as LocalCompressedId;\n\t\t\tlet overrideIndex = 0;\n\t\t\tbenchmark({\n\t\t\t\ttype,\n\t\t\t\ttitle: `finalize a range of IDs (cluster size =${clusterSize}${override ? ', overrides present' : ''})`,\n\t\t\t\tbefore: () => {\n\t\t\t\t\tsetupCompressors(clusterSize, false, false);\n\t\t\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t\t\t},\n\t\t\t\tbenchmarkFn: () => {\n\t\t\t\t\t// Create a range with as minimal overhead as possible, as we'd like for this code to not exist\n\t\t\t\t\t// in the timing loop at all (but benchmark forces us to do so)\n\t\t\t\t\tconst isLocal = session === session1;\n\t\t\t\t\tconst first = ((isLocal ? lastFinalizedLocalId1 : lastFinalizedLocalId2) - 1) as LocalCompressedId &\n\t\t\t\t\t\tOpSpaceCompressedId;\n\t\t\t\t\tlet overrides: Mutable<IdCreationRange.Overrides> | undefined;\n\t\t\t\t\tconst actualOverrideCount = override ? overrideCount : 0;\n\t\t\t\t\tif (actualOverrideCount > 0) {\n\t\t\t\t\t\toverrides = [] as unknown as Mutable<IdCreationRange.Overrides>;\n\t\t\t\t\t\tfor (let i = 0; i < actualOverrideCount; i++) {\n\t\t\t\t\t\t\toverrides.push([\n\t\t\t\t\t\t\t\t(first - i) as LocalCompressedId & OpSpaceCompressedId,\n\t\t\t\t\t\t\t\t`override${overrideIndex++}`,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst last = (first - numIds) as UnackedLocalId;\n\t\t\t\t\tconst range: IdCreationRange = {\n\t\t\t\t\t\tsessionId: session,\n\t\t\t\t\t\tids: {\n\t\t\t\t\t\t\tfirst,\n\t\t\t\t\t\t\tlast,\n\t\t\t\t\t\t\toverrides,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tperfCompressor!.finalizeCreationRange(range);\n\n\t\t\t\t\tif (isLocal) {\n\t\t\t\t\t\tlastFinalizedLocalId1 = last;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlastFinalizedLocalId2 = last;\n\t\t\t\t\t}\n\t\t\t\t\t// Alternate clients to sidestep optimization that packs them all into last cluster\n\t\t\t\t\tsession = isLocal ? session1 : session2;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t});\n\n\tbenchmark({\n\t\ttype,\n\t\ttitle: `takes a ID creation range'})`,\n\t\tbefore: () => {\n\t\t\tsetupCompressors(defaultClusterCapacity, true, false);\n\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t},\n\t\tbenchmarkFn: () => {\n\t\t\tperfCompressor!.generateCompressedId();\n\t\t\tperfCompressor!.takeNextCreationRange();\n\t\t},\n\t});\n\n\tbenchmarkWithIdTypes((local, override, titleSuffix) => {\n\t\tlet idToDecompress!: CompressedId;\n\t\tconst before = () => {\n\t\t\tidToDecompress = setupCompressorWithId(local, override, true);\n\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t};\n\t\tconst benchmarkFn = () => {\n\t\t\tperfCompressor!.decompress(idToDecompress);\n\t\t};\n\t\tif (local) {\n\t\t\tbenchmark({\n\t\t\t\ttype,\n\t\t\t\ttitle: `decompress local ID into stable IDs${titleSuffix}`,\n\t\t\t\tbefore,\n\t\t\t\tbenchmarkFn,\n\t\t\t});\n\t\t} else {\n\t\t\tconst titleBase = 'decompress final ID into stable IDs';\n\t\t\tif (override) {\n\t\t\t\tbenchmark({\n\t\t\t\t\ttype,\n\t\t\t\t\ttitle: titleBase + titleSuffix,\n\t\t\t\t\tbefore,\n\t\t\t\t\tbenchmarkFn,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tfor (const clusterHasOverride of [true, false]) {\n\t\t\t\t\tbenchmark({\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\ttitle: `${titleBase} (sequential, overrides ${\n\t\t\t\t\t\t\tclusterHasOverride ? 'present' : 'not present'\n\t\t\t\t\t\t} in owning cluster)`,\n\t\t\t\t\t\tbefore: () => {\n\t\t\t\t\t\t\tidToDecompress = setupCompressorWithId(local, override, clusterHasOverride);\n\t\t\t\t\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbenchmarkFn,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tbenchmarkWithIdTypes((local, override, titleSuffix) => {\n\t\tlet stableToCompress!: string;\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `compress a stable ID to a ${local ? 'local' : 'final'} ID${titleSuffix}`,\n\t\t\tbefore: () => {\n\t\t\t\tconst idAdded = setupCompressorWithId(local, override, true);\n\t\t\t\tstableToCompress = compressor.decompress(idAdded);\n\t\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tperfCompressor!.recompress(stableToCompress);\n\t\t\t},\n\t\t});\n\t});\n\n\tlet final!: FinalCompressedId;\n\tbenchmark({\n\t\ttype,\n\t\ttitle: `normalize a final ID from the local session to session space`,\n\t\tbefore: () => {\n\t\t\tconst network = setupCompressors(defaultClusterCapacity, true, true);\n\t\t\tnetwork.allocateAndSendIds(localClient, 1);\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t\tconst log = network.getSequencedIdLog(localClient);\n\t\t\tconst id = compressor.normalizeToOpSpace(log[log.length - 1].id);\n\t\t\tfinal = isFinalId(id) ? id : fail('not a final ID');\n\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t},\n\t\tbenchmarkFn: () => {\n\t\t\tperfCompressor!.normalizeToSessionSpace(final, compressor.localSessionId);\n\t\t},\n\t});\n\n\tfunction getLastLocalId(client: Client, network: IdCompressorTestNetwork): LocalCompressedId {\n\t\tconst log = network.getIdLog(client);\n\t\tfor (let i = log.length - 1; i > 0; i--) {\n\t\t\tconst cur = log[i].id;\n\t\t\tif (isLocalId(cur)) {\n\t\t\t\treturn cur;\n\t\t\t}\n\t\t}\n\t\tfail('no local ID found in log');\n\t}\n\n\tlet localId!: LocalCompressedId;\n\tbenchmark({\n\t\ttype,\n\t\ttitle: `normalize a local ID from the local session to session space`,\n\t\tbefore: () => {\n\t\t\tconst network = setupCompressors(defaultClusterCapacity, true, true);\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t\tlocalId = getLastLocalId(localClient, network);\n\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t},\n\t\tbenchmarkFn: () => {\n\t\t\tperfCompressor!.normalizeToOpSpace(localId);\n\t\t},\n\t});\n\n\tconst remoteSessionId = sessionIds.get(remoteClient);\n\tlet opSpaceId: OpSpaceCompressedId | undefined;\n\tbenchmark({\n\t\ttype,\n\t\ttitle: `normalize a local ID from a remote session to session space`,\n\t\tbefore: () => {\n\t\t\tconst network = setupCompressors(defaultClusterCapacity, true, true);\n\t\t\tnetwork.deliverOperations(localClient);\n\t\t\topSpaceId = getLastLocalId(remoteClient, network) as OpSpaceCompressedId;\n\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t},\n\t\tbenchmarkFn: () => {\n\t\t\tperfCompressor!.normalizeToSessionSpace(opSpaceId ?? fail(), remoteSessionId);\n\t\t},\n\t});\n\n\tfor (const overrideInClusters of [true, false]) {\n\t\tconst titleSuffix = ` (${overrideInClusters ? 'with' : 'without'} overrides)`;\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `serialize an IdCompressor${titleSuffix}`,\n\t\t\tbefore: () => {\n\t\t\t\tsetupCompressors(defaultClusterCapacity, false, overrideInClusters);\n\t\t\t\tperfCompressor = network.getCompressorUnsafeNoProxy(localClient);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tperfCompressor!.serialize(false);\n\t\t\t},\n\t\t});\n\n\t\tlet serialized!: SerializedIdCompressorWithNoSession;\n\t\tconst remoteSessionId = createSessionId();\n\t\tbenchmark({\n\t\t\ttype,\n\t\t\ttitle: `deserialize an IdCompressor${titleSuffix}`,\n\t\t\tbefore: () => {\n\t\t\t\tsetupCompressors(defaultClusterCapacity, false, overrideInClusters);\n\t\t\t\tserialized = compressor.serialize(false);\n\t\t\t},\n\t\t\tbenchmarkFn: () => {\n\t\t\t\tIdCompressor.deserialize(serialized, remoteSessionId);\n\t\t\t},\n\t\t});\n\t}\n});\n"]}
@@ -10,8 +10,8 @@ import { assert, assertNotUndefined, fail } from '../Common';
10
10
  import { createSessionId, incrementUuid, numericUuidFromStableId, stableIdFromNumericUuid, } from '../id-compressor/NumericUuid';
11
11
  import { getIds } from '../id-compressor/IdRange';
12
12
  import { assertIsStableId, generateStableId, isStableId } from '../UuidUtilities';
13
- import { createCompressor, performFuzzActions, sessionIds, IdCompressorTestNetwork, Client, DestinationClient, MetaClient, expectSerializes, roundtrip, sessionNumericUuids, makeOpGenerator, attributionIds, } from './utilities/IdCompressorTestUtilities';
14
- import { expectDefined } from './utilities/TestCommon';
13
+ import { createCompressor, performFuzzActions, sessionIds, IdCompressorTestNetwork, Client, DestinationClient, MetaClient, expectSerializes, roundtrip, sessionNumericUuids, makeOpGenerator, attributionIds, generateCompressedIds, } from './utilities/IdCompressorTestUtilities';
14
+ import { expectDefined, expectAssert } from './utilities/TestCommon';
15
15
  describe('IdCompressor', () => {
16
16
  it('detects invalid cluster sizes', () => {
17
17
  const compressor = createCompressor(Client.Client1, 1);
@@ -145,17 +145,11 @@ describe('IdCompressor', () => {
145
145
  const localId2 = compressor.generateCompressedId(stableId);
146
146
  expect(localId2).to.equal(id, 'only one local ID should be allocated for the same sequential uuid');
147
147
  });
148
- it('cannot create negative amounts of local IDs', () => {
149
- expect(() => createCompressor(Client.Client1).generateCompressedIdRange(-1)).to.throw('Must generate a nonzero number of IDs.');
150
- });
151
- it('cannot create unacceptably large amounts of local IDs', () => {
152
- expect(() => createCompressor(Client.Client1).generateCompressedIdRange(Number.MAX_SAFE_INTEGER + 2)).to.throw('The number of allocated local IDs must not exceed the JS maximum safe integer.');
153
- });
154
148
  });
155
149
  describe('can enumerate all locally created IDs', () => {
156
150
  const idCount = 10;
157
151
  it('created without finalization', () => {
158
- const compressor = createCompressor(Client.Client1);
152
+ const compressor = createCompressor(Client.Client1, idCount);
159
153
  const ids = [];
160
154
  for (let i = 0; i < idCount; i++) {
161
155
  ids.push(compressor.generateCompressedId());
@@ -164,7 +158,7 @@ describe('IdCompressor', () => {
164
158
  expect(returnedIds).to.deep.equal(ids);
165
159
  });
166
160
  it('created with finalization', () => {
167
- const compressor = createCompressor(Client.Client1, 10);
161
+ const compressor = createCompressor(Client.Client1, idCount);
168
162
  const ids = [];
169
163
  for (let i = 0; i < idCount; i++) {
170
164
  if (i === Math.floor(idCount / 2)) {
@@ -175,6 +169,31 @@ describe('IdCompressor', () => {
175
169
  const returnedIds = [...compressor.getAllIdsFromLocalSession()];
176
170
  expect(returnedIds).to.deep.equal(ids);
177
171
  });
172
+ it('created with expanded finalization', () => {
173
+ const compressor = createCompressor(Client.Client1, idCount);
174
+ const ids = [];
175
+ for (let i = 0; i < idCount * 4; i++) {
176
+ if (i !== 0 && i % Math.floor(idCount / 3) === 0) {
177
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
178
+ }
179
+ ids.push(compressor.generateCompressedId());
180
+ }
181
+ const returnedIds = [...compressor.getAllIdsFromLocalSession()];
182
+ expect(returnedIds).to.deep.equal(ids);
183
+ });
184
+ it('created with overrides', () => {
185
+ const capacity = 100;
186
+ const compressor = createCompressor(Client.Client1, capacity);
187
+ const ids = [];
188
+ for (let i = 0; i < capacity; i++) {
189
+ if (i === 1) {
190
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
191
+ }
192
+ ids.push(compressor.generateCompressedId(i % 3 === 0 ? undefined : `override${i}`));
193
+ }
194
+ const returnedIds = [...compressor.getAllIdsFromLocalSession()];
195
+ expect(returnedIds).to.deep.equal(ids);
196
+ });
178
197
  });
179
198
  it('has default attribution ID', () => {
180
199
  const compressor = createCompressor(Client.Client1);
@@ -311,7 +330,7 @@ describe('IdCompressor', () => {
311
330
  });
312
331
  it('prevents attempts to finalize ranges twice', () => {
313
332
  const rangeCompressor = createCompressor(Client.Client1);
314
- rangeCompressor.generateCompressedIdRange(3);
333
+ generateCompressedIds(rangeCompressor, 3);
315
334
  const batchRange = rangeCompressor.takeNextCreationRange();
316
335
  rangeCompressor.finalizeCreationRange(batchRange);
317
336
  expect(() => rangeCompressor.finalizeCreationRange(batchRange)).to.throw('Ranges finalized out of order.');
@@ -333,14 +352,21 @@ describe('IdCompressor', () => {
333
352
  });
334
353
  it('prevents finalizing unacceptably enormous amounts of ID allocation', () => {
335
354
  const compressor1 = createCompressor(Client.Client1);
336
- const compressor2 = createCompressor(Client.Client2);
337
355
  const integerLargerThanHalfMax = Math.round((Number.MAX_SAFE_INTEGER / 3) * 2);
338
- compressor1.generateCompressedIdRange(integerLargerThanHalfMax);
339
- compressor2.generateCompressedIdRange(integerLargerThanHalfMax);
340
- const range1 = compressor1.takeNextCreationRange();
341
- const range2 = compressor2.takeNextCreationRange();
342
- compressor1.finalizeCreationRange(range1);
343
- expect(() => compressor1.finalizeCreationRange(range2)).to.throw('The number of allocated final IDs must not exceed the JS maximum safe integer.');
356
+ const midPoint = -integerLargerThanHalfMax;
357
+ const largeRange1 = {
358
+ sessionId: sessionIds.get(Client.Client2),
359
+ ids: { first: -1, last: midPoint },
360
+ };
361
+ compressor1.finalizeCreationRange(largeRange1);
362
+ const largeRange2 = {
363
+ sessionId: sessionIds.get(Client.Client2),
364
+ ids: {
365
+ first: (midPoint - 1),
366
+ last: (-Number.MAX_SAFE_INTEGER - 2),
367
+ },
368
+ };
369
+ expect(() => compressor1.finalizeCreationRange(largeRange2)).to.throw('The number of allocated final IDs must not exceed the JS maximum safe integer.');
344
370
  });
345
371
  });
346
372
  describe('Compression', () => {
@@ -384,11 +410,20 @@ describe('IdCompressor', () => {
384
410
  expect(compressor.tryRecompress(stableIdFromNumericUuid(sessionNumericUuids.get(Client.Client1), 1))).to.be
385
411
  .undefined;
386
412
  compressor.generateCompressedId(override);
387
- compressor.generateCompressedIdRange(2);
413
+ generateCompressedIds(compressor, 2);
388
414
  compressor.finalizeCreationRange(compressor.takeNextCreationRange());
389
415
  expect(compressor.tryRecompress(stableIdFromNumericUuid(sessionNumericUuids.get(Client.Client1), 4))).to.be
390
416
  .undefined;
391
417
  });
418
+ it('can re-compress an eagerly generated final ID that is not finalized', () => {
419
+ const compressor = createCompressor(Client.Client1, 5);
420
+ compressor.generateCompressedId();
421
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
422
+ const finalId = compressor.generateCompressedId();
423
+ expect(isFinalId(finalId)).to.be.true;
424
+ const stableId = stableIdFromNumericUuid(numericUuidFromStableId(sessionIds.get(Client.Client1)), 1);
425
+ expect(compressor.recompress(stableId)).to.equal(finalId);
426
+ });
392
427
  });
393
428
  describe('Decompression', () => {
394
429
  it('can decompress a local ID before and after finalizing', () => {
@@ -418,9 +453,9 @@ describe('IdCompressor', () => {
418
453
  });
419
454
  it('can decompress a final ID', () => {
420
455
  const compressor = createCompressor(Client.Client1);
421
- const range = compressor.generateCompressedIdRange(1);
456
+ const id = compressor.generateCompressedId();
422
457
  compressor.finalizeCreationRange(compressor.takeNextCreationRange());
423
- const finalId = compressor.normalizeToOpSpace(compressor.getIdsFromRange(range, compressor.localSessionId).get(0));
458
+ const finalId = compressor.normalizeToOpSpace(id);
424
459
  if (isLocalId(finalId)) {
425
460
  expect.fail('Op space ID was finalized but is local');
426
461
  }
@@ -462,6 +497,14 @@ describe('IdCompressor', () => {
462
497
  const id = compressor.generateCompressedId(override);
463
498
  expect(compressor.decompress(id)).to.equal(override);
464
499
  });
500
+ it('can decompress an eagerly generated final ID that is not finalized', () => {
501
+ const compressor = createCompressor(Client.Client1, 5);
502
+ compressor.generateCompressedId();
503
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
504
+ const finalId = compressor.generateCompressedId();
505
+ expect(isFinalId(finalId)).to.be.true;
506
+ expect(compressor.decompress(finalId)).to.equal(stableIdFromNumericUuid(numericUuidFromStableId(sessionIds.get(Client.Client1)), 1));
507
+ });
465
508
  });
466
509
  describe('Normalization', () => {
467
510
  it('can normalize a local ID to op space before finalizing', () => {
@@ -479,6 +522,17 @@ describe('IdCompressor', () => {
479
522
  expect(isFinalId(normalized)).to.be.true;
480
523
  expect(id).to.not.equal(normalized);
481
524
  });
525
+ it('can normalize an eagerly generated final ID', () => {
526
+ const compressor = createCompressor(Client.Client1, 5);
527
+ compressor.generateCompressedId();
528
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
529
+ const eagerFinalId = compressor.generateCompressedId();
530
+ expect(isFinalId(eagerFinalId)).to.be.true;
531
+ const opNormalized = compressor.normalizeToOpSpace(eagerFinalId);
532
+ expect(eagerFinalId).to.equal(opNormalized);
533
+ const sessionNormalized = compressor.normalizeToSessionSpace(opNormalized, compressor.localSessionId);
534
+ expect(sessionNormalized).to.equal(opNormalized);
535
+ });
482
536
  it('cannot normalize a remote ID to session space if it has not been finalized', () => {
483
537
  const compressor1 = createCompressor(Client.Client1);
484
538
  const compressor2 = createCompressor(Client.Client2);
@@ -499,6 +553,20 @@ describe('IdCompressor', () => {
499
553
  expect(compressor2.normalizeToSessionSpace(normalizedFinal, compressor1.localSessionId)).to.equal(normalizedFinal);
500
554
  expect(compressor2.normalizeToSessionSpace(normalizedLocal, compressor1.localSessionId)).to.equal(normalizedFinal);
501
555
  });
556
+ it("can normalize a final ID created by the local session but sent in another client's op space", () => {
557
+ // Regression test for the situation in which a client creates a final ID and another client references
558
+ // that final ID in a message back to the creating client. The creating client will normalize it and
559
+ // pass the session ID of the remote (non-creating) client. This should be handled correctly.
560
+ const compressor = createCompressor(Client.Client1, 5);
561
+ const compressor2 = createCompressor(Client.Client2, 5);
562
+ const id = compressor.generateCompressedId();
563
+ const creationRange = compressor.takeNextCreationRange();
564
+ compressor.finalizeCreationRange(creationRange);
565
+ compressor2.finalizeCreationRange(creationRange);
566
+ const idInClient2OpSpace = compressor2.normalizeToOpSpace(compressor2.normalizeToSessionSpace(compressor.normalizeToOpSpace(id), compressor.localSessionId));
567
+ const normalizedToClient1SessionSpace = compressor.normalizeToSessionSpace(idInClient2OpSpace, compressor2.localSessionId);
568
+ expect(normalizedToClient1SessionSpace).to.equal(id);
569
+ });
502
570
  });
503
571
  describe('Serialization', () => {
504
572
  it('can serialize an empty compressor', () => {
@@ -623,6 +691,14 @@ describe('IdCompressor', () => {
623
691
  }
624
692
  }
625
693
  });
694
+ itNetwork('eagerly generated final IDs that are not finalized', (network) => {
695
+ const compressor = network.getCompressor(Client.Client1);
696
+ network.allocateAndSendIds(Client.Client1, 1);
697
+ network.deliverOperations(DestinationClient.All);
698
+ const ids = network.allocateAndSendIds(Client.Client1, 1);
699
+ const id = compressor.normalizeToSessionSpace(ids[0], compressor.localSessionId);
700
+ expect(compressor.attributeId(id)).to.equal(attributionIds.get(Client.Client1));
701
+ });
626
702
  });
627
703
  itNetwork('upholds the invariant that IDs always decompress to the same UUID', 2, (network) => {
628
704
  var _a;
@@ -681,18 +757,20 @@ describe('IdCompressor', () => {
681
757
  });
682
758
  itNetwork('can normalize local op space IDs from a local session to session space IDs', (network) => {
683
759
  const compressor = network.getCompressor(Client.Client1);
684
- const { range, sessionId } = network.allocateAndSendIds(Client.Client1, 1);
760
+ network.allocateAndSendIds(Client.Client1, 1);
685
761
  network.deliverOperations(Client.Client1);
686
- const id = compressor.normalizeToOpSpace(compressor.getIdsFromRange(range, sessionId).get(0));
687
- expect(isFinalId(id)).to.be.true;
688
- expect(isLocalId(compressor.normalizeToSessionSpace(id, compressor.localSessionId))).to.be.true;
762
+ const sessionSpaceIds = network.getIdLog(Client.Client1);
763
+ const opSpaceId = compressor.normalizeToOpSpace(sessionSpaceIds[0].id);
764
+ const sessionSpaceId = compressor.normalizeToSessionSpace(opSpaceId, compressor.localSessionId);
765
+ expect(isFinalId(opSpaceId)).to.be.true;
766
+ expect(isLocalId(sessionSpaceId)).to.be.true;
689
767
  });
690
768
  itNetwork('can normalize local op space IDs from a remote session to session space IDs', (network) => {
691
769
  const compressor1 = network.getCompressor(Client.Client1);
692
770
  const compressor2 = network.getCompressor(Client.Client2);
693
- const { range, sessionId } = network.allocateAndSendIds(Client.Client1, 1);
771
+ const opSpaceIds = network.allocateAndSendIds(Client.Client1, 1);
694
772
  // Mimic sending a reference to an ID that hasn't been acked yet, such as in a slow network
695
- const id = compressor1.normalizeToOpSpace(compressor1.getIdsFromRange(range, sessionId).get(0));
773
+ const id = opSpaceIds[0];
696
774
  const getSessionNormalizedId = () => compressor2.normalizeToSessionSpace(id, compressor1.localSessionId);
697
775
  expect(getSessionNormalizedId).to.throw('No IDs have ever been finalized by the supplied session.');
698
776
  network.deliverOperations(Client.Client2);
@@ -832,93 +910,25 @@ describe('IdCompressor', () => {
832
910
  });
833
911
  itNetwork('can set the cluster size via constructor', 2, (network) => {
834
912
  const compressor = network.getCompressor(Client.Client1);
913
+ const compressor2 = network.getCompressor(Client.Client2);
835
914
  network.allocateAndSendIds(Client.Client1, 1);
836
- const { range, sessionId } = network.allocateAndSendIds(Client.Client2, 2);
915
+ const opSpaceIds = network.allocateAndSendIds(Client.Client2, 2);
837
916
  network.deliverOperations(DestinationClient.All);
838
- const id = compressor.getIdsFromRange(range, sessionId).get(0);
839
917
  // Glass box test, as it knows the order of final IDs
840
- expect(id).to.equal(compressor.reservedIdCount + compressor.clusterCapacity);
918
+ expect(compressor.normalizeToSessionSpace(opSpaceIds[0], compressor2.localSessionId)).to.equal(compressor.reservedIdCount + compressor.clusterCapacity);
841
919
  });
842
920
  itNetwork('can set the cluster size via API', 2, (network) => {
843
921
  const compressor = network.getCompressor(Client.Client1);
922
+ const compressor2 = network.getCompressor(Client.Client2);
844
923
  const initialClusterCapacity = compressor.clusterCapacity;
845
924
  network.allocateAndSendIds(Client.Client1, initialClusterCapacity);
846
925
  network.allocateAndSendIds(Client.Client2, initialClusterCapacity);
847
926
  network.enqueueCapacityChange(5);
848
927
  network.allocateAndSendIds(Client.Client1, 1);
849
- const { range, sessionId } = network.allocateAndSendIds(Client.Client2, 1);
928
+ const opSpaceIds = network.allocateAndSendIds(Client.Client2, 1);
850
929
  network.deliverOperations(DestinationClient.All);
851
- const id = compressor.getIdsFromRange(range, sessionId).get(0);
852
930
  // Glass box test, as it knows the order of final IDs
853
- expect(id).to.equal(compressor.reservedIdCount + initialClusterCapacity * 2 + compressor.clusterCapacity);
854
- });
855
- describe('can get IDs from ranges', () => {
856
- itNetwork('unless they are unfinalized and from a remote session', (network) => {
857
- const compressor = network.getCompressor(Client.Client1);
858
- const { range: unackedRemoteRange, sessionId } = network.allocateAndSendIds(Client.Client2, 5);
859
- expect(() => compressor.getIdsFromRange(unackedRemoteRange, sessionId)).to.throw('Unknown session, range may not be finalized.');
860
- network.deliverOperations(Client.Client1);
861
- const { range: unackedRemoteRange2, sessionId: sessionId2 } = network.allocateAndSendIds(Client.Client2, 5);
862
- expect(() => compressor.getIdsFromRange(unackedRemoteRange2, sessionId2)).to.throw('Remote range must be finalized before getting IDs.');
863
- });
864
- itNetwork('that are unacked', (network) => {
865
- const compressor = network.getCompressor(Client.Client1);
866
- const { range: rangeDescriptor1, sessionId: sessionId1 } = network.allocateAndSendIds(Client.Client1, 5);
867
- const range1 = compressor.getIdsFromRange(rangeDescriptor1, sessionId1);
868
- for (let i = 0; i < range1.length; i++) {
869
- expect(range1.get(i)).to.equal(-(i + 1));
870
- }
871
- const { range: rangeDescriptor2, sessionId: sessionId2 } = network.allocateAndSendIds(Client.Client1, 7);
872
- const range2 = compressor.getIdsFromRange(rangeDescriptor2, sessionId2);
873
- for (let i = 0; i < range2.length; i++) {
874
- expect(range2.get(i)).to.equal(-(i + 1 + range1.length));
875
- }
876
- });
877
- itNetwork('from the local session that are acked', (network) => {
878
- const compressor = network.getCompressor(Client.Client1);
879
- const { range, sessionId } = network.allocateAndSendIds(Client.Client1, 5);
880
- const range1 = compressor.getIdsFromRange(range, sessionId);
881
- network.deliverOperations(Client.Client1);
882
- for (let i = 0; i < range1.length; i++) {
883
- expect(range1.get(i)).to.equal(-(i + 1));
884
- }
885
- });
886
- itNetwork('from a remote session that are in a single cluster', 5, (network) => {
887
- const compressor = network.getCompressor(Client.Client1);
888
- const clusterCapacity = compressor.clusterCapacity;
889
- network.allocateAndSendIds(Client.Client1, 1);
890
- // Spans an entire cluster
891
- const { range: rangeFullCluster, sessionId: sessionId2 } = network.allocateAndSendIds(Client.Client2, clusterCapacity);
892
- network.allocateAndSendIds(Client.Client1, 1);
893
- network.allocateAndSendIds(Client.Client2, 1);
894
- // Spans the middle 3 IDs in a cluster of size 5
895
- const { range: rangeMiddleCluster } = network.allocateAndSendIds(Client.Client2, clusterCapacity - 2);
896
- network.deliverOperations(Client.Client1);
897
- const idsFullCluster = compressor.getIdsFromRange(rangeFullCluster, sessionId2);
898
- for (let i = 0; i < idsFullCluster.length; i++) {
899
- expect(idsFullCluster.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity + i);
900
- }
901
- const idsMiddleCluster = compressor.getIdsFromRange(rangeMiddleCluster, sessionId2);
902
- for (let i = 0; i < idsMiddleCluster.length; i++) {
903
- expect(idsMiddleCluster.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity * 2 + 1 + i);
904
- }
905
- });
906
- itNetwork('from a remote session that span multiple clusters', 5, (network) => {
907
- const compressor = network.getCompressor(Client.Client1);
908
- const clusterCapacity = compressor.clusterCapacity;
909
- network.allocateAndSendIds(Client.Client1, clusterCapacity);
910
- network.allocateAndSendIds(Client.Client2, clusterCapacity - 2);
911
- network.allocateAndSendIds(Client.Client1, 1);
912
- const { range: rangeSpanningClusters, sessionId } = network.allocateAndSendIds(Client.Client2, clusterCapacity);
913
- network.deliverOperations(Client.Client1);
914
- const idsSpanningClusters = compressor.getIdsFromRange(rangeSpanningClusters, sessionId);
915
- for (let i = 0; i < 2; i++) {
916
- expect(idsSpanningClusters.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity + 3 + i);
917
- }
918
- for (let i = 2; i < idsSpanningClusters.length; i++) {
919
- expect(idsSpanningClusters.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity * 2 + 3 + i);
920
- }
921
- });
931
+ expect(compressor.normalizeToSessionSpace(opSpaceIds[0], compressor2.localSessionId)).to.equal(compressor.reservedIdCount + initialClusterCapacity * 2 + compressor.clusterCapacity);
922
932
  });
923
933
  itNetwork('does not decompress ids for empty parts of clusters', 2, (network) => {
924
934
  // This is a glass box test in that it creates a final ID outside of the ID compressor
@@ -930,6 +940,91 @@ describe('IdCompressor', () => {
930
940
  const emptyId = (id + 1);
931
941
  expect(() => network.getCompressor(Client.Client2).decompress(emptyId)).to.throw('Compressed ID was not generated by this compressor');
932
942
  });
943
+ describe('Eager final ID allocation', () => {
944
+ it('eagerly allocates final IDs when cluster creation has been finalized', () => {
945
+ const compressor = createCompressor(Client.Client1, 5);
946
+ const localId1 = compressor.generateCompressedId();
947
+ expect(isLocalId(localId1)).to.be.true;
948
+ const localId2 = compressor.generateCompressedId();
949
+ expect(isLocalId(localId2)).to.be.true;
950
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
951
+ const finalId3 = compressor.generateCompressedId();
952
+ expect(isFinalId(finalId3)).to.be.true;
953
+ const finalId4 = compressor.generateCompressedId();
954
+ expect(isFinalId(finalId4)).to.be.true;
955
+ const finalId5 = compressor.generateCompressedId();
956
+ expect(isFinalId(finalId5)).to.be.true;
957
+ const localId6 = compressor.generateCompressedId();
958
+ expect(isLocalId(localId6)).to.be.true;
959
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
960
+ const opSpaceId1 = compressor.normalizeToOpSpace(localId1);
961
+ const opSpaceId2 = compressor.normalizeToOpSpace(localId2);
962
+ const opSpaceId3 = compressor.normalizeToOpSpace(finalId3);
963
+ const opSpaceId4 = compressor.normalizeToOpSpace(finalId4);
964
+ const opSpaceId5 = compressor.normalizeToOpSpace(finalId5);
965
+ const opSpaceId6 = compressor.normalizeToOpSpace(localId6);
966
+ expectAssert(isFinalId(opSpaceId1));
967
+ expectAssert(isFinalId(opSpaceId2));
968
+ expectAssert(isFinalId(opSpaceId3) && opSpaceId3 === finalId3);
969
+ expectAssert(isFinalId(opSpaceId4) && opSpaceId4 === finalId4);
970
+ expectAssert(isFinalId(opSpaceId5) && opSpaceId5 === finalId5);
971
+ expectAssert(isFinalId(opSpaceId6));
972
+ expect(compressor.normalizeToSessionSpace(opSpaceId1)).to.equal(localId1);
973
+ expect(compressor.normalizeToSessionSpace(opSpaceId2)).to.equal(localId2);
974
+ expect(compressor.normalizeToSessionSpace(opSpaceId3)).to.equal(finalId3);
975
+ expect(compressor.normalizeToSessionSpace(opSpaceId4)).to.equal(finalId4);
976
+ expect(compressor.normalizeToSessionSpace(opSpaceId5)).to.equal(finalId5);
977
+ expect(compressor.normalizeToSessionSpace(opSpaceId6)).to.equal(localId6);
978
+ });
979
+ it('does not eagerly allocate final IDs for IDs with overrides', () => {
980
+ const compressor = createCompressor(Client.Client1, 5);
981
+ const localId1 = compressor.generateCompressedId();
982
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
983
+ const override1 = compressor.generateCompressedId('override1');
984
+ expect(isLocalId(override1)).to.be.true;
985
+ const finalId1 = compressor.generateCompressedId();
986
+ expect(isFinalId(finalId1)).to.be.true;
987
+ generateCompressedIds(compressor, 5);
988
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
989
+ const override2 = compressor.generateCompressedId('override2');
990
+ expect(isLocalId(override2)).to.be.true;
991
+ const finalId2 = compressor.generateCompressedId();
992
+ expect(isFinalId(finalId2)).to.be.true;
993
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
994
+ const opSpaceId1 = compressor.normalizeToOpSpace(localId1);
995
+ const opSpaceId2 = compressor.normalizeToOpSpace(override1);
996
+ const opSpaceId3 = compressor.normalizeToOpSpace(finalId1);
997
+ const opSpaceId4 = compressor.normalizeToOpSpace(override2);
998
+ const opSpaceId5 = compressor.normalizeToOpSpace(finalId2);
999
+ expectAssert(isFinalId(opSpaceId1));
1000
+ expectAssert(isFinalId(opSpaceId2));
1001
+ expectAssert(isFinalId(opSpaceId3) && opSpaceId3 === finalId1);
1002
+ expectAssert(isFinalId(opSpaceId4));
1003
+ expectAssert(isFinalId(opSpaceId5) && opSpaceId5 === finalId2);
1004
+ expect(compressor.normalizeToSessionSpace(opSpaceId1)).to.equal(localId1);
1005
+ expect(compressor.normalizeToSessionSpace(opSpaceId2)).to.equal(override1);
1006
+ expect(compressor.normalizeToSessionSpace(opSpaceId3)).to.equal(finalId1);
1007
+ expect(compressor.normalizeToSessionSpace(opSpaceId4)).to.equal(override2);
1008
+ expect(compressor.normalizeToSessionSpace(opSpaceId5)).to.equal(finalId2);
1009
+ });
1010
+ it('correctly normalizes eagerly allocated final IDs', () => {
1011
+ const compressor = createCompressor(Client.Client1, 5);
1012
+ const localId1 = compressor.generateCompressedId();
1013
+ const range1 = compressor.takeNextCreationRange();
1014
+ const localId2 = compressor.generateCompressedId();
1015
+ const range2 = compressor.takeNextCreationRange();
1016
+ expect(isLocalId(localId1)).to.be.true;
1017
+ expect(isLocalId(localId2)).to.be.true;
1018
+ compressor.finalizeCreationRange(range1);
1019
+ compressor.finalizeCreationRange(range2);
1020
+ const opSpaceId1 = compressor.normalizeToOpSpace(localId1);
1021
+ const opSpaceId2 = compressor.normalizeToOpSpace(localId2);
1022
+ expectAssert(isFinalId(opSpaceId1));
1023
+ expectAssert(isFinalId(opSpaceId2));
1024
+ expect(compressor.normalizeToSessionSpace(opSpaceId1)).to.equal(localId1);
1025
+ expect(compressor.normalizeToSessionSpace(opSpaceId2)).to.equal(localId2);
1026
+ });
1027
+ });
933
1028
  describe('Finalizing', () => {
934
1029
  itNetwork('can finalize IDs from multiple clients', (network) => {
935
1030
  network.allocateAndSendIds(Client.Client1, 3, {