@fluidframework/container-runtime 2.0.0-internal.3.0.1 → 2.0.0-internal.3.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/.eslintrc.js +19 -19
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +9 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +80 -33
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +11 -9
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +3 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +10 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +140 -72
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +11 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +18 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +66 -15
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -3
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +26 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +103 -18
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +8 -3
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/garbageCollection.d.ts +34 -14
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +188 -93
- package/dist/garbageCollection.js.map +1 -1
- package/dist/garbageCollectionConstants.d.ts +3 -0
- package/dist/garbageCollectionConstants.d.ts.map +1 -1
- package/dist/garbageCollectionConstants.js +6 -1
- package/dist/garbageCollectionConstants.js.map +1 -1
- package/dist/garbageCollectionHelpers.d.ts +26 -0
- package/dist/garbageCollectionHelpers.d.ts.map +1 -0
- package/dist/garbageCollectionHelpers.js +45 -0
- package/dist/garbageCollectionHelpers.js.map +1 -0
- package/dist/gcSweepReadyUsageDetection.d.ts +5 -5
- package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/dist/gcSweepReadyUsageDetection.js +14 -10
- package/dist/gcSweepReadyUsageDetection.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +5 -5
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +19 -12
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +5 -2
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +4 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +19 -17
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js +1 -3
- package/dist/opProperties.js.map +1 -1
- package/dist/orderedClientElection.d.ts.map +1 -1
- package/dist/orderedClientElection.js +10 -4
- package/dist/orderedClientElection.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 +7 -0
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +7 -4
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +34 -21
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +3 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/serializedSnapshotStorage.d.ts +2 -2
- package/dist/serializedSnapshotStorage.d.ts.map +1 -1
- package/dist/serializedSnapshotStorage.js +5 -3
- package/dist/serializedSnapshotStorage.js.map +1 -1
- package/dist/summarizer.d.ts +2 -2
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +37 -17
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerClientElection.d.ts.map +1 -1
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summarizerHandle.d.ts.map +1 -1
- package/dist/summarizerHandle.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +6 -9
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +21 -21
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.d.ts.map +1 -1
- package/dist/summaryCollection.js +18 -8
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryFormat.d.ts +22 -0
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +18 -10
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +34 -15
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +21 -9
- package/dist/summaryManager.js.map +1 -1
- package/dist/throttler.d.ts +2 -2
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -4
- package/dist/throttler.js.map +1 -1
- package/garbageCollection.md +15 -2
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +9 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +82 -35
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +11 -9
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +3 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +10 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +146 -78
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +11 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +18 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +68 -17
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -3
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +26 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +109 -24
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +9 -4
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/garbageCollection.d.ts +34 -14
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +190 -95
- package/lib/garbageCollection.js.map +1 -1
- package/lib/garbageCollectionConstants.d.ts +3 -0
- package/lib/garbageCollectionConstants.d.ts.map +1 -1
- package/lib/garbageCollectionConstants.js +5 -0
- package/lib/garbageCollectionConstants.js.map +1 -1
- package/lib/garbageCollectionHelpers.d.ts +26 -0
- package/lib/garbageCollectionHelpers.d.ts.map +1 -0
- package/lib/garbageCollectionHelpers.js +40 -0
- package/lib/garbageCollectionHelpers.js.map +1 -0
- package/lib/gcSweepReadyUsageDetection.d.ts +5 -5
- package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/lib/gcSweepReadyUsageDetection.js +14 -10
- package/lib/gcSweepReadyUsageDetection.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +5 -5
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +19 -12
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +5 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +5 -2
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +19 -17
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js +1 -3
- package/lib/opProperties.js.map +1 -1
- package/lib/orderedClientElection.d.ts.map +1 -1
- package/lib/orderedClientElection.js +10 -4
- package/lib/orderedClientElection.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 +7 -0
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +7 -4
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +35 -22
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/serializedSnapshotStorage.d.ts +2 -2
- package/lib/serializedSnapshotStorage.d.ts.map +1 -1
- package/lib/serializedSnapshotStorage.js +5 -3
- package/lib/serializedSnapshotStorage.js.map +1 -1
- package/lib/summarizer.d.ts +2 -2
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +37 -17
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerClientElection.d.ts.map +1 -1
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summarizerHandle.d.ts.map +1 -1
- package/lib/summarizerHandle.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +6 -9
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +21 -21
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.d.ts.map +1 -1
- package/lib/summaryCollection.js +18 -8
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryFormat.d.ts +22 -0
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +20 -12
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +34 -15
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +21 -9
- package/lib/summaryManager.js.map +1 -1
- package/lib/throttler.d.ts +2 -2
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +121 -149
- package/prettier.config.cjs +1 -1
- package/src/batchTracker.ts +54 -49
- package/src/blobManager.ts +793 -672
- package/src/connectionTelemetry.ts +280 -249
- package/src/containerHandleContext.ts +27 -29
- package/src/containerRuntime.ts +3168 -2940
- package/src/dataStore.ts +172 -159
- package/src/dataStoreContext.ts +1098 -996
- package/src/dataStoreContexts.ts +178 -161
- package/src/dataStoreRegistry.ts +25 -20
- package/src/dataStores.ts +884 -728
- package/src/deltaScheduler.ts +158 -150
- package/src/garbageCollection.ts +1883 -1692
- package/src/garbageCollectionConstants.ts +6 -0
- package/src/garbageCollectionHelpers.ts +61 -0
- package/src/gcSweepReadyUsageDetection.ts +89 -83
- package/src/index.ts +67 -66
- package/src/opLifecycle/README.md +152 -0
- package/src/opLifecycle/batchManager.ts +145 -141
- package/src/opLifecycle/definitions.ts +29 -29
- package/src/opLifecycle/index.ts +5 -5
- package/src/opLifecycle/opCompressor.ts +54 -53
- package/src/opLifecycle/opDecompressor.ts +100 -81
- package/src/opLifecycle/opSplitter.ts +214 -188
- package/src/opLifecycle/outbox.ts +204 -194
- package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
- package/src/opProperties.ts +11 -9
- package/src/orderedClientElection.ts +489 -457
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +384 -338
- package/src/runWhileConnectedCoordinator.ts +78 -71
- package/src/runningSummarizer.ts +619 -581
- package/src/scheduleManager.ts +299 -269
- package/src/serializedSnapshotStorage.ts +126 -112
- package/src/summarizer.ts +417 -381
- package/src/summarizerClientElection.ts +107 -100
- package/src/summarizerHandle.ts +11 -9
- package/src/summarizerHeuristics.ts +183 -186
- package/src/summarizerTypes.ts +344 -330
- package/src/summaryCollection.ts +378 -349
- package/src/summaryFormat.ts +170 -126
- package/src/summaryGenerator.ts +465 -406
- package/src/summaryManager.ts +377 -348
- package/src/throttler.ts +131 -122
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.js +0 -23
- package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.js +0 -19
- package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
- package/src/garbageCollectionTombstoneUtils.ts +0 -28
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opDecompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAAmC;AAEnC,+DAAqF;AACrF,0DAA4D;AAG5D;;;;;;;GAOG;AACH,MAAa,cAAc;IAA3B;
|
|
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 { CompressionAlgorithms } from \"../containerRuntime\";\nimport { IMessageProcessingResult } from \"./definitions\";\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\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 (message.metadata?.batch === true && message.compression === CompressionAlgorithms.lz4) {\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(message.contents.packedContents, \"base64\");\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\tmessage.metadata?.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 (this.rootMessageContents !== undefined && message.metadata?.batch === false) {\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\tmessage.metadata?.batch === undefined &&\n\t\t\tmessage.compression === CompressionAlgorithms.lz4\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(message.contents.packedContents, \"base64\");\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\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\tmetadata: { ...originalMessage.metadata },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAKtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE3F;;GAEG;AACH,qBAAa,UAAU;IAOrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAPrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAGvB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EACX,aAAa,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,MAAM,CAAC,GAAG,SAAS,EAC/D,gBAAgB,EAAE,MAAM,EACxB,mBAAmB,EAAE,MAAM,EAC5C,MAAM,EAAE,gBAAgB;IAMzB,IAAW,sBAAsB,IAAI,OAAO,CAE3C;IAED,IAAW,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEjD;IAEM,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB;IAoClF,kBAAkB,CAAC,QAAQ,EAAE,MAAM;IAM1C,OAAO,CAAC,QAAQ;IA0BhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAoDlD;AAoBD,eAAO,MAAM,OAAO,OAAQ,YAAY,oBAAoB,MAAM,KAAG,UAAU,EA+B9E,CAAC"}
|
|
@@ -132,7 +132,10 @@ class OpSplitter {
|
|
|
132
132
|
}
|
|
133
133
|
exports.OpSplitter = OpSplitter;
|
|
134
134
|
const chunkToBatchMessage = (chunk, referenceSequenceNumber, metadata = undefined) => {
|
|
135
|
-
const payload = {
|
|
135
|
+
const payload = {
|
|
136
|
+
type: containerRuntime_1.ContainerMessageType.ChunkedOp,
|
|
137
|
+
contents: chunk,
|
|
138
|
+
};
|
|
136
139
|
return {
|
|
137
140
|
contents: JSON.stringify(payload),
|
|
138
141
|
deserializedContent: payload,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport { DataCorruptionError, extractSafePropertiesFromMessage } from \"@fluidframework/container-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Responsible for creating and reconstructing chunked messages.\n */\nexport class OpSplitter {\n // Local copy of incomplete received chunks.\n private readonly chunkMap: Map<string, string[]>;\n private readonly logger;\n\n constructor(\n chunks: [string, string[]][],\n private readonly submitBatchFn: ((batch: IBatchMessage[]) => number) | undefined,\n private readonly chunkSizeInBytes: number,\n private readonly maxBatchSizeInBytes: number,\n logger: ITelemetryLogger,\n ) {\n this.chunkMap = new Map<string, string[]>(chunks);\n this.logger = ChildLogger.create(logger, \"OpSplitter\");\n }\n\n public get isBatchChunkingEnabled(): boolean {\n return this.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined;\n }\n\n public get chunks(): ReadonlyMap<string, string[]> {\n return this.chunkMap;\n }\n\n public processRemoteMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n if (message.type !== ContainerMessageType.ChunkedOp) {\n return {\n message,\n state: \"Skipped\",\n };\n }\n\n const clientId = message.clientId;\n const chunkedContent = message.contents as IChunkedOp;\n this.addChunk(clientId, chunkedContent, message);\n\n if (chunkedContent.chunkId < chunkedContent.totalChunks) {\n // We are processing the op in chunks but haven't reached\n // the last chunk yet in order to reconstruct the original op\n return {\n message,\n state: \"Accepted\",\n };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const serializedContent = this.chunkMap.get(clientId)!.join(\"\");\n this.clearPartialChunks(clientId);\n\n const newMessage = { ...message };\n newMessage.contents = serializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n newMessage.type = chunkedContent.originalType;\n newMessage.metadata = chunkedContent.originalMetadata;\n newMessage.compression = chunkedContent.originalCompression;\n return {\n message: newMessage,\n state: \"Processed\",\n };\n }\n\n public clearPartialChunks(clientId: string) {\n if (this.chunkMap.has(clientId)) {\n this.chunkMap.delete(clientId);\n }\n }\n\n private addChunk(clientId: string, chunkedContent: IChunkedOp, originalMessage: ISequencedDocumentMessage) {\n let map = this.chunkMap.get(clientId);\n if (map === undefined) {\n map = [];\n this.chunkMap.set(clientId, map);\n }\n\n if (chunkedContent.chunkId !== map.length + 1) {\n // We are expecting the chunks to be processed sequentially, in the same order as they are sent.\n // Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)\n // holding the existing chunks for that particular clientId.\n throw new DataCorruptionError(\"Chunk Id mismatch\", {\n ...extractSafePropertiesFromMessage(originalMessage),\n chunkMapLength: map.length,\n chunkId: chunkedContent.chunkId,\n totalChunks: chunkedContent.totalChunks,\n });\n }\n\n map.push(chunkedContent.contents);\n }\n\n /**\n * Splits the first op of a compressed batch in chunks, sends the chunks separately and\n * returns a new batch composed of the last chunk and the rest of the ops in the original batch.\n *\n * A compressed batch is formed by one large op at the first position, followed by a series of placeholder ops\n * which are used in order to reserve the sequence numbers for when the first op gets unrolled into the original\n * uncompressed ops at ingestion in the runtime.\n *\n * If the first op is too large, it can be chunked (split into smaller op) which can be sent individually over the wire\n * and accumulate at ingestion, until the last op in the chunk is processed, when the original op is unrolled.\n *\n * This method will send the first N - 1 chunks separately and use the last chunk as the first message in the result batch\n * and then appends the original placeholder ops. This will ensure that the batch semantics of the original (non-compressed) batch\n * are preserved, as the original chunked op will be unrolled by the runtime when the first message in the batch is processed\n * (as it is the last chunk).\n *\n * To illustrate, if the input is `[largeOp, emptyOp, emptyOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4, emptyOp, emptyOp]` will be returned.\n *\n * @param batch - the compressed batch which needs to be processed\n * @returns A new adjusted batch which can be sent over the wire\n */\n public splitCompressedBatch(batch: IBatch): IBatch {\n assert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n assert(batch.contentSizeInBytes > 0 && batch.content.length > 0, 0x514 /* Batch needs to be non-empty */);\n assert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);\n assert(this.chunkSizeInBytes < this.maxBatchSizeInBytes, 0x516 /* Chunk size needs to be smaller than the max batch size */);\n\n const firstMessage = batch.content[0]; // we expect this to be the large compressed op, which needs to be split\n assert(firstMessage.metadata?.compressed === true || firstMessage.compression !== undefined, 0x517 /* Batch needs to be compressed */);\n assert((firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes, 0x518 /* First message in the batch needs to be chunkable */);\n\n const restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers\n const chunks = splitOp(firstMessage, this.chunkSizeInBytes);\n\n assert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);\n // Send the first N-1 chunks immediately\n for (const chunk of chunks.slice(0, -1)) {\n this.submitBatchFn([chunkToBatchMessage(chunk, firstMessage.referenceSequenceNumber)]);\n }\n\n // The last chunk will be part of the new batch and needs to\n // preserve the batch metadata of the original batch\n const lastChunk = chunkToBatchMessage(\n chunks[chunks.length - 1],\n firstMessage.referenceSequenceNumber,\n { batch: firstMessage.metadata?.batch });\n\n this.logger.sendPerformanceEvent({\n eventName: \"Chunked compressed batch\",\n length: batch.content.length,\n sizeInBytes: batch.contentSizeInBytes,\n chunks: chunks.length,\n chunkSizeInBytes: this.chunkSizeInBytes,\n });\n\n return {\n content: [lastChunk, ...restOfMessages],\n contentSizeInBytes: lastChunk.contents?.length ?? 0,\n };\n }\n}\n\nconst chunkToBatchMessage = (\n chunk: IChunkedOp,\n referenceSequenceNumber: number,\n metadata: Record<string, unknown> | undefined = undefined,\n): BatchMessage => {\n const payload: ContainerRuntimeMessage = { type: ContainerMessageType.ChunkedOp, contents: chunk };\n return {\n contents: JSON.stringify(payload),\n deserializedContent: payload,\n metadata,\n localOpMetadata: undefined,\n referenceSequenceNumber,\n };\n}\n\nexport const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[] => {\n const chunks: IChunkedOp[] = [];\n assert(op.contents !== undefined && op.contents !== null, 0x51a /* We should have something to chunk */);\n\n const contentLength = op.contents.length;\n const chunkN = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1;\n let offset = 0;\n for (let i = 1; i <= chunkN; i++) {\n const chunk: IChunkedOp = {\n chunkId: i,\n contents: op.contents.substr(offset, chunkSizeInBytes),\n originalType: op.deserializedContent.type,\n totalChunks: chunkN,\n }\n\n if (i === chunkN) {\n // We don't need to port these to all the chunks,\n // as we rebuild the original op when we process the\n // last chunk, therefore it is the only one that needs it.\n chunk.originalMetadata = op.metadata;\n chunk.originalCompression = op.compression;\n }\n\n chunks.push(chunk);\n offset += chunkSizeInBytes;\n }\n\n return chunks;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport {\n\tDataCorruptionError,\n\textractSafePropertiesFromMessage,\n} from \"@fluidframework/container-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Responsible for creating and reconstructing chunked messages.\n */\nexport class OpSplitter {\n\t// Local copy of incomplete received chunks.\n\tprivate readonly chunkMap: Map<string, string[]>;\n\tprivate readonly logger;\n\n\tconstructor(\n\t\tchunks: [string, string[]][],\n\t\tprivate readonly submitBatchFn: ((batch: IBatchMessage[]) => number) | undefined,\n\t\tprivate readonly chunkSizeInBytes: number,\n\t\tprivate readonly maxBatchSizeInBytes: number,\n\t\tlogger: ITelemetryLogger,\n\t) {\n\t\tthis.chunkMap = new Map<string, string[]>(chunks);\n\t\tthis.logger = ChildLogger.create(logger, \"OpSplitter\");\n\t}\n\n\tpublic get isBatchChunkingEnabled(): boolean {\n\t\treturn this.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined;\n\t}\n\n\tpublic get chunks(): ReadonlyMap<string, string[]> {\n\t\treturn this.chunkMap;\n\t}\n\n\tpublic processRemoteMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tif (message.type !== ContainerMessageType.ChunkedOp) {\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Skipped\",\n\t\t\t};\n\t\t}\n\n\t\tconst clientId = message.clientId;\n\t\tconst chunkedContent = message.contents as IChunkedOp;\n\t\tthis.addChunk(clientId, chunkedContent, message);\n\n\t\tif (chunkedContent.chunkId < chunkedContent.totalChunks) {\n\t\t\t// We are processing the op in chunks but haven't reached\n\t\t\t// the last chunk yet in order to reconstruct the original op\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst serializedContent = this.chunkMap.get(clientId)!.join(\"\");\n\t\tthis.clearPartialChunks(clientId);\n\n\t\tconst newMessage = { ...message };\n\t\tnewMessage.contents = serializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n\t\tnewMessage.type = chunkedContent.originalType;\n\t\tnewMessage.metadata = chunkedContent.originalMetadata;\n\t\tnewMessage.compression = chunkedContent.originalCompression;\n\t\treturn {\n\t\t\tmessage: newMessage,\n\t\t\tstate: \"Processed\",\n\t\t};\n\t}\n\n\tpublic clearPartialChunks(clientId: string) {\n\t\tif (this.chunkMap.has(clientId)) {\n\t\t\tthis.chunkMap.delete(clientId);\n\t\t}\n\t}\n\n\tprivate addChunk(\n\t\tclientId: string,\n\t\tchunkedContent: IChunkedOp,\n\t\toriginalMessage: ISequencedDocumentMessage,\n\t) {\n\t\tlet map = this.chunkMap.get(clientId);\n\t\tif (map === undefined) {\n\t\t\tmap = [];\n\t\t\tthis.chunkMap.set(clientId, map);\n\t\t}\n\n\t\tif (chunkedContent.chunkId !== map.length + 1) {\n\t\t\t// We are expecting the chunks to be processed sequentially, in the same order as they are sent.\n\t\t\t// Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)\n\t\t\t// holding the existing chunks for that particular clientId.\n\t\t\tthrow new DataCorruptionError(\"Chunk Id mismatch\", {\n\t\t\t\t...extractSafePropertiesFromMessage(originalMessage),\n\t\t\t\tchunkMapLength: map.length,\n\t\t\t\tchunkId: chunkedContent.chunkId,\n\t\t\t\ttotalChunks: chunkedContent.totalChunks,\n\t\t\t});\n\t\t}\n\n\t\tmap.push(chunkedContent.contents);\n\t}\n\n\t/**\n\t * Splits the first op of a compressed batch in chunks, sends the chunks separately and\n\t * returns a new batch composed of the last chunk and the rest of the ops in the original batch.\n\t *\n\t * A compressed batch is formed by one large op at the first position, followed by a series of placeholder ops\n\t * which are used in order to reserve the sequence numbers for when the first op gets unrolled into the original\n\t * uncompressed ops at ingestion in the runtime.\n\t *\n\t * If the first op is too large, it can be chunked (split into smaller op) which can be sent individually over the wire\n\t * and accumulate at ingestion, until the last op in the chunk is processed, when the original op is unrolled.\n\t *\n\t * This method will send the first N - 1 chunks separately and use the last chunk as the first message in the result batch\n\t * and then appends the original placeholder ops. This will ensure that the batch semantics of the original (non-compressed) batch\n\t * are preserved, as the original chunked op will be unrolled by the runtime when the first message in the batch is processed\n\t * (as it is the last chunk).\n\t *\n\t * To illustrate, if the input is `[largeOp, emptyOp, emptyOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n\t * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4, emptyOp, emptyOp]` will be returned.\n\t *\n\t * @param batch - the compressed batch which needs to be processed\n\t * @returns A new adjusted batch which can be sent over the wire\n\t */\n\tpublic splitCompressedBatch(batch: IBatch): IBatch {\n\t\tassert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.content.length > 0,\n\t\t\t0x514 /* Batch needs to be non-empty */,\n\t\t);\n\t\tassert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);\n\t\tassert(\n\t\t\tthis.chunkSizeInBytes < this.maxBatchSizeInBytes,\n\t\t\t0x516 /* Chunk size needs to be smaller than the max batch size */,\n\t\t);\n\n\t\tconst firstMessage = batch.content[0]; // we expect this to be the large compressed op, which needs to be split\n\t\tassert(\n\t\t\tfirstMessage.metadata?.compressed === true || firstMessage.compression !== undefined,\n\t\t\t0x517 /* Batch needs to be compressed */,\n\t\t);\n\t\tassert(\n\t\t\t(firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes,\n\t\t\t0x518 /* First message in the batch needs to be chunkable */,\n\t\t);\n\n\t\tconst restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers\n\t\tconst chunks = splitOp(firstMessage, this.chunkSizeInBytes);\n\n\t\tassert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);\n\t\t// Send the first N-1 chunks immediately\n\t\tfor (const chunk of chunks.slice(0, -1)) {\n\t\t\tthis.submitBatchFn([chunkToBatchMessage(chunk, firstMessage.referenceSequenceNumber)]);\n\t\t}\n\n\t\t// The last chunk will be part of the new batch and needs to\n\t\t// preserve the batch metadata of the original batch\n\t\tconst lastChunk = chunkToBatchMessage(\n\t\t\tchunks[chunks.length - 1],\n\t\t\tfirstMessage.referenceSequenceNumber,\n\t\t\t{ batch: firstMessage.metadata?.batch },\n\t\t);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"Chunked compressed batch\",\n\t\t\tlength: batch.content.length,\n\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\tchunks: chunks.length,\n\t\t\tchunkSizeInBytes: this.chunkSizeInBytes,\n\t\t});\n\n\t\treturn {\n\t\t\tcontent: [lastChunk, ...restOfMessages],\n\t\t\tcontentSizeInBytes: lastChunk.contents?.length ?? 0,\n\t\t};\n\t}\n}\n\nconst chunkToBatchMessage = (\n\tchunk: IChunkedOp,\n\treferenceSequenceNumber: number,\n\tmetadata: Record<string, unknown> | undefined = undefined,\n): BatchMessage => {\n\tconst payload: ContainerRuntimeMessage = {\n\t\ttype: ContainerMessageType.ChunkedOp,\n\t\tcontents: chunk,\n\t};\n\treturn {\n\t\tcontents: JSON.stringify(payload),\n\t\tdeserializedContent: payload,\n\t\tmetadata,\n\t\tlocalOpMetadata: undefined,\n\t\treferenceSequenceNumber,\n\t};\n};\n\nexport const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[] => {\n\tconst chunks: IChunkedOp[] = [];\n\tassert(\n\t\top.contents !== undefined && op.contents !== null,\n\t\t0x51a /* We should have something to chunk */,\n\t);\n\n\tconst contentLength = op.contents.length;\n\tconst chunkN = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1;\n\tlet offset = 0;\n\tfor (let i = 1; i <= chunkN; i++) {\n\t\tconst chunk: IChunkedOp = {\n\t\t\tchunkId: i,\n\t\t\tcontents: op.contents.substr(offset, chunkSizeInBytes),\n\t\t\toriginalType: op.deserializedContent.type,\n\t\t\ttotalChunks: chunkN,\n\t\t};\n\n\t\tif (i === chunkN) {\n\t\t\t// We don't need to port these to all the chunks,\n\t\t\t// as we rebuild the original op when we process the\n\t\t\t// last chunk, therefore it is the only one that needs it.\n\t\t\tchunk.originalMetadata = op.metadata;\n\t\t\tchunk.originalCompression = op.compression;\n\t\t}\n\n\t\tchunks.push(chunk);\n\t\toffset += chunkSizeInBytes;\n\t}\n\n\treturn chunks;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAU,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,aAAa;
|
|
1
|
+
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAU,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IAExD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAClD,QAAQ,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CAClC;AAED,qBAAa,MAAM;IAKN,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,iCAAiC,CAAa;gBAElC,MAAM,EAAE,iBAAiB;IAyBtD,IAAW,OAAO,IAAI,OAAO,CAE5B;IAEM,MAAM,CAAC,OAAO,EAAE,YAAY;IAW5B,YAAY,CAAC,OAAO,EAAE,YAAY;IA6BlC,KAAK;IAKZ,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IA+BrB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IA6CjB,OAAO,CAAC,YAAY;IAkBb,UAAU;;;;CAMjB"}
|
|
@@ -9,12 +9,12 @@ const common_utils_1 = require("@fluidframework/common-utils");
|
|
|
9
9
|
const container_utils_1 = require("@fluidframework/container-utils");
|
|
10
10
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
11
11
|
const batchManager_1 = require("./batchManager");
|
|
12
|
-
;
|
|
13
12
|
class Outbox {
|
|
14
13
|
constructor(params) {
|
|
15
14
|
this.params = params;
|
|
16
15
|
this.defaultAttachFlowSoftLimitInBytes = 64 * 1024;
|
|
17
|
-
const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !==
|
|
16
|
+
const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !==
|
|
17
|
+
Number.POSITIVE_INFINITY;
|
|
18
18
|
// We need to allow infinite size batches if we enable compression
|
|
19
19
|
const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
|
|
20
20
|
const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
|
|
@@ -34,9 +34,9 @@ class Outbox {
|
|
|
34
34
|
submit(message) {
|
|
35
35
|
var _a, _b;
|
|
36
36
|
if (!this.mainBatch.push(message)) {
|
|
37
|
-
throw new container_utils_1.GenericError("BatchTooLarge",
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
throw new container_utils_1.GenericError("BatchTooLarge", /* error */ undefined, {
|
|
38
|
+
opSize: (_b = (_a = message.contents) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
|
|
39
|
+
batchSize: this.mainBatch.contentSizeInBytes,
|
|
40
40
|
count: this.mainBatch.length,
|
|
41
41
|
limit: this.mainBatch.options.hardLimit,
|
|
42
42
|
});
|
|
@@ -50,9 +50,9 @@ class Outbox {
|
|
|
50
50
|
// Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
|
|
51
51
|
this.flushInternal(this.attachFlowBatch.popBatch());
|
|
52
52
|
if (!this.attachFlowBatch.push(message)) {
|
|
53
|
-
throw new container_utils_1.GenericError("BatchTooLarge",
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
throw new container_utils_1.GenericError("BatchTooLarge", /* error */ undefined, {
|
|
54
|
+
opSize: (_b = (_a = message.contents) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
|
|
55
|
+
batchSize: this.attachFlowBatch.contentSizeInBytes,
|
|
56
56
|
count: this.attachFlowBatch.length,
|
|
57
57
|
limit: this.attachFlowBatch.options.hardLimit,
|
|
58
58
|
});
|
|
@@ -63,7 +63,8 @@ class Outbox {
|
|
|
63
63
|
// of the overall size of the accumulated ops in the batch.
|
|
64
64
|
// However, it is more efficient to flush these ops faster, preferably
|
|
65
65
|
// after they reach a size which would benefit from compression.
|
|
66
|
-
if (this.attachFlowBatch.contentSizeInBytes >=
|
|
66
|
+
if (this.attachFlowBatch.contentSizeInBytes >=
|
|
67
|
+
this.params.config.compressionOptions.minimumBatchSizeInBytes) {
|
|
67
68
|
this.flushInternal(this.attachFlowBatch.popBatch());
|
|
68
69
|
}
|
|
69
70
|
}
|
|
@@ -77,9 +78,9 @@ class Outbox {
|
|
|
77
78
|
this.persistBatch(clientSequenceNumber, rawBatch.content);
|
|
78
79
|
}
|
|
79
80
|
compressBatch(batch) {
|
|
80
|
-
if (batch.content.length === 0
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
if (batch.content.length === 0 ||
|
|
82
|
+
this.params.config.compressionOptions === undefined ||
|
|
83
|
+
this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes) {
|
|
83
84
|
// Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress
|
|
84
85
|
return batch;
|
|
85
86
|
}
|
|
@@ -92,12 +93,13 @@ class Outbox {
|
|
|
92
93
|
return this.params.splitter.splitCompressedBatch(compressedBatch);
|
|
93
94
|
}
|
|
94
95
|
// If we've reached this point, the runtime would attempt to send a batch larger than the allowed size
|
|
95
|
-
throw new container_utils_1.GenericError("BatchTooLarge",
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
count:
|
|
96
|
+
throw new container_utils_1.GenericError("BatchTooLarge", /* error */ undefined, {
|
|
97
|
+
batchSize: batch.contentSizeInBytes,
|
|
98
|
+
compressedBatchSize: compressedBatch.contentSizeInBytes,
|
|
99
|
+
count: compressedBatch.content.length,
|
|
99
100
|
limit: this.params.config.maxBatchSizeInBytes,
|
|
100
|
-
|
|
101
|
+
chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
|
|
102
|
+
compressionOptions: JSON.stringify(this.params.config.compressionOptions),
|
|
101
103
|
});
|
|
102
104
|
}
|
|
103
105
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainerContext } from \"@fluidframework/container-definitions\";\nimport { GenericError } from \"@fluidframework/container-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ICompressionRuntimeOptions } from \"../containerRuntime\";\nimport { PendingStateManager } from \"../pendingStateManager\";\nimport { BatchManager } from \"./batchManager\";\nimport { BatchMessage, IBatch } from \"./definitions\";\nimport { OpCompressor } from \"./opCompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport interface IOutboxConfig {\n readonly compressionOptions: ICompressionRuntimeOptions;\n // The maximum size of a batch that we can send over the wire.\n readonly maxBatchSizeInBytes: number;\n readonly enableOpReentryCheck?: boolean;\n};\n\nexport interface IOutboxParameters {\n readonly shouldSend: () => boolean,\n readonly pendingStateManager: PendingStateManager,\n readonly containerContext: IContainerContext,\n readonly config: IOutboxConfig,\n readonly compressor: OpCompressor;\n readonly splitter: OpSplitter;\n readonly logger: ITelemetryLogger;\n}\n\nexport class Outbox {\n private readonly attachFlowBatch: BatchManager;\n private readonly mainBatch: BatchManager;\n private readonly defaultAttachFlowSoftLimitInBytes = 64 * 1024;\n\n constructor(private readonly params: IOutboxParameters) {\n const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY;\n // We need to allow infinite size batches if we enable compression\n const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;\n const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;\n\n this.attachFlowBatch = new BatchManager({\n hardLimit,\n softLimit,\n enableOpReentryCheck: params.config.enableOpReentryCheck,\n }, params.logger);\n this.mainBatch = new BatchManager({\n hardLimit,\n enableOpReentryCheck: params.config.enableOpReentryCheck,\n }, params.logger);\n }\n\n public get isEmpty(): boolean {\n return this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;\n }\n\n public submit(message: BatchMessage) {\n if (!this.mainBatch.push(message)) {\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: (message.contents?.length) ?? 0,\n count: this.mainBatch.length,\n limit: this.mainBatch.options.hardLimit,\n });\n }\n }\n\n public submitAttach(message: BatchMessage) {\n if (!this.attachFlowBatch.push(message)) {\n // BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged\n // when queue is not empty.\n // Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit\n this.flushInternal(this.attachFlowBatch.popBatch());\n if (!this.attachFlowBatch.push(message)) {\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: (message.contents?.length) ?? 0,\n count: this.attachFlowBatch.length,\n limit: this.attachFlowBatch.options.hardLimit,\n });\n }\n }\n\n // If compression is enabled, we will always successfully receive\n // attach ops and compress then send them at the next JS turn, regardless\n // of the overall size of the accumulated ops in the batch.\n // However, it is more efficient to flush these ops faster, preferably\n // after they reach a size which would benefit from compression.\n if (this.attachFlowBatch.contentSizeInBytes >= this.params.config.compressionOptions.minimumBatchSizeInBytes) {\n this.flushInternal(this.attachFlowBatch.popBatch());\n }\n }\n\n public flush() {\n this.flushInternal(this.attachFlowBatch.popBatch());\n this.flushInternal(this.mainBatch.popBatch());\n }\n\n private flushInternal(rawBatch: IBatch) {\n const processedBatch = this.compressBatch(rawBatch);\n const clientSequenceNumber = this.sendBatch(processedBatch);\n\n this.persistBatch(clientSequenceNumber, rawBatch.content);\n }\n\n private compressBatch(batch: IBatch): IBatch {\n if (batch.content.length === 0\n || this.params.config.compressionOptions === undefined\n || this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes) {\n // Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress\n return batch;\n }\n\n const compressedBatch = this.params.compressor.compressBatch(batch);\n if (compressedBatch.contentSizeInBytes <= this.params.config.maxBatchSizeInBytes) {\n // If we don't reach the maximum supported size of a batch, it can safely be sent as is\n return compressedBatch;\n }\n\n if (this.params.splitter.isBatchChunkingEnabled) {\n return this.params.splitter.splitCompressedBatch(compressedBatch);\n }\n\n // If we've reached this point, the runtime would attempt to send a batch larger than the allowed size\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: batch.contentSizeInBytes,\n count: batch.content.length,\n limit: this.params.config.maxBatchSizeInBytes,\n compressed: true,\n });\n }\n\n /**\n * Sends the batch object to the container context to be sent over the wire.\n *\n * @param batch - batch to be sent\n * @returns the client sequence number of the last batched op which was sent and\n * -1 if there are no ops or the container cannot send ops.\n */\n private sendBatch(batch: IBatch): number {\n let clientSequenceNumber: number = -1;\n const length = batch.content.length;\n\n // Did we disconnect in the middle of turn-based batch?\n // If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n if (length === 0 || !this.params.shouldSend()) {\n return clientSequenceNumber;\n }\n\n if (this.params.containerContext.submitBatchFn === undefined) {\n // Legacy path - supporting old loader versions. Can be removed only when LTS moves above\n // version that has support for batches (submitBatchFn)\n for (const message of batch.content) {\n // Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways\n if (message.metadata?.compressed) {\n delete message.metadata.compressed;\n }\n\n clientSequenceNumber = this.params.containerContext.submitFn(\n MessageType.Operation,\n message.deserializedContent,\n true, // batch\n message.metadata);\n }\n\n this.params.containerContext.deltaManager.flush();\n } else {\n // returns clientSequenceNumber of last message in a batch\n clientSequenceNumber = this.params.containerContext.submitBatchFn(\n batch.content.map((message) => ({\n contents: message.contents,\n metadata: message.metadata,\n compression: message.compression,\n })));\n }\n\n // Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.\n clientSequenceNumber -= length - 1;\n assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);\n return clientSequenceNumber;\n }\n\n private persistBatch(initialClientSequenceNumber: number, batch: BatchMessage[]) {\n let clientSequenceNumber = initialClientSequenceNumber;\n // Let the PendingStateManager know that a message was submitted.\n // In future, need to shift toward keeping batch as a whole!\n for (const message of batch) {\n this.params.pendingStateManager.onSubmitMessage(\n message.deserializedContent.type,\n clientSequenceNumber,\n message.referenceSequenceNumber,\n message.deserializedContent.contents,\n message.localOpMetadata,\n message.metadata,\n );\n\n clientSequenceNumber++;\n }\n }\n\n public checkpoint() {\n return {\n mainBatch: this.mainBatch.checkpoint(),\n attachFlowBatch: this.attachFlowBatch.checkpoint(),\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainerContext } from \"@fluidframework/container-definitions\";\nimport { GenericError } from \"@fluidframework/container-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ICompressionRuntimeOptions } from \"../containerRuntime\";\nimport { PendingStateManager } from \"../pendingStateManager\";\nimport { BatchManager } from \"./batchManager\";\nimport { BatchMessage, IBatch } from \"./definitions\";\nimport { OpCompressor } from \"./opCompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t// The maximum size of a batch that we can send over the wire.\n\treadonly maxBatchSizeInBytes: number;\n\treadonly enableOpReentryCheck?: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly containerContext: IContainerContext;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryLogger;\n}\n\nexport class Outbox {\n\tprivate readonly attachFlowBatch: BatchManager;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly defaultAttachFlowSoftLimitInBytes = 64 * 1024;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tconst isCompressionEnabled =\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes !==\n\t\t\tNumber.POSITIVE_INFINITY;\n\t\t// We need to allow infinite size batches if we enable compression\n\t\tconst hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;\n\t\tconst softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;\n\n\t\tthis.attachFlowBatch = new BatchManager(\n\t\t\t{\n\t\t\t\thardLimit,\n\t\t\t\tsoftLimit,\n\t\t\t\tenableOpReentryCheck: params.config.enableOpReentryCheck,\n\t\t\t},\n\t\t\tparams.logger,\n\t\t);\n\t\tthis.mainBatch = new BatchManager(\n\t\t\t{\n\t\t\t\thardLimit,\n\t\t\t\tenableOpReentryCheck: params.config.enableOpReentryCheck,\n\t\t\t},\n\t\t\tparams.logger,\n\t\t);\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;\n\t}\n\n\tpublic submit(message: BatchMessage) {\n\t\tif (!this.mainBatch.push(message)) {\n\t\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\t\topSize: message.contents?.length ?? 0,\n\t\t\t\tbatchSize: this.mainBatch.contentSizeInBytes,\n\t\t\t\tcount: this.mainBatch.length,\n\t\t\t\tlimit: this.mainBatch.options.hardLimit,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic submitAttach(message: BatchMessage) {\n\t\tif (!this.attachFlowBatch.push(message)) {\n\t\t\t// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged\n\t\t\t// when queue is not empty.\n\t\t\t// Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit\n\t\t\tthis.flushInternal(this.attachFlowBatch.popBatch());\n\t\t\tif (!this.attachFlowBatch.push(message)) {\n\t\t\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\t\t\topSize: message.contents?.length ?? 0,\n\t\t\t\t\tbatchSize: this.attachFlowBatch.contentSizeInBytes,\n\t\t\t\t\tcount: this.attachFlowBatch.length,\n\t\t\t\t\tlimit: this.attachFlowBatch.options.hardLimit,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// If compression is enabled, we will always successfully receive\n\t\t// attach ops and compress then send them at the next JS turn, regardless\n\t\t// of the overall size of the accumulated ops in the batch.\n\t\t// However, it is more efficient to flush these ops faster, preferably\n\t\t// after they reach a size which would benefit from compression.\n\t\tif (\n\t\t\tthis.attachFlowBatch.contentSizeInBytes >=\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes\n\t\t) {\n\t\t\tthis.flushInternal(this.attachFlowBatch.popBatch());\n\t\t}\n\t}\n\n\tpublic flush() {\n\t\tthis.flushInternal(this.attachFlowBatch.popBatch());\n\t\tthis.flushInternal(this.mainBatch.popBatch());\n\t}\n\n\tprivate flushInternal(rawBatch: IBatch) {\n\t\tconst processedBatch = this.compressBatch(rawBatch);\n\t\tconst clientSequenceNumber = this.sendBatch(processedBatch);\n\n\t\tthis.persistBatch(clientSequenceNumber, rawBatch.content);\n\t}\n\n\tprivate compressBatch(batch: IBatch): IBatch {\n\t\tif (\n\t\t\tbatch.content.length === 0 ||\n\t\t\tthis.params.config.compressionOptions === undefined ||\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes\n\t\t) {\n\t\t\t// Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress\n\t\t\treturn batch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(batch);\n\t\tif (compressedBatch.contentSizeInBytes <= this.params.config.maxBatchSizeInBytes) {\n\t\t\t// If we don't reach the maximum supported size of a batch, it can safely be sent as is\n\t\t\treturn compressedBatch;\n\t\t}\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn this.params.splitter.splitCompressedBatch(compressedBatch);\n\t\t}\n\n\t\t// If we've reached this point, the runtime would attempt to send a batch larger than the allowed size\n\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\tbatchSize: batch.contentSizeInBytes,\n\t\t\tcompressedBatchSize: compressedBatch.contentSizeInBytes,\n\t\t\tcount: compressedBatch.content.length,\n\t\t\tlimit: this.params.config.maxBatchSizeInBytes,\n\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t});\n\t}\n\n\t/**\n\t * Sends the batch object to the container context to be sent over the wire.\n\t *\n\t * @param batch - batch to be sent\n\t * @returns the client sequence number of the last batched op which was sent and\n\t * -1 if there are no ops or the container cannot send ops.\n\t */\n\tprivate sendBatch(batch: IBatch): number {\n\t\tlet clientSequenceNumber: number = -1;\n\t\tconst length = batch.content.length;\n\n\t\t// Did we disconnect in the middle of turn-based batch?\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\tif (length === 0 || !this.params.shouldSend()) {\n\t\t\treturn clientSequenceNumber;\n\t\t}\n\n\t\tif (this.params.containerContext.submitBatchFn === undefined) {\n\t\t\t// Legacy path - supporting old loader versions. Can be removed only when LTS moves above\n\t\t\t// version that has support for batches (submitBatchFn)\n\t\t\tfor (const message of batch.content) {\n\t\t\t\t// Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways\n\t\t\t\tif (message.metadata?.compressed) {\n\t\t\t\t\tdelete message.metadata.compressed;\n\t\t\t\t}\n\n\t\t\t\tclientSequenceNumber = this.params.containerContext.submitFn(\n\t\t\t\t\tMessageType.Operation,\n\t\t\t\t\tmessage.deserializedContent,\n\t\t\t\t\ttrue, // batch\n\t\t\t\t\tmessage.metadata,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.params.containerContext.deltaManager.flush();\n\t\t} else {\n\t\t\t// returns clientSequenceNumber of last message in a batch\n\t\t\tclientSequenceNumber = this.params.containerContext.submitBatchFn(\n\t\t\t\tbatch.content.map((message) => ({\n\t\t\t\t\tcontents: message.contents,\n\t\t\t\t\tmetadata: message.metadata,\n\t\t\t\t\tcompression: message.compression,\n\t\t\t\t})),\n\t\t\t);\n\t\t}\n\n\t\t// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.\n\t\tclientSequenceNumber -= length - 1;\n\t\tassert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);\n\t\treturn clientSequenceNumber;\n\t}\n\n\tprivate persistBatch(initialClientSequenceNumber: number, batch: BatchMessage[]) {\n\t\tlet clientSequenceNumber = initialClientSequenceNumber;\n\t\t// Let the PendingStateManager know that a message was submitted.\n\t\t// In future, need to shift toward keeping batch as a whole!\n\t\tfor (const message of batch) {\n\t\t\tthis.params.pendingStateManager.onSubmitMessage(\n\t\t\t\tmessage.deserializedContent.type,\n\t\t\t\tclientSequenceNumber,\n\t\t\t\tmessage.referenceSequenceNumber,\n\t\t\t\tmessage.deserializedContent.contents,\n\t\t\t\tmessage.localOpMetadata,\n\t\t\t\tmessage.metadata,\n\t\t\t);\n\n\t\t\tclientSequenceNumber++;\n\t\t}\n\t}\n\n\tpublic checkpoint() {\n\t\treturn {\n\t\t\tmainBatch: this.mainBatch.checkpoint(),\n\t\t\tattachFlowBatch: this.attachFlowBatch.checkpoint(),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAe,MAAM,sCAAsC,CAAC;AAE9F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,qBAAa,sBAAsB;
|
|
1
|
+
{"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAe,MAAM,sCAAsC,CAAC;AAE9F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,qBAAa,sBAAsB;IAEjC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADd,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc;IAGhD,IAAW,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,MAAM;IAIxC,OAAO,CAAC,aAAa,EAAE,yBAAyB,GAAG,yBAAyB;CAyBnF;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAkBhF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteMessageProcessor.js","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA8F;AAC9F,0DAAoF;AAIpF,MAAa,sBAAsB;
|
|
1
|
+
{"version":3,"file":"remoteMessageProcessor.js","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA8F;AAC9F,0DAAoF;AAIpF,MAAa,sBAAsB;IAClC,YACkB,UAAsB,EACtB,cAA8B;QAD9B,eAAU,GAAV,UAAU,CAAY;QACtB,mBAAc,GAAd,cAAc,CAAgB;IAC7C,CAAC;IAEJ,IAAW,eAAe;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;IAC/B,CAAC;IAEM,uBAAuB,CAAC,QAAgB;QAC9C,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAEM,OAAO,CAAC,aAAwC;QACtD,IAAI,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAClC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;QAC9D,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAE9B,MAAM,qBAAqB,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC5E,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC;QACxC,IAAI,qBAAqB,CAAC,KAAK,KAAK,WAAW,EAAE;YAChD,6FAA6F;YAC7F,0CAA0C;YAC1C,OAAO,OAAO,CAAC;SACf;QAED,MAAM,0BAA0B,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC/E,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC;QAC7C,IAAI,0BAA0B,CAAC,KAAK,KAAK,SAAS,EAAE;YACnD,8DAA8D;YAC9D,0CAA0C;YAC1C,OAAO,OAAO,CAAC;SACf;QAED,kEAAkE;QAClE,MAAM,CAAC,OAAO,CAAC,CAAC;QAChB,OAAO,OAAO,CAAC;IAChB,CAAC;CACD;AAvCD,wDAuCC;AAED,MAAM,IAAI,GAAG,CAAC,aAAwC,EAA6B,EAAE;IACpF,qEAAqE;IACrE,qEAAqE;IACrE,4FAA4F;IAC5F,wCAAwC;IACxC,MAAM,OAAO,qBAAQ,aAAa,CAAE,CAAC;IAErC,iGAAiG;IACjG,+GAA+G;IAC/G,qDAAqD;IACrD,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,EAAE,EAAE;QACpE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;KAChD;IAED,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,GAAG,CAAC,OAAkC,EAAE,EAAE;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,QAAmC,CAAC;IAClE,OAAO,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC;IAClC,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAC3C,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAgB,oBAAoB,CAAC,OAAkC;IACtE,IAAI,OAAO,CAAC,IAAI,KAAK,kCAAW,CAAC,SAAS,EAAE;QAC3C,8CAA8C;QAC9C,sDAAsD;QACtD,+BAA+B;QAC/B,8BAA8B;QAC9B,OAAO,KAAK,CAAC;KACb;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE;QAClF,OAAO,CAAC,IAAI,GAAG,uCAAoB,CAAC,gBAAgB,CAAC;KACrD;SAAM;QACN,aAAa;QACb,MAAM,CAAC,OAAO,CAAC,CAAC;KAChB;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAlBD,oDAkBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { OpDecompressor } from \"./opDecompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport class RemoteMessageProcessor {\n\tconstructor(\n\t\tprivate readonly opSplitter: OpSplitter,\n\t\tprivate readonly opDecompressor: OpDecompressor,\n\t) {}\n\n\tpublic get partialMessages(): ReadonlyMap<string, string[]> {\n\t\treturn this.opSplitter.chunks;\n\t}\n\n\tpublic clearPartialMessagesFor(clientId: string) {\n\t\tthis.opSplitter.clearPartialChunks(clientId);\n\t}\n\n\tpublic process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {\n\t\tlet message = copy(remoteMessage);\n\t\tmessage = this.opDecompressor.processMessage(message).message;\n\t\tunpackRuntimeMessage(message);\n\n\t\tconst chunkProcessingResult = this.opSplitter.processRemoteMessage(message);\n\t\tmessage = chunkProcessingResult.message;\n\t\tif (chunkProcessingResult.state !== \"Processed\") {\n\t\t\t// If the message is not chunked or if the splitter is still rebuilding the original message,\n\t\t\t// there is no need to continue processing\n\t\t\treturn message;\n\t\t}\n\n\t\tconst decompressionAfterChunking = this.opDecompressor.processMessage(message);\n\t\tmessage = decompressionAfterChunking.message;\n\t\tif (decompressionAfterChunking.state === \"Skipped\") {\n\t\t\t// After chunking, if the original message was not compressed,\n\t\t\t// there is no need to continue processing\n\t\t\treturn message;\n\t\t}\n\n\t\t// The message needs to be unpacked after chunking + decompression\n\t\tunpack(message);\n\t\treturn message;\n\t}\n}\n\nconst copy = (remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage => {\n\t// Do shallow copy of message, as the processing flow will modify it.\n\t// There might be multiple container instances receiving same message\n\t// We do not need to make deep copy, as each layer will just replace message.content itself,\n\t// but would not modify contents details\n\tconst message = { ...remoteMessage };\n\n\t// back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!\n\t// System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.\n\t// Old ops may contain empty string (I assume noops).\n\tif (typeof message.contents === \"string\" && message.contents !== \"\") {\n\t\tmessage.contents = JSON.parse(message.contents);\n\t}\n\n\treturn message;\n};\n\n/**\n * For a given message, it moves the nested contents and type on level up.\n *\n */\nconst unpack = (message: ISequencedDocumentMessage) => {\n\tconst innerContents = message.contents as ContainerRuntimeMessage;\n\tmessage.type = innerContents.type;\n\tmessage.contents = innerContents.contents;\n};\n\n/**\n * Unpacks runtime messages.\n *\n * @remarks This API makes no promises regarding backward-compatibility. This is internal API.\n * @param message - message (as it observed in storage / service)\n * @returns unpacked runtime message\n *\n * @internal\n */\nexport function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolean {\n\tif (message.type !== MessageType.Operation) {\n\t\t// Legacy format, but it's already \"unpacked\",\n\t\t// i.e. message.type is actually ContainerMessageType.\n\t\t// Or it's non-runtime message.\n\t\t// Nothing to do in such case.\n\t\treturn false;\n\t}\n\n\t// legacy op format?\n\tif (message.contents.address !== undefined && message.contents.type === undefined) {\n\t\tmessage.type = ContainerMessageType.FluidDataStoreOp;\n\t} else {\n\t\t// new format\n\t\tunpack(message);\n\t}\n\n\treturn true;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opProperties.d.ts","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"opProperties.d.ts","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,yBAAyB,EAEzB,MAAM,sCAAsC,CAAC;AAE9C,eAAO,MAAM,MAAM,OAAQ,yBAAyB,KAAG,MAOtD,CAAC"}
|
package/dist/opProperties.js
CHANGED
|
@@ -9,9 +9,7 @@ const opSize = (op) => {
|
|
|
9
9
|
var _a;
|
|
10
10
|
// Some messages may already have string contents,
|
|
11
11
|
// so stringifying them again will add inaccurate overhead.
|
|
12
|
-
const content = typeof op.contents === "string" ?
|
|
13
|
-
op.contents :
|
|
14
|
-
(_a = JSON.stringify(op.contents)) !== null && _a !== void 0 ? _a : "";
|
|
12
|
+
const content = typeof op.contents === "string" ? op.contents : (_a = JSON.stringify(op.contents)) !== null && _a !== void 0 ? _a : "";
|
|
15
13
|
const data = opHasData(op) ? op.data : "";
|
|
16
14
|
return content.length + data.length;
|
|
17
15
|
};
|
package/dist/opProperties.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opProperties.js","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;
|
|
1
|
+
{"version":3,"file":"opProperties.js","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAOI,MAAM,MAAM,GAAG,CAAC,EAA6B,EAAU,EAAE;;IAC/D,kDAAkD;IAClD,2DAA2D;IAC3D,MAAM,OAAO,GACZ,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAA,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,mCAAI,EAAE,CAAC;IACnF,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,OAAO,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;AACrC,CAAC,CAAC;AAPW,QAAA,MAAM,UAOjB;AAEF,MAAM,SAAS,GAAG,CAAC,EAA6B,EAAyC,EAAE,CACzF,EAAsC,CAAC,IAAI,KAAK,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tISequencedDocumentMessage,\n\tISequencedDocumentSystemMessage,\n} from \"@fluidframework/protocol-definitions\";\n\nexport const opSize = (op: ISequencedDocumentMessage): number => {\n\t// Some messages may already have string contents,\n\t// so stringifying them again will add inaccurate overhead.\n\tconst content =\n\t\ttypeof op.contents === \"string\" ? op.contents : JSON.stringify(op.contents) ?? \"\";\n\tconst data = opHasData(op) ? op.data : \"\";\n\treturn content.length + data.length;\n};\n\nconst opHasData = (op: ISequencedDocumentMessage): op is ISequencedDocumentSystemMessage =>\n\t(op as ISequencedDocumentSystemMessage).data !== undefined;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orderedClientElection.d.ts","sourceRoot":"","sources":["../src/orderedClientElection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC9F,OAAO,EAAU,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAEtE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAoB,MAAM,sCAAsC,CAAC;AAMjG,oBAAY,mBAAmB,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAC1F,oBAAY,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,mBAAmB,
|
|
1
|
+
{"version":3,"file":"orderedClientElection.d.ts","sourceRoot":"","sources":["../src/orderedClientElection.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,7 +38,11 @@ class OrderedClientCollection extends common_utils_1.TypedEventEmitter {
|
|
|
38
38
|
const sequenceNumber = deltaManager.lastSequenceNumber;
|
|
39
39
|
const removeClient = this.removeClient(clientId);
|
|
40
40
|
if (removeClient === undefined) {
|
|
41
|
-
this.logger.sendErrorEvent({
|
|
41
|
+
this.logger.sendErrorEvent({
|
|
42
|
+
eventName: "ClientNotFound",
|
|
43
|
+
clientId,
|
|
44
|
+
sequenceNumber,
|
|
45
|
+
});
|
|
42
46
|
}
|
|
43
47
|
else {
|
|
44
48
|
this.emit("removeClient", removeClient, sequenceNumber);
|
|
@@ -263,7 +267,8 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
|
|
|
263
267
|
findFirstEligibleParent(client) {
|
|
264
268
|
let candidateClient = client;
|
|
265
269
|
while (candidateClient !== undefined &&
|
|
266
|
-
(!this.isEligibleFn(candidateClient) ||
|
|
270
|
+
(!this.isEligibleFn(candidateClient) ||
|
|
271
|
+
candidateClient.client.details.type === summarizerClientElection_1.summarizerClientType)) {
|
|
267
272
|
candidateClient = candidateClient.youngerClient;
|
|
268
273
|
}
|
|
269
274
|
return candidateClient;
|
|
@@ -281,7 +286,8 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
|
|
|
281
286
|
const newClientIsSummarizer = client.client.details.type === summarizerClientElection_1.summarizerClientType;
|
|
282
287
|
const electedClientIsSummarizer = ((_a = this._electedClient) === null || _a === void 0 ? void 0 : _a.client.details.type) === summarizerClientElection_1.summarizerClientType;
|
|
283
288
|
// Note that we allow a summarizer client to supercede an interactive client as elected client.
|
|
284
|
-
if (this._electedClient === undefined ||
|
|
289
|
+
if (this._electedClient === undefined ||
|
|
290
|
+
(!electedClientIsSummarizer && newClientIsSummarizer)) {
|
|
285
291
|
this.tryElectingClient(client, sequenceNumber);
|
|
286
292
|
}
|
|
287
293
|
else if (this._electedParent === undefined && !newClientIsSummarizer) {
|
|
@@ -365,7 +371,7 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
|
|
|
365
371
|
}
|
|
366
372
|
peekNextElectedClient() {
|
|
367
373
|
var _a, _b;
|
|
368
|
-
return (_b = this.findFirstEligibleParent((_a = this._electedParent) === null || _a === void 0 ? void 0 : _a.youngerClient)) !== null && _b !== void 0 ? _b : this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);
|
|
374
|
+
return ((_b = this.findFirstEligibleParent((_a = this._electedParent) === null || _a === void 0 ? void 0 : _a.youngerClient)) !== null && _b !== void 0 ? _b : this.findFirstEligibleParent(this.orderedClientCollection.oldestClient));
|
|
369
375
|
}
|
|
370
376
|
serialize() {
|
|
371
377
|
var _a, _b;
|