@fluidframework/container-runtime 2.0.0-internal.7.2.2 → 2.0.0-internal.7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -2
  3. package/api-extractor-lint.json +13 -0
  4. package/api-extractor.json +9 -1
  5. package/api-report/container-runtime.api.md +124 -107
  6. package/dist/batchTracker.d.ts +1 -0
  7. package/dist/batchTracker.d.ts.map +1 -1
  8. package/dist/blobManager.d.ts +4 -4
  9. package/dist/blobManager.d.ts.map +1 -1
  10. package/dist/blobManager.js.map +1 -1
  11. package/dist/connectionTelemetry.js +1 -1
  12. package/dist/connectionTelemetry.js.map +1 -1
  13. package/dist/container-runtime-alpha.d.ts +1473 -0
  14. package/dist/container-runtime-beta.d.ts +300 -0
  15. package/dist/container-runtime-public.d.ts +300 -0
  16. package/dist/container-runtime-untrimmed.d.ts +1836 -0
  17. package/dist/containerRuntime.d.ts +34 -40
  18. package/dist/containerRuntime.d.ts.map +1 -1
  19. package/dist/containerRuntime.js +79 -67
  20. package/dist/containerRuntime.js.map +1 -1
  21. package/dist/dataStoreRegistry.d.ts +1 -1
  22. package/dist/dataStoreRegistry.js +1 -1
  23. package/dist/dataStoreRegistry.js.map +1 -1
  24. package/dist/dataStores.d.ts +10 -15
  25. package/dist/dataStores.d.ts.map +1 -1
  26. package/dist/dataStores.js +77 -40
  27. package/dist/dataStores.js.map +1 -1
  28. package/dist/gc/garbageCollection.d.ts +41 -13
  29. package/dist/gc/garbageCollection.d.ts.map +1 -1
  30. package/dist/gc/garbageCollection.js +215 -78
  31. package/dist/gc/garbageCollection.js.map +1 -1
  32. package/dist/gc/gcConfigs.d.ts.map +1 -1
  33. package/dist/gc/gcConfigs.js +34 -37
  34. package/dist/gc/gcConfigs.js.map +1 -1
  35. package/dist/gc/gcDefinitions.d.ts +121 -46
  36. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  37. package/dist/gc/gcDefinitions.js +26 -18
  38. package/dist/gc/gcDefinitions.js.map +1 -1
  39. package/dist/gc/gcHelpers.d.ts +18 -25
  40. package/dist/gc/gcHelpers.d.ts.map +1 -1
  41. package/dist/gc/gcHelpers.js +29 -45
  42. package/dist/gc/gcHelpers.js.map +1 -1
  43. package/dist/gc/gcTelemetry.d.ts +0 -5
  44. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  45. package/dist/gc/gcTelemetry.js +14 -42
  46. package/dist/gc/gcTelemetry.js.map +1 -1
  47. package/dist/gc/gcUnreferencedStateTracker.d.ts +11 -5
  48. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  49. package/dist/gc/gcUnreferencedStateTracker.js +43 -19
  50. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  51. package/dist/gc/index.d.ts +1 -1
  52. package/dist/gc/index.d.ts.map +1 -1
  53. package/dist/gc/index.js +4 -5
  54. package/dist/gc/index.js.map +1 -1
  55. package/dist/index.d.ts +14 -2
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +16 -5
  58. package/dist/index.js.map +1 -1
  59. package/dist/messageTypes.d.ts +16 -11
  60. package/dist/messageTypes.d.ts.map +1 -1
  61. package/dist/messageTypes.js +6 -1
  62. package/dist/messageTypes.js.map +1 -1
  63. package/dist/metadata.d.ts +6 -0
  64. package/dist/metadata.d.ts.map +1 -1
  65. package/dist/metadata.js.map +1 -1
  66. package/dist/opLifecycle/definitions.d.ts +1 -1
  67. package/dist/opLifecycle/definitions.js.map +1 -1
  68. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  69. package/dist/opLifecycle/opGroupingManager.js +10 -1
  70. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  71. package/dist/opLifecycle/outbox.d.ts +2 -0
  72. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  73. package/dist/opLifecycle/outbox.js +21 -0
  74. package/dist/opLifecycle/outbox.js.map +1 -1
  75. package/dist/packageVersion.d.ts +1 -1
  76. package/dist/packageVersion.js +1 -1
  77. package/dist/packageVersion.js.map +1 -1
  78. package/dist/pendingStateManager.d.ts +1 -1
  79. package/dist/pendingStateManager.d.ts.map +1 -1
  80. package/dist/pendingStateManager.js +2 -11
  81. package/dist/pendingStateManager.js.map +1 -1
  82. package/dist/scheduleManager.d.ts +1 -0
  83. package/dist/scheduleManager.d.ts.map +1 -1
  84. package/dist/summary/orderedClientElection.d.ts +1 -1
  85. package/dist/summary/orderedClientElection.js.map +1 -1
  86. package/dist/summary/runWhileConnectedCoordinator.d.ts +2 -2
  87. package/dist/summary/runWhileConnectedCoordinator.js +1 -1
  88. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  89. package/dist/summary/summarizer.d.ts +1 -1
  90. package/dist/summary/summarizer.js +1 -1
  91. package/dist/summary/summarizer.js.map +1 -1
  92. package/dist/summary/summarizerTypes.d.ts +30 -30
  93. package/dist/summary/summarizerTypes.js.map +1 -1
  94. package/dist/summary/summaryCollection.d.ts +10 -10
  95. package/dist/summary/summaryCollection.js +1 -1
  96. package/dist/summary/summaryCollection.js.map +1 -1
  97. package/dist/summary/summaryFormat.d.ts +3 -3
  98. package/dist/summary/summaryFormat.js.map +1 -1
  99. package/dist/tsdoc-metadata.json +1 -1
  100. package/lib/batchTracker.d.ts +1 -0
  101. package/lib/batchTracker.d.ts.map +1 -1
  102. package/lib/blobManager.d.ts +4 -4
  103. package/lib/blobManager.d.ts.map +1 -1
  104. package/lib/blobManager.js.map +1 -1
  105. package/lib/connectionTelemetry.js +1 -1
  106. package/lib/connectionTelemetry.js.map +1 -1
  107. package/lib/container-runtime-alpha.d.ts +1473 -0
  108. package/lib/container-runtime-beta.d.ts +300 -0
  109. package/lib/container-runtime-public.d.ts +300 -0
  110. package/lib/container-runtime-untrimmed.d.ts +1836 -0
  111. package/lib/containerRuntime.d.ts +34 -40
  112. package/lib/containerRuntime.d.ts.map +1 -1
  113. package/lib/containerRuntime.js +81 -69
  114. package/lib/containerRuntime.js.map +1 -1
  115. package/lib/dataStoreRegistry.d.ts +1 -1
  116. package/lib/dataStoreRegistry.js +1 -1
  117. package/lib/dataStoreRegistry.js.map +1 -1
  118. package/lib/dataStores.d.ts +10 -15
  119. package/lib/dataStores.d.ts.map +1 -1
  120. package/lib/dataStores.js +80 -43
  121. package/lib/dataStores.js.map +1 -1
  122. package/lib/gc/garbageCollection.d.ts +41 -13
  123. package/lib/gc/garbageCollection.d.ts.map +1 -1
  124. package/lib/gc/garbageCollection.js +217 -80
  125. package/lib/gc/garbageCollection.js.map +1 -1
  126. package/lib/gc/gcConfigs.d.ts.map +1 -1
  127. package/lib/gc/gcConfigs.js +37 -40
  128. package/lib/gc/gcConfigs.js.map +1 -1
  129. package/lib/gc/gcDefinitions.d.ts +121 -46
  130. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  131. package/lib/gc/gcDefinitions.js +25 -17
  132. package/lib/gc/gcDefinitions.js.map +1 -1
  133. package/lib/gc/gcHelpers.d.ts +18 -25
  134. package/lib/gc/gcHelpers.d.ts.map +1 -1
  135. package/lib/gc/gcHelpers.js +27 -43
  136. package/lib/gc/gcHelpers.js.map +1 -1
  137. package/lib/gc/gcTelemetry.d.ts +0 -5
  138. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  139. package/lib/gc/gcTelemetry.js +15 -43
  140. package/lib/gc/gcTelemetry.js.map +1 -1
  141. package/lib/gc/gcUnreferencedStateTracker.d.ts +11 -5
  142. package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  143. package/lib/gc/gcUnreferencedStateTracker.js +43 -19
  144. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
  145. package/lib/gc/index.d.ts +1 -1
  146. package/lib/gc/index.d.ts.map +1 -1
  147. package/lib/gc/index.js +1 -1
  148. package/lib/gc/index.js.map +1 -1
  149. package/lib/index.d.ts +14 -2
  150. package/lib/index.d.ts.map +1 -1
  151. package/lib/index.js +15 -1
  152. package/lib/index.js.map +1 -1
  153. package/lib/messageTypes.d.ts +16 -11
  154. package/lib/messageTypes.d.ts.map +1 -1
  155. package/lib/messageTypes.js +6 -1
  156. package/lib/messageTypes.js.map +1 -1
  157. package/lib/metadata.d.ts +6 -0
  158. package/lib/metadata.d.ts.map +1 -1
  159. package/lib/metadata.js.map +1 -1
  160. package/lib/opLifecycle/definitions.d.ts +1 -1
  161. package/lib/opLifecycle/definitions.js.map +1 -1
  162. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  163. package/lib/opLifecycle/opGroupingManager.js +10 -1
  164. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  165. package/lib/opLifecycle/outbox.d.ts +2 -0
  166. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  167. package/lib/opLifecycle/outbox.js +21 -0
  168. package/lib/opLifecycle/outbox.js.map +1 -1
  169. package/lib/packageVersion.d.ts +1 -1
  170. package/lib/packageVersion.js +1 -1
  171. package/lib/packageVersion.js.map +1 -1
  172. package/lib/pendingStateManager.d.ts +1 -1
  173. package/lib/pendingStateManager.d.ts.map +1 -1
  174. package/lib/pendingStateManager.js +2 -11
  175. package/lib/pendingStateManager.js.map +1 -1
  176. package/lib/scheduleManager.d.ts +1 -0
  177. package/lib/scheduleManager.d.ts.map +1 -1
  178. package/lib/summary/orderedClientElection.d.ts +1 -1
  179. package/lib/summary/orderedClientElection.js.map +1 -1
  180. package/lib/summary/runWhileConnectedCoordinator.d.ts +2 -2
  181. package/lib/summary/runWhileConnectedCoordinator.js +1 -1
  182. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  183. package/lib/summary/summarizer.d.ts +1 -1
  184. package/lib/summary/summarizer.js +1 -1
  185. package/lib/summary/summarizer.js.map +1 -1
  186. package/lib/summary/summarizerTypes.d.ts +30 -30
  187. package/lib/summary/summarizerTypes.js.map +1 -1
  188. package/lib/summary/summaryCollection.d.ts +10 -10
  189. package/lib/summary/summaryCollection.js +1 -1
  190. package/lib/summary/summaryCollection.js.map +1 -1
  191. package/lib/summary/summaryFormat.d.ts +3 -3
  192. package/lib/summary/summaryFormat.js.map +1 -1
  193. package/package.json +56 -29
  194. package/src/blobManager.ts +5 -5
  195. package/src/connectionTelemetry.ts +1 -1
  196. package/src/containerRuntime.ts +113 -90
  197. package/src/dataStoreRegistry.ts +1 -1
  198. package/src/dataStores.ts +140 -69
  199. package/src/gc/garbageCollection.md +14 -15
  200. package/src/gc/garbageCollection.ts +256 -96
  201. package/src/gc/gcConfigs.ts +50 -52
  202. package/src/gc/gcDefinitions.ts +137 -52
  203. package/src/gc/gcHelpers.ts +31 -52
  204. package/src/gc/gcTelemetry.ts +16 -57
  205. package/src/gc/gcUnreferencedStateTracker.ts +61 -22
  206. package/src/gc/index.ts +6 -4
  207. package/src/index.ts +19 -1
  208. package/src/messageTypes.ts +21 -11
  209. package/src/metadata.ts +7 -0
  210. package/src/opLifecycle/definitions.ts +1 -1
  211. package/src/opLifecycle/opGroupingManager.ts +10 -1
  212. package/src/opLifecycle/outbox.ts +34 -0
  213. package/src/packageVersion.ts +1 -1
  214. package/src/pendingStateManager.ts +3 -13
  215. package/src/summary/orderedClientElection.ts +1 -1
  216. package/src/summary/runWhileConnectedCoordinator.ts +2 -2
  217. package/src/summary/summarizer.ts +1 -1
  218. package/src/summary/summarizerTypes.ts +30 -30
  219. package/src/summary/summaryCollection.ts +10 -10
  220. package/src/summary/summaryFormat.ts +3 -3
  221. package/dist/id-compressor/appendOnlySortedMap.d.ts +0 -124
  222. package/dist/id-compressor/appendOnlySortedMap.d.ts.map +0 -1
  223. package/dist/id-compressor/appendOnlySortedMap.js +0 -318
  224. package/dist/id-compressor/appendOnlySortedMap.js.map +0 -1
  225. package/dist/id-compressor/finalSpace.d.ts +0 -29
  226. package/dist/id-compressor/finalSpace.d.ts.map +0 -1
  227. package/dist/id-compressor/finalSpace.js +0 -62
  228. package/dist/id-compressor/finalSpace.js.map +0 -1
  229. package/dist/id-compressor/idCompressor.d.ts +0 -54
  230. package/dist/id-compressor/idCompressor.d.ts.map +0 -1
  231. package/dist/id-compressor/idCompressor.js +0 -495
  232. package/dist/id-compressor/idCompressor.js.map +0 -1
  233. package/dist/id-compressor/identifiers.d.ts +0 -32
  234. package/dist/id-compressor/identifiers.d.ts.map +0 -1
  235. package/dist/id-compressor/identifiers.js +0 -15
  236. package/dist/id-compressor/identifiers.js.map +0 -1
  237. package/dist/id-compressor/index.d.ts +0 -13
  238. package/dist/id-compressor/index.d.ts.map +0 -1
  239. package/dist/id-compressor/index.js +0 -32
  240. package/dist/id-compressor/index.js.map +0 -1
  241. package/dist/id-compressor/persistanceUtilities.d.ts +0 -22
  242. package/dist/id-compressor/persistanceUtilities.d.ts.map +0 -1
  243. package/dist/id-compressor/persistanceUtilities.js +0 -43
  244. package/dist/id-compressor/persistanceUtilities.js.map +0 -1
  245. package/dist/id-compressor/sessionSpaceNormalizer.d.ts +0 -46
  246. package/dist/id-compressor/sessionSpaceNormalizer.d.ts.map +0 -1
  247. package/dist/id-compressor/sessionSpaceNormalizer.js +0 -80
  248. package/dist/id-compressor/sessionSpaceNormalizer.js.map +0 -1
  249. package/dist/id-compressor/sessions.d.ts +0 -115
  250. package/dist/id-compressor/sessions.d.ts.map +0 -1
  251. package/dist/id-compressor/sessions.js +0 -305
  252. package/dist/id-compressor/sessions.js.map +0 -1
  253. package/dist/id-compressor/utilities.d.ts +0 -52
  254. package/dist/id-compressor/utilities.d.ts.map +0 -1
  255. package/dist/id-compressor/utilities.js +0 -169
  256. package/dist/id-compressor/utilities.js.map +0 -1
  257. package/lib/id-compressor/appendOnlySortedMap.d.ts +0 -124
  258. package/lib/id-compressor/appendOnlySortedMap.d.ts.map +0 -1
  259. package/lib/id-compressor/appendOnlySortedMap.js +0 -314
  260. package/lib/id-compressor/appendOnlySortedMap.js.map +0 -1
  261. package/lib/id-compressor/finalSpace.d.ts +0 -29
  262. package/lib/id-compressor/finalSpace.d.ts.map +0 -1
  263. package/lib/id-compressor/finalSpace.js +0 -58
  264. package/lib/id-compressor/finalSpace.js.map +0 -1
  265. package/lib/id-compressor/idCompressor.d.ts +0 -54
  266. package/lib/id-compressor/idCompressor.d.ts.map +0 -1
  267. package/lib/id-compressor/idCompressor.js +0 -491
  268. package/lib/id-compressor/idCompressor.js.map +0 -1
  269. package/lib/id-compressor/identifiers.d.ts +0 -32
  270. package/lib/id-compressor/identifiers.d.ts.map +0 -1
  271. package/lib/id-compressor/identifiers.js +0 -11
  272. package/lib/id-compressor/identifiers.js.map +0 -1
  273. package/lib/id-compressor/index.d.ts +0 -13
  274. package/lib/id-compressor/index.d.ts.map +0 -1
  275. package/lib/id-compressor/index.js +0 -13
  276. package/lib/id-compressor/index.js.map +0 -1
  277. package/lib/id-compressor/persistanceUtilities.d.ts +0 -22
  278. package/lib/id-compressor/persistanceUtilities.d.ts.map +0 -1
  279. package/lib/id-compressor/persistanceUtilities.js +0 -34
  280. package/lib/id-compressor/persistanceUtilities.js.map +0 -1
  281. package/lib/id-compressor/sessionSpaceNormalizer.d.ts +0 -46
  282. package/lib/id-compressor/sessionSpaceNormalizer.d.ts.map +0 -1
  283. package/lib/id-compressor/sessionSpaceNormalizer.js +0 -76
  284. package/lib/id-compressor/sessionSpaceNormalizer.js.map +0 -1
  285. package/lib/id-compressor/sessions.d.ts +0 -115
  286. package/lib/id-compressor/sessions.d.ts.map +0 -1
  287. package/lib/id-compressor/sessions.js +0 -290
  288. package/lib/id-compressor/sessions.js.map +0 -1
  289. package/lib/id-compressor/utilities.d.ts +0 -52
  290. package/lib/id-compressor/utilities.d.ts.map +0 -1
  291. package/lib/id-compressor/utilities.js +0 -151
  292. package/lib/id-compressor/utilities.js.map +0 -1
  293. package/src/id-compressor/README.md +0 -3
  294. package/src/id-compressor/appendOnlySortedMap.ts +0 -366
  295. package/src/id-compressor/finalSpace.ts +0 -67
  296. package/src/id-compressor/idCompressor.ts +0 -630
  297. package/src/id-compressor/identifiers.ts +0 -42
  298. package/src/id-compressor/index.ts +0 -26
  299. package/src/id-compressor/persistanceUtilities.ts +0 -58
  300. package/src/id-compressor/sessionSpaceNormalizer.ts +0 -83
  301. package/src/id-compressor/sessions.ts +0 -405
  302. package/src/id-compressor/utilities.ts +0 -190
@@ -1,491 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { assert } from "@fluidframework/core-utils";
6
- import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
7
- import { initialClusterCapacity, } from "@fluidframework/runtime-definitions";
8
- import { createChildLogger } from "@fluidframework/telemetry-utils";
9
- import { isFinalId } from "./identifiers";
10
- import { createSessionId, localIdFromGenCount, genCountFromLocalId, numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, subtractNumericUuids, } from "./utilities";
11
- import { readBoolean, readNumber, readNumericUuid, writeBoolean, writeNumber, writeNumericUuid, } from "./persistanceUtilities";
12
- import { getAlignedLocal, getAlignedFinal, lastFinalizedLocal, Session, Sessions, } from "./sessions";
13
- import { SessionSpaceNormalizer } from "./sessionSpaceNormalizer";
14
- import { FinalSpace } from "./finalSpace";
15
- /**
16
- * The version of IdCompressor that is currently persisted.
17
- * This should not be changed without careful consideration to compatibility.
18
- */
19
- const currentWrittenVersion = 1;
20
- /**
21
- * See {@link IIdCompressor} and {@link IIdCompressorCore}
22
- */
23
- export class IdCompressor {
24
- // -----------------------
25
- constructor(localSessionIdOrDeserialized, logger) {
26
- this.logger = logger;
27
- this.normalizer = new SessionSpaceNormalizer();
28
- // The number of IDs generated by the local session
29
- this.localGenCount = 0;
30
- // -----------------------
31
- // ----- Final state -----
32
- // The gen count to be annotated on the range returned by the next call to `takeNextCreationRange`.
33
- // This is updated to be equal to `generatedIdCount` + 1 each time it is called.
34
- this.nextRangeBaseGenCount = 1;
35
- // The capacity of the next cluster to be created
36
- this.newClusterCapacity = initialClusterCapacity;
37
- this.sessions = new Sessions();
38
- this.finalSpace = new FinalSpace();
39
- // -----------------------
40
- // ----- Telemetry state -----
41
- // The number of local IDs generated since the last telemetry was sent.
42
- this.telemetryLocalIdCount = 0;
43
- // The number of eager final IDs generated since the last telemetry was sent.
44
- this.telemetryEagerFinalIdCount = 0;
45
- if (typeof localSessionIdOrDeserialized === "string") {
46
- this.localSessionId = localSessionIdOrDeserialized;
47
- this.localSession = this.sessions.getOrCreate(localSessionIdOrDeserialized);
48
- }
49
- else {
50
- // Deserialize case
51
- this.sessions = localSessionIdOrDeserialized;
52
- // As policy, the first session is always the local session. Preserve this invariant
53
- // during deserialization.
54
- const firstSession = localSessionIdOrDeserialized.sessions().next();
55
- assert(!firstSession.done, 0x754 /* First session must be present. */);
56
- this.localSession = firstSession.value;
57
- this.localSessionId = stableIdFromNumericUuid(this.localSession.sessionUuid);
58
- }
59
- }
60
- static create(sessionIdOrLogger, loggerOrUndefined) {
61
- let localSessionId;
62
- let logger;
63
- if (sessionIdOrLogger === undefined) {
64
- localSessionId = createSessionId();
65
- }
66
- else {
67
- if (typeof sessionIdOrLogger === "string") {
68
- localSessionId = sessionIdOrLogger;
69
- logger = loggerOrUndefined;
70
- }
71
- else {
72
- localSessionId = createSessionId();
73
- logger = loggerOrUndefined;
74
- }
75
- }
76
- const compressor = new IdCompressor(localSessionId, logger === undefined ? undefined : createChildLogger({ logger }));
77
- return compressor;
78
- }
79
- /**
80
- * The size of each newly created ID cluster.
81
- */
82
- get clusterCapacity() {
83
- return this.newClusterCapacity;
84
- }
85
- /**
86
- * Must only be set with a value upon which consensus has been reached. Value must be greater than zero and less than
87
- * `IdCompressor.maxClusterSize`.
88
- */
89
- set clusterCapacity(value) {
90
- if (value <= 0) {
91
- throw new Error("Clusters must have a positive capacity.");
92
- }
93
- if (value > IdCompressor.maxClusterSize) {
94
- throw new Error("Clusters must not exceed max cluster size.");
95
- }
96
- this.newClusterCapacity = value;
97
- }
98
- generateCompressedId() {
99
- this.localGenCount++;
100
- const lastCluster = this.localSession.getLastCluster();
101
- if (lastCluster === undefined) {
102
- this.telemetryLocalIdCount++;
103
- return this.generateNextLocalId();
104
- }
105
- // If there exists a cluster of final IDs already claimed by the local session that still has room in it,
106
- // it is known prior to range sequencing what a local ID's corresponding final ID will be.
107
- // In this case, it is safe to return the final ID immediately. This is guaranteed to be safe because
108
- // any op that the local session sends that contains one of those final IDs are guaranteed to arrive to
109
- // collaborators *after* the one containing the creation range.
110
- const clusterOffset = this.localGenCount - genCountFromLocalId(lastCluster.baseLocalId);
111
- if (lastCluster.capacity > clusterOffset) {
112
- this.telemetryEagerFinalIdCount++;
113
- // Space in the cluster: eager final
114
- return (lastCluster.baseFinalId +
115
- clusterOffset);
116
- }
117
- // No space in the cluster, return next local
118
- this.telemetryLocalIdCount++;
119
- return this.generateNextLocalId();
120
- }
121
- generateNextLocalId() {
122
- // Must tell the normalizer that we generated a local ID
123
- this.normalizer.addLocalRange(this.localGenCount, 1);
124
- return localIdFromGenCount(this.localGenCount);
125
- }
126
- takeNextCreationRange() {
127
- const count = this.localGenCount - (this.nextRangeBaseGenCount - 1);
128
- if (count === 0) {
129
- return {
130
- sessionId: this.localSessionId,
131
- };
132
- }
133
- const range = {
134
- sessionId: this.localSessionId,
135
- ids: {
136
- firstGenCount: this.nextRangeBaseGenCount,
137
- count,
138
- },
139
- };
140
- this.nextRangeBaseGenCount = this.localGenCount + 1;
141
- return range;
142
- }
143
- finalizeCreationRange(range) {
144
- // Check if the range has IDs
145
- if (range.ids === undefined) {
146
- return;
147
- }
148
- assert(range.ids.count > 0, 0x755 /* Malformed ID Range. */);
149
- const { sessionId, ids } = range;
150
- const { count, firstGenCount } = ids;
151
- const session = this.sessions.getOrCreate(sessionId);
152
- const isLocal = session === this.localSession;
153
- const rangeBaseLocal = localIdFromGenCount(firstGenCount);
154
- let lastCluster = session.getLastCluster();
155
- if (lastCluster === undefined) {
156
- // This is the first cluster in the session space
157
- if (rangeBaseLocal !== -1) {
158
- throw new Error("Ranges finalized out of order.");
159
- }
160
- lastCluster = this.addEmptyCluster(session, this.clusterCapacity + count);
161
- if (isLocal) {
162
- this.logger?.sendTelemetryEvent({
163
- eventName: "RuntimeIdCompressor:FirstCluster",
164
- sessionId: this.localSessionId,
165
- });
166
- }
167
- }
168
- const remainingCapacity = lastCluster.capacity - lastCluster.count;
169
- if (lastCluster.baseLocalId - lastCluster.count !== rangeBaseLocal) {
170
- throw new Error("Ranges finalized out of order.");
171
- }
172
- if (remainingCapacity >= count) {
173
- // The current range fits in the existing cluster
174
- lastCluster.count += count;
175
- }
176
- else {
177
- const overflow = count - remainingCapacity;
178
- const newClaimedFinalCount = overflow + this.clusterCapacity;
179
- if (lastCluster === this.finalSpace.getLastCluster()) {
180
- // The last cluster in the sessions chain is the last cluster globally, so it can be expanded.
181
- lastCluster.capacity += newClaimedFinalCount;
182
- lastCluster.count += count;
183
- assert(!this.sessions.clusterCollides(lastCluster), 0x756 /* Cluster collision detected. */);
184
- if (isLocal) {
185
- this.logger?.sendTelemetryEvent({
186
- eventName: "RuntimeIdCompressor:ClusterExpansion",
187
- sessionId: this.localSessionId,
188
- previousCapacity: lastCluster.capacity - newClaimedFinalCount,
189
- newCapacity: lastCluster.capacity,
190
- overflow,
191
- });
192
- }
193
- }
194
- else {
195
- // The last cluster in the sessions chain is *not* the last cluster globally. Fill and overflow to new.
196
- lastCluster.count = lastCluster.capacity;
197
- const newCluster = this.addEmptyCluster(session, newClaimedFinalCount);
198
- newCluster.count += overflow;
199
- if (isLocal) {
200
- this.logger?.sendTelemetryEvent({
201
- eventName: "RuntimeIdCompressor:NewCluster",
202
- sessionId: this.localSessionId,
203
- });
204
- }
205
- }
206
- }
207
- if (isLocal) {
208
- this.logger?.sendTelemetryEvent({
209
- eventName: "RuntimeIdCompressor:IdCompressorStatus",
210
- eagerFinalIdCount: this.telemetryEagerFinalIdCount,
211
- localIdCount: this.telemetryLocalIdCount,
212
- sessionId: this.localSessionId,
213
- });
214
- this.telemetryEagerFinalIdCount = 0;
215
- this.telemetryLocalIdCount = 0;
216
- }
217
- assert(!session.isEmpty(), 0x757 /* Empty sessions should not be created. */);
218
- }
219
- addEmptyCluster(session, capacity) {
220
- const newCluster = session.addNewCluster(this.finalSpace.getAllocatedIdLimit(), capacity, 0);
221
- assert(!this.sessions.clusterCollides(newCluster), 0x758 /* Cluster collision detected. */);
222
- this.finalSpace.addCluster(newCluster);
223
- return newCluster;
224
- }
225
- normalizeToOpSpace(id) {
226
- if (isFinalId(id)) {
227
- return id;
228
- }
229
- else {
230
- const local = id;
231
- if (!this.normalizer.contains(local)) {
232
- throw new Error("Invalid ID to normalize.");
233
- }
234
- const finalForm = this.localSession.tryConvertToFinal(local, true);
235
- return finalForm === undefined
236
- ? local
237
- : finalForm;
238
- }
239
- }
240
- normalizeToSessionSpace(id, originSessionId) {
241
- if (isFinalId(id)) {
242
- const containingCluster = this.localSession.getClusterByAllocatedFinal(id);
243
- if (containingCluster === undefined) {
244
- // Does not exist in local cluster chain
245
- if (id >= this.finalSpace.getFinalizedIdLimit()) {
246
- throw new Error("Unknown op space ID.");
247
- }
248
- return id;
249
- }
250
- else {
251
- const alignedLocal = getAlignedLocal(containingCluster, id);
252
- if (this.normalizer.contains(alignedLocal)) {
253
- return alignedLocal;
254
- }
255
- else {
256
- if (genCountFromLocalId(alignedLocal) > this.localGenCount) {
257
- throw new Error("Unknown op space ID.");
258
- }
259
- return id;
260
- }
261
- }
262
- }
263
- else {
264
- const localToNormalize = id;
265
- if (originSessionId === this.localSessionId) {
266
- if (this.normalizer.contains(localToNormalize)) {
267
- return localToNormalize;
268
- }
269
- else {
270
- // We never generated this local ID, so fail
271
- throw new Error("Unknown op space ID.");
272
- }
273
- }
274
- else {
275
- // LocalId from a remote session
276
- const remoteSession = this.sessions.get(originSessionId);
277
- if (remoteSession === undefined) {
278
- throw new Error("No IDs have ever been finalized by the supplied session.");
279
- }
280
- const correspondingFinal = remoteSession.tryConvertToFinal(localToNormalize, false);
281
- if (correspondingFinal === undefined) {
282
- throw new Error("Unknown op space ID.");
283
- }
284
- return correspondingFinal;
285
- }
286
- }
287
- }
288
- decompress(id) {
289
- if (isFinalId(id)) {
290
- const containingCluster = Session.getContainingCluster(id, this.finalSpace.clusters);
291
- if (containingCluster === undefined) {
292
- throw new Error("Unknown ID");
293
- }
294
- const alignedLocal = getAlignedLocal(containingCluster, id);
295
- const alignedGenCount = genCountFromLocalId(alignedLocal);
296
- const lastFinalizedGenCount = genCountFromLocalId(lastFinalizedLocal(containingCluster));
297
- if (alignedGenCount > lastFinalizedGenCount) {
298
- // should be an eager final id generated by the local session
299
- if (containingCluster.session === this.localSession) {
300
- assert(!this.normalizer.contains(alignedLocal), 0x759 /* Normalizer out of sync. */);
301
- }
302
- else {
303
- throw new Error("Unknown ID");
304
- }
305
- }
306
- return stableIdFromNumericUuid(offsetNumericUuid(containingCluster.session.sessionUuid, alignedGenCount - 1));
307
- }
308
- else {
309
- const localToDecompress = id;
310
- if (!this.normalizer.contains(localToDecompress)) {
311
- throw new Error("Unknown ID");
312
- }
313
- return stableIdFromNumericUuid(offsetNumericUuid(this.localSession.sessionUuid, genCountFromLocalId(localToDecompress) - 1));
314
- }
315
- }
316
- recompress(uncompressed) {
317
- const recompressed = this.tryRecompress(uncompressed);
318
- if (recompressed === undefined) {
319
- throw new Error("Could not recompress.");
320
- }
321
- return recompressed;
322
- }
323
- tryRecompress(uncompressed) {
324
- const match = this.sessions.getContainingCluster(uncompressed);
325
- if (match === undefined) {
326
- const numericUncompressed = numericUuidFromStableId(uncompressed);
327
- const offset = subtractNumericUuids(numericUncompressed, this.localSession.sessionUuid);
328
- if (offset < Number.MAX_SAFE_INTEGER) {
329
- const genCountEquivalent = Number(offset) + 1;
330
- const localEquivalent = localIdFromGenCount(genCountEquivalent);
331
- if (this.normalizer.contains(localEquivalent)) {
332
- return localEquivalent;
333
- }
334
- }
335
- return undefined;
336
- }
337
- else {
338
- const [containingCluster, alignedLocal] = match;
339
- if (containingCluster.session === this.localSession) {
340
- // Local session
341
- if (this.normalizer.contains(alignedLocal)) {
342
- return alignedLocal;
343
- }
344
- else {
345
- assert(genCountFromLocalId(alignedLocal) <= this.localGenCount, 0x75a /* Clusters out of sync. */);
346
- // Id is an eager final
347
- return getAlignedFinal(containingCluster, alignedLocal);
348
- }
349
- }
350
- else {
351
- // Not the local session
352
- return genCountFromLocalId(alignedLocal) >= lastFinalizedLocal(containingCluster)
353
- ? getAlignedFinal(containingCluster, alignedLocal)
354
- : undefined;
355
- }
356
- }
357
- }
358
- serialize(hasLocalState) {
359
- const { normalizer, finalSpace, sessions } = this;
360
- const sessionIndexMap = new Map();
361
- let sessionIndex = 0;
362
- for (const session of sessions.sessions()) {
363
- // Filter empty sessions to prevent them accumulating in the serialized state
364
- if (!session.isEmpty() || hasLocalState) {
365
- sessionIndexMap.set(session, sessionIndex);
366
- sessionIndex++;
367
- }
368
- }
369
- const localStateSize = hasLocalState
370
- ? 1 + // generated ID count
371
- 1 + // next range base genCount
372
- 1 + // count of normalizer pairs
373
- this.normalizer.idRanges.size * 2 // pairs
374
- : 0;
375
- // Layout size, in 8 byte increments
376
- const totalSize = 1 + // version
377
- 1 + // hasLocalState
378
- 1 + // cluster capacity
379
- 1 + // session count
380
- 1 + // cluster count
381
- sessionIndexMap.size * 2 + // session IDs
382
- finalSpace.clusters.length * 3 + // clusters: (sessionIndex, capacity, count)[]
383
- localStateSize; // local state, if present
384
- const serializedFloat = new Float64Array(totalSize);
385
- const serializedUint = new BigUint64Array(serializedFloat.buffer);
386
- let index = 0;
387
- index = writeNumber(serializedFloat, index, currentWrittenVersion);
388
- index = writeBoolean(serializedFloat, index, hasLocalState);
389
- index = writeNumber(serializedFloat, index, this.clusterCapacity);
390
- index = writeNumber(serializedFloat, index, sessionIndexMap.size);
391
- index = writeNumber(serializedFloat, index, finalSpace.clusters.length);
392
- for (const [session] of sessionIndexMap.entries()) {
393
- index = writeNumericUuid(serializedUint, index, session.sessionUuid);
394
- }
395
- finalSpace.clusters.forEach((cluster) => {
396
- index = writeNumber(serializedFloat, index, sessionIndexMap.get(cluster.session));
397
- index = writeNumber(serializedFloat, index, cluster.capacity);
398
- index = writeNumber(serializedFloat, index, cluster.count);
399
- });
400
- if (hasLocalState) {
401
- index = writeNumber(serializedFloat, index, this.localGenCount);
402
- index = writeNumber(serializedFloat, index, this.nextRangeBaseGenCount);
403
- index = writeNumber(serializedFloat, index, normalizer.idRanges.size);
404
- for (const [leadingGenCount, count] of normalizer.idRanges.entries()) {
405
- index = writeNumber(serializedFloat, index, leadingGenCount);
406
- index = writeNumber(serializedFloat, index, count);
407
- }
408
- }
409
- assert(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);
410
- this.logger?.sendTelemetryEvent({
411
- eventName: "RuntimeIdCompressor:SerializedIdCompressorSize",
412
- size: serializedFloat.byteLength,
413
- clusterCount: finalSpace.clusters.length,
414
- sessionCount: sessionIndexMap.size,
415
- });
416
- return bufferToString(serializedFloat.buffer, "base64");
417
- }
418
- static deserialize(serialized, sessionId) {
419
- const buffer = stringToBuffer(serialized, "base64");
420
- const index = {
421
- index: 0,
422
- bufferFloat: new Float64Array(buffer),
423
- bufferUint: new BigUint64Array(buffer),
424
- };
425
- const version = readNumber(index);
426
- assert(version === currentWrittenVersion, 0x75c /* Unknown serialized version. */);
427
- const hasLocalState = readBoolean(index);
428
- const clusterCapacity = readNumber(index);
429
- const sessionCount = readNumber(index);
430
- const clusterCount = readNumber(index);
431
- // Sessions
432
- let sessionOffset = 0;
433
- const sessions = [];
434
- if (!hasLocalState) {
435
- // If !hasLocalState, there won't be a serialized local session ID so insert one at the beginning
436
- assert(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);
437
- const localSessionNumeric = numericUuidFromStableId(sessionId);
438
- sessions.push([localSessionNumeric, new Session(localSessionNumeric)]);
439
- sessionOffset = 1;
440
- }
441
- else {
442
- assert(sessionId === undefined, 0x75e /* Local state should not exist in serialized form. */);
443
- }
444
- for (let i = 0; i < sessionCount; i++) {
445
- const numeric = readNumericUuid(index);
446
- sessions.push([numeric, new Session(numeric)]);
447
- }
448
- const compressor = new IdCompressor(new Sessions(sessions));
449
- compressor.clusterCapacity = clusterCapacity;
450
- // Clusters
451
- let baseFinalId = 0;
452
- for (let i = 0; i < clusterCount; i++) {
453
- const sessionIndex = readNumber(index);
454
- const session = sessions[sessionIndex + sessionOffset][1];
455
- const capacity = readNumber(index);
456
- const count = readNumber(index);
457
- const cluster = session.addNewCluster(baseFinalId, capacity, count);
458
- compressor.finalSpace.addCluster(cluster);
459
- baseFinalId += capacity;
460
- }
461
- // Local state
462
- if (hasLocalState) {
463
- compressor.localGenCount = readNumber(index);
464
- compressor.nextRangeBaseGenCount = readNumber(index);
465
- const normalizerCount = readNumber(index);
466
- for (let i = 0; i < normalizerCount; i++) {
467
- compressor.normalizer.addLocalRange(readNumber(index), readNumber(index));
468
- }
469
- }
470
- assert(index.index === index.bufferFloat.length, 0x75f /* Failed to read entire serialized compressor. */);
471
- return compressor;
472
- }
473
- equals(other, includeLocalState) {
474
- if (includeLocalState &&
475
- (this.localSessionId !== other.localSessionId ||
476
- !this.localSession.equals(other.localSession) ||
477
- !this.normalizer.equals(other.normalizer) ||
478
- this.nextRangeBaseGenCount !== other.nextRangeBaseGenCount ||
479
- this.localGenCount !== other.localGenCount)) {
480
- return false;
481
- }
482
- return (this.newClusterCapacity === other.newClusterCapacity &&
483
- this.sessions.equals(other.sessions, includeLocalState) &&
484
- this.finalSpace.equals(other.finalSpace));
485
- }
486
- }
487
- /**
488
- * Max allowed initial cluster size.
489
- */
490
- IdCompressor.maxClusterSize = 2 ** 20;
491
- //# sourceMappingURL=idCompressor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"idCompressor.js","sourceRoot":"","sources":["../../src/id-compressor/idCompressor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport { bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport {\n\tIdCreationRange,\n\tIIdCompressor,\n\tIIdCompressorCore,\n\tOpSpaceCompressedId,\n\tSerializedIdCompressor,\n\tSerializedIdCompressorWithNoSession,\n\tSerializedIdCompressorWithOngoingSession,\n\tSessionId,\n\tSessionSpaceCompressedId,\n\tStableId,\n\tinitialClusterCapacity,\n} from \"@fluidframework/runtime-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ITelemetryLoggerExt, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { FinalCompressedId, isFinalId, LocalCompressedId, NumericUuid } from \"./identifiers\";\nimport {\n\tcreateSessionId,\n\tlocalIdFromGenCount,\n\tgenCountFromLocalId,\n\tnumericUuidFromStableId,\n\toffsetNumericUuid,\n\tstableIdFromNumericUuid,\n\tsubtractNumericUuids,\n} from \"./utilities\";\nimport {\n\tIndex,\n\treadBoolean,\n\treadNumber,\n\treadNumericUuid,\n\twriteBoolean,\n\twriteNumber,\n\twriteNumericUuid,\n} from \"./persistanceUtilities\";\nimport {\n\tgetAlignedLocal,\n\tgetAlignedFinal,\n\tIdCluster,\n\tlastFinalizedLocal,\n\tSession,\n\tSessions,\n} from \"./sessions\";\nimport { SessionSpaceNormalizer } from \"./sessionSpaceNormalizer\";\nimport { FinalSpace } from \"./finalSpace\";\n\n/**\n * The version of IdCompressor that is currently persisted.\n * This should not be changed without careful consideration to compatibility.\n */\nconst currentWrittenVersion = 1;\n\n/**\n * See {@link IIdCompressor} and {@link IIdCompressorCore}\n */\nexport class IdCompressor implements IIdCompressor, IIdCompressorCore {\n\t/**\n\t * Max allowed initial cluster size.\n\t */\n\tpublic static readonly maxClusterSize = 2 ** 20;\n\n\t// ----- Local state -----\n\n\tpublic readonly localSessionId: SessionId;\n\tprivate readonly localSession: Session;\n\tprivate readonly normalizer = new SessionSpaceNormalizer();\n\t// The number of IDs generated by the local session\n\tprivate localGenCount = 0;\n\n\t// -----------------------\n\n\t// ----- Final state -----\n\n\t// The gen count to be annotated on the range returned by the next call to `takeNextCreationRange`.\n\t// This is updated to be equal to `generatedIdCount` + 1 each time it is called.\n\tprivate nextRangeBaseGenCount = 1;\n\t// The capacity of the next cluster to be created\n\tprivate newClusterCapacity = initialClusterCapacity;\n\tprivate readonly sessions = new Sessions();\n\tprivate readonly finalSpace = new FinalSpace();\n\n\t// -----------------------\n\n\t// ----- Telemetry state -----\n\n\t// The number of local IDs generated since the last telemetry was sent.\n\tprivate telemetryLocalIdCount = 0;\n\t// The number of eager final IDs generated since the last telemetry was sent.\n\tprivate telemetryEagerFinalIdCount = 0;\n\n\t// -----------------------\n\n\tprivate constructor(\n\t\tlocalSessionIdOrDeserialized: SessionId | Sessions,\n\t\tprivate readonly logger?: ITelemetryLoggerExt,\n\t) {\n\t\tif (typeof localSessionIdOrDeserialized === \"string\") {\n\t\t\tthis.localSessionId = localSessionIdOrDeserialized;\n\t\t\tthis.localSession = this.sessions.getOrCreate(localSessionIdOrDeserialized);\n\t\t} else {\n\t\t\t// Deserialize case\n\t\t\tthis.sessions = localSessionIdOrDeserialized;\n\t\t\t// As policy, the first session is always the local session. Preserve this invariant\n\t\t\t// during deserialization.\n\t\t\tconst firstSession = localSessionIdOrDeserialized.sessions().next();\n\t\t\tassert(!firstSession.done, 0x754 /* First session must be present. */);\n\t\t\tthis.localSession = firstSession.value;\n\t\t\tthis.localSessionId = stableIdFromNumericUuid(\n\t\t\t\tthis.localSession.sessionUuid,\n\t\t\t) as SessionId;\n\t\t}\n\t}\n\n\tpublic static create(logger?: ITelemetryBaseLogger): IdCompressor;\n\tpublic static create(sessionId: SessionId, logger?: ITelemetryBaseLogger): IdCompressor;\n\tpublic static create(\n\t\tsessionIdOrLogger?: SessionId | ITelemetryBaseLogger,\n\t\tloggerOrUndefined?: ITelemetryBaseLogger,\n\t): IdCompressor {\n\t\tlet localSessionId: SessionId;\n\t\tlet logger: ITelemetryBaseLogger | undefined;\n\t\tif (sessionIdOrLogger === undefined) {\n\t\t\tlocalSessionId = createSessionId();\n\t\t} else {\n\t\t\tif (typeof sessionIdOrLogger === \"string\") {\n\t\t\t\tlocalSessionId = sessionIdOrLogger;\n\t\t\t\tlogger = loggerOrUndefined;\n\t\t\t} else {\n\t\t\t\tlocalSessionId = createSessionId();\n\t\t\t\tlogger = loggerOrUndefined;\n\t\t\t}\n\t\t}\n\t\tconst compressor = new IdCompressor(\n\t\t\tlocalSessionId,\n\t\t\tlogger === undefined ? undefined : createChildLogger({ logger }),\n\t\t);\n\t\treturn compressor;\n\t}\n\n\t/**\n\t * The size of each newly created ID cluster.\n\t */\n\tpublic get clusterCapacity(): number {\n\t\treturn this.newClusterCapacity;\n\t}\n\n\t/**\n\t * Must only be set with a value upon which consensus has been reached. Value must be greater than zero and less than\n\t * `IdCompressor.maxClusterSize`.\n\t */\n\tpublic set clusterCapacity(value: number) {\n\t\tif (value <= 0) {\n\t\t\tthrow new Error(\"Clusters must have a positive capacity.\");\n\t\t}\n\t\tif (value > IdCompressor.maxClusterSize) {\n\t\t\tthrow new Error(\"Clusters must not exceed max cluster size.\");\n\t\t}\n\t\tthis.newClusterCapacity = value;\n\t}\n\n\tpublic generateCompressedId(): SessionSpaceCompressedId {\n\t\tthis.localGenCount++;\n\t\tconst lastCluster = this.localSession.getLastCluster();\n\t\tif (lastCluster === undefined) {\n\t\t\tthis.telemetryLocalIdCount++;\n\t\t\treturn this.generateNextLocalId();\n\t\t}\n\n\t\t// If there exists a cluster of final IDs already claimed by the local session that still has room in it,\n\t\t// it is known prior to range sequencing what a local ID's corresponding final ID will be.\n\t\t// In this case, it is safe to return the final ID immediately. This is guaranteed to be safe because\n\t\t// any op that the local session sends that contains one of those final IDs are guaranteed to arrive to\n\t\t// collaborators *after* the one containing the creation range.\n\t\tconst clusterOffset = this.localGenCount - genCountFromLocalId(lastCluster.baseLocalId);\n\t\tif (lastCluster.capacity > clusterOffset) {\n\t\t\tthis.telemetryEagerFinalIdCount++;\n\t\t\t// Space in the cluster: eager final\n\t\t\treturn ((lastCluster.baseFinalId as number) +\n\t\t\t\tclusterOffset) as SessionSpaceCompressedId;\n\t\t}\n\t\t// No space in the cluster, return next local\n\t\tthis.telemetryLocalIdCount++;\n\t\treturn this.generateNextLocalId();\n\t}\n\n\tprivate generateNextLocalId(): LocalCompressedId {\n\t\t// Must tell the normalizer that we generated a local ID\n\t\tthis.normalizer.addLocalRange(this.localGenCount, 1);\n\t\treturn localIdFromGenCount(this.localGenCount);\n\t}\n\n\tpublic takeNextCreationRange(): IdCreationRange {\n\t\tconst count = this.localGenCount - (this.nextRangeBaseGenCount - 1);\n\t\tif (count === 0) {\n\t\t\treturn {\n\t\t\t\tsessionId: this.localSessionId,\n\t\t\t};\n\t\t}\n\t\tconst range: IdCreationRange = {\n\t\t\tsessionId: this.localSessionId,\n\t\t\tids: {\n\t\t\t\tfirstGenCount: this.nextRangeBaseGenCount,\n\t\t\t\tcount,\n\t\t\t},\n\t\t};\n\t\tthis.nextRangeBaseGenCount = this.localGenCount + 1;\n\t\treturn range;\n\t}\n\n\tpublic finalizeCreationRange(range: IdCreationRange): void {\n\t\t// Check if the range has IDs\n\t\tif (range.ids === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tassert(range.ids.count > 0, 0x755 /* Malformed ID Range. */);\n\t\tconst { sessionId, ids } = range;\n\t\tconst { count, firstGenCount } = ids;\n\t\tconst session = this.sessions.getOrCreate(sessionId);\n\t\tconst isLocal = session === this.localSession;\n\t\tconst rangeBaseLocal = localIdFromGenCount(firstGenCount);\n\t\tlet lastCluster = session.getLastCluster();\n\t\tif (lastCluster === undefined) {\n\t\t\t// This is the first cluster in the session space\n\t\t\tif (rangeBaseLocal !== -1) {\n\t\t\t\tthrow new Error(\"Ranges finalized out of order.\");\n\t\t\t}\n\t\t\tlastCluster = this.addEmptyCluster(session, this.clusterCapacity + count);\n\t\t\tif (isLocal) {\n\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\teventName: \"RuntimeIdCompressor:FirstCluster\",\n\t\t\t\t\tsessionId: this.localSessionId,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst remainingCapacity = lastCluster.capacity - lastCluster.count;\n\t\tif (lastCluster.baseLocalId - lastCluster.count !== rangeBaseLocal) {\n\t\t\tthrow new Error(\"Ranges finalized out of order.\");\n\t\t}\n\n\t\tif (remainingCapacity >= count) {\n\t\t\t// The current range fits in the existing cluster\n\t\t\tlastCluster.count += count;\n\t\t} else {\n\t\t\tconst overflow = count - remainingCapacity;\n\t\t\tconst newClaimedFinalCount = overflow + this.clusterCapacity;\n\t\t\tif (lastCluster === this.finalSpace.getLastCluster()) {\n\t\t\t\t// The last cluster in the sessions chain is the last cluster globally, so it can be expanded.\n\t\t\t\tlastCluster.capacity += newClaimedFinalCount;\n\t\t\t\tlastCluster.count += count;\n\t\t\t\tassert(\n\t\t\t\t\t!this.sessions.clusterCollides(lastCluster),\n\t\t\t\t\t0x756 /* Cluster collision detected. */,\n\t\t\t\t);\n\t\t\t\tif (isLocal) {\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"RuntimeIdCompressor:ClusterExpansion\",\n\t\t\t\t\t\tsessionId: this.localSessionId,\n\t\t\t\t\t\tpreviousCapacity: lastCluster.capacity - newClaimedFinalCount,\n\t\t\t\t\t\tnewCapacity: lastCluster.capacity,\n\t\t\t\t\t\toverflow,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// The last cluster in the sessions chain is *not* the last cluster globally. Fill and overflow to new.\n\t\t\t\tlastCluster.count = lastCluster.capacity;\n\t\t\t\tconst newCluster = this.addEmptyCluster(session, newClaimedFinalCount);\n\t\t\t\tnewCluster.count += overflow;\n\t\t\t\tif (isLocal) {\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"RuntimeIdCompressor:NewCluster\",\n\t\t\t\t\t\tsessionId: this.localSessionId,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isLocal) {\n\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\teventName: \"RuntimeIdCompressor:IdCompressorStatus\",\n\t\t\t\teagerFinalIdCount: this.telemetryEagerFinalIdCount,\n\t\t\t\tlocalIdCount: this.telemetryLocalIdCount,\n\t\t\t\tsessionId: this.localSessionId,\n\t\t\t});\n\t\t\tthis.telemetryEagerFinalIdCount = 0;\n\t\t\tthis.telemetryLocalIdCount = 0;\n\t\t}\n\n\t\tassert(!session.isEmpty(), 0x757 /* Empty sessions should not be created. */);\n\t}\n\n\tprivate addEmptyCluster(session: Session, capacity: number): IdCluster {\n\t\tconst newCluster = session.addNewCluster(\n\t\t\tthis.finalSpace.getAllocatedIdLimit(),\n\t\t\tcapacity,\n\t\t\t0,\n\t\t);\n\t\tassert(!this.sessions.clusterCollides(newCluster), 0x758 /* Cluster collision detected. */);\n\t\tthis.finalSpace.addCluster(newCluster);\n\t\treturn newCluster;\n\t}\n\n\tpublic normalizeToOpSpace(id: SessionSpaceCompressedId): OpSpaceCompressedId {\n\t\tif (isFinalId(id)) {\n\t\t\treturn id;\n\t\t} else {\n\t\t\tconst local = id as unknown as LocalCompressedId;\n\t\t\tif (!this.normalizer.contains(local)) {\n\t\t\t\tthrow new Error(\"Invalid ID to normalize.\");\n\t\t\t}\n\t\t\tconst finalForm = this.localSession.tryConvertToFinal(local, true);\n\t\t\treturn finalForm === undefined\n\t\t\t\t? (local as unknown as OpSpaceCompressedId)\n\t\t\t\t: (finalForm as OpSpaceCompressedId);\n\t\t}\n\t}\n\n\tpublic normalizeToSessionSpace(\n\t\tid: OpSpaceCompressedId,\n\t\toriginSessionId: SessionId,\n\t): SessionSpaceCompressedId {\n\t\tif (isFinalId(id)) {\n\t\t\tconst containingCluster = this.localSession.getClusterByAllocatedFinal(id);\n\t\t\tif (containingCluster === undefined) {\n\t\t\t\t// Does not exist in local cluster chain\n\t\t\t\tif (id >= this.finalSpace.getFinalizedIdLimit()) {\n\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t}\n\t\t\t\treturn id as unknown as SessionSpaceCompressedId;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = getAlignedLocal(containingCluster, id);\n\t\t\t\tif (this.normalizer.contains(alignedLocal)) {\n\t\t\t\t\treturn alignedLocal;\n\t\t\t\t} else {\n\t\t\t\t\tif (genCountFromLocalId(alignedLocal) > this.localGenCount) {\n\t\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t\t}\n\t\t\t\t\treturn id as unknown as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst localToNormalize = id as unknown as LocalCompressedId;\n\t\t\tif (originSessionId === this.localSessionId) {\n\t\t\t\tif (this.normalizer.contains(localToNormalize)) {\n\t\t\t\t\treturn localToNormalize;\n\t\t\t\t} else {\n\t\t\t\t\t// We never generated this local ID, so fail\n\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// LocalId from a remote session\n\t\t\t\tconst remoteSession = this.sessions.get(originSessionId);\n\t\t\t\tif (remoteSession === undefined) {\n\t\t\t\t\tthrow new Error(\"No IDs have ever been finalized by the supplied session.\");\n\t\t\t\t}\n\t\t\t\tconst correspondingFinal = remoteSession.tryConvertToFinal(localToNormalize, false);\n\t\t\t\tif (correspondingFinal === undefined) {\n\t\t\t\t\tthrow new Error(\"Unknown op space ID.\");\n\t\t\t\t}\n\t\t\t\treturn correspondingFinal as unknown as SessionSpaceCompressedId;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic decompress(id: SessionSpaceCompressedId): StableId {\n\t\tif (isFinalId(id)) {\n\t\t\tconst containingCluster = Session.getContainingCluster(id, this.finalSpace.clusters);\n\t\t\tif (containingCluster === undefined) {\n\t\t\t\tthrow new Error(\"Unknown ID\");\n\t\t\t}\n\t\t\tconst alignedLocal = getAlignedLocal(containingCluster, id);\n\t\t\tconst alignedGenCount = genCountFromLocalId(alignedLocal);\n\t\t\tconst lastFinalizedGenCount = genCountFromLocalId(\n\t\t\t\tlastFinalizedLocal(containingCluster),\n\t\t\t);\n\t\t\tif (alignedGenCount > lastFinalizedGenCount) {\n\t\t\t\t// should be an eager final id generated by the local session\n\t\t\t\tif (containingCluster.session === this.localSession) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!this.normalizer.contains(alignedLocal),\n\t\t\t\t\t\t0x759 /* Normalizer out of sync. */,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(\"Unknown ID\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn stableIdFromNumericUuid(\n\t\t\t\toffsetNumericUuid(containingCluster.session.sessionUuid, alignedGenCount - 1),\n\t\t\t);\n\t\t} else {\n\t\t\tconst localToDecompress = id as unknown as LocalCompressedId;\n\t\t\tif (!this.normalizer.contains(localToDecompress)) {\n\t\t\t\tthrow new Error(\"Unknown ID\");\n\t\t\t}\n\t\t\treturn stableIdFromNumericUuid(\n\t\t\t\toffsetNumericUuid(\n\t\t\t\t\tthis.localSession.sessionUuid,\n\t\t\t\t\tgenCountFromLocalId(localToDecompress) - 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic recompress(uncompressed: StableId): SessionSpaceCompressedId {\n\t\tconst recompressed = this.tryRecompress(uncompressed);\n\t\tif (recompressed === undefined) {\n\t\t\tthrow new Error(\"Could not recompress.\");\n\t\t}\n\t\treturn recompressed;\n\t}\n\n\tpublic tryRecompress(uncompressed: StableId): SessionSpaceCompressedId | undefined {\n\t\tconst match = this.sessions.getContainingCluster(uncompressed);\n\t\tif (match === undefined) {\n\t\t\tconst numericUncompressed = numericUuidFromStableId(uncompressed);\n\t\t\tconst offset = subtractNumericUuids(numericUncompressed, this.localSession.sessionUuid);\n\t\t\tif (offset < Number.MAX_SAFE_INTEGER) {\n\t\t\t\tconst genCountEquivalent = Number(offset) + 1;\n\t\t\t\tconst localEquivalent = localIdFromGenCount(genCountEquivalent);\n\t\t\t\tif (this.normalizer.contains(localEquivalent)) {\n\t\t\t\t\treturn localEquivalent;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t} else {\n\t\t\tconst [containingCluster, alignedLocal] = match;\n\t\t\tif (containingCluster.session === this.localSession) {\n\t\t\t\t// Local session\n\t\t\t\tif (this.normalizer.contains(alignedLocal)) {\n\t\t\t\t\treturn alignedLocal;\n\t\t\t\t} else {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tgenCountFromLocalId(alignedLocal) <= this.localGenCount,\n\t\t\t\t\t\t0x75a /* Clusters out of sync. */,\n\t\t\t\t\t);\n\t\t\t\t\t// Id is an eager final\n\t\t\t\t\treturn getAlignedFinal(containingCluster, alignedLocal) as\n\t\t\t\t\t\t| SessionSpaceCompressedId\n\t\t\t\t\t\t| undefined;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Not the local session\n\t\t\t\treturn genCountFromLocalId(alignedLocal) >= lastFinalizedLocal(containingCluster)\n\t\t\t\t\t? (getAlignedFinal(containingCluster, alignedLocal) as\n\t\t\t\t\t\t\t| SessionSpaceCompressedId\n\t\t\t\t\t\t\t| undefined)\n\t\t\t\t\t: undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(withSession: true): SerializedIdCompressorWithOngoingSession;\n\tpublic serialize(withSession: false): SerializedIdCompressorWithNoSession;\n\tpublic serialize(hasLocalState: boolean): SerializedIdCompressor {\n\t\tconst { normalizer, finalSpace, sessions } = this;\n\t\tconst sessionIndexMap = new Map<Session, number>();\n\t\tlet sessionIndex = 0;\n\t\tfor (const session of sessions.sessions()) {\n\t\t\t// Filter empty sessions to prevent them accumulating in the serialized state\n\t\t\tif (!session.isEmpty() || hasLocalState) {\n\t\t\t\tsessionIndexMap.set(session, sessionIndex);\n\t\t\t\tsessionIndex++;\n\t\t\t}\n\t\t}\n\t\tconst localStateSize = hasLocalState\n\t\t\t? 1 + // generated ID count\n\t\t\t 1 + // next range base genCount\n\t\t\t 1 + // count of normalizer pairs\n\t\t\t this.normalizer.idRanges.size * 2 // pairs\n\t\t\t: 0;\n\t\t// Layout size, in 8 byte increments\n\t\tconst totalSize =\n\t\t\t1 + // version\n\t\t\t1 + // hasLocalState\n\t\t\t1 + // cluster capacity\n\t\t\t1 + // session count\n\t\t\t1 + // cluster count\n\t\t\tsessionIndexMap.size * 2 + // session IDs\n\t\t\tfinalSpace.clusters.length * 3 + // clusters: (sessionIndex, capacity, count)[]\n\t\t\tlocalStateSize; // local state, if present\n\n\t\tconst serializedFloat = new Float64Array(totalSize);\n\t\tconst serializedUint = new BigUint64Array(serializedFloat.buffer);\n\t\tlet index = 0;\n\t\tindex = writeNumber(serializedFloat, index, currentWrittenVersion);\n\t\tindex = writeBoolean(serializedFloat, index, hasLocalState);\n\t\tindex = writeNumber(serializedFloat, index, this.clusterCapacity);\n\t\tindex = writeNumber(serializedFloat, index, sessionIndexMap.size);\n\t\tindex = writeNumber(serializedFloat, index, finalSpace.clusters.length);\n\n\t\tfor (const [session] of sessionIndexMap.entries()) {\n\t\t\tindex = writeNumericUuid(serializedUint, index, session.sessionUuid);\n\t\t}\n\n\t\tfinalSpace.clusters.forEach((cluster) => {\n\t\t\tindex = writeNumber(\n\t\t\t\tserializedFloat,\n\t\t\t\tindex,\n\t\t\t\tsessionIndexMap.get(cluster.session) as number,\n\t\t\t);\n\t\t\tindex = writeNumber(serializedFloat, index, cluster.capacity);\n\t\t\tindex = writeNumber(serializedFloat, index, cluster.count);\n\t\t});\n\n\t\tif (hasLocalState) {\n\t\t\tindex = writeNumber(serializedFloat, index, this.localGenCount);\n\t\t\tindex = writeNumber(serializedFloat, index, this.nextRangeBaseGenCount);\n\t\t\tindex = writeNumber(serializedFloat, index, normalizer.idRanges.size);\n\t\t\tfor (const [leadingGenCount, count] of normalizer.idRanges.entries()) {\n\t\t\t\tindex = writeNumber(serializedFloat, index, leadingGenCount);\n\t\t\t\tindex = writeNumber(serializedFloat, index, count);\n\t\t\t}\n\t\t}\n\n\t\tassert(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);\n\t\tthis.logger?.sendTelemetryEvent({\n\t\t\teventName: \"RuntimeIdCompressor:SerializedIdCompressorSize\",\n\t\t\tsize: serializedFloat.byteLength,\n\t\t\tclusterCount: finalSpace.clusters.length,\n\t\t\tsessionCount: sessionIndexMap.size,\n\t\t});\n\n\t\treturn bufferToString(serializedFloat.buffer, \"base64\") as SerializedIdCompressor;\n\t}\n\n\tpublic static deserialize(serialized: SerializedIdCompressorWithOngoingSession): IdCompressor;\n\tpublic static deserialize(\n\t\tserialized: SerializedIdCompressorWithNoSession,\n\t\tnewSessionId: SessionId,\n\t): IdCompressor;\n\tpublic static deserialize(\n\t\tserialized: SerializedIdCompressor,\n\t\tsessionId?: SessionId,\n\t): IdCompressor {\n\t\tconst buffer = stringToBuffer(serialized, \"base64\");\n\t\tconst index: Index = {\n\t\t\tindex: 0,\n\t\t\tbufferFloat: new Float64Array(buffer),\n\t\t\tbufferUint: new BigUint64Array(buffer),\n\t\t};\n\t\tconst version = readNumber(index);\n\t\tassert(version === currentWrittenVersion, 0x75c /* Unknown serialized version. */);\n\t\tconst hasLocalState = readBoolean(index);\n\t\tconst clusterCapacity = readNumber(index);\n\t\tconst sessionCount = readNumber(index);\n\t\tconst clusterCount = readNumber(index);\n\n\t\t// Sessions\n\t\tlet sessionOffset = 0;\n\t\tconst sessions: [NumericUuid, Session][] = [];\n\t\tif (!hasLocalState) {\n\t\t\t// If !hasLocalState, there won't be a serialized local session ID so insert one at the beginning\n\t\t\tassert(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);\n\t\t\tconst localSessionNumeric = numericUuidFromStableId(sessionId);\n\t\t\tsessions.push([localSessionNumeric, new Session(localSessionNumeric)]);\n\t\t\tsessionOffset = 1;\n\t\t} else {\n\t\t\tassert(\n\t\t\t\tsessionId === undefined,\n\t\t\t\t0x75e /* Local state should not exist in serialized form. */,\n\t\t\t);\n\t\t}\n\n\t\tfor (let i = 0; i < sessionCount; i++) {\n\t\t\tconst numeric = readNumericUuid(index);\n\t\t\tsessions.push([numeric, new Session(numeric)]);\n\t\t}\n\n\t\tconst compressor = new IdCompressor(new Sessions(sessions));\n\t\tcompressor.clusterCapacity = clusterCapacity;\n\n\t\t// Clusters\n\t\tlet baseFinalId = 0;\n\t\tfor (let i = 0; i < clusterCount; i++) {\n\t\t\tconst sessionIndex = readNumber(index);\n\t\t\tconst session = sessions[sessionIndex + sessionOffset][1];\n\t\t\tconst capacity = readNumber(index);\n\t\t\tconst count = readNumber(index);\n\t\t\tconst cluster = session.addNewCluster(\n\t\t\t\tbaseFinalId as FinalCompressedId,\n\t\t\t\tcapacity,\n\t\t\t\tcount,\n\t\t\t);\n\t\t\tcompressor.finalSpace.addCluster(cluster);\n\t\t\tbaseFinalId += capacity;\n\t\t}\n\n\t\t// Local state\n\t\tif (hasLocalState) {\n\t\t\tcompressor.localGenCount = readNumber(index);\n\t\t\tcompressor.nextRangeBaseGenCount = readNumber(index);\n\t\t\tconst normalizerCount = readNumber(index);\n\t\t\tfor (let i = 0; i < normalizerCount; i++) {\n\t\t\t\tcompressor.normalizer.addLocalRange(readNumber(index), readNumber(index));\n\t\t\t}\n\t\t}\n\n\t\tassert(\n\t\t\tindex.index === index.bufferFloat.length,\n\t\t\t0x75f /* Failed to read entire serialized compressor. */,\n\t\t);\n\t\treturn compressor;\n\t}\n\n\tpublic equals(other: IdCompressor, includeLocalState: boolean): boolean {\n\t\tif (\n\t\t\tincludeLocalState &&\n\t\t\t(this.localSessionId !== other.localSessionId ||\n\t\t\t\t!this.localSession.equals(other.localSession) ||\n\t\t\t\t!this.normalizer.equals(other.normalizer) ||\n\t\t\t\tthis.nextRangeBaseGenCount !== other.nextRangeBaseGenCount ||\n\t\t\t\tthis.localGenCount !== other.localGenCount)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (\n\t\t\tthis.newClusterCapacity === other.newClusterCapacity &&\n\t\t\tthis.sessions.equals(other.sessions, includeLocalState) &&\n\t\t\tthis.finalSpace.equals(other.finalSpace)\n\t\t);\n\t}\n}\n"]}
@@ -1,32 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { OpSpaceCompressedId, SessionSpaceCompressedId } from "@fluidframework/runtime-definitions";
6
- /**
7
- * A compressed ID that is stable and unique within the scope of network of compressors (i.e. a document).
8
- * It can only be used/decompressed in the context of the originating document.
9
- */
10
- export type FinalCompressedId = number & {
11
- readonly FinalCompressedId: "5d83d1e2-98b7-4e4e-a889-54c855cfa73d";
12
- readonly OpNormalized: "9209432d-a959-4df7-b2ad-767ead4dbcae";
13
- };
14
- /**
15
- * A compressed ID that is local to a session (can only be decompressed when paired with a SessionId).
16
- * Internally, it should not be persisted outside a scope annotated with the originating SessionId in order to be unambiguous.
17
- * If external persistence is needed (e.g. by a client), a StableId should be used instead.
18
- */
19
- export type LocalCompressedId = number & {
20
- readonly LocalCompressedId: "6fccb42f-e2a4-4243-bd29-f13d12b9c6d1";
21
- } & SessionSpaceCompressedId;
22
- /**
23
- * @returns true if the supplied ID is a final ID.
24
- */
25
- export declare function isFinalId(id: SessionSpaceCompressedId | OpSpaceCompressedId): id is FinalCompressedId;
26
- /**
27
- * A StableId which is suitable for use as a session identifier
28
- */
29
- export type NumericUuid = bigint & {
30
- readonly NumericUuid: "be04dd4d-9d7e-4337-a833-eec64c61aa46";
31
- };
32
- //# sourceMappingURL=identifiers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"identifiers.d.ts","sourceRoot":"","sources":["../../src/id-compressor/identifiers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAEpG;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG;IACxC,QAAQ,CAAC,iBAAiB,EAAE,sCAAsC,CAAC;IAGnE,QAAQ,CAAC,YAAY,EAAE,sCAAsC,CAAC;CAC9D,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG;IACxC,QAAQ,CAAC,iBAAiB,EAAE,sCAAsC,CAAC;CACnE,GAAG,wBAAwB,CAAC;AAE7B;;GAEG;AACH,wBAAgB,SAAS,CACxB,EAAE,EAAE,wBAAwB,GAAG,mBAAmB,GAChD,EAAE,IAAI,iBAAiB,CAEzB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG;IAClC,QAAQ,CAAC,WAAW,EAAE,sCAAsC,CAAC;CAC7D,CAAC"}
@@ -1,11 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- /**
6
- * @returns true if the supplied ID is a final ID.
7
- */
8
- export function isFinalId(id) {
9
- return id >= 0;
10
- }
11
- //# sourceMappingURL=identifiers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"identifiers.js","sourceRoot":"","sources":["../../src/id-compressor/identifiers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwBH;;GAEG;AACH,MAAM,UAAU,SAAS,CACxB,EAAkD;IAElD,OAAO,EAAE,IAAI,CAAC,CAAC;AAChB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { OpSpaceCompressedId, SessionSpaceCompressedId } from \"@fluidframework/runtime-definitions\";\n\n/**\n * A compressed ID that is stable and unique within the scope of network of compressors (i.e. a document).\n * It can only be used/decompressed in the context of the originating document.\n */\nexport type FinalCompressedId = number & {\n\treadonly FinalCompressedId: \"5d83d1e2-98b7-4e4e-a889-54c855cfa73d\";\n\n\t// Same brand as OpNormalizedCompressedId, as final IDs are always finally normalized\n\treadonly OpNormalized: \"9209432d-a959-4df7-b2ad-767ead4dbcae\";\n};\n\n/**\n * A compressed ID that is local to a session (can only be decompressed when paired with a SessionId).\n * Internally, it should not be persisted outside a scope annotated with the originating SessionId in order to be unambiguous.\n * If external persistence is needed (e.g. by a client), a StableId should be used instead.\n */\nexport type LocalCompressedId = number & {\n\treadonly LocalCompressedId: \"6fccb42f-e2a4-4243-bd29-f13d12b9c6d1\";\n} & SessionSpaceCompressedId; // Same brand as CompressedId, as local IDs are always locally normalized\n\n/**\n * @returns true if the supplied ID is a final ID.\n */\nexport function isFinalId(\n\tid: SessionSpaceCompressedId | OpSpaceCompressedId,\n): id is FinalCompressedId {\n\treturn id >= 0;\n}\n\n/**\n * A StableId which is suitable for use as a session identifier\n */\nexport type NumericUuid = bigint & {\n\treadonly NumericUuid: \"be04dd4d-9d7e-4337-a833-eec64c61aa46\";\n};\n"]}
@@ -1,13 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- /**
6
- * Exports for `id-compressor`
7
- */
8
- export { IdCompressor } from "./idCompressor";
9
- export { compareFiniteNumbers, createSessionId, assertIsSessionId, numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, subtractNumericUuids, addNumericUuids, assertIsStableId, generateStableId, isStableId, } from "./utilities";
10
- export { readNumericUuid, writeNumericUuid } from "./persistanceUtilities";
11
- export { AppendOnlySortedMap } from "./appendOnlySortedMap";
12
- export { SessionSpaceNormalizer } from "./sessionSpaceNormalizer";
13
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/id-compressor/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,GACV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}