@fluidframework/container-runtime 2.0.0-internal.5.4.0 → 2.0.0-internal.6.1.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.
- package/CHANGELOG.md +75 -0
- package/dist/batchTracker.d.ts +2 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +4 -1
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +61 -26
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.js +10 -2
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +26 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +189 -131
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +8 -2
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +24 -26
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +20 -4
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +107 -53
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.d.ts +35 -0
- package/dist/deltaManagerProxyBase.d.ts.map +1 -0
- package/dist/deltaManagerProxyBase.js +77 -0
- package/dist/deltaManagerProxyBase.js.map +1 -0
- package/dist/deltaManagerSummarizerProxy.d.ts +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +2 -2
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/gc/garbageCollection.js +17 -20
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.js +13 -11
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcHelpers.js +4 -6
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +4 -6
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +55 -37
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/id-compressor/idCompressor.js +49 -51
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/idRange.js +2 -2
- package/dist/id-compressor/idRange.js.map +1 -1
- package/dist/id-compressor/sessionIdNormalizer.js +11 -16
- package/dist/id-compressor/sessionIdNormalizer.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.js +10 -6
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/opCompressor.js +6 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +11 -9
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +13 -5
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.js +10 -6
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.js +1 -2
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.js +1 -2
- package/dist/opProperties.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +2 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +22 -22
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.js +14 -10
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +17 -18
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +35 -57
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.js +4 -7
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.js +5 -9
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +8 -12
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +22 -15
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +2 -4
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +17 -16
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summaryCollection.js +3 -5
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.js +1 -2
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +62 -21
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.js +3 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +2 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +4 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +61 -26
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.js +10 -2
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +26 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +189 -131
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +8 -2
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +24 -26
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +20 -4
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +107 -53
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.d.ts +35 -0
- package/lib/deltaManagerProxyBase.d.ts.map +1 -0
- package/lib/deltaManagerProxyBase.js +73 -0
- package/lib/deltaManagerProxyBase.js.map +1 -0
- package/lib/deltaManagerSummarizerProxy.d.ts +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js +1 -1
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/gc/garbageCollection.js +17 -20
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.js +13 -11
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcHelpers.js +4 -6
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +4 -6
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +55 -37
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/id-compressor/idCompressor.js +49 -51
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/idRange.js +2 -2
- package/lib/id-compressor/idRange.js.map +1 -1
- package/lib/id-compressor/sessionIdNormalizer.js +11 -16
- package/lib/id-compressor/sessionIdNormalizer.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.js +10 -6
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/opCompressor.js +6 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +11 -9
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +13 -5
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.js +10 -6
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.js +1 -2
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.js +1 -2
- package/lib/opProperties.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +2 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +22 -22
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.js +14 -10
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +17 -18
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +35 -57
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.js +4 -7
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.js +5 -9
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +8 -12
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +22 -15
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +2 -4
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +17 -16
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summaryCollection.js +3 -5
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.js +1 -2
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +62 -21
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.js +3 -5
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +19 -19
- package/src/batchTracker.ts +2 -1
- package/src/blobManager.ts +43 -2
- package/src/containerRuntime.ts +95 -67
- package/src/dataStore.ts +7 -1
- package/src/dataStoreContext.ts +1 -2
- package/src/dataStores.ts +95 -55
- package/src/deltaManagerProxyBase.ts +111 -0
- package/src/deltaManagerSummarizerProxy.ts +2 -1
- package/src/gc/gcTelemetry.ts +1 -2
- package/src/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +12 -15
- package/src/summary/orderedClientElection.ts +2 -1
- package/src/summary/runningSummarizer.ts +9 -31
- package/src/summary/summaryGenerator.ts +0 -1
|
@@ -84,8 +84,8 @@ export class SessionIdNormalizer {
|
|
|
84
84
|
* Converts the local ID to its corresponding final ID, if one exists.
|
|
85
85
|
*/
|
|
86
86
|
getFinalId(localId) {
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
const localRange = this.idRanges.getPairOrNextLower(localId) ??
|
|
88
|
+
fail("Local ID was never recorded with this normalizer.");
|
|
89
89
|
const [firstLocal, [lastLocal, finalRanges]] = localRange;
|
|
90
90
|
if (localId < lastLocal) {
|
|
91
91
|
fail("Local ID was never recorded with this normalizer.");
|
|
@@ -125,7 +125,6 @@ export class SessionIdNormalizer {
|
|
|
125
125
|
* Returns the session-space ID at the supplied creation index, if one exists.
|
|
126
126
|
*/
|
|
127
127
|
getIdByCreationIndex(index) {
|
|
128
|
-
var _a;
|
|
129
128
|
const localByIndex = -(index + 1);
|
|
130
129
|
const localRange = this.idRanges.getPairOrNextLower(localByIndex);
|
|
131
130
|
if (localRange === undefined) {
|
|
@@ -135,7 +134,8 @@ export class SessionIdNormalizer {
|
|
|
135
134
|
if (localByIndex >= lastLocal) {
|
|
136
135
|
return localByIndex;
|
|
137
136
|
}
|
|
138
|
-
const finalRange =
|
|
137
|
+
const finalRange = getPairOrNextLower(firstLocal, finalRanges, localByIndex) ??
|
|
138
|
+
fail("Final ranges not aligned with owning local range.");
|
|
139
139
|
const [alignedLocal, [firstFinal, lastFinal]] = finalRange;
|
|
140
140
|
const localDelta = alignedLocal - localByIndex;
|
|
141
141
|
const finalId = firstFinal + localDelta;
|
|
@@ -223,9 +223,8 @@ export class SessionIdNormalizer {
|
|
|
223
223
|
* ^final ID 9 is not contiguous and does not have a corresponding local ID
|
|
224
224
|
*/
|
|
225
225
|
addFinalIds(firstFinal, lastFinal, rangeObject) {
|
|
226
|
-
var _a;
|
|
227
226
|
assert(lastFinal >= firstFinal, 0x5ae /* Malformed normalization range. */);
|
|
228
|
-
const [firstLocal, finalRangesObj] =
|
|
227
|
+
const [firstLocal, finalRangesObj] = this.idRanges.last() ?? fail("Final IDs must be added to an existing local range.");
|
|
229
228
|
const [lastLocal, finalRanges] = finalRangesObj;
|
|
230
229
|
let nextLocal;
|
|
231
230
|
if (finalRanges === undefined) {
|
|
@@ -284,9 +283,9 @@ export class SessionIdNormalizer {
|
|
|
284
283
|
*
|
|
285
284
|
*/
|
|
286
285
|
registerFinalIdBlock(firstFinalInBlock, count, rangeObject) {
|
|
287
|
-
var _a;
|
|
288
286
|
assert(count >= 1, 0x5af /* Malformed normalization block. */);
|
|
289
|
-
const [firstLocal, [lastLocal, finalRanges]] =
|
|
287
|
+
const [firstLocal, [lastLocal, finalRanges]] = this.idRanges.last() ??
|
|
288
|
+
fail("Final ID block should not be registered before any locals.");
|
|
290
289
|
let unalignedLocalCount;
|
|
291
290
|
if (finalRanges === undefined) {
|
|
292
291
|
unalignedLocalCount = firstLocal - lastLocal + 1;
|
|
@@ -302,7 +301,6 @@ export class SessionIdNormalizer {
|
|
|
302
301
|
this.addFinalIds(firstFinalInBlock, lastFinal, rangeObject);
|
|
303
302
|
}
|
|
304
303
|
getAlignmentOfLastRange(firstLocal, finalRanges) {
|
|
305
|
-
var _a;
|
|
306
304
|
const isSingle = isSingleRange(finalRanges);
|
|
307
305
|
let lastFinalRange;
|
|
308
306
|
let firstAlignedLocal;
|
|
@@ -312,7 +310,7 @@ export class SessionIdNormalizer {
|
|
|
312
310
|
}
|
|
313
311
|
else {
|
|
314
312
|
[firstAlignedLocal, lastFinalRange] =
|
|
315
|
-
|
|
313
|
+
finalRanges.last() ?? fail("Map should be non-empty.");
|
|
316
314
|
}
|
|
317
315
|
const [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;
|
|
318
316
|
const lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);
|
|
@@ -327,7 +325,6 @@ export class SessionIdNormalizer {
|
|
|
327
325
|
* Returns an enumerable of all session-space IDs known to this normalizer, in creation order.
|
|
328
326
|
*/
|
|
329
327
|
*[Symbol.iterator]() {
|
|
330
|
-
var _a;
|
|
331
328
|
for (const [firstLocal, [lastLocal, finalRanges]] of this.idRanges.entries()) {
|
|
332
329
|
for (let i = firstLocal; i >= lastLocal; i--) {
|
|
333
330
|
yield i;
|
|
@@ -342,7 +339,7 @@ export class SessionIdNormalizer {
|
|
|
342
339
|
}
|
|
343
340
|
else {
|
|
344
341
|
[alignedLocal, lastFinalRange] =
|
|
345
|
-
|
|
342
|
+
finalRanges.last() ?? fail("Map should be non-empty.");
|
|
346
343
|
}
|
|
347
344
|
const [firstFinal, lastFinal] = lastFinalRange;
|
|
348
345
|
const localRangeDelta = alignedLocal - lastLocal;
|
|
@@ -429,18 +426,16 @@ function isSingleRange(ranges) {
|
|
|
429
426
|
return Array.isArray(ranges);
|
|
430
427
|
}
|
|
431
428
|
function getLastRange(finalRanges) {
|
|
432
|
-
var _a;
|
|
433
429
|
if (isSingleRange(finalRanges)) {
|
|
434
430
|
return finalRanges;
|
|
435
431
|
}
|
|
436
|
-
return (
|
|
432
|
+
return (finalRanges.last() ?? fail("Map must be non-empty"))[1];
|
|
437
433
|
}
|
|
438
434
|
function getFirstRange(finalRanges) {
|
|
439
|
-
var _a;
|
|
440
435
|
if (isSingleRange(finalRanges)) {
|
|
441
436
|
return finalRanges;
|
|
442
437
|
}
|
|
443
|
-
return (
|
|
438
|
+
return (finalRanges.first() ?? fail("Map must be non-empty"))[1];
|
|
444
439
|
}
|
|
445
440
|
function extractFirstFinalFromRange(finalRange) {
|
|
446
441
|
return finalRange[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionIdNormalizer.js","sourceRoot":"","sources":["../../src/id-compressor/sessionIdNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8DAA8D;AAE9D,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAOtD,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,IAAI,EAAW,MAAM,SAAS,CAAC;AAC5F,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,OAAO,mBAAmB;IAkB/B,YAAoC,mBAAmB,KAAK;QAAxB,qBAAgB,GAAhB,gBAAgB,CAAQ;QAjBpD,gBAAW,GAAsB,CAAC,CAAsB,CAAC;QAChD,aAAQ,GAIrB,IAAI,yBAAyB,CAChC,4BAA4B,EAC5B,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,EAAE;YACpB,IAAI,WAAW,KAAK,SAAS,EAAE;gBAC9B,MAAM,KAAK,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;gBACzC,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC;aACzC;YACD,OAAO,MAAM,CAAC,iBAAsC,CAAC;QACtD,CAAC,EACD,oBAAoB,CACpB,CAAC;IAE6D,CAAC;IAEhE;;;OAGG;IACI,iBAAiB,CAAC,OAA0B;QAClD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;QACpE,IAAI,UAAU,KAAK,SAAS,EAAE;YAC7B,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,UAAU,CAAC;YAC1D,MAAM,UAAU,GAAG,yBAAyB,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;YAC/E,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC7B,MAAM,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,GAAG,UAAU,CAAC;gBAC3D,IAAI,OAAO,IAAI,SAAS,EAAE;oBACzB,MAAM,eAAe,GAAG,YAAY,GAAG,SAAS,CAAC;oBACjD,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;oBACxC,IAAI,UAAU,IAAI,eAAe,EAAE;wBAClC,OAAO,CAAC,YAAY,GAAG,UAAU,CAAsB,CAAC;qBACxD;oBACD,8CAA8C;oBAC9C,OAAO,OAAmC,CAAC;iBAC3C;aACD;SACD;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,UAAU,CAAC,OAA0B;;QAC3C,MAAM,UAAU,GACf,MAAA,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,OAAO,CAAC,mCACzC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAC3D,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,UAAU,CAAC;QAC1D,IAAI,OAAO,GAAG,SAAS,EAAE;YACxB,IAAI,CAAC,mDAAmD,CAAC,CAAC;SAC1D;QACD,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QACxE,IAAI,UAAU,KAAK,SAAS,EAAE;YAC7B,MAAM,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,UAAU,CAAC;YACxE,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;YAC1C,MAAM,UAAU,GAAG,YAAY,GAAG,OAAO,CAAC;YAC1C,IAAI,UAAU,IAAI,UAAU,EAAE;gBAC7B,iEAAiE;gBACjE,OAAO,CAAC,CAAC,UAAU,GAAG,UAAU,CAAsB,EAAE,WAAW,CAAC,CAAC;aACrE;SACD;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;OAGG;IACI,gBAAgB,CAAC,OAA0B;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;QACpE,IAAI,UAAU,KAAK,SAAS,EAAE;YAC7B,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,UAAU,CAAC;YAClD,MAAM,UAAU,GAAG,yBAAyB,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;YAC/E,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC7B,MAAM,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,GAAG,UAAU,CAAC;gBAC3D,IAAI,OAAO,IAAI,SAAS,EAAE;oBACzB,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;oBACxC,OAAO,CAAC,YAAY,GAAG,CAAC,GAAG,UAAU,CAAC;iBACtC;aACD;SACD;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,oBAAoB,CAAC,KAAa;;QACxC,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAsB,CAAC;QACvD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAClE,IAAI,UAAU,KAAK,SAAS,EAAE;YAC7B,OAAO,SAAS,CAAC;SACjB;QACD,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,UAAU,CAAC;QAC1D,IAAI,YAAY,IAAI,SAAS,EAAE;YAC9B,OAAO,YAAY,CAAC;SACpB;QACD,MAAM,UAAU,GACf,MAAA,kBAAkB,CAAC,UAAU,EAAE,WAAW,EAAE,YAAY,CAAC,mCACzD,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAE3D,MAAM,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,GAAG,UAAU,CAAC;QAC3D,MAAM,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC;QAC/C,MAAM,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;QACxC,IAAI,OAAO,IAAI,SAAS,EAAE;YACzB,8CAA8C;YAC9C,OAAO,OAAmC,CAAC;SAC3C;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAEO,MAAM,CAAC,kBAAkB;QAChC,OAAO,IAAI,yBAAyB,CACnC,4BAA4B,EAC5B,0BAA0B,EAC1B,oBAAoB,CACpB,CAAC;IACH,CAAC;IAED;;OAEG;IACI,cAAc;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;QACzC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;QAChD,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,YAAY,EAAE,CAAC,EAAE,EAAE;YAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/C,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC7B,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrC,IAAI,WAAW,KAAK,SAAS,EAAE;oBAC9B,OAAO,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;iBACpC;aACD;SACD;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;;;OAMG;IACI,UAAU;QAChB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAuB,CAAC;QACxD,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,cAAc,KAAK,SAAS,EAAE;YACjC,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,OAAO,KAAK,SAAS,GAAG,CAAC,EAAE;gBAC9B,wDAAwD;gBACxD,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;gBAC/B,OAAO,OAAO,CAAC;aACf;SACD;QAED,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAC1B,IAAI,cAAc,KAAK,SAAS,EAAE;gBACjC,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,sCAAsC,CAAC,CAAC;aACrE;iBAAM;gBACN,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,cAAc,CAAC;gBACtD,IAAI,UAAU,GAAG,CAAC,CAAC;gBACnB,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,IAAI,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE;oBAC7E,UAAU,IAAI,SAAS,GAAG,UAAU,GAAG,CAAC,CAAC;iBACzC;gBACD,MAAM,CACL,OAAO,KAAK,UAAU,GAAG,UAAU,EACnC,KAAK,CAAC,wCAAwC,CAC9C,CAAC;aACF;SACD;QAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACI,WAAW,CACjB,UAA6B,EAC7B,SAA4B,EAC5B,WAAyB;;QAEzB,MAAM,CAAC,SAAS,IAAI,UAAU,EAAE,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC5E,MAAM,CAAC,UAAU,EAAE,cAAc,CAAC,GACjC,MAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,mCAAI,IAAI,CAAC,qDAAqD,CAAC,CAAC;QACrF,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,GAAG,cAAc,CAAC;QAChD,IAAI,SAA4B,CAAC;QACjC,IAAI,WAAW,KAAK,SAAS,EAAE;YAC9B,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;YACzD,SAAS,GAAG,IAAI,CAAC,GAAG,CACnB,IAAI,CAAC,WAAW,EAChB,UAAU,GAAG,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CACpB,CAAC;SACvB;aAAM;YACN,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,CAAC,GAC5E,IAAI,CAAC,uBAAuB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YACvD,SAAS,GAAG,IAAI,CAAC,GAAG,CACnB,IAAI,CAAC,WAAW,EAChB,gBAAgB,GAAG,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAC1B,CAAC;YACvB,IAAI,UAAU,KAAK,gBAAgB,GAAG,CAAC,EAAE;gBACxC,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;aAC9B;iBAAM;gBACN,MAAM,YAAY,GAAG,CAAC,gBAAgB,GAAG,CAAC,CAAsB,CAAC;gBACjE,IAAI,QAAsC,CAAC;gBAC3C,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE;oBAC/B,iDAAiD;oBACjD,QAAQ,GAAG,mBAAmB,CAAC,kBAAkB,EAAE,CAAC;oBACpD,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;oBACnD,cAAc,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;iBAC7B;qBAAM;oBACN,QAAQ,GAAG,WAAW,CAAC;iBACvB;gBACD,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;gBACpE,MAAM,CACL,YAAY,IAAI,SAAS,EACzB,KAAK,CAAC,gDAAgD,CACtD,CAAC;aACF;YACD,IAAI,IAAI,CAAC,gBAAgB,EAAE;gBAC1B,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;aAC5B;SACD;QAED,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACI,oBAAoB,CAC1B,iBAAoC,EACpC,KAAa,EACb,WAAyB;;QAEzB,MAAM,CAAC,KAAK,IAAI,CAAC,EAAE,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC/D,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,GAC3C,MAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,mCACpB,IAAI,CAAC,4DAA4D,CAAC,CAAC;QACpE,IAAI,mBAA2B,CAAC;QAChC,IAAI,WAAW,KAAK,SAAS,EAAE;YAC9B,mBAAmB,GAAG,UAAU,GAAG,SAAS,GAAG,CAAC,CAAC;SACjD;aAAM;YACN,MAAM,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,IAAI,CAAC,uBAAuB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YACpF,mBAAmB,GAAG,gBAAgB,GAAG,SAAS,CAAC;SACnD;QACD,MAAM,CACL,mBAAmB,GAAG,CAAC,EACvB,KAAK,CAAC,8EAA8E,CACpF,CAAC;QACF,MAAM,SAAS,GAAG,CAAC,iBAAiB;YACnC,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC;YACpC,CAAC,CAAsB,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAC7D,CAAC;IAEO,uBAAuB,CAC9B,UAA6B,EAC7B,WAAsC;;QAOtC,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,cAAwC,CAAC;QAC7C,IAAI,iBAAoC,CAAC;QACzC,IAAI,QAAQ,EAAE;YACb,iBAAiB,GAAG,UAAU,CAAC;YAC/B,cAAc,GAAG,WAAW,CAAC;SAC7B;aAAM;YACN,CAAC,iBAAiB,EAAE,cAAc,CAAC;gBAClC,MAAA,WAAW,CAAC,IAAI,EAAE,mCAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;SACxD;QAED,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,GAAG,cAAc,CAAC;QAC7D,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,CAAC;QACpF,OAAO;YACN,iBAAiB;YACjB,gBAAqC;YACrC,gBAAgB;YAChB,cAAc;SACd,CAAC;IACH,CAAC;IAED;;OAEG;IACI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;;QACxB,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;YAC7E,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,EAAE,EAAE;gBAC7C,MAAM,CAAC,CAAC;aACR;YACD,IAAI,WAAW,KAAK,SAAS,EAAE;gBAC9B,+GAA+G;gBAC/G,IAAI,cAAwC,CAAC;gBAC7C,IAAI,YAA+B,CAAC;gBACpC,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE;oBAC/B,YAAY,GAAG,UAAU,CAAC;oBAC1B,cAAc,GAAG,WAAW,CAAC;iBAC7B;qBAAM;oBACN,CAAC,YAAY,EAAE,cAAc,CAAC;wBAC7B,MAAA,WAAW,CAAC,IAAI,EAAE,mCAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;iBACxD;gBACD,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,GAAG,cAAc,CAAC;gBAC/C,MAAM,eAAe,GAAG,YAAY,GAAG,SAAS,CAAC;gBACjD,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,eAAe,GAAG,CAAC,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,EAAE,EAAE;oBACnE,MAAM,CAA6B,CAAC;iBACpC;aACD;SACD;IACF,CAAC;IAEM,SAAS;QACf,MAAM,UAAU,GAA2C;YAC1D,WAAW,EAAE,EAAE;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;SAC7B,CAAC;QACF,MAAM,WAAW,GAAG,UAAU,CAAC,WAAqD,CAAC;QACrF,KAAK,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;YAChE,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC,GAAG,WAAW,CAAC;YAClD,IAAI,gBAAgB,KAAK,SAAS,EAAE;gBACnC,MAAM,qBAAqB,GAIrB,EAAE,CAAC;gBACT,KAAK,MAAM,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,IAAI,OAAO,CAC5D,UAAU,EACV,gBAAgB,CAChB,EAAE;oBACF,qBAAqB,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;iBAClE;gBACD,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC,CAAC;aACjE;iBAAM;gBACN,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;aAC1C;SACD;QACD,OAAO,UAAU,CAAC;IACnB,CAAC;IAEM,MAAM,CAAC,WAAW,CACxB,UAAyC,EACzC,cAA4D;QAE5D,MAAM,UAAU,GAAG,IAAI,mBAAmB,EAAgB,CAAC;QAC3D,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC;QAChC,KAAK,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,qBAAqB,CAAC,IAAI,UAAU,CAAC,WAAW,EAAE;YACpF,IAAI,WAAkD,CAAC;YACvD,IAAI,qBAAqB,KAAK,SAAS,EAAE;gBACxC,MAAM,CACL,qBAAqB,CAAC,MAAM,KAAK,CAAC,EAClC,KAAK,CAAC,wCAAwC,CAC9C,CAAC;gBACF,IAAI,qBAAqB,CAAC,MAAM,KAAK,CAAC,EAAE;oBACvC,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;oBAC5D,WAAW,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;iBAClE;qBAAM;oBACN,WAAW,GAAG,mBAAmB,CAAC,kBAAkB,EAAgB,CAAC;oBACrE,KAAK,MAAM,CAAC,YAAY,EAAE,UAAU,EAAE,SAAS,CAAC,IAAI,qBAAqB,EAAE;wBAC1E,WAAW,CAAC,MAAM,CAAC,YAAY,EAAE;4BAChC,UAAU;4BACV,SAAS;4BACT,cAAc,CAAC,UAAU,CAAC;yBAC1B,CAAC,CAAC;qBACH;iBACD;aACD;YACD,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;SACtD;QACD,UAAU,CAAC,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;QAChD,OAAO,UAAU,CAAC;IACnB,CAAC;IAEM,MAAM,CACZ,KAAwC,EACxC,sBAAqE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC;QAEtF,OAAO,CACN,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW;YACtC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE;gBACjE,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,WAAW,CAAC;gBAC/C,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,WAAW,CAAC;gBAC/C,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE;oBAC7D,OAAO,YAAY,KAAK,YAAY,CAAC;iBACrC;gBAED,MAAM,WAAW,GAAG,CACnB,WAAqC,EACrC,WAAqC,EACpC,EAAE;oBACH,MAAM,CAAC,WAAW,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,WAAW,CAAC;oBAC5D,MAAM,CAAC,WAAW,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,WAAW,CAAC;oBAC5D,OAAO,CACN,WAAW,KAAK,WAAW;wBAC3B,UAAU,KAAK,UAAU;wBACzB,mBAAmB,CAAC,YAAY,EAAE,YAAY,CAAC,CAC/C,CAAC;gBACH,CAAC,CAAC;gBAEF,IAAI,aAAa,CAAC,YAAY,CAAC,IAAI,aAAa,CAAC,YAAY,CAAC,EAAE;oBAC/D,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE;wBACjE,OAAO,KAAK,CAAC;qBACb;oBACD,OAAO,WAAW,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;iBAC/C;gBAED,OAAO,UAAU,KAAK,UAAU,IAAI,YAAY,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;YACpF,CAAC,CAAC,CACF,CAAC;IACH,CAAC;CACD;AAgBD,SAAS,aAAa,CACrB,MAAiC;IAEjC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,YAAY,CACpB,WAAsC;;IAEtC,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE;QAC/B,OAAO,WAAW,CAAC;KACnB;IACD,OAAO,CAAC,MAAA,WAAW,CAAC,IAAI,EAAE,mCAAI,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,aAAa,CACrB,WAAsC;;IAEtC,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE;QAC/B,OAAO,WAAW,CAAC;KACnB;IACD,OAAO,CAAC,MAAA,WAAW,CAAC,KAAK,EAAE,mCAAI,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,0BAA0B,CAClC,UAAoC;IAEpC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,yBAAyB,CACjC,UAA6B,EAC7B,WAAkD,EAClD,OAA0B;IAE1B,IAAI,WAAW,KAAK,SAAS,EAAE;QAC9B,OAAO,SAAS,CAAC;KACjB;IACD,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE;QAC/B,IAAI,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE;YAC7B,OAAO,SAAS,CAAC;SACjB;QACD,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;KACjC;IACD,OAAO,WAAW,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,kBAAkB,CAC1B,UAA6B,EAC7B,WAAkD,EAClD,OAA0B;IAE1B,IAAI,WAAW,KAAK,SAAS,EAAE;QAC9B,OAAO,SAAS,CAAC;KACjB;IACD,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE;QAC/B,IAAI,OAAO,GAAG,UAAU,EAAE;YACzB,OAAO,SAAS,CAAC;SACjB;QACD,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;KACjC;IACD,OAAO,WAAW,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,QAAQ,CAAC,CAAC,OAAO,CAChB,UAA6B,EAC7B,WAAkD;IAElD,IAAI,WAAW,KAAK,SAAS,EAAE;QAC9B,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE;YAC/B,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;SAChC;aAAM;YACN,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE;gBAC1C,MAAM,KAAK,CAAC;aACZ;SACD;KACD;AACF,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/restrict-plus-operands */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tSessionSpaceCompressedId,\n\tSerializedSessionIdNormalizer,\n} from \"@fluidframework/runtime-definitions\";\nimport { compareFiniteNumbers, compareFiniteNumbersReversed, fail, Mutable } from \"./utils\";\nimport { AppendOnlyDoublySortedMap } from \"./appendOnlySortedMap\";\n\n/**\n * Maps IDs created by a session between their local and final forms (i.e. normalization). These IDs are in a contiguous range.\n * The local and final forms of IDs made by a session can be thought of as two equal-length sparse arrays, aligned such\n * that normalizeLocalToFinal(locals[i]) === finals[i] and vice versa.\n * Below is an example to illustrate how various mappings can arise:\n *\n * ```\n * +- Creation Index\n * / +- Locals\n * / / +- Finals\n * / / /\n * ---+-----+----\n * 0 | -1 | 0 -|___ Two IDs are allocated as locals since no cluster exists. A new cluster is created when acked.\n * 1 | -2 | 1 -|\n * 2 | | 2 -|\n * 3 | | 3 --|-- Three more IDs are allocated as finals eagerly since a cluster exists with available capacity.\n * 4 | | 4 -|\n * 5 | -6 | 10 ----- One ID is allocated as a local (it overflows the existing cluster) and a new cluster is created after ack.\n * 6 | | 11 ----- One ID is allocated as a final eagerly into the existing cluster.\n * 7 | -8 | 12 ----- A local ID with an override is allocated. The override forces it to be a local ID.\n * 8 | | 13\n * 9 | | 14\n * 10 | -11 | ----- A local ID is allocated. It has no corresponding final ID since it has not been acked.\n * ```\n *\n * Note that in this example, some IDs (those at indices 2, 3, 4, 6, 8, and 9) have no local form. The ID at index 10 has no final form.\n * These kinds of \"gaps\" occur due to the timing of allocation calls on the client and how they relate to finalization/cluster creation,\n * which depends on receiving an ack/sequence number from the server. Given this context, \"session space\" can be thought of as:\n *\n * ```\n * for each index in the range of IDs created by a session:\n * \tthe local form if it exists, otherwise the final form\n * ```\n *\n * This class is designed to efficiently build and query these mappings by leveraging the facts that much of the range (in both local and\n * final space) is uninterrupted by \"gaps\" and can be compactly represented by a (first, last) pair and is easily binary searched for\n * normalization between local and final space.\n */\nexport class SessionIdNormalizer<TRangeObject> {\n\tprivate nextLocalId: LocalCompressedId = -1 as LocalCompressedId;\n\tprivate readonly idRanges: AppendOnlyDoublySortedMap<\n\t\tLocalCompressedId,\n\t\t[lastLocal: LocalCompressedId, finalRanges: FinalRanges<TRangeObject> | undefined],\n\t\tFinalCompressedId\n\t> = new AppendOnlyDoublySortedMap(\n\t\tcompareFiniteNumbersReversed,\n\t\t([_, finalRanges]) => {\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\tconst first = getFirstRange(finalRanges);\n\t\t\t\treturn extractFirstFinalFromRange(first);\n\t\t\t}\n\t\t\treturn Number.POSITIVE_INFINITY as FinalCompressedId;\n\t\t},\n\t\tcompareFiniteNumbers,\n\t);\n\n\tpublic constructor(private readonly expensiveAsserts = false) {}\n\n\t/**\n\t * Converts the final ID to its session-space representation.\n\t * This will be the corresponding local if a local form exists, and `finalId` otherwise.\n\t */\n\tpublic getSessionSpaceId(finalId: FinalCompressedId): SessionSpaceCompressedId | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\tif (finalDelta <= localRangeDelta) {\n\t\t\t\t\t\treturn (alignedLocal - finalDelta) as LocalCompressedId;\n\t\t\t\t\t}\n\t\t\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Converts the local ID to its corresponding final ID, if one exists.\n\t */\n\tpublic getFinalId(localId: LocalCompressedId): [FinalCompressedId, TRangeObject] | undefined {\n\t\tconst localRange =\n\t\t\tthis.idRanges.getPairOrNextLower(localId) ??\n\t\t\tfail(\"Local ID was never recorded with this normalizer.\");\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localId < lastLocal) {\n\t\t\tfail(\"Local ID was never recorded with this normalizer.\");\n\t\t}\n\t\tconst finalRange = getPairOrNextLower(firstLocal, finalRanges, localId);\n\t\tif (finalRange !== undefined) {\n\t\t\tconst [alignedLocal, [firstFinal, lastFinal, rangeObject]] = finalRange;\n\t\t\tconst rangeDelta = lastFinal - firstFinal;\n\t\t\tconst localDelta = alignedLocal - localId;\n\t\t\tif (localDelta <= rangeDelta) {\n\t\t\t\t// Local is within a range segment that has a corresponding final\n\t\t\t\treturn [(firstFinal + localDelta) as FinalCompressedId, rangeObject];\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the index of the local ID corresponding to the supplied final ID in the total range of IDs created by the session,\n\t * if the ID was created by the session for this `SessionIdNormalizer`.\n\t */\n\tpublic getCreationIndex(finalId: FinalCompressedId): number | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [_, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\treturn -alignedLocal - 1 + finalDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the session-space ID at the supplied creation index, if one exists.\n\t */\n\tpublic getIdByCreationIndex(index: number): SessionSpaceCompressedId | undefined {\n\t\tconst localByIndex = -(index + 1) as LocalCompressedId;\n\t\tconst localRange = this.idRanges.getPairOrNextLower(localByIndex);\n\t\tif (localRange === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localByIndex >= lastLocal) {\n\t\t\treturn localByIndex;\n\t\t}\n\t\tconst finalRange =\n\t\t\tgetPairOrNextLower(firstLocal, finalRanges, localByIndex) ??\n\t\t\tfail(\"Final ranges not aligned with owning local range.\");\n\n\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\tconst localDelta = alignedLocal - localByIndex;\n\t\tconst finalId = firstFinal + localDelta;\n\t\tif (finalId <= lastFinal) {\n\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate static makeFinalRangesMap<TRangeObject>(): FinalRangesMap<TRangeObject> {\n\t\treturn new AppendOnlyDoublySortedMap(\n\t\t\tcompareFiniteNumbersReversed,\n\t\t\textractFirstFinalFromRange,\n\t\t\tcompareFiniteNumbers,\n\t\t);\n\t}\n\n\t/**\n\t * Returns the last final ID known to this normalizer.\n\t */\n\tpublic getLastFinalId(): FinalCompressedId | undefined {\n\t\tconst lastIndex = this.idRanges.size - 1;\n\t\tconst secondToLast = Math.max(0, lastIndex - 1);\n\t\tfor (let i = lastIndex; i >= secondToLast; i--) {\n\t\t\tconst localRange = this.idRanges.getAtIndex(i);\n\t\t\tif (localRange !== undefined) {\n\t\t\t\tconst finalRanges = localRange[1][1];\n\t\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t\treturn getLastRange(finalRanges)[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Registers and returns the next ID in local space with this normalizer. An example:\n\t *\n\t * Locals: [-1, -2, X, X]\n\t * Finals: [ 0, 1, 2, 3]\n\t * In this scenario, a call to this method would generate and return -5.\n\t */\n\tpublic addLocalId(): LocalCompressedId {\n\t\tconst localId = this.nextLocalId-- as LocalCompressedId;\n\t\tconst lastLocalRange = this.idRanges.last();\n\t\tif (lastLocalRange !== undefined) {\n\t\t\tconst lastLocal = lastLocalRange[1][0];\n\t\t\tif (localId === lastLocal - 1) {\n\t\t\t\t// New local simply expands the last local range tracked\n\t\t\t\tlastLocalRange[1][0] = localId;\n\t\t\t\treturn localId;\n\t\t\t}\n\t\t}\n\n\t\tif (this.expensiveAsserts) {\n\t\t\tif (lastLocalRange === undefined) {\n\t\t\t\tassert(localId === -1, 0x49e /* Local ID space must start at -1. */);\n\t\t\t} else {\n\t\t\t\tconst [firstLocal, [_, finalRanges]] = lastLocalRange;\n\t\t\t\tlet finalDelta = 0;\n\t\t\t\tfor (const [__, [firstFinal, lastFinal]] of entries(firstLocal, finalRanges)) {\n\t\t\t\t\tfinalDelta += lastFinal - firstFinal + 1;\n\t\t\t\t}\n\t\t\t\tassert(\n\t\t\t\t\tlocalId === firstLocal - finalDelta,\n\t\t\t\t\t0x49f /* Local ID space must be contiguous. */,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.idRanges.append(localId, [localId, undefined]);\n\t\treturn localId;\n\t}\n\n\t/**\n\t * Registers one or more final IDs with this normalizer.\n\t * If there are any local IDs at the tip of session-space that do not have a corresponding final, they will be registered (aligned)\n\t * starting with the first of those. Otherwise, will be registered as the next ID in session space in creation order.\n\t *\n\t * An example:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, X]\n\t * Calling `addFinalIds` with first === last === 5 results in the following:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, 5]\n\t * Subsequently calling `addFinalIds` with first === last === 6 results in the following:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 6]\n\t *\n\t * Non-contiguous final IDs (i.e. the first final after a \"gap\" in final space) must always correspond to a local ID. For example,\n\t * in the final call to `addFinalIds` above would fail if first === last === 9, because the resulting state would have a\n\t * non-contiguous final ID without a local form:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 9]\n\t *\n\t * ^final ID 9 is not contiguous and does not have a corresponding local ID\n\t */\n\tpublic addFinalIds(\n\t\tfirstFinal: FinalCompressedId,\n\t\tlastFinal: FinalCompressedId,\n\t\trangeObject: TRangeObject,\n\t): void {\n\t\tassert(lastFinal >= firstFinal, 0x5ae /* Malformed normalization range. */);\n\t\tconst [firstLocal, finalRangesObj] =\n\t\t\tthis.idRanges.last() ?? fail(\"Final IDs must be added to an existing local range.\");\n\t\tconst [lastLocal, finalRanges] = finalRangesObj;\n\t\tlet nextLocal: LocalCompressedId;\n\t\tif (finalRanges === undefined) {\n\t\t\tfinalRangesObj[1] = [firstFinal, lastFinal, rangeObject];\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tfirstLocal - (lastFinal - firstFinal) - 1,\n\t\t\t) as LocalCompressedId;\n\t\t} else {\n\t\t\tconst [firstAlignedLocal, lastAlignedLocal, lastAlignedFinal, lastFinalRange] =\n\t\t\t\tthis.getAlignmentOfLastRange(firstLocal, finalRanges);\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tlastAlignedLocal - (lastFinal - firstFinal) - 2,\n\t\t\t) as LocalCompressedId;\n\t\t\tif (firstFinal === lastAlignedFinal + 1) {\n\t\t\t\tlastFinalRange[1] = lastFinal;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = (lastAlignedLocal - 1) as LocalCompressedId;\n\t\t\t\tlet rangeMap: FinalRangesMap<TRangeObject>;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\t// Convert the single range to a range collection\n\t\t\t\t\trangeMap = SessionIdNormalizer.makeFinalRangesMap();\n\t\t\t\t\trangeMap.append(firstAlignedLocal, lastFinalRange);\n\t\t\t\t\tfinalRangesObj[1] = rangeMap;\n\t\t\t\t} else {\n\t\t\t\t\trangeMap = finalRanges;\n\t\t\t\t}\n\t\t\t\trangeMap.append(alignedLocal, [firstFinal, lastFinal, rangeObject]);\n\t\t\t\tassert(\n\t\t\t\t\talignedLocal >= lastLocal,\n\t\t\t\t\t0x4a0 /* Gaps in final space must align to a local. */,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.expensiveAsserts) {\n\t\t\t\tthis.idRanges.assertValid();\n\t\t\t}\n\t\t}\n\n\t\tthis.nextLocalId = nextLocal;\n\t}\n\n\t/**\n\t * Alerts the normalizer to the existence of a block of final IDs that are *allocated* (but may not be entirely used).\n\t *\n\t * The normalizer may have unaligned (unfinalized) local IDs; any such outstanding locals will be eagerly aligned with\n\t * as many finals from the registered block as possible.\n\t *\n\t * It is important to register blocks via this method as soon as they are created for future eager final generations to be utilized, as such\n\t * generation is dependant on the normalizer being up-to-date with which local IDs have been aligned with finals. If, for instance,\n\t * a block of finals is not immediately registered with the normalizer and there are outstanding locals that would have aligned with them,\n\t * those locals will not be finalized until their creation range is finalized, which could be later if the block was created by an earlier\n\t * creation range's finalization but is large enough to span them both. In this scenario, no eager finals can be generated until the second\n\t * creation range is finalized.\n\t *\n\t * A usage example:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, X, X, X]\n\t * Calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 10 results in the following:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, 5, 6, 7]\n\t * Instead calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 2 results in the following:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, 5, 6, X]\n\t *\n\t */\n\tpublic registerFinalIdBlock(\n\t\tfirstFinalInBlock: FinalCompressedId,\n\t\tcount: number,\n\t\trangeObject: TRangeObject,\n\t): void {\n\t\tassert(count >= 1, 0x5af /* Malformed normalization block. */);\n\t\tconst [firstLocal, [lastLocal, finalRanges]] =\n\t\t\tthis.idRanges.last() ??\n\t\t\tfail(\"Final ID block should not be registered before any locals.\");\n\t\tlet unalignedLocalCount: number;\n\t\tif (finalRanges === undefined) {\n\t\t\tunalignedLocalCount = firstLocal - lastLocal + 1;\n\t\t} else {\n\t\t\tconst [_, lastAlignedLocal] = this.getAlignmentOfLastRange(firstLocal, finalRanges);\n\t\t\tunalignedLocalCount = lastAlignedLocal - lastLocal;\n\t\t}\n\t\tassert(\n\t\t\tunalignedLocalCount > 0,\n\t\t\t0x51b /* Final ID block should not be registered without an existing local range. */,\n\t\t);\n\t\tconst lastFinal = (firstFinalInBlock +\n\t\t\tMath.min(unalignedLocalCount, count) -\n\t\t\t1) as FinalCompressedId;\n\t\tthis.addFinalIds(firstFinalInBlock, lastFinal, rangeObject);\n\t}\n\n\tprivate getAlignmentOfLastRange(\n\t\tfirstLocal: LocalCompressedId,\n\t\tfinalRanges: FinalRanges<TRangeObject>,\n\t): [\n\t\tfirstAlignedLocal: LocalCompressedId,\n\t\tlastAlignedLocal: LocalCompressedId,\n\t\tlastAlignedFinal: FinalCompressedId,\n\t\tlastFinalRange: FinalRange<TRangeObject>,\n\t] {\n\t\tconst isSingle = isSingleRange(finalRanges);\n\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\tlet firstAlignedLocal: LocalCompressedId;\n\t\tif (isSingle) {\n\t\t\tfirstAlignedLocal = firstLocal;\n\t\t\tlastFinalRange = finalRanges;\n\t\t} else {\n\t\t\t[firstAlignedLocal, lastFinalRange] =\n\t\t\t\tfinalRanges.last() ?? fail(\"Map should be non-empty.\");\n\t\t}\n\n\t\tconst [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;\n\t\tconst lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);\n\t\treturn [\n\t\t\tfirstAlignedLocal,\n\t\t\tlastAlignedLocal as LocalCompressedId,\n\t\t\tlastAlignedFinal,\n\t\t\tlastFinalRange,\n\t\t];\n\t}\n\n\t/**\n\t * Returns an enumerable of all session-space IDs known to this normalizer, in creation order.\n\t */\n\tpublic *[Symbol.iterator](): IterableIterator<SessionSpaceCompressedId> {\n\t\tfor (const [firstLocal, [lastLocal, finalRanges]] of this.idRanges.entries()) {\n\t\t\tfor (let i = firstLocal; i >= lastLocal; i--) {\n\t\t\t\tyield i;\n\t\t\t}\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t// Safe to get only the last final range, as all others must have corresponding locals (see `addFinalIds` docs)\n\t\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\t\tlet alignedLocal: LocalCompressedId;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\talignedLocal = firstLocal;\n\t\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t\t} else {\n\t\t\t\t\t[alignedLocal, lastFinalRange] =\n\t\t\t\t\t\tfinalRanges.last() ?? fail(\"Map should be non-empty.\");\n\t\t\t\t}\n\t\t\t\tconst [firstFinal, lastFinal] = lastFinalRange;\n\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\tfor (let i = firstFinal + localRangeDelta + 1; i <= lastFinal; i++) {\n\t\t\t\t\tyield i as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(): SerializedSessionIdNormalizer {\n\t\tconst serialized: Mutable<SerializedSessionIdNormalizer> = {\n\t\t\tlocalRanges: [],\n\t\t\tnextLocalId: this.nextLocalId,\n\t\t};\n\t\tconst localRanges = serialized.localRanges as Mutable<typeof serialized.localRanges>;\n\t\tfor (const [firstLocal, finalRanges] of this.idRanges.entries()) {\n\t\t\tconst [lastLocal, finalRangesTable] = finalRanges;\n\t\t\tif (finalRangesTable !== undefined) {\n\t\t\t\tconst serializedFinalRanges: [\n\t\t\t\t\tLocalCompressedId,\n\t\t\t\t\tFinalCompressedId,\n\t\t\t\t\tFinalCompressedId,\n\t\t\t\t][] = [];\n\t\t\t\tfor (const [alignedLocal, [firstFinal, lastFinal]] of entries(\n\t\t\t\t\tfirstLocal,\n\t\t\t\t\tfinalRangesTable,\n\t\t\t\t)) {\n\t\t\t\t\tserializedFinalRanges.push([alignedLocal, firstFinal, lastFinal]);\n\t\t\t\t}\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal, serializedFinalRanges]);\n\t\t\t} else {\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal]);\n\t\t\t}\n\t\t}\n\t\treturn serialized;\n\t}\n\n\tpublic static deserialize<TRangeObject>(\n\t\tserialized: SerializedSessionIdNormalizer,\n\t\tgetRangeObject: (finalId: FinalCompressedId) => TRangeObject,\n\t): SessionIdNormalizer<TRangeObject> {\n\t\tconst normalizer = new SessionIdNormalizer<TRangeObject>();\n\t\tconst { idRanges } = normalizer;\n\t\tfor (const [firstLocal, lastLocal, serializedFinalRanges] of serialized.localRanges) {\n\t\t\tlet finalRanges: FinalRanges<TRangeObject> | undefined;\n\t\t\tif (serializedFinalRanges !== undefined) {\n\t\t\t\tassert(\n\t\t\t\t\tserializedFinalRanges.length !== 0,\n\t\t\t\t\t0x4a1 /* Empty range should not be reified. */,\n\t\t\t\t);\n\t\t\t\tif (serializedFinalRanges.length === 1) {\n\t\t\t\t\tconst [_, firstFinal, lastFinal] = serializedFinalRanges[0];\n\t\t\t\t\tfinalRanges = [firstFinal, lastFinal, getRangeObject(firstFinal)];\n\t\t\t\t} else {\n\t\t\t\t\tfinalRanges = SessionIdNormalizer.makeFinalRangesMap<TRangeObject>();\n\t\t\t\t\tfor (const [alignedLocal, firstFinal, lastFinal] of serializedFinalRanges) {\n\t\t\t\t\t\tfinalRanges.append(alignedLocal, [\n\t\t\t\t\t\t\tfirstFinal,\n\t\t\t\t\t\t\tlastFinal,\n\t\t\t\t\t\t\tgetRangeObject(firstFinal),\n\t\t\t\t\t\t]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tidRanges.append(firstLocal, [lastLocal, finalRanges]);\n\t\t}\n\t\tnormalizer.nextLocalId = serialized.nextLocalId;\n\t\treturn normalizer;\n\t}\n\n\tpublic equals(\n\t\tother: SessionIdNormalizer<TRangeObject>,\n\t\tcompareRangeObjects: (a: TRangeObject, b: TRangeObject) => boolean = (a, b) => a === b,\n\t): boolean {\n\t\treturn (\n\t\t\tthis.nextLocalId === other.nextLocalId &&\n\t\t\tthis.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {\n\t\t\t\tconst [lastLocalA, finalRangesA] = localRangeA;\n\t\t\t\tconst [lastLocalB, finalRangesB] = localRangeB;\n\t\t\t\tif (finalRangesA === undefined || finalRangesB === undefined) {\n\t\t\t\t\treturn finalRangesA === finalRangesB;\n\t\t\t\t}\n\n\t\t\t\tconst rangeEquals = (\n\t\t\t\t\tfinalRangeA: FinalRange<TRangeObject>,\n\t\t\t\t\tfinalRangeB: FinalRange<TRangeObject>,\n\t\t\t\t) => {\n\t\t\t\t\tconst [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;\n\t\t\t\t\tconst [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;\n\t\t\t\t\treturn (\n\t\t\t\t\t\tfirstFinalA === firstFinalB &&\n\t\t\t\t\t\tlastFinalA === lastFinalB &&\n\t\t\t\t\t\tcompareRangeObjects(rangeObjectA, rangeObjectB)\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\tif (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {\n\t\t\t\t\tif (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn rangeEquals(finalRangesA, finalRangesB);\n\t\t\t\t}\n\n\t\t\t\treturn lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);\n\t\t\t})\n\t\t);\n\t}\n}\n\ntype FinalRange<TRangeObject> = [\n\tfirstFinal: FinalCompressedId,\n\tlastFinal: FinalCompressedId,\n\trangeObject: TRangeObject,\n];\n\ntype FinalRangesMap<TRangeObject> = AppendOnlyDoublySortedMap<\n\tLocalCompressedId,\n\tFinalRange<TRangeObject>,\n\tFinalCompressedId\n>;\n\ntype FinalRanges<TRangeObject> = FinalRange<TRangeObject> | FinalRangesMap<TRangeObject>;\n\nfunction isSingleRange<TRangeObject>(\n\tranges: FinalRanges<TRangeObject>,\n): ranges is FinalRange<TRangeObject> {\n\treturn Array.isArray(ranges);\n}\n\nfunction getLastRange<TRangeObject>(\n\tfinalRanges: FinalRanges<TRangeObject>,\n): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.last() ?? fail(\"Map must be non-empty\"))[1];\n}\n\nfunction getFirstRange<TRangeObject>(\n\tfinalRanges: FinalRanges<TRangeObject>,\n): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.first() ?? fail(\"Map must be non-empty\"))[1];\n}\n\nfunction extractFirstFinalFromRange<TRangeObject>(\n\tfinalRange: FinalRange<TRangeObject>,\n): FinalCompressedId {\n\treturn finalRange[0];\n}\n\nfunction getPairOrNextLowerByValue<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tfinalId: FinalCompressedId,\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (finalId < finalRanges[0]) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLowerByValue(finalId);\n}\n\nfunction getPairOrNextLower<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tlocalId: LocalCompressedId,\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (localId > firstLocal) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLower(localId);\n}\n\nfunction* entries<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n): IterableIterator<readonly [LocalCompressedId, FinalRange<TRangeObject>]> {\n\tif (finalRanges !== undefined) {\n\t\tif (isSingleRange(finalRanges)) {\n\t\t\tyield [firstLocal, finalRanges];\n\t\t} else {\n\t\t\tfor (const range of finalRanges.entries()) {\n\t\t\t\tyield range;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sessionIdNormalizer.js","sourceRoot":"","sources":["../../src/id-compressor/sessionIdNormalizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/restrict-plus-operands */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tSessionSpaceCompressedId,\n\tSerializedSessionIdNormalizer,\n} from \"@fluidframework/runtime-definitions\";\nimport { compareFiniteNumbers, compareFiniteNumbersReversed, fail, Mutable } from \"./utils\";\nimport { AppendOnlyDoublySortedMap } from \"./appendOnlySortedMap\";\n\n/**\n * Maps IDs created by a session between their local and final forms (i.e. normalization). These IDs are in a contiguous range.\n * The local and final forms of IDs made by a session can be thought of as two equal-length sparse arrays, aligned such\n * that normalizeLocalToFinal(locals[i]) === finals[i] and vice versa.\n * Below is an example to illustrate how various mappings can arise:\n *\n * ```\n * +- Creation Index\n * / +- Locals\n * / / +- Finals\n * / / /\n * ---+-----+----\n * 0 | -1 | 0 -|___ Two IDs are allocated as locals since no cluster exists. A new cluster is created when acked.\n * 1 | -2 | 1 -|\n * 2 | | 2 -|\n * 3 | | 3 --|-- Three more IDs are allocated as finals eagerly since a cluster exists with available capacity.\n * 4 | | 4 -|\n * 5 | -6 | 10 ----- One ID is allocated as a local (it overflows the existing cluster) and a new cluster is created after ack.\n * 6 | | 11 ----- One ID is allocated as a final eagerly into the existing cluster.\n * 7 | -8 | 12 ----- A local ID with an override is allocated. The override forces it to be a local ID.\n * 8 | | 13\n * 9 | | 14\n * 10 | -11 | ----- A local ID is allocated. It has no corresponding final ID since it has not been acked.\n * ```\n *\n * Note that in this example, some IDs (those at indices 2, 3, 4, 6, 8, and 9) have no local form. The ID at index 10 has no final form.\n * These kinds of \"gaps\" occur due to the timing of allocation calls on the client and how they relate to finalization/cluster creation,\n * which depends on receiving an ack/sequence number from the server. Given this context, \"session space\" can be thought of as:\n *\n * ```\n * for each index in the range of IDs created by a session:\n * \tthe local form if it exists, otherwise the final form\n * ```\n *\n * This class is designed to efficiently build and query these mappings by leveraging the facts that much of the range (in both local and\n * final space) is uninterrupted by \"gaps\" and can be compactly represented by a (first, last) pair and is easily binary searched for\n * normalization between local and final space.\n */\nexport class SessionIdNormalizer<TRangeObject> {\n\tprivate nextLocalId: LocalCompressedId = -1 as LocalCompressedId;\n\tprivate readonly idRanges: AppendOnlyDoublySortedMap<\n\t\tLocalCompressedId,\n\t\t[lastLocal: LocalCompressedId, finalRanges: FinalRanges<TRangeObject> | undefined],\n\t\tFinalCompressedId\n\t> = new AppendOnlyDoublySortedMap(\n\t\tcompareFiniteNumbersReversed,\n\t\t([_, finalRanges]) => {\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\tconst first = getFirstRange(finalRanges);\n\t\t\t\treturn extractFirstFinalFromRange(first);\n\t\t\t}\n\t\t\treturn Number.POSITIVE_INFINITY as FinalCompressedId;\n\t\t},\n\t\tcompareFiniteNumbers,\n\t);\n\n\tpublic constructor(private readonly expensiveAsserts = false) {}\n\n\t/**\n\t * Converts the final ID to its session-space representation.\n\t * This will be the corresponding local if a local form exists, and `finalId` otherwise.\n\t */\n\tpublic getSessionSpaceId(finalId: FinalCompressedId): SessionSpaceCompressedId | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\tif (finalDelta <= localRangeDelta) {\n\t\t\t\t\t\treturn (alignedLocal - finalDelta) as LocalCompressedId;\n\t\t\t\t\t}\n\t\t\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Converts the local ID to its corresponding final ID, if one exists.\n\t */\n\tpublic getFinalId(localId: LocalCompressedId): [FinalCompressedId, TRangeObject] | undefined {\n\t\tconst localRange =\n\t\t\tthis.idRanges.getPairOrNextLower(localId) ??\n\t\t\tfail(\"Local ID was never recorded with this normalizer.\");\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localId < lastLocal) {\n\t\t\tfail(\"Local ID was never recorded with this normalizer.\");\n\t\t}\n\t\tconst finalRange = getPairOrNextLower(firstLocal, finalRanges, localId);\n\t\tif (finalRange !== undefined) {\n\t\t\tconst [alignedLocal, [firstFinal, lastFinal, rangeObject]] = finalRange;\n\t\t\tconst rangeDelta = lastFinal - firstFinal;\n\t\t\tconst localDelta = alignedLocal - localId;\n\t\t\tif (localDelta <= rangeDelta) {\n\t\t\t\t// Local is within a range segment that has a corresponding final\n\t\t\t\treturn [(firstFinal + localDelta) as FinalCompressedId, rangeObject];\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the index of the local ID corresponding to the supplied final ID in the total range of IDs created by the session,\n\t * if the ID was created by the session for this `SessionIdNormalizer`.\n\t */\n\tpublic getCreationIndex(finalId: FinalCompressedId): number | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [_, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\treturn -alignedLocal - 1 + finalDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the session-space ID at the supplied creation index, if one exists.\n\t */\n\tpublic getIdByCreationIndex(index: number): SessionSpaceCompressedId | undefined {\n\t\tconst localByIndex = -(index + 1) as LocalCompressedId;\n\t\tconst localRange = this.idRanges.getPairOrNextLower(localByIndex);\n\t\tif (localRange === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localByIndex >= lastLocal) {\n\t\t\treturn localByIndex;\n\t\t}\n\t\tconst finalRange =\n\t\t\tgetPairOrNextLower(firstLocal, finalRanges, localByIndex) ??\n\t\t\tfail(\"Final ranges not aligned with owning local range.\");\n\n\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\tconst localDelta = alignedLocal - localByIndex;\n\t\tconst finalId = firstFinal + localDelta;\n\t\tif (finalId <= lastFinal) {\n\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate static makeFinalRangesMap<TRangeObject>(): FinalRangesMap<TRangeObject> {\n\t\treturn new AppendOnlyDoublySortedMap(\n\t\t\tcompareFiniteNumbersReversed,\n\t\t\textractFirstFinalFromRange,\n\t\t\tcompareFiniteNumbers,\n\t\t);\n\t}\n\n\t/**\n\t * Returns the last final ID known to this normalizer.\n\t */\n\tpublic getLastFinalId(): FinalCompressedId | undefined {\n\t\tconst lastIndex = this.idRanges.size - 1;\n\t\tconst secondToLast = Math.max(0, lastIndex - 1);\n\t\tfor (let i = lastIndex; i >= secondToLast; i--) {\n\t\t\tconst localRange = this.idRanges.getAtIndex(i);\n\t\t\tif (localRange !== undefined) {\n\t\t\t\tconst finalRanges = localRange[1][1];\n\t\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t\treturn getLastRange(finalRanges)[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Registers and returns the next ID in local space with this normalizer. An example:\n\t *\n\t * Locals: [-1, -2, X, X]\n\t * Finals: [ 0, 1, 2, 3]\n\t * In this scenario, a call to this method would generate and return -5.\n\t */\n\tpublic addLocalId(): LocalCompressedId {\n\t\tconst localId = this.nextLocalId-- as LocalCompressedId;\n\t\tconst lastLocalRange = this.idRanges.last();\n\t\tif (lastLocalRange !== undefined) {\n\t\t\tconst lastLocal = lastLocalRange[1][0];\n\t\t\tif (localId === lastLocal - 1) {\n\t\t\t\t// New local simply expands the last local range tracked\n\t\t\t\tlastLocalRange[1][0] = localId;\n\t\t\t\treturn localId;\n\t\t\t}\n\t\t}\n\n\t\tif (this.expensiveAsserts) {\n\t\t\tif (lastLocalRange === undefined) {\n\t\t\t\tassert(localId === -1, 0x49e /* Local ID space must start at -1. */);\n\t\t\t} else {\n\t\t\t\tconst [firstLocal, [_, finalRanges]] = lastLocalRange;\n\t\t\t\tlet finalDelta = 0;\n\t\t\t\tfor (const [__, [firstFinal, lastFinal]] of entries(firstLocal, finalRanges)) {\n\t\t\t\t\tfinalDelta += lastFinal - firstFinal + 1;\n\t\t\t\t}\n\t\t\t\tassert(\n\t\t\t\t\tlocalId === firstLocal - finalDelta,\n\t\t\t\t\t0x49f /* Local ID space must be contiguous. */,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.idRanges.append(localId, [localId, undefined]);\n\t\treturn localId;\n\t}\n\n\t/**\n\t * Registers one or more final IDs with this normalizer.\n\t * If there are any local IDs at the tip of session-space that do not have a corresponding final, they will be registered (aligned)\n\t * starting with the first of those. Otherwise, will be registered as the next ID in session space in creation order.\n\t *\n\t * An example:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, X]\n\t * Calling `addFinalIds` with first === last === 5 results in the following:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, 5]\n\t * Subsequently calling `addFinalIds` with first === last === 6 results in the following:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 6]\n\t *\n\t * Non-contiguous final IDs (i.e. the first final after a \"gap\" in final space) must always correspond to a local ID. For example,\n\t * in the final call to `addFinalIds` above would fail if first === last === 9, because the resulting state would have a\n\t * non-contiguous final ID without a local form:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 9]\n\t *\n\t * ^final ID 9 is not contiguous and does not have a corresponding local ID\n\t */\n\tpublic addFinalIds(\n\t\tfirstFinal: FinalCompressedId,\n\t\tlastFinal: FinalCompressedId,\n\t\trangeObject: TRangeObject,\n\t): void {\n\t\tassert(lastFinal >= firstFinal, 0x5ae /* Malformed normalization range. */);\n\t\tconst [firstLocal, finalRangesObj] =\n\t\t\tthis.idRanges.last() ?? fail(\"Final IDs must be added to an existing local range.\");\n\t\tconst [lastLocal, finalRanges] = finalRangesObj;\n\t\tlet nextLocal: LocalCompressedId;\n\t\tif (finalRanges === undefined) {\n\t\t\tfinalRangesObj[1] = [firstFinal, lastFinal, rangeObject];\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tfirstLocal - (lastFinal - firstFinal) - 1,\n\t\t\t) as LocalCompressedId;\n\t\t} else {\n\t\t\tconst [firstAlignedLocal, lastAlignedLocal, lastAlignedFinal, lastFinalRange] =\n\t\t\t\tthis.getAlignmentOfLastRange(firstLocal, finalRanges);\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tlastAlignedLocal - (lastFinal - firstFinal) - 2,\n\t\t\t) as LocalCompressedId;\n\t\t\tif (firstFinal === lastAlignedFinal + 1) {\n\t\t\t\tlastFinalRange[1] = lastFinal;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = (lastAlignedLocal - 1) as LocalCompressedId;\n\t\t\t\tlet rangeMap: FinalRangesMap<TRangeObject>;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\t// Convert the single range to a range collection\n\t\t\t\t\trangeMap = SessionIdNormalizer.makeFinalRangesMap();\n\t\t\t\t\trangeMap.append(firstAlignedLocal, lastFinalRange);\n\t\t\t\t\tfinalRangesObj[1] = rangeMap;\n\t\t\t\t} else {\n\t\t\t\t\trangeMap = finalRanges;\n\t\t\t\t}\n\t\t\t\trangeMap.append(alignedLocal, [firstFinal, lastFinal, rangeObject]);\n\t\t\t\tassert(\n\t\t\t\t\talignedLocal >= lastLocal,\n\t\t\t\t\t0x4a0 /* Gaps in final space must align to a local. */,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.expensiveAsserts) {\n\t\t\t\tthis.idRanges.assertValid();\n\t\t\t}\n\t\t}\n\n\t\tthis.nextLocalId = nextLocal;\n\t}\n\n\t/**\n\t * Alerts the normalizer to the existence of a block of final IDs that are *allocated* (but may not be entirely used).\n\t *\n\t * The normalizer may have unaligned (unfinalized) local IDs; any such outstanding locals will be eagerly aligned with\n\t * as many finals from the registered block as possible.\n\t *\n\t * It is important to register blocks via this method as soon as they are created for future eager final generations to be utilized, as such\n\t * generation is dependant on the normalizer being up-to-date with which local IDs have been aligned with finals. If, for instance,\n\t * a block of finals is not immediately registered with the normalizer and there are outstanding locals that would have aligned with them,\n\t * those locals will not be finalized until their creation range is finalized, which could be later if the block was created by an earlier\n\t * creation range's finalization but is large enough to span them both. In this scenario, no eager finals can be generated until the second\n\t * creation range is finalized.\n\t *\n\t * A usage example:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, X, X, X]\n\t * Calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 10 results in the following:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, 5, 6, 7]\n\t * Instead calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 2 results in the following:\n\t * Locals: [-1, -2, X, -4, -5, -6]\n\t * Finals: [ 0, 1, 2, 5, 6, X]\n\t *\n\t */\n\tpublic registerFinalIdBlock(\n\t\tfirstFinalInBlock: FinalCompressedId,\n\t\tcount: number,\n\t\trangeObject: TRangeObject,\n\t): void {\n\t\tassert(count >= 1, 0x5af /* Malformed normalization block. */);\n\t\tconst [firstLocal, [lastLocal, finalRanges]] =\n\t\t\tthis.idRanges.last() ??\n\t\t\tfail(\"Final ID block should not be registered before any locals.\");\n\t\tlet unalignedLocalCount: number;\n\t\tif (finalRanges === undefined) {\n\t\t\tunalignedLocalCount = firstLocal - lastLocal + 1;\n\t\t} else {\n\t\t\tconst [_, lastAlignedLocal] = this.getAlignmentOfLastRange(firstLocal, finalRanges);\n\t\t\tunalignedLocalCount = lastAlignedLocal - lastLocal;\n\t\t}\n\t\tassert(\n\t\t\tunalignedLocalCount > 0,\n\t\t\t0x51b /* Final ID block should not be registered without an existing local range. */,\n\t\t);\n\t\tconst lastFinal = (firstFinalInBlock +\n\t\t\tMath.min(unalignedLocalCount, count) -\n\t\t\t1) as FinalCompressedId;\n\t\tthis.addFinalIds(firstFinalInBlock, lastFinal, rangeObject);\n\t}\n\n\tprivate getAlignmentOfLastRange(\n\t\tfirstLocal: LocalCompressedId,\n\t\tfinalRanges: FinalRanges<TRangeObject>,\n\t): [\n\t\tfirstAlignedLocal: LocalCompressedId,\n\t\tlastAlignedLocal: LocalCompressedId,\n\t\tlastAlignedFinal: FinalCompressedId,\n\t\tlastFinalRange: FinalRange<TRangeObject>,\n\t] {\n\t\tconst isSingle = isSingleRange(finalRanges);\n\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\tlet firstAlignedLocal: LocalCompressedId;\n\t\tif (isSingle) {\n\t\t\tfirstAlignedLocal = firstLocal;\n\t\t\tlastFinalRange = finalRanges;\n\t\t} else {\n\t\t\t[firstAlignedLocal, lastFinalRange] =\n\t\t\t\tfinalRanges.last() ?? fail(\"Map should be non-empty.\");\n\t\t}\n\n\t\tconst [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;\n\t\tconst lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);\n\t\treturn [\n\t\t\tfirstAlignedLocal,\n\t\t\tlastAlignedLocal as LocalCompressedId,\n\t\t\tlastAlignedFinal,\n\t\t\tlastFinalRange,\n\t\t];\n\t}\n\n\t/**\n\t * Returns an enumerable of all session-space IDs known to this normalizer, in creation order.\n\t */\n\tpublic *[Symbol.iterator](): IterableIterator<SessionSpaceCompressedId> {\n\t\tfor (const [firstLocal, [lastLocal, finalRanges]] of this.idRanges.entries()) {\n\t\t\tfor (let i = firstLocal; i >= lastLocal; i--) {\n\t\t\t\tyield i;\n\t\t\t}\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t// Safe to get only the last final range, as all others must have corresponding locals (see `addFinalIds` docs)\n\t\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\t\tlet alignedLocal: LocalCompressedId;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\talignedLocal = firstLocal;\n\t\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t\t} else {\n\t\t\t\t\t[alignedLocal, lastFinalRange] =\n\t\t\t\t\t\tfinalRanges.last() ?? fail(\"Map should be non-empty.\");\n\t\t\t\t}\n\t\t\t\tconst [firstFinal, lastFinal] = lastFinalRange;\n\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\tfor (let i = firstFinal + localRangeDelta + 1; i <= lastFinal; i++) {\n\t\t\t\t\tyield i as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(): SerializedSessionIdNormalizer {\n\t\tconst serialized: Mutable<SerializedSessionIdNormalizer> = {\n\t\t\tlocalRanges: [],\n\t\t\tnextLocalId: this.nextLocalId,\n\t\t};\n\t\tconst localRanges = serialized.localRanges as Mutable<typeof serialized.localRanges>;\n\t\tfor (const [firstLocal, finalRanges] of this.idRanges.entries()) {\n\t\t\tconst [lastLocal, finalRangesTable] = finalRanges;\n\t\t\tif (finalRangesTable !== undefined) {\n\t\t\t\tconst serializedFinalRanges: [\n\t\t\t\t\tLocalCompressedId,\n\t\t\t\t\tFinalCompressedId,\n\t\t\t\t\tFinalCompressedId,\n\t\t\t\t][] = [];\n\t\t\t\tfor (const [alignedLocal, [firstFinal, lastFinal]] of entries(\n\t\t\t\t\tfirstLocal,\n\t\t\t\t\tfinalRangesTable,\n\t\t\t\t)) {\n\t\t\t\t\tserializedFinalRanges.push([alignedLocal, firstFinal, lastFinal]);\n\t\t\t\t}\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal, serializedFinalRanges]);\n\t\t\t} else {\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal]);\n\t\t\t}\n\t\t}\n\t\treturn serialized;\n\t}\n\n\tpublic static deserialize<TRangeObject>(\n\t\tserialized: SerializedSessionIdNormalizer,\n\t\tgetRangeObject: (finalId: FinalCompressedId) => TRangeObject,\n\t): SessionIdNormalizer<TRangeObject> {\n\t\tconst normalizer = new SessionIdNormalizer<TRangeObject>();\n\t\tconst { idRanges } = normalizer;\n\t\tfor (const [firstLocal, lastLocal, serializedFinalRanges] of serialized.localRanges) {\n\t\t\tlet finalRanges: FinalRanges<TRangeObject> | undefined;\n\t\t\tif (serializedFinalRanges !== undefined) {\n\t\t\t\tassert(\n\t\t\t\t\tserializedFinalRanges.length !== 0,\n\t\t\t\t\t0x4a1 /* Empty range should not be reified. */,\n\t\t\t\t);\n\t\t\t\tif (serializedFinalRanges.length === 1) {\n\t\t\t\t\tconst [_, firstFinal, lastFinal] = serializedFinalRanges[0];\n\t\t\t\t\tfinalRanges = [firstFinal, lastFinal, getRangeObject(firstFinal)];\n\t\t\t\t} else {\n\t\t\t\t\tfinalRanges = SessionIdNormalizer.makeFinalRangesMap<TRangeObject>();\n\t\t\t\t\tfor (const [alignedLocal, firstFinal, lastFinal] of serializedFinalRanges) {\n\t\t\t\t\t\tfinalRanges.append(alignedLocal, [\n\t\t\t\t\t\t\tfirstFinal,\n\t\t\t\t\t\t\tlastFinal,\n\t\t\t\t\t\t\tgetRangeObject(firstFinal),\n\t\t\t\t\t\t]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tidRanges.append(firstLocal, [lastLocal, finalRanges]);\n\t\t}\n\t\tnormalizer.nextLocalId = serialized.nextLocalId;\n\t\treturn normalizer;\n\t}\n\n\tpublic equals(\n\t\tother: SessionIdNormalizer<TRangeObject>,\n\t\tcompareRangeObjects: (a: TRangeObject, b: TRangeObject) => boolean = (a, b) => a === b,\n\t): boolean {\n\t\treturn (\n\t\t\tthis.nextLocalId === other.nextLocalId &&\n\t\t\tthis.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {\n\t\t\t\tconst [lastLocalA, finalRangesA] = localRangeA;\n\t\t\t\tconst [lastLocalB, finalRangesB] = localRangeB;\n\t\t\t\tif (finalRangesA === undefined || finalRangesB === undefined) {\n\t\t\t\t\treturn finalRangesA === finalRangesB;\n\t\t\t\t}\n\n\t\t\t\tconst rangeEquals = (\n\t\t\t\t\tfinalRangeA: FinalRange<TRangeObject>,\n\t\t\t\t\tfinalRangeB: FinalRange<TRangeObject>,\n\t\t\t\t) => {\n\t\t\t\t\tconst [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;\n\t\t\t\t\tconst [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;\n\t\t\t\t\treturn (\n\t\t\t\t\t\tfirstFinalA === firstFinalB &&\n\t\t\t\t\t\tlastFinalA === lastFinalB &&\n\t\t\t\t\t\tcompareRangeObjects(rangeObjectA, rangeObjectB)\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\tif (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {\n\t\t\t\t\tif (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn rangeEquals(finalRangesA, finalRangesB);\n\t\t\t\t}\n\n\t\t\t\treturn lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);\n\t\t\t})\n\t\t);\n\t}\n}\n\ntype FinalRange<TRangeObject> = [\n\tfirstFinal: FinalCompressedId,\n\tlastFinal: FinalCompressedId,\n\trangeObject: TRangeObject,\n];\n\ntype FinalRangesMap<TRangeObject> = AppendOnlyDoublySortedMap<\n\tLocalCompressedId,\n\tFinalRange<TRangeObject>,\n\tFinalCompressedId\n>;\n\ntype FinalRanges<TRangeObject> = FinalRange<TRangeObject> | FinalRangesMap<TRangeObject>;\n\nfunction isSingleRange<TRangeObject>(\n\tranges: FinalRanges<TRangeObject>,\n): ranges is FinalRange<TRangeObject> {\n\treturn Array.isArray(ranges);\n}\n\nfunction getLastRange<TRangeObject>(\n\tfinalRanges: FinalRanges<TRangeObject>,\n): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.last() ?? fail(\"Map must be non-empty\"))[1];\n}\n\nfunction getFirstRange<TRangeObject>(\n\tfinalRanges: FinalRanges<TRangeObject>,\n): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.first() ?? fail(\"Map must be non-empty\"))[1];\n}\n\nfunction extractFirstFinalFromRange<TRangeObject>(\n\tfinalRange: FinalRange<TRangeObject>,\n): FinalCompressedId {\n\treturn finalRange[0];\n}\n\nfunction getPairOrNextLowerByValue<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tfinalId: FinalCompressedId,\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (finalId < finalRanges[0]) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLowerByValue(finalId);\n}\n\nfunction getPairOrNextLower<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tlocalId: LocalCompressedId,\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (localId > firstLocal) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLower(localId);\n}\n\nfunction* entries<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n): IterableIterator<readonly [LocalCompressedId, FinalRange<TRangeObject>]> {\n\tif (finalRanges !== undefined) {\n\t\tif (isSingleRange(finalRanges)) {\n\t\t\tyield [firstLocal, finalRanges];\n\t\t} else {\n\t\t\tfor (const range of finalRanges.entries()) {\n\t\t\t\tyield range;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { ContainerMessageType, ContainerRuntimeMessage, ISummaryRuntimeOptions, ISummaryBaseConfiguration, ISummaryConfigurationHeuristics, ISummaryConfigurationDisableSummarizer, ISummaryConfigurationDisableHeuristics, IContainerRuntimeOptions,
|
|
5
|
+
export { ContainerMessageType, ContainerRuntimeMessage, ISummaryRuntimeOptions, ISummaryBaseConfiguration, ISummaryConfigurationHeuristics, ISummaryConfigurationDisableSummarizer, ISummaryConfigurationDisableHeuristics, IContainerRuntimeOptions, isRuntimeMessage, RuntimeMessage, agentSchedulerId, ContainerRuntime, RuntimeHeaders, AllowTombstoneRequestHeaderKey, TombstoneResponseHeaderKey, ISummaryConfiguration, DefaultSummaryConfiguration, ICompressionRuntimeOptions, CompressionAlgorithms, } from "./containerRuntime";
|
|
6
6
|
export { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
7
7
|
export { IGCRuntimeOptions, IGCStats } from "./gc";
|
|
8
8
|
export { IAckedSummary, ISummarizer, ISummarizeResults, ISummaryCancellationToken, neverCancelledSummaryToken, Summarizer, SummarizerStopReason, SummaryCollection, EnqueueSummarizeResult, IAckSummaryResult, IBaseSummarizeResult, IBroadcastSummaryResult, ICancellationToken, IConnectableRuntime, IEnqueueSummarizeOptions, IGenerateSummaryTreeResult, IGeneratedSummaryStats, INackSummaryResult, IOnDemandSummarizeOptions, IRefreshSummaryAckOptions, ISubmitSummaryOpResult, ISubmitSummaryOptions, ISummarizeOptions, ISummarizerEvents, ISummarizerInternalsProvider, ISummarizerRuntime, ISummarizingWarning, IUploadSummaryResult, SubmitSummaryResult, SummarizeResultPart, IClientSummaryWatcher, ISummary, ISummaryCollectionOpEvents, ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage, OpActionEventListener, OpActionEventName, ICancellableSummarizerController, SubmitSummaryFailureData, SummaryStage, } from "./summary";
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,wBAAwB,EACxB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,8BAA8B,EAC9B,0BAA0B,EAC1B,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,yBAAyB,EACzB,0BAA0B,EAC1B,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,4BAA4B,EAC5B,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,QAAQ,EACR,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,gCAAgC,EAChC,wBAAwB,EACxB,YAAY,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EAQpB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,8BAA8B,EAC9B,0BAA0B,EAE1B,2BAA2B,EAE3B,qBAAqB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAKN,0BAA0B,EAC1B,UAAU,EAEV,iBAAiB,GAkCjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAc,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tContainerMessageType,\n\tContainerRuntimeMessage,\n\tISummaryRuntimeOptions,\n\tISummaryBaseConfiguration,\n\tISummaryConfigurationHeuristics,\n\tISummaryConfigurationDisableSummarizer,\n\tISummaryConfigurationDisableHeuristics,\n\tIContainerRuntimeOptions,\n\tisRuntimeMessage,\n\tRuntimeMessage,\n\tagentSchedulerId,\n\tContainerRuntime,\n\tRuntimeHeaders,\n\tAllowTombstoneRequestHeaderKey,\n\tTombstoneResponseHeaderKey,\n\tISummaryConfiguration,\n\tDefaultSummaryConfiguration,\n\tICompressionRuntimeOptions,\n\tCompressionAlgorithms,\n} from \"./containerRuntime\";\nexport { FluidDataStoreRegistry } from \"./dataStoreRegistry\";\nexport { IGCRuntimeOptions, IGCStats } from \"./gc\";\nexport {\n\tIAckedSummary,\n\tISummarizer,\n\tISummarizeResults,\n\tISummaryCancellationToken,\n\tneverCancelledSummaryToken,\n\tSummarizer,\n\tSummarizerStopReason,\n\tSummaryCollection,\n\tEnqueueSummarizeResult,\n\tIAckSummaryResult,\n\tIBaseSummarizeResult,\n\tIBroadcastSummaryResult,\n\tICancellationToken,\n\tIConnectableRuntime,\n\tIEnqueueSummarizeOptions,\n\tIGenerateSummaryTreeResult,\n\tIGeneratedSummaryStats,\n\tINackSummaryResult,\n\tIOnDemandSummarizeOptions,\n\tIRefreshSummaryAckOptions,\n\tISubmitSummaryOpResult,\n\tISubmitSummaryOptions,\n\tISummarizeOptions,\n\tISummarizerEvents,\n\tISummarizerInternalsProvider,\n\tISummarizerRuntime,\n\tISummarizingWarning,\n\tIUploadSummaryResult,\n\tSubmitSummaryResult,\n\tSummarizeResultPart,\n\tIClientSummaryWatcher,\n\tISummary,\n\tISummaryCollectionOpEvents,\n\tISummaryAckMessage,\n\tISummaryNackMessage,\n\tISummaryOpMessage,\n\tOpActionEventListener,\n\tOpActionEventName,\n\tICancellableSummarizerController,\n\tSubmitSummaryFailureData,\n\tSummaryStage,\n} from \"./summary\";\nexport { IChunkedOp, unpackRuntimeMessage } from \"./opLifecycle\";\nexport { generateStableId, isStableId, assertIsStableId } from \"./id-compressor\";\n"]}
|
|
@@ -35,8 +35,7 @@ export class BatchManager {
|
|
|
35
35
|
: this.pendingBatch[this.pendingBatch.length - 1].referenceSequenceNumber;
|
|
36
36
|
}
|
|
37
37
|
push(message, reentrant, currentClientSequenceNumber) {
|
|
38
|
-
|
|
39
|
-
const contentSize = this.batchContentSize + ((_b = (_a = message.contents) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0);
|
|
38
|
+
const contentSize = this.batchContentSize + (message.contents?.length ?? 0);
|
|
40
39
|
const opCount = this.pendingBatch.length;
|
|
41
40
|
this.hasReentrantOps = this.hasReentrantOps || reentrant;
|
|
42
41
|
// Attempt to estimate batch size, aka socket message size.
|
|
@@ -88,11 +87,10 @@ export class BatchManager {
|
|
|
88
87
|
const startPoint = this.pendingBatch.length;
|
|
89
88
|
return {
|
|
90
89
|
rollback: (process) => {
|
|
91
|
-
var _a, _b;
|
|
92
90
|
for (let i = this.pendingBatch.length; i > startPoint;) {
|
|
93
91
|
i--;
|
|
94
92
|
const message = this.pendingBatch[i];
|
|
95
|
-
this.batchContentSize -=
|
|
93
|
+
this.batchContentSize -= message.contents?.length ?? 0;
|
|
96
94
|
process(message);
|
|
97
95
|
}
|
|
98
96
|
this.pendingBatch.length = startPoint;
|
|
@@ -102,8 +100,14 @@ export class BatchManager {
|
|
|
102
100
|
}
|
|
103
101
|
const addBatchMetadata = (batch) => {
|
|
104
102
|
if (batch.content.length > 1) {
|
|
105
|
-
batch.content[0].metadata =
|
|
106
|
-
|
|
103
|
+
batch.content[0].metadata = {
|
|
104
|
+
...batch.content[0].metadata,
|
|
105
|
+
batch: true,
|
|
106
|
+
};
|
|
107
|
+
batch.content[batch.content.length - 1].metadata = {
|
|
108
|
+
...batch.content[batch.content.length - 1].metadata,
|
|
109
|
+
batch: false,
|
|
110
|
+
};
|
|
107
111
|
}
|
|
108
112
|
return batch;
|
|
109
113
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batchManager.js","sourceRoot":"","sources":["../../src/opLifecycle/batchManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH;;;GAGG;AACH,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;GAEG;AACH,MAAM,OAAO,YAAY;IA2BxB,YAA4B,OAA6B;QAA7B,YAAO,GAAP,OAAO,CAAsB;QA1BjD,iBAAY,GAAmB,EAAE,CAAC;QAClC,qBAAgB,GAAG,CAAC,CAAC;QACrB,oBAAe,GAAG,KAAK,CAAC;IAwB4B,CAAC;IAtB7D,IAAW,MAAM;QAChB,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;IACjC,CAAC;IACD,IAAW,kBAAkB;QAC5B,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC9B,CAAC;IAED,IAAW,eAAe;QACzB,OAAO;YACN,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;YACrD,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;SAC/C,CAAC;IACH,CAAC;IAED,IAAY,uBAAuB;QAClC,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;YACpC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,uBAAuB,CAAC;IAC5E,CAAC;IAMM,IAAI,CACV,OAAqB,EACrB,SAAkB,EAClB,2BAAoC
|
|
1
|
+
{"version":3,"file":"batchManager.js","sourceRoot":"","sources":["../../src/opLifecycle/batchManager.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 { ICompressionRuntimeOptions } from \"../containerRuntime\";\nimport { BatchMessage, IBatch, IBatchCheckpoint } from \"./definitions\";\n\nexport interface IBatchManagerOptions {\n\treadonly hardLimit: number;\n\treadonly softLimit?: number;\n\treadonly compressionOptions?: ICompressionRuntimeOptions;\n}\n\nexport interface BatchSequenceNumbers {\n\treferenceSequenceNumber?: number;\n\tclientSequenceNumber?: number;\n}\n\n/**\n * Estimated size of the stringification overhead for an op accumulated\n * from runtime to loader to the service.\n */\nconst opOverhead = 200;\n\n/**\n * Helper class that manages partial batch & rollback.\n */\nexport class BatchManager {\n\tprivate pendingBatch: BatchMessage[] = [];\n\tprivate batchContentSize = 0;\n\tprivate hasReentrantOps = false;\n\n\tpublic get length() {\n\t\treturn this.pendingBatch.length;\n\t}\n\tpublic get contentSizeInBytes() {\n\t\treturn this.batchContentSize;\n\t}\n\n\tpublic get sequenceNumbers(): BatchSequenceNumbers {\n\t\treturn {\n\t\t\treferenceSequenceNumber: this.referenceSequenceNumber,\n\t\t\tclientSequenceNumber: this.clientSequenceNumber,\n\t\t};\n\t}\n\n\tprivate get referenceSequenceNumber(): number | undefined {\n\t\treturn this.pendingBatch.length === 0\n\t\t\t? undefined\n\t\t\t: this.pendingBatch[this.pendingBatch.length - 1].referenceSequenceNumber;\n\t}\n\n\tprivate clientSequenceNumber: number | undefined;\n\n\tconstructor(public readonly options: IBatchManagerOptions) {}\n\n\tpublic push(\n\t\tmessage: BatchMessage,\n\t\treentrant: boolean,\n\t\tcurrentClientSequenceNumber?: number,\n\t): boolean {\n\t\tconst contentSize = this.batchContentSize + (message.contents?.length ?? 0);\n\t\tconst opCount = this.pendingBatch.length;\n\t\tthis.hasReentrantOps = this.hasReentrantOps || reentrant;\n\n\t\t// Attempt to estimate batch size, aka socket message size.\n\t\t// Each op has pretty large envelope, estimating to be 200 bytes.\n\t\t// Also content will be strigified, and that adds a lot of overhead due to a lot of escape characters.\n\t\t// Not taking it into account, as compression work should help there - compressed payload will be\n\t\t// initially stored as base64, and that requires only 2 extra escape characters.\n\t\tconst socketMessageSize = contentSize + opOverhead * opCount;\n\n\t\t// If we were provided soft limit, check for exceeding it.\n\t\t// But only if we have any ops, as the intention here is to flush existing ops (on exceeding this limit)\n\t\t// and start over. That's not an option if we have no ops.\n\t\t// If compression is enabled, the soft and hard limit are ignored and the message will be pushed anyways.\n\t\t// Cases where the message is still too large will be handled by the maxConsecutiveReconnects path.\n\t\tif (\n\t\t\tthis.options.softLimit !== undefined &&\n\t\t\tthis.length > 0 &&\n\t\t\tsocketMessageSize >= this.options.softLimit\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (socketMessageSize >= this.options.hardLimit) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.pendingBatch.length === 0) {\n\t\t\tthis.clientSequenceNumber = currentClientSequenceNumber;\n\t\t}\n\n\t\tthis.batchContentSize = contentSize;\n\t\tthis.pendingBatch.push(message);\n\t\treturn true;\n\t}\n\n\tpublic get empty() {\n\t\treturn this.pendingBatch.length === 0;\n\t}\n\n\tpublic popBatch(): IBatch {\n\t\tconst batch: IBatch = {\n\t\t\tcontent: this.pendingBatch,\n\t\t\tcontentSizeInBytes: this.batchContentSize,\n\t\t\treferenceSequenceNumber: this.referenceSequenceNumber,\n\t\t\thasReentrantOps: this.hasReentrantOps,\n\t\t};\n\n\t\tthis.pendingBatch = [];\n\t\tthis.batchContentSize = 0;\n\t\tthis.clientSequenceNumber = undefined;\n\t\tthis.hasReentrantOps = false;\n\n\t\treturn addBatchMetadata(batch);\n\t}\n\n\t/**\n\t * Capture the pending state at this point\n\t */\n\tpublic checkpoint(): IBatchCheckpoint {\n\t\tconst startPoint = this.pendingBatch.length;\n\t\treturn {\n\t\t\trollback: (process: (message: BatchMessage) => void) => {\n\t\t\t\tfor (let i = this.pendingBatch.length; i > startPoint; ) {\n\t\t\t\t\ti--;\n\t\t\t\t\tconst message = this.pendingBatch[i];\n\t\t\t\t\tthis.batchContentSize -= message.contents?.length ?? 0;\n\t\t\t\t\tprocess(message);\n\t\t\t\t}\n\n\t\t\t\tthis.pendingBatch.length = startPoint;\n\t\t\t},\n\t\t};\n\t}\n}\n\nconst addBatchMetadata = (batch: IBatch): IBatch => {\n\tif (batch.content.length > 1) {\n\t\tbatch.content[0].metadata = {\n\t\t\t...batch.content[0].metadata,\n\t\t\tbatch: true,\n\t\t};\n\t\tbatch.content[batch.content.length - 1].metadata = {\n\t\t\t...batch.content[batch.content.length - 1].metadata,\n\t\t\tbatch: false,\n\t\t};\n\t}\n\n\treturn batch;\n};\n\n/**\n * Estimates the real size in bytes on the socket for a given batch. It assumes that\n * the envelope size (and the size of an empty op) is 200 bytes, taking into account\n * extra overhead from stringification.\n *\n * @param batch - the batch to inspect\n * @returns An estimate of the payload size in bytes which will be produced when the batch is sent over the wire\n */\nexport const estimateSocketSize = (batch: IBatch): number => {\n\treturn batch.contentSizeInBytes + opOverhead * batch.content.length;\n};\n\nexport const sequenceNumbersMatch = (\n\tseqNums: BatchSequenceNumbers,\n\totherSeqNums: BatchSequenceNumbers,\n): boolean => {\n\treturn (\n\t\t(seqNums.referenceSequenceNumber === undefined ||\n\t\t\totherSeqNums.referenceSequenceNumber === undefined ||\n\t\t\tseqNums.referenceSequenceNumber === otherSeqNums.referenceSequenceNumber) &&\n\t\t(seqNums.clientSequenceNumber === undefined ||\n\t\t\totherSeqNums.clientSequenceNumber === undefined ||\n\t\t\tseqNums.clientSequenceNumber === otherSeqNums.clientSequenceNumber)\n\t);\n};\n"]}
|
|
@@ -25,7 +25,12 @@ export class OpCompressor {
|
|
|
25
25
|
const compressedContent = IsoBuffer.from(compressedContents).toString("base64");
|
|
26
26
|
const duration = Date.now() - compressionStart;
|
|
27
27
|
const messages = [];
|
|
28
|
-
messages.push(
|
|
28
|
+
messages.push({
|
|
29
|
+
...batch.content[0],
|
|
30
|
+
contents: JSON.stringify({ packedContents: compressedContent }),
|
|
31
|
+
metadata: batch.content[0].metadata,
|
|
32
|
+
compression: CompressionAlgorithms.lz4,
|
|
33
|
+
});
|
|
29
34
|
// Add empty placeholder messages to reserve the sequence numbers
|
|
30
35
|
for (const message of batch.content.slice(1)) {
|
|
31
36
|
messages.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opCompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opCompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpD;;;;GAIG;AACH,MAAM,OAAO,YAAY;IAGxB,YAAY,MAA4B;QACvC,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC;IACxE,CAAC;IAEM,aAAa,CAAC,KAAa;QACjC,MAAM,CACL,KAAK,CAAC,kBAAkB,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EACxD,KAAK,CAAC,+BAA+B,CACrC,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,gBAAgB,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9E,MAAM,kBAAkB,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACtD,MAAM,iBAAiB,GAAG,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC;QAE/C,MAAM,QAAQ,GAAmB,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"opCompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opCompressor.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 { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { assert, IsoBuffer } from \"@fluidframework/common-utils\";\nimport { UsageError } from \"@fluidframework/container-utils\";\nimport { compress } from \"lz4js\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { estimateSocketSize } from \"./batchManager\";\nimport { IBatch, BatchMessage } from \"./definitions\";\n\n/**\n * Compresses batches of ops. It generates a single compressed op that contains\n * the contents of each op in the batch. It then submits empty ops for each original\n * op to reserve sequence numbers.\n */\nexport class OpCompressor {\n\tprivate readonly logger;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpCompressor\" });\n\t}\n\n\tpublic compressBatch(batch: IBatch): IBatch {\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.content.length > 0,\n\t\t\t0x5a4 /* Batch should not be empty */,\n\t\t);\n\n\t\tconst compressionStart = Date.now();\n\t\tconst contentsAsBuffer = new TextEncoder().encode(this.serializeBatch(batch));\n\t\tconst compressedContents = compress(contentsAsBuffer);\n\t\tconst compressedContent = IsoBuffer.from(compressedContents).toString(\"base64\");\n\t\tconst duration = Date.now() - compressionStart;\n\n\t\tconst messages: BatchMessage[] = [];\n\t\tmessages.push({\n\t\t\t...batch.content[0],\n\t\t\tcontents: JSON.stringify({ packedContents: compressedContent }),\n\t\t\tmetadata: batch.content[0].metadata,\n\t\t\tcompression: CompressionAlgorithms.lz4,\n\t\t});\n\n\t\t// Add empty placeholder messages to reserve the sequence numbers\n\t\tfor (const message of batch.content.slice(1)) {\n\t\t\tmessages.push({\n\t\t\t\ttype: message.type,\n\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\tmetadata: message.metadata,\n\t\t\t\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t});\n\t\t}\n\n\t\tconst compressedBatch: IBatch = {\n\t\t\tcontentSizeInBytes: compressedContent.length,\n\t\t\tcontent: messages,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\n\t\tif (batch.contentSizeInBytes > 200000) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"CompressedBatch\",\n\t\t\t\tduration,\n\t\t\t\tsizeBeforeCompression: batch.contentSizeInBytes,\n\t\t\t\tsizeAfterCompression: compressedBatch.contentSizeInBytes,\n\t\t\t\topCount: compressedBatch.content.length,\n\t\t\t\tsocketSize: estimateSocketSize(compressedBatch),\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\n\t}\n\n\tprivate serializeBatch(batch: IBatch): string {\n\t\ttry {\n\t\t\treturn `[${batch.content.map((message) => message.contents).join(\",\")}]`;\n\t\t} catch (e: any) {\n\t\t\tif (e.message === \"Invalid string length\") {\n\t\t\t\t// This is how JSON.stringify signals that\n\t\t\t\t// the content size exceeds its capacity\n\t\t\t\tconst error = new UsageError(\"Payload too large\");\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"BatchTooLarge\",\n\t\t\t\t\t\tsize: batch.contentSizeInBytes,\n\t\t\t\t\t\tlength: batch.content.length,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n"]}
|
|
@@ -21,9 +21,8 @@ export class OpDecompressor {
|
|
|
21
21
|
this.logger = createChildLogger({ logger, namespace: "OpDecompressor" });
|
|
22
22
|
}
|
|
23
23
|
processMessage(message) {
|
|
24
|
-
var _a, _b, _c, _d;
|
|
25
24
|
assert(message.compression === undefined || message.compression === CompressionAlgorithms.lz4, 0x511 /* Only lz4 compression is supported */);
|
|
26
|
-
if (
|
|
25
|
+
if (message.metadata?.batch === true &&
|
|
27
26
|
this.isCompressed(message)) {
|
|
28
27
|
// Beginning of a compressed batch
|
|
29
28
|
assert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);
|
|
@@ -43,7 +42,7 @@ export class OpDecompressor {
|
|
|
43
42
|
};
|
|
44
43
|
}
|
|
45
44
|
if (this.rootMessageContents !== undefined &&
|
|
46
|
-
|
|
45
|
+
message.metadata?.batch === undefined &&
|
|
47
46
|
this.activeBatch) {
|
|
48
47
|
assert(message.contents === undefined, 0x512 /* Expecting empty message */);
|
|
49
48
|
// Continuation of compressed batch
|
|
@@ -53,7 +52,7 @@ export class OpDecompressor {
|
|
|
53
52
|
};
|
|
54
53
|
}
|
|
55
54
|
if (this.rootMessageContents !== undefined &&
|
|
56
|
-
|
|
55
|
+
message.metadata?.batch === false) {
|
|
57
56
|
// End of compressed batch
|
|
58
57
|
const returnMessage = newMessage(message, this.rootMessageContents[this.processedCount++]);
|
|
59
58
|
this.activeBatch = false;
|
|
@@ -64,7 +63,7 @@ export class OpDecompressor {
|
|
|
64
63
|
state: "Processed",
|
|
65
64
|
};
|
|
66
65
|
}
|
|
67
|
-
if (
|
|
66
|
+
if (message.metadata?.batch === undefined &&
|
|
68
67
|
this.isCompressed(message)) {
|
|
69
68
|
// Single compressed message
|
|
70
69
|
assert(this.activeBatch === false, 0x4ba /* shouldn't receive compressed message in middle of a batch */);
|
|
@@ -83,7 +82,6 @@ export class OpDecompressor {
|
|
|
83
82
|
};
|
|
84
83
|
}
|
|
85
84
|
isCompressed(message) {
|
|
86
|
-
var _a;
|
|
87
85
|
if (message.compression === CompressionAlgorithms.lz4) {
|
|
88
86
|
return true;
|
|
89
87
|
}
|
|
@@ -110,7 +108,7 @@ export class OpDecompressor {
|
|
|
110
108
|
this.logger.sendTelemetryEvent({
|
|
111
109
|
eventName: "LegacyCompression",
|
|
112
110
|
type: message.type,
|
|
113
|
-
batch:
|
|
111
|
+
batch: message.metadata?.batch,
|
|
114
112
|
});
|
|
115
113
|
return true;
|
|
116
114
|
}
|
|
@@ -122,8 +120,12 @@ export class OpDecompressor {
|
|
|
122
120
|
}
|
|
123
121
|
}
|
|
124
122
|
// We should not be mutating the input message nor its metadata
|
|
125
|
-
const newMessage = (originalMessage, contents) => (
|
|
123
|
+
const newMessage = (originalMessage, contents) => ({
|
|
124
|
+
...originalMessage,
|
|
125
|
+
contents,
|
|
126
|
+
compression: undefined,
|
|
126
127
|
// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.
|
|
127
128
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
128
|
-
metadata:
|
|
129
|
+
metadata: { ...originalMessage.metadata },
|
|
130
|
+
});
|
|
129
131
|
//# sourceMappingURL=opDecompressor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opDecompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.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 { decompress } from \"lz4js\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { assert, IsoBuffer, Uint8ArrayToString } from \"@fluidframework/common-utils\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { IBatchMetadata } from \"../metadata\";\nimport { IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Compression makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IPackedContentsContents {\n\tpackedContents: string;\n}\n\n/**\n * State machine that \"unrolls\" contents of compressed batches of ops after decompressing them.\n * This class relies on some implicit contracts defined below:\n * 1. A compressed batch will have its first message with batch metadata set to true and compressed set to true\n * 2. Messages in the middle of a compressed batch will have neither batch metadata nor the compression property set\n * 3. The final message of a batch will have batch metadata set to false\n * 4. An individually compressed op will have undefined batch metadata and compression set to true\n */\nexport class OpDecompressor {\n\tprivate activeBatch = false;\n\tprivate rootMessageContents: any | undefined;\n\tprivate processedCount = 0;\n\tprivate readonly logger;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpDecompressor\" });\n\t}\n\n\tpublic processMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tassert(\n\t\t\tmessage.compression === undefined || message.compression === CompressionAlgorithms.lz4,\n\t\t\t0x511 /* Only lz4 compression is supported */,\n\t\t);\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === true &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Beginning of a compressed batch\n\t\t\tassert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n\t\t\tif (message.compression) {\n\t\t\t\t// lz4 is the only supported compression algorithm for now\n\t\t\t\tassert(\n\t\t\t\t\tmessage.compression === CompressionAlgorithms.lz4,\n\t\t\t\t\t0x4b9 /* lz4 is currently the only supported compression algorithm */,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.activeBatch = true;\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = Uint8ArrayToString(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\t\t\tthis.rootMessageContents = asObj;\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.activeBatch\n\t\t) {\n\t\t\tassert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n\t\t\t// Continuation of compressed batch\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === false\n\t\t) {\n\t\t\t// End of compressed batch\n\t\t\tconst returnMessage = newMessage(\n\t\t\t\tmessage,\n\t\t\t\tthis.rootMessageContents[this.processedCount++],\n\t\t\t);\n\n\t\t\tthis.activeBatch = false;\n\t\t\tthis.rootMessageContents = undefined;\n\t\t\tthis.processedCount = 0;\n\n\t\t\treturn {\n\t\t\t\tmessage: returnMessage,\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Single compressed message\n\t\t\tassert(\n\t\t\t\tthis.activeBatch === false,\n\t\t\t\t0x4ba /* shouldn't receive compressed message in middle of a batch */,\n\t\t\t);\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = new TextDecoder().decode(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, asObj[0]),\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmessage,\n\t\t\tstate: \"Skipped\",\n\t\t};\n\t}\n\n\tprivate isCompressed(message: ISequencedDocumentMessage) {\n\t\tif (message.compression === CompressionAlgorithms.lz4) {\n\t\t\treturn true;\n\t\t}\n\n\t\t/**\n\t\t * Back-compat self healing mechanism for ADO:3538, as loaders from\n\t\t * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not\n\t\t * support adding the proper compression metadata to compressed messages submitted\n\t\t * by the runtime. Should be removed after the loader reaches sufficient saturation\n\t\t * for a version greater or equal than client_v2.0.0-internal.2.2.0.\n\t\t *\n\t\t * The condition holds true for compressed messages, regardless of metadata. We are ultimately\n\t\t * looking for a message with a single property `packedContents` inside `contents`, of type 'string'\n\t\t * with a base64 encoded value.\n\t\t */\n\t\ttry {\n\t\t\tif (\n\t\t\t\tmessage.contents !== null &&\n\t\t\t\ttypeof message.contents === \"object\" &&\n\t\t\t\tObject.keys(message.contents).length === 1 &&\n\t\t\t\ttypeof (message.contents as { packedContents?: unknown }).packedContents ===\n\t\t\t\t\t\"string\" &&\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents.length > 0 &&\n\t\t\t\tIsoBuffer.from(\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\t\"base64\",\n\t\t\t\t).toString(\"base64\") ===\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents\n\t\t\t) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"LegacyCompression\",\n\t\t\t\t\ttype: message.type,\n\t\t\t\t\tbatch: (message.metadata as IBatchMetadata | undefined)?.batch,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (\n\toriginalMessage: ISequencedDocumentMessage,\n\tcontents: any,\n): ISequencedDocumentMessage => ({\n\t...originalMessage,\n\tcontents,\n\tcompression: undefined,\n\t// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\tmetadata: { ...(originalMessage.metadata as any) },\n});\n"]}
|
|
1
|
+
{"version":3,"file":"opDecompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.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 { decompress } from \"lz4js\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { assert, IsoBuffer, Uint8ArrayToString } from \"@fluidframework/common-utils\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { IBatchMetadata } from \"../metadata\";\nimport { IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Compression makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IPackedContentsContents {\n\tpackedContents: string;\n}\n\n/**\n * State machine that \"unrolls\" contents of compressed batches of ops after decompressing them.\n * This class relies on some implicit contracts defined below:\n * 1. A compressed batch will have its first message with batch metadata set to true and compressed set to true\n * 2. Messages in the middle of a compressed batch will have neither batch metadata nor the compression property set\n * 3. The final message of a batch will have batch metadata set to false\n * 4. An individually compressed op will have undefined batch metadata and compression set to true\n */\nexport class OpDecompressor {\n\tprivate activeBatch = false;\n\tprivate rootMessageContents: any | undefined;\n\tprivate processedCount = 0;\n\tprivate readonly logger;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpDecompressor\" });\n\t}\n\n\tpublic processMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tassert(\n\t\t\tmessage.compression === undefined || message.compression === CompressionAlgorithms.lz4,\n\t\t\t0x511 /* Only lz4 compression is supported */,\n\t\t);\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === true &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Beginning of a compressed batch\n\t\t\tassert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n\t\t\tif (message.compression) {\n\t\t\t\t// lz4 is the only supported compression algorithm for now\n\t\t\t\tassert(\n\t\t\t\t\tmessage.compression === CompressionAlgorithms.lz4,\n\t\t\t\t\t0x4b9 /* lz4 is currently the only supported compression algorithm */,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.activeBatch = true;\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = Uint8ArrayToString(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\t\t\tthis.rootMessageContents = asObj;\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.activeBatch\n\t\t) {\n\t\t\tassert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n\t\t\t// Continuation of compressed batch\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === false\n\t\t) {\n\t\t\t// End of compressed batch\n\t\t\tconst returnMessage = newMessage(\n\t\t\t\tmessage,\n\t\t\t\tthis.rootMessageContents[this.processedCount++],\n\t\t\t);\n\n\t\t\tthis.activeBatch = false;\n\t\t\tthis.rootMessageContents = undefined;\n\t\t\tthis.processedCount = 0;\n\n\t\t\treturn {\n\t\t\t\tmessage: returnMessage,\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Single compressed message\n\t\t\tassert(\n\t\t\t\tthis.activeBatch === false,\n\t\t\t\t0x4ba /* shouldn't receive compressed message in middle of a batch */,\n\t\t\t);\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = new TextDecoder().decode(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, asObj[0]),\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmessage,\n\t\t\tstate: \"Skipped\",\n\t\t};\n\t}\n\n\tprivate isCompressed(message: ISequencedDocumentMessage) {\n\t\tif (message.compression === CompressionAlgorithms.lz4) {\n\t\t\treturn true;\n\t\t}\n\n\t\t/**\n\t\t * Back-compat self healing mechanism for ADO:3538, as loaders from\n\t\t * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not\n\t\t * support adding the proper compression metadata to compressed messages submitted\n\t\t * by the runtime. Should be removed after the loader reaches sufficient saturation\n\t\t * for a version greater or equal than client_v2.0.0-internal.2.2.0.\n\t\t *\n\t\t * The condition holds true for compressed messages, regardless of metadata. We are ultimately\n\t\t * looking for a message with a single property `packedContents` inside `contents`, of type 'string'\n\t\t * with a base64 encoded value.\n\t\t */\n\t\ttry {\n\t\t\tif (\n\t\t\t\tmessage.contents !== null &&\n\t\t\t\ttypeof message.contents === \"object\" &&\n\t\t\t\tObject.keys(message.contents).length === 1 &&\n\t\t\t\ttypeof (message.contents as { packedContents?: unknown }).packedContents ===\n\t\t\t\t\t\"string\" &&\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents.length > 0 &&\n\t\t\t\tIsoBuffer.from(\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\t\"base64\",\n\t\t\t\t).toString(\"base64\") ===\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents\n\t\t\t) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"LegacyCompression\",\n\t\t\t\t\ttype: message.type,\n\t\t\t\t\tbatch: (message.metadata as IBatchMetadata | undefined)?.batch,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (\n\toriginalMessage: ISequencedDocumentMessage,\n\tcontents: any,\n): ISequencedDocumentMessage => ({\n\t...originalMessage,\n\tcontents,\n\tcompression: undefined,\n\t// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\tmetadata: { ...(originalMessage.metadata as any) },\n});\n"]}
|