@fluidframework/container-runtime 2.41.0-338401 → 2.42.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 +8 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/channelCollection.d.ts +1 -1
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +4 -4
- package/dist/channelCollection.js.map +1 -1
- package/dist/compatUtils.d.ts +22 -1
- package/dist/compatUtils.d.ts.map +1 -1
- package/dist/compatUtils.js +109 -7
- package/dist/compatUtils.js.map +1 -1
- package/dist/containerRuntime.d.ts +67 -28
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +332 -186
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +5 -0
- package/dist/dataStore.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +2 -0
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +1 -1
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.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/messageTypes.d.ts +5 -4
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/metadata.d.ts +1 -1
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +4 -0
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +7 -0
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +6 -5
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +9 -0
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +6 -4
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSerialization.d.ts +2 -1
- package/dist/opLifecycle/opSerialization.d.ts.map +1 -1
- package/dist/opLifecycle/opSerialization.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +1 -0
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +6 -1
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +22 -5
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +34 -11
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runCounter.d.ts.map +1 -1
- package/dist/runCounter.js +1 -1
- package/dist/runCounter.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +42 -18
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +62 -52
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/index.d.ts +1 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js.map +1 -1
- package/lib/channelCollection.d.ts +1 -1
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +4 -4
- package/lib/channelCollection.js.map +1 -1
- package/lib/compatUtils.d.ts +22 -1
- package/lib/compatUtils.d.ts.map +1 -1
- package/lib/compatUtils.js +102 -3
- package/lib/compatUtils.js.map +1 -1
- package/lib/containerRuntime.d.ts +67 -28
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +333 -188
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +5 -0
- package/lib/dataStore.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +2 -0
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +1 -1
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.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/messageTypes.d.ts +5 -4
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/metadata.d.ts +1 -1
- package/lib/metadata.d.ts.map +1 -1
- package/lib/metadata.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +4 -0
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +7 -0
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +6 -5
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +9 -0
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +6 -4
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSerialization.d.ts +2 -1
- package/lib/opLifecycle/opSerialization.d.ts.map +1 -1
- package/lib/opLifecycle/opSerialization.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +1 -0
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +6 -1
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +22 -5
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +34 -11
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runCounter.d.ts.map +1 -1
- package/lib/runCounter.js +1 -1
- package/lib/runCounter.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +42 -18
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +62 -52
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/index.d.ts +1 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js.map +1 -1
- package/package.json +19 -19
- package/src/channelCollection.ts +4 -4
- package/src/compatUtils.ts +145 -10
- package/src/containerRuntime.ts +472 -225
- package/src/dataStore.ts +7 -0
- package/src/gc/garbageCollection.ts +2 -0
- package/src/gc/gcDefinitions.ts +1 -1
- package/src/index.ts +2 -1
- package/src/messageTypes.ts +12 -5
- package/src/metadata.ts +1 -1
- package/src/opLifecycle/batchManager.ts +8 -0
- package/src/opLifecycle/definitions.ts +7 -3
- package/src/opLifecycle/index.ts +1 -0
- package/src/opLifecycle/opGroupingManager.ts +17 -4
- package/src/opLifecycle/opSerialization.ts +6 -1
- package/src/opLifecycle/outbox.ts +8 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +64 -20
- package/src/runCounter.ts +4 -1
- package/src/summary/documentSchema.ts +111 -86
- package/src/summary/index.ts +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opGroupingManager.js","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,kEAA6D;AAE7D,uEAGkD;AAsBlD,SAAS,eAAe,CAAC,UAAmB;IAC3C,OAAO,CACL,UAAoD,EAAE,IAAI;QAC3D,iBAAiB,CAAC,cAAc,CAChC,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,EAA6B;IAC3D,OAAO,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAFD,wCAEC;
|
|
1
|
+
{"version":3,"file":"opGroupingManager.js","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.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 { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport {\n\ttype LocalEmptyBatchPlaceholder,\n\ttype OutboundBatch,\n\ttype OutboundSingletonBatch,\n} from \"./definitions.js\";\n\n/**\n * Grouping makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IGroupedBatchMessageContents {\n\ttype: typeof OpGroupingManager.groupedBatchOp;\n\tcontents: IGroupedMessage[];\n}\n\ninterface IGroupedMessage {\n\tcontents?: unknown;\n\tmetadata?: Record<string, unknown>;\n\tcompression?: string;\n}\n\nfunction isGroupContents(opContents: unknown): opContents is IGroupedBatchMessageContents {\n\treturn (\n\t\t(opContents as Partial<IGroupedBatchMessageContents>)?.type ===\n\t\tOpGroupingManager.groupedBatchOp\n\t);\n}\n\nexport function isGroupedBatch(op: ISequencedDocumentMessage): boolean {\n\treturn isGroupContents(op.contents);\n}\n\nexport interface OpGroupingManagerConfig {\n\treadonly groupedBatchingEnabled: boolean;\n}\n\n/**\n * This is the type of an empty grouped batch we send over the wire\n * We also put this in the placeholder for an empty batch in the PendingStateManager.\n * But most places throughout the ContainerRuntime, this will not be used (just as Grouped Batches in general don't appear outside opLifecycle dir)\n */\nexport interface EmptyGroupedBatch {\n\ttype: typeof OpGroupingManager.groupedBatchOp;\n\tcontents: readonly unknown[];\n}\n\nexport class OpGroupingManager {\n\tstatic readonly groupedBatchOp = \"groupedBatch\";\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tconstructor(\n\t\tprivate readonly config: OpGroupingManagerConfig,\n\t\tlogger: ITelemetryBaseLogger,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpGroupingManager\" });\n\t}\n\n\t/**\n\t * Creates a new batch with a single message of type \"groupedBatch\" and empty contents.\n\t * This is needed as a placeholder if a batch becomes empty on resubmit, but we are tracking batch IDs.\n\t * @param resubmittingBatchId - batch ID of the resubmitting batch\n\t * @param referenceSequenceNumber - reference sequence number\n\t * @returns - The outbound batch as well as the interior placeholder message\n\t */\n\tpublic createEmptyGroupedBatch(\n\t\tresubmittingBatchId: string,\n\t\treferenceSequenceNumber: number,\n\t): {\n\t\toutboundBatch: OutboundSingletonBatch;\n\t\tplaceholderMessage: LocalEmptyBatchPlaceholder;\n\t} {\n\t\tassert(\n\t\t\tthis.config.groupedBatchingEnabled,\n\t\t\t0xa00 /* cannot create empty grouped batch when grouped batching is disabled */,\n\t\t);\n\n\t\tconst emptyGroupedBatch: EmptyGroupedBatch = {\n\t\t\ttype: \"groupedBatch\",\n\t\t\tcontents: [],\n\t\t};\n\t\tconst serializedOp = JSON.stringify(emptyGroupedBatch);\n\n\t\tconst placeholderMessage: LocalEmptyBatchPlaceholder = {\n\t\t\tmetadata: { batchId: resubmittingBatchId },\n\t\t\tlocalOpMetadata: { emptyBatch: true },\n\t\t\treferenceSequenceNumber,\n\t\t\truntimeOp: emptyGroupedBatch,\n\t\t};\n\t\tconst outboundBatch: OutboundSingletonBatch = {\n\t\t\tcontentSizeInBytes: 0,\n\t\t\tmessages: [{ ...placeholderMessage, runtimeOp: undefined, contents: serializedOp }],\n\t\t\treferenceSequenceNumber,\n\t\t};\n\t\treturn { outboundBatch, placeholderMessage };\n\t}\n\n\t/**\n\t * Converts the given batch into a \"grouped batch\" - a batch with a single message of type \"groupedBatch\",\n\t * with contents being an array of the original batch's messages.\n\t *\n\t * If the batch already has only 1 message, it is returned as-is.\n\t *\n\t * @remarks - Remember that a BatchMessage has its content JSON serialized, so the incoming batch message contents\n\t * must be parsed first, and then the type and contents mentioned above are hidden in that JSON serialization.\n\t */\n\tpublic groupBatch(batch: OutboundBatch): OutboundSingletonBatch {\n\t\tassert(this.groupedBatchingEnabled(), 0xb79 /* grouping disabled! */);\n\t\tassert(batch.messages.length > 0, 0xb7a /* Unexpected attempt to group an empty batch */);\n\n\t\tif (batch.messages.length === 1) {\n\t\t\treturn batch as OutboundSingletonBatch;\n\t\t}\n\n\t\tif (batch.messages.length >= 1000) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"GroupLargeBatch\",\n\t\t\t\tlength: batch.messages.length,\n\t\t\t\treentrant: batch.hasReentrantOps,\n\t\t\t\treferenceSequenceNumber: batch.messages[0].referenceSequenceNumber,\n\t\t\t});\n\t\t}\n\t\t// We expect this will be on the first message, if present at all.\n\t\tlet groupedBatchId;\n\t\tfor (const message of batch.messages) {\n\t\t\tif (message.metadata) {\n\t\t\t\tconst { batch: _batch, batchId, ...rest } = message.metadata;\n\t\t\t\tif (batchId) {\n\t\t\t\t\tgroupedBatchId = batchId;\n\t\t\t\t}\n\t\t\t\tassert(Object.keys(rest).length === 0, 0x5dd /* cannot group ops with metadata */);\n\t\t\t}\n\t\t}\n\n\t\tconst serializedContent = JSON.stringify({\n\t\t\ttype: OpGroupingManager.groupedBatchOp,\n\t\t\tcontents: batch.messages.map<IGroupedMessage>((message) => ({\n\t\t\t\tcontents: message.contents === undefined ? undefined : JSON.parse(message.contents),\n\t\t\t\tmetadata: message.metadata,\n\t\t\t\tcompression: message.compression,\n\t\t\t})),\n\t\t});\n\n\t\tconst groupedBatch: OutboundSingletonBatch = {\n\t\t\t...batch,\n\t\t\tmessages: [\n\t\t\t\t{\n\t\t\t\t\tmetadata: { batchId: groupedBatchId },\n\t\t\t\t\treferenceSequenceNumber: batch.messages[0].referenceSequenceNumber,\n\t\t\t\t\tcontents: serializedContent,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t\treturn groupedBatch;\n\t}\n\n\tpublic ungroupOp(op: ISequencedDocumentMessage): ISequencedDocumentMessage[] {\n\t\tassert(isGroupContents(op.contents), 0x947 /* can only ungroup a grouped batch */);\n\t\tconst contents: IGroupedBatchMessageContents = op.contents;\n\n\t\tlet fakeCsn = 1;\n\t\treturn contents.contents.map((subMessage) => ({\n\t\t\t...op,\n\t\t\tclientSequenceNumber: fakeCsn++,\n\t\t\tcontents: subMessage.contents,\n\t\t\tmetadata: subMessage.metadata,\n\t\t\tcompression: subMessage.compression,\n\t\t}));\n\t}\n\n\tpublic groupedBatchingEnabled(): boolean {\n\t\treturn this.config.groupedBatchingEnabled;\n\t}\n}\n"]}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
6
6
|
import type { LocalContainerRuntimeMessage } from "../messageTypes.js";
|
|
7
|
+
import type { EmptyGroupedBatch } from "./opGroupingManager.js";
|
|
7
8
|
/**
|
|
8
9
|
* Takes an incoming runtime message (outer type "op"), JSON.parses the message's contents in place,
|
|
9
10
|
* if needed (old Loader does this for us).
|
|
@@ -18,5 +19,5 @@ export declare function ensureContentsDeserialized(mutableMessage: ISequencedDoc
|
|
|
18
19
|
*
|
|
19
20
|
* @param toSerialize - op message to serialize. Also supports an array of ops.
|
|
20
21
|
*/
|
|
21
|
-
export declare function serializeOp(toSerialize: LocalContainerRuntimeMessage | LocalContainerRuntimeMessage[]): string;
|
|
22
|
+
export declare function serializeOp(toSerialize: EmptyGroupedBatch | LocalContainerRuntimeMessage | LocalContainerRuntimeMessage[]): string;
|
|
22
23
|
//# sourceMappingURL=opSerialization.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opSerialization.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSerialization.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAO7F,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAEvE;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,cAAc,EAAE,yBAAyB,GAAG,IAAI,CAM1F;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAC1B,WAAW,
|
|
1
|
+
{"version":3,"file":"opSerialization.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSerialization.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAO7F,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,cAAc,EAAE,yBAAyB,GAAG,IAAI,CAM1F;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAC1B,WAAW,EACR,iBAAiB,GACjB,4BAA4B,GAC5B,4BAA4B,EAAE,GAC/B,MAAM,CAYR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opSerialization.js","sourceRoot":"","sources":["../../src/opLifecycle/opSerialization.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,qEAIgD;
|
|
1
|
+
{"version":3,"file":"opSerialization.js","sourceRoot":"","sources":["../../src/opLifecycle/opSerialization.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,qEAIgD;AAMhD;;;;;;GAMG;AACH,SAAgB,0BAA0B,CAAC,cAAyC;IACnF,yEAAyE;IACzE,qFAAqF;IACrF,IAAI,OAAO,cAAc,CAAC,QAAQ,KAAK,QAAQ,IAAI,cAAc,CAAC,QAAQ,KAAK,EAAE,EAAE,CAAC;QACnF,cAAc,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC;AACF,CAAC;AAND,gEAMC;AAED;;;;;GAKG;AACH,SAAgB,WAAW,CAC1B,WAGiC;IAEjC,OAAO,IAAI,CAAC,SAAS,CACpB,WAAW;IACX,YAAY;IACZ,CAAC,GAAG,EAAE,KAAc,EAAE,EAAE;QACvB,yDAAyD;QACzD,IAAI,IAAA,wBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAA,uCAA4B,EAAC,IAAA,gCAAqB,EAAC,KAAK,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC,CACD,CAAC;AACH,CAAC;AAjBD,kCAiBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tencodeHandleForSerialization,\n\tisFluidHandle,\n\ttoFluidHandleInternal,\n} from \"@fluidframework/runtime-utils/internal\";\n\nimport type { LocalContainerRuntimeMessage } from \"../messageTypes.js\";\n\nimport type { EmptyGroupedBatch } from \"./opGroupingManager.js\";\n\n/**\n * Takes an incoming runtime message (outer type \"op\"), JSON.parses the message's contents in place,\n * if needed (old Loader does this for us).\n * Only to be used for runtime messages. The contents here would be the virtualized payload for a batch of ops.\n * @remarks - Serialization during submit happens via {@link serializeOp}\n * @param mutableMessage - op message received\n */\nexport function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMessage): void {\n\t// This should become unconditional once Loader LTS reaches 2.4 or later.\n\t// There will be a long time of needing both cases, until LTS advances to that point.\n\tif (typeof mutableMessage.contents === \"string\" && mutableMessage.contents !== \"\") {\n\t\tmutableMessage.contents = JSON.parse(mutableMessage.contents);\n\t}\n}\n\n/**\n * Before submitting an op to the Outbox, its contents must be serialized using this function.\n * @remarks - The deserialization on process happens via the function {@link ensureContentsDeserialized}.\n *\n * @param toSerialize - op message to serialize. Also supports an array of ops.\n */\nexport function serializeOp(\n\ttoSerialize:\n\t\t| EmptyGroupedBatch\n\t\t| LocalContainerRuntimeMessage\n\t\t| LocalContainerRuntimeMessage[],\n): string {\n\treturn JSON.stringify(\n\t\ttoSerialize,\n\t\t// replacer:\n\t\t(key, value: unknown) => {\n\t\t\t// If 'value' is an IFluidHandle return its encoded form.\n\t\t\tif (isFluidHandle(value)) {\n\t\t\t\treturn encodeHandleForSerialization(toFluidHandleInternal(value));\n\t\t\t}\n\t\t\treturn value;\n\t\t},\n\t);\n}\n"]}
|
|
@@ -114,6 +114,7 @@ export declare class Outbox {
|
|
|
114
114
|
get blobAttachBatchMessageCount(): number;
|
|
115
115
|
get idAllocationBatchMessageCount(): number;
|
|
116
116
|
get isEmpty(): boolean;
|
|
117
|
+
containsUserChanges(): boolean;
|
|
117
118
|
/**
|
|
118
119
|
* Detect whether batching has been interrupted by an incoming message being processed. In this case,
|
|
119
120
|
* we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -133,6 +133,11 @@ class Outbox {
|
|
|
133
133
|
get isEmpty() {
|
|
134
134
|
return this.messageCount === 0;
|
|
135
135
|
}
|
|
136
|
+
containsUserChanges() {
|
|
137
|
+
return (this.mainBatch.containsUserChanges() || this.blobAttachBatch.containsUserChanges()
|
|
138
|
+
// ID Allocation ops are not user changes
|
|
139
|
+
);
|
|
140
|
+
}
|
|
136
141
|
/**
|
|
137
142
|
* Detect whether batching has been interrupted by an incoming message being processed. In this case,
|
|
138
143
|
* we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new
|
|
@@ -267,7 +272,7 @@ class Outbox {
|
|
|
267
272
|
const rawBatch = batchManager.popBatch(resubmitInfo?.batchId);
|
|
268
273
|
// On resubmit we use the original batch's staged state, so these should match as well.
|
|
269
274
|
const staged = rawBatch.staged === true;
|
|
270
|
-
(0, internal_1.assert)(resubmitInfo === undefined || resubmitInfo.staged === staged,
|
|
275
|
+
(0, internal_1.assert)(resubmitInfo === undefined || resubmitInfo.staged === staged, 0xba3 /* Mismatch in staged state tracking */);
|
|
271
276
|
const groupingEnabled = !disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();
|
|
272
277
|
if (batchManager.options.canRebase &&
|
|
273
278
|
rawBatch.hasReentrantOps === true &&
|
|
@@ -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 { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport {\n\tITelemetryBaseLogger,\n\ttype ITelemetryBaseProperties,\n} from \"@fluidframework/core-interfaces\";\nimport { assert, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tUsageError,\n\tcreateChildLogger,\n\ttype IFluidErrorBase,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ICompressionRuntimeOptions } from \"../compressionDefinitions.js\";\nimport { PendingMessageResubmitData, PendingStateManager } from \"../pendingStateManager.js\";\n\nimport {\n\tBatchManager,\n\tBatchSequenceNumbers,\n\tsequenceNumbersMatch,\n\ttype BatchId,\n} from \"./batchManager.js\";\nimport {\n\tLocalBatchMessage,\n\tIBatchCheckpoint,\n\ttype OutboundBatchMessage,\n\ttype OutboundSingletonBatch,\n\ttype LocalBatch,\n\ttype OutboundBatch,\n} from \"./definitions.js\";\nimport { OpCompressor } from \"./opCompressor.js\";\nimport { OpGroupingManager } from \"./opGroupingManager.js\";\nimport { serializeOp } from \"./opSerialization.js\";\nimport { OpSplitter } from \"./opSplitter.js\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t/**\n\t * The maximum size of a batch that we can send over the wire.\n\t */\n\treadonly maxBatchSizeInBytes: number;\n\t/**\n\t * If true, maybeFlushPartialBatch will flush the batch if the reference sequence number changed\n\t * since the batch started. Otherwise, it will throw in this case (apart from reentrancy which is handled elsewhere).\n\t * Once the new throw-based flow is proved in a production environment, this option will be removed.\n\t */\n\treadonly flushPartialBatches: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly submitBatchFn:\n\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t| undefined;\n\treadonly legacySendBatchFn: (batch: OutboundBatch) => number;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryBaseLogger;\n\treadonly groupingManager: OpGroupingManager;\n\treadonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;\n\treadonly reSubmit: (message: PendingMessageResubmitData, squash: boolean) => void;\n\treadonly opReentrancy: () => boolean;\n}\n\n/**\n * Info needed to correctly resubmit a batch\n */\nexport interface BatchResubmitInfo {\n\t/**\n\t * If defined, indicates the Batch ID of the batch being resubmitted.\n\t * This must be preserved on the new batch about to be submitted so they can be correlated/deduped in case both are sent.\n\t */\n\tbatchId?: string;\n\t/**\n\t * Indicates whether or not this batch is \"staged\", meaning it should not be sent to the ordering service yet\n\t * This is important on resubmit because we may be in Staging Mode for new changes,\n\t * but resubmitting a non-staged change from before entering Staging Mode\n\t */\n\tstaged: boolean;\n}\n\n/**\n * Temporarily increase the stack limit while executing the provided action.\n * If a negative value is provided for `length`, no stack frames will be collected.\n * If Infinity is provided, all frames will be collected.\n *\n * ADO:4663 - add this to the common packages.\n *\n * @param action - action which returns an error\n * @param length - number of stack frames to collect, 50 if unspecified.\n * @returns the result of the action provided\n */\nexport function getLongStack<T>(action: () => T, length: number = 50): T {\n\t// TODO: better typing here\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n\tconst errorObj = Error as any;\n\tif (\n\t\t/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */\n\t\t// ?? is not logically equivalent when the first clause returns false.\n\t\t(\n\t\t\tObject.getOwnPropertyDescriptor(errorObj, \"stackTraceLimit\") ||\n\t\t\tObject.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), \"stackTraceLimit\")\n\t\t)?.writable !== true\n\t\t/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */\n\t) {\n\t\treturn action();\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\tconst originalStackTraceLimit = errorObj.stackTraceLimit;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\terrorObj.stackTraceLimit = length;\n\t\treturn action();\n\t} finally {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\terrorObj.stackTraceLimit = originalStackTraceLimit;\n\t}\n}\n\n/**\n * Convert from local batch to outbound batch, including computing contentSizeInBytes.\n */\nexport function localBatchToOutboundBatch({\n\tstaged: _staged, // Peel this off the incoming batch, it's irrelevant (see Note below)\n\t...localBatch\n}: LocalBatch): OutboundBatch {\n\t// Note: the staged property might be misleading here, in case a pre-staging batch is resubmitted during staging mode.\n\t// It will be set to true, but the batch was not actually staged.\n\n\t// Shallow copy each message as we switch types\n\tconst outboundMessages = localBatch.messages.map<OutboundBatchMessage>(\n\t\t({ runtimeOp, ...message }) => ({\n\t\t\tcontents: serializeOp(runtimeOp),\n\t\t\t...message,\n\t\t}),\n\t);\n\tconst contentSizeInBytes = outboundMessages.reduce(\n\t\t(acc, message) => acc + (message.contents?.length ?? 0),\n\t\t0,\n\t);\n\n\t// Shallow copy the local batch, updating the messages to be outbound messages and adding contentSizeInBytes\n\tconst outboundBatch: OutboundBatch = {\n\t\t...localBatch,\n\t\tmessages: outboundMessages,\n\t\tcontentSizeInBytes,\n\t};\n\n\treturn outboundBatch;\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 * 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 * @remarks\n * Also content will be stringified, and that adds a lot of overhead due to a lot of escape characters.\n * Not taking it into account, as compression work should help there - compressed payload will be\n * initially stored as base64, and that requires only 2 extra escape characters.\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: OutboundBatch): number => {\n\treturn batch.contentSizeInBytes + opOverhead * batch.messages.length;\n};\n\n/**\n * The Outbox collects messages submitted by the ContainerRuntime into a batch,\n * and then flushes the batch when requested.\n *\n * @remarks There are actually multiple independent batches (some are for a specific message type),\n * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping).\n */\nexport class Outbox {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly blobAttachBatch: BatchManager;\n\tprivate readonly idAllocationBatch: BatchManager;\n\tprivate batchRebasesToReport = 5;\n\tprivate rebasing = false;\n\n\t/**\n\t * Track the number of ops which were detected to have a mismatched\n\t * reference sequence number, in order to self-throttle the telemetry events.\n\t *\n\t * This should be removed as part of ADO:2322\n\t */\n\tprivate readonly maxMismatchedOpsToReport = 3;\n\tprivate mismatchedOpsReported = 0;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tthis.logger = createChildLogger({ logger: params.logger, namespace: \"Outbox\" });\n\n\t\tthis.mainBatch = new BatchManager({ canRebase: true });\n\t\tthis.blobAttachBatch = new BatchManager({ canRebase: true });\n\t\tthis.idAllocationBatch = new BatchManager({\n\t\t\tcanRebase: false,\n\t\t\tignoreBatchId: true,\n\t\t});\n\t}\n\n\tpublic get messageCount(): number {\n\t\treturn this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;\n\t}\n\n\tpublic get mainBatchMessageCount(): number {\n\t\treturn this.mainBatch.length;\n\t}\n\n\tpublic get blobAttachBatchMessageCount(): number {\n\t\treturn this.blobAttachBatch.length;\n\t}\n\n\tpublic get idAllocationBatchMessageCount(): number {\n\t\treturn this.idAllocationBatch.length;\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.messageCount === 0;\n\t}\n\n\t/**\n\t * Detect whether batching has been interrupted by an incoming message being processed. In this case,\n\t * we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new\n\t * message as the first message. If flushing partial batch is not enabled, we will throw (except for reentrant ops).\n\t * This would indicate we expected this case to be precluded by logic elsewhere.\n\t *\n\t * @remarks - To detect batch interruption, we compare both the reference sequence number\n\t * (i.e. last message processed by DeltaManager) and the client sequence number of the\n\t * last message processed by the ContainerRuntime. In the absence of op reentrancy, this\n\t * pair will remain stable during a single JS turn during which the batch is being built up.\n\t */\n\tprivate maybeFlushPartialBatch(): void {\n\t\tconst mainBatchSeqNums = this.mainBatch.sequenceNumbers;\n\t\tconst blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;\n\t\tconst idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;\n\t\tassert(\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&\n\t\t\t\tsequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums),\n\t\t\t0x58d /* Reference sequence numbers from both batches must be in sync */,\n\t\t);\n\n\t\tconst currentSequenceNumbers = this.params.getCurrentSequenceNumbers();\n\n\t\tif (\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)\n\t\t) {\n\t\t\t// The reference sequence numbers are stable, there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\t// Reference and/or Client sequence number will be advancing while processing this batch,\n\t\t// so we can't use this check to detect wrongdoing. But we will still log via telemetry.\n\t\t// This is rare, and the reentrancy will be handled during Flush.\n\t\tconst expectedDueToReentrancy = this.isContextReentrant();\n\n\t\tconst errorWrapper = new Lazy(() =>\n\t\t\tgetLongStack(() =>\n\t\t\t\tDataProcessingError.create(\n\t\t\t\t\t\"Sequence numbers advanced as if ops were processed while a batch is accumulating\",\n\t\t\t\t\t\"outboxSequenceNumberCoherencyCheck\",\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tif (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\t// Only log error if this is truly unexpected\n\t\t\t\t\tcategory:\n\t\t\t\t\t\texpectedDueToReentrancy || this.params.config.flushPartialBatches\n\t\t\t\t\t\t\t? \"generic\"\n\t\t\t\t\t\t\t: \"error\",\n\t\t\t\t\teventName: \"ReferenceSequenceNumberMismatch\",\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\texpectedDueToReentrancy,\n\t\t\t\t\t\tmainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tmainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tblobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tblobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tcurrentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,\n\t\t\t\t\t\tcurrentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\terrorWrapper.value,\n\t\t\t);\n\t\t}\n\n\t\t// If we're configured to flush partial batches, do that now and return (don't throw)\n\t\tif (this.params.config.flushPartialBatches) {\n\t\t\tthis.flushAll();\n\t\t\treturn;\n\t\t}\n\n\t\t// If we are in a reentrant context, we know this can happen without causing any harm.\n\t\tif (expectedDueToReentrancy) {\n\t\t\treturn;\n\t\t}\n\n\t\tthrow errorWrapper.value;\n\t}\n\n\tpublic submit(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.mainBatch, message);\n\t}\n\n\tpublic submitBlobAttach(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.blobAttachBatch, message);\n\t}\n\n\tpublic submitIdAllocation(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.idAllocationBatch, message);\n\t}\n\n\tprivate addMessageToBatchManager(\n\t\tbatchManager: BatchManager,\n\t\tmessage: LocalBatchMessage,\n\t): void {\n\t\tbatchManager.push(\n\t\t\tmessage,\n\t\t\tthis.isContextReentrant(),\n\t\t\tthis.params.getCurrentSequenceNumbers().clientSequenceNumber,\n\t\t);\n\t}\n\n\t/**\n\t * Flush all the batches to the ordering service.\n\t * This method is expected to be called at the end of a batch.\n\t *\n\t * @throws If called from a reentrant context, or if the batch being flushed is too large.\n\t * @param resubmitInfo - Key information when flushing a resubmitted batch. Undefined means this is not resubmit.\n\t */\n\tpublic flush(resubmitInfo?: BatchResubmitInfo): void {\n\t\tassert(\n\t\t\t!this.isContextReentrant(),\n\t\t\t0xb7b /* Flushing must not happen while incoming changes are being processed */,\n\t\t);\n\t\tthis.flushAll(resubmitInfo);\n\t}\n\n\tprivate flushAll(resubmitInfo?: BatchResubmitInfo): void {\n\t\tconst allBatchesEmpty =\n\t\t\tthis.idAllocationBatch.empty && this.blobAttachBatch.empty && this.mainBatch.empty;\n\t\tif (allBatchesEmpty) {\n\t\t\t// If we're resubmitting with a batchId and all batches are empty, we need to flush an empty batch.\n\t\t\t// Note that we currently resubmit one batch at a time, so on resubmit, 1 of the 2 batches will *always* be empty.\n\t\t\t// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored\n\t\t\t// by the rest of the system, including remote clients.\n\t\t\t// In some cases we *must* resubmit the empty batch (to match up with a non-empty version tracked locally by a container fork), so we do it always.\n\t\t\tif (resubmitInfo?.batchId !== undefined) {\n\t\t\t\tthis.flushEmptyBatch(resubmitInfo.batchId, resubmitInfo.staged);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't use resubmittingBatchId for idAllocationBatch.\n\t\t// ID Allocation messages are not directly resubmitted so don't pass the resubmitInfo\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.idAllocationBatch,\n\t\t\t// Note: For now, we will never stage ID Allocation messages.\n\t\t\t// They won't contain personal info and no harm in extra allocations in case of discarding the staged changes\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.blobAttachBatch,\n\t\t\tdisableGroupedBatching: true,\n\t\t\tresubmitInfo,\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.mainBatch,\n\t\t\tresubmitInfo,\n\t\t});\n\t}\n\n\tprivate flushEmptyBatch(\n\t\tresubmittingBatchId: BatchId,\n\t\tresubmittingStagedBatch: boolean,\n\t): void {\n\t\tconst referenceSequenceNumber =\n\t\t\tthis.params.getCurrentSequenceNumbers().referenceSequenceNumber;\n\t\tassert(\n\t\t\treferenceSequenceNumber !== undefined,\n\t\t\t0xa01 /* reference sequence number should be defined */,\n\t\t);\n\t\tconst { outboundBatch, placeholderMessage } =\n\t\t\tthis.params.groupingManager.createEmptyGroupedBatch(\n\t\t\t\tresubmittingBatchId,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t);\n\t\tlet clientSequenceNumber: number | undefined;\n\t\tif (this.params.shouldSend() && !resubmittingStagedBatch) {\n\t\t\tclientSequenceNumber = this.sendBatch(outboundBatch);\n\t\t}\n\n\t\t// Push the empty batch placeholder to the PendingStateManager\n\t\tthis.params.pendingStateManager.onFlushEmptyBatch(\n\t\t\tplaceholderMessage,\n\t\t\tclientSequenceNumber,\n\t\t\tresubmittingStagedBatch,\n\t\t);\n\t\treturn;\n\t}\n\n\tprivate flushInternal(params: {\n\t\tbatchManager: BatchManager;\n\t\tdisableGroupedBatching?: boolean;\n\t\tresubmitInfo?: BatchResubmitInfo; // undefined if not resubmitting\n\t}): void {\n\t\tconst { batchManager, disableGroupedBatching = false, resubmitInfo } = params;\n\t\tif (batchManager.empty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rawBatch = batchManager.popBatch(resubmitInfo?.batchId);\n\n\t\t// On resubmit we use the original batch's staged state, so these should match as well.\n\t\tconst staged = rawBatch.staged === true;\n\t\tassert(\n\t\t\tresubmitInfo === undefined || resubmitInfo.staged === staged,\n\t\t\t\"Mismatch in staged state tracking\",\n\t\t);\n\n\t\tconst groupingEnabled =\n\t\t\t!disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();\n\t\tif (\n\t\t\tbatchManager.options.canRebase &&\n\t\t\trawBatch.hasReentrantOps === true &&\n\t\t\t// NOTE: This is too restrictive. We should rebase for any reentrant op, not just if it's going to be a grouped batch\n\t\t\t// However there is some test that is depending on this behavior so we haven't removed these conditions yet. See AB#33427\n\t\t\tgroupingEnabled &&\n\t\t\trawBatch.messages.length > 1\n\t\t) {\n\t\t\tassert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);\n\t\t\t// If a batch contains reentrant ops (ops created as a result from processing another op)\n\t\t\t// it needs to be rebased so that we can ensure consistent reference sequence numbers\n\t\t\t// and eventual consistency at the DDS level.\n\t\t\t// Note: Since this is happening in the same turn the ops were originally created with,\n\t\t\t// and they haven't gone to PendingStateManager yet, we can just let them respect\n\t\t\t// ContainerRuntime.inStagingMode\n\t\t\tthis.rebase(rawBatch, batchManager);\n\t\t\treturn;\n\t\t}\n\n\t\tlet clientSequenceNumber: number | undefined;\n\t\t// Did we disconnect? (i.e. is shouldSend false?)\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\t// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.\n\t\tif (this.params.shouldSend() && !staged) {\n\t\t\tconst virtualizedBatch = this.virtualizeBatch(rawBatch, groupingEnabled);\n\n\t\t\tclientSequenceNumber = this.sendBatch(virtualizedBatch);\n\t\t\tassert(\n\t\t\t\tclientSequenceNumber === undefined || clientSequenceNumber >= 0,\n\t\t\t\t0x9d2 /* unexpected negative clientSequenceNumber (empty batch should yield undefined) */,\n\t\t\t);\n\t\t}\n\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\trawBatch.messages,\n\t\t\tclientSequenceNumber,\n\t\t\tstaged,\n\t\t\tbatchManager.options.ignoreBatchId,\n\t\t);\n\t}\n\n\t/**\n\t * Rebases a batch. All the ops in the batch are resubmitted to the runtime and\n\t * they will end up back in the same batch manager they were flushed from and subsequently flushed.\n\t *\n\t * @param rawBatch - the batch to be rebased\n\t */\n\tprivate rebase(rawBatch: LocalBatch, batchManager: BatchManager): void {\n\t\tassert(!this.rebasing, 0x6fb /* Reentrancy */);\n\t\tassert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);\n\n\t\tthis.rebasing = true;\n\t\tconst squash = false;\n\t\tfor (const message of rawBatch.messages) {\n\t\t\tthis.params.reSubmit(\n\t\t\t\t{\n\t\t\t\t\truntimeOp: message.runtimeOp,\n\t\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\t\topMetadata: message.metadata,\n\t\t\t\t},\n\t\t\t\tsquash,\n\t\t\t);\n\t\t}\n\n\t\tif (this.batchRebasesToReport > 0) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"BatchRebase\",\n\t\t\t\t\tlength: rawBatch.messages.length,\n\t\t\t\t\treferenceSequenceNumber: rawBatch.referenceSequenceNumber,\n\t\t\t\t},\n\t\t\t\tnew UsageError(\"BatchRebase\"),\n\t\t\t);\n\t\t\tthis.batchRebasesToReport--;\n\t\t}\n\n\t\tthis.flushInternal({ batchManager });\n\t\tthis.rebasing = false;\n\t}\n\n\tprivate isContextReentrant(): boolean {\n\t\treturn this.params.opReentrancy() && !this.rebasing;\n\t}\n\n\t/**\n\t * As necessary and enabled, groups / compresses / chunks the given batch.\n\t *\n\t * @remarks - If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @param localBatch - Local Batch to be virtualized - i.e. transformed into an Outbound Batch\n\t * @param groupingEnabled - If true, Grouped batching is enabled.\n\t * @returns One of the following:\n\t * - (A) The original batch (Based on what's enabled)\n\t * - (B) A grouped batch (it's a singleton batch)\n\t * - (C) A compressed singleton batch\n\t * - (D) A singleton batch containing the last chunk.\n\t */\n\tprivate virtualizeBatch(localBatch: LocalBatch, groupingEnabled: boolean): OutboundBatch {\n\t\t// Shallow copy the local batch, updating the messages to be outbound messages\n\t\tconst originalBatch = localBatchToOutboundBatch(localBatch);\n\n\t\tconst originalOrGroupedBatch = groupingEnabled\n\t\t\t? this.params.groupingManager.groupBatch(originalBatch)\n\t\t\t: originalBatch;\n\n\t\tif (originalOrGroupedBatch.messages.length !== 1) {\n\t\t\t// Compression requires a single message, so return early otherwise.\n\t\t\treturn originalOrGroupedBatch;\n\t\t}\n\n\t\t// Regardless of whether we grouped or not, we now have a batch with a single message.\n\t\t// Now proceed to compress/chunk it if necessary.\n\t\tconst singletonBatch = originalOrGroupedBatch as OutboundSingletonBatch;\n\n\t\tif (\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes >\n\t\t\t\tsingletonBatch.contentSizeInBytes ||\n\t\t\tthis.params.submitBatchFn === undefined\n\t\t) {\n\t\t\t// Nothing to do if compression is disabled, unnecessary or unsupported.\n\t\t\treturn singletonBatch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(singletonBatch);\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes\n\t\t\t\t? compressedBatch\n\t\t\t\t: this.params.splitter.splitSingletonBatchMessage(compressedBatch);\n\t\t}\n\n\t\t// We want to distinguish this \"BatchTooLarge\" case from the generic \"BatchTooLarge\" case in sendBatch\n\t\tif (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(compressedBatch, \"CompressionInsufficient\", {\n\t\t\t\tuncompressedSizeInBytes: singletonBatch.contentSizeInBytes,\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\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 clientSequenceNumber of the start of the batch, or undefined if nothing was sent\n\t */\n\tprivate sendBatch(batch: OutboundBatch): number | undefined {\n\t\tconst length = batch.messages.length;\n\t\tif (length === 0) {\n\t\t\treturn undefined; // Nothing submitted\n\t\t}\n\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tif (socketSize >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(batch, \"CannotSend\");\n\t\t}\n\n\t\tlet clientSequenceNumber: number;\n\t\tif (this.params.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\tassert(\n\t\t\t\tbatch.messages[0].compression === undefined,\n\t\t\t\t0x5a6 /* Compression should not have happened if the loader does not support it */,\n\t\t\t);\n\n\t\t\tclientSequenceNumber = this.params.legacySendBatchFn(batch);\n\t\t} else {\n\t\t\tassert(batch.referenceSequenceNumber !== undefined, 0x58e /* Batch must not be empty */);\n\t\t\tclientSequenceNumber = this.params.submitBatchFn(\n\t\t\t\tbatch.messages.map<IBatchMessage>((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\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t\t})),\n\t\t\t\tbatch.referenceSequenceNumber,\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 makeBatchTooLargeError(\n\t\tbatch: OutboundBatch,\n\t\tcodepath: string,\n\t\tmoreDetails?: ITelemetryBaseProperties,\n\t): IFluidErrorBase {\n\t\treturn DataProcessingError.create(\n\t\t\t\"BatchTooLarge\",\n\t\t\tcodepath,\n\t\t\t/* sequencedMessage */ undefined,\n\t\t\t{\n\t\t\t\terrorDetails: {\n\t\t\t\t\topCount: batch.messages.length,\n\t\t\t\t\tcontentSizeInBytes: batch.contentSizeInBytes,\n\t\t\t\t\tsocketSize: estimateSocketSize(batch),\n\t\t\t\t\tmaxBatchSizeInBytes: this.params.config.maxBatchSizeInBytes,\n\t\t\t\t\tgroupedBatchingEnabled: this.params.groupingManager.groupedBatchingEnabled(),\n\t\t\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\t\t\tchunkSizeInBytes: this.params.splitter.chunkSizeInBytes,\n\t\t\t\t\t...moreDetails,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back.\n\t */\n\tpublic getBatchCheckpoints(): {\n\t\tmainBatch: IBatchCheckpoint;\n\t\tidAllocationBatch: IBatchCheckpoint;\n\t\tblobAttachBatch: IBatchCheckpoint;\n\t} {\n\t\t// This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type.\n\t\t// When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve.\n\t\tconst mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();\n\t\treturn {\n\t\t\tmainBatch,\n\t\t\tidAllocationBatch: this.idAllocationBatch.checkpoint(),\n\t\t\tblobAttachBatch: this.blobAttachBatch.checkpoint(),\n\t\t};\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAOH,kEAAmE;AACnE,uEAMkD;AAKlD,uDAK2B;AAW3B,6DAAmD;AAmDnD;;;;;;;;;;GAUG;AACH,SAAgB,YAAY,CAAI,MAAe,EAAE,SAAiB,EAAE;IACnE,2BAA2B;IAC3B,uGAAuG;IACvG,MAAM,QAAQ,GAAG,KAAY,CAAC;IAC9B;IACC,iEAAiE;IACjE,sEAAsE;IACtE,CACC,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,CAAC;QAC5D,MAAM,CAAC,wBAAwB,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC,CACnF,EAAE,QAAQ,KAAK,IAAI;IACpB,gEAAgE;MAC/D,CAAC;QACF,OAAO,MAAM,EAAE,CAAC;IACjB,CAAC;IAED,+GAA+G;IAC/G,MAAM,uBAAuB,GAAG,QAAQ,CAAC,eAAe,CAAC;IACzD,IAAI,CAAC;QACJ,sEAAsE;QACtE,QAAQ,CAAC,eAAe,GAAG,MAAM,CAAC;QAClC,OAAO,MAAM,EAAE,CAAC;IACjB,CAAC;YAAS,CAAC;QACV,+GAA+G;QAC/G,QAAQ,CAAC,eAAe,GAAG,uBAAuB,CAAC;IACpD,CAAC;AACF,CAAC;AA1BD,oCA0BC;AAED;;GAEG;AACH,SAAgB,yBAAyB,CAAC,EACzC,MAAM,EAAE,OAAO,EAAE,qEAAqE;AACtF,GAAG,UAAU,EACD;IACZ,sHAAsH;IACtH,iEAAiE;IAEjE,+CAA+C;IAC/C,MAAM,gBAAgB,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAC/C,CAAC,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/B,QAAQ,EAAE,IAAA,gCAAW,EAAC,SAAS,CAAC;QAChC,GAAG,OAAO;KACV,CAAC,CACF,CAAC;IACF,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,MAAM,CACjD,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,EACvD,CAAC,CACD,CAAC;IAEF,4GAA4G;IAC5G,MAAM,aAAa,GAAkB;QACpC,GAAG,UAAU;QACb,QAAQ,EAAE,gBAAgB;QAC1B,kBAAkB;KAClB,CAAC;IAEF,OAAO,aAAa,CAAC;AACtB,CAAC;AA3BD,8DA2BC;AAED;;;GAGG;AACH,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;;;;;;;;;GAYG;AACI,MAAM,kBAAkB,GAAG,CAAC,KAAoB,EAAU,EAAE;IAClE,OAAO,KAAK,CAAC,kBAAkB,GAAG,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;AACtE,CAAC,CAAC;AAFW,QAAA,kBAAkB,sBAE7B;AAEF;;;;;;GAMG;AACH,MAAa,MAAM;IAiBlB,YAA6B,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;QAZ9C,yBAAoB,GAAG,CAAC,CAAC;QACzB,aAAQ,GAAG,KAAK,CAAC;QAEzB;;;;;WAKG;QACc,6BAAwB,GAAG,CAAC,CAAC;QACtC,0BAAqB,GAAG,CAAC,CAAC;QAGjC,IAAI,CAAC,MAAM,GAAG,IAAA,4BAAiB,EAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,SAAS,GAAG,IAAI,8BAAY,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,eAAe,GAAG,IAAI,8BAAY,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,iBAAiB,GAAG,IAAI,8BAAY,CAAC;YACzC,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,IAAI;SACnB,CAAC,CAAC;IACJ,CAAC;IAED,IAAW,YAAY;QACtB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;IAC5F,CAAC;IAED,IAAW,qBAAqB;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,IAAW,2BAA2B;QACrC,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;IACpC,CAAC;IAED,IAAW,6BAA6B;QACvC,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;IACtC,CAAC;IAED,IAAW,OAAO;QACjB,OAAO,IAAI,CAAC,YAAY,KAAK,CAAC,CAAC;IAChC,CAAC;IAEM,mBAAmB;QACzB,OAAO,CACN,IAAI,CAAC,SAAS,CAAC,mBAAmB,EAAE,IAAI,IAAI,CAAC,eAAe,CAAC,mBAAmB,EAAE;QAClF,yCAAyC;SACzC,CAAC;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACK,sBAAsB;QAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC;QACxD,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC;QAC/D,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC;QAC9D,IAAA,iBAAM,EACL,IAAA,sCAAoB,EAAC,gBAAgB,EAAE,iBAAiB,CAAC;YACxD,IAAA,sCAAoB,EAAC,gBAAgB,EAAE,cAAc,CAAC,EACvD,KAAK,CAAC,kEAAkE,CACxE,CAAC;QAEF,MAAM,sBAAsB,GAAG,IAAI,CAAC,MAAM,CAAC,yBAAyB,EAAE,CAAC;QAEvE,IACC,IAAA,sCAAoB,EAAC,gBAAgB,EAAE,sBAAsB,CAAC;YAC9D,IAAA,sCAAoB,EAAC,iBAAiB,EAAE,sBAAsB,CAAC;YAC/D,IAAA,sCAAoB,EAAC,cAAc,EAAE,sBAAsB,CAAC,EAC3D,CAAC;YACF,oEAAoE;YACpE,OAAO;QACR,CAAC;QAED,yFAAyF;QACzF,wFAAwF;QACxF,iEAAiE;QACjE,MAAM,uBAAuB,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE1D,MAAM,YAAY,GAAG,IAAI,eAAI,CAAC,GAAG,EAAE,CAClC,YAAY,CAAC,GAAG,EAAE,CACjB,8BAAmB,CAAC,MAAM,CACzB,kFAAkF,EAClF,oCAAoC,CACpC,CACD,CACD,CAAC;QACF,IAAI,EAAE,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACnE,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAC7B;gBACC,6CAA6C;gBAC7C,QAAQ,EACP,uBAAuB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB;oBAChE,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,OAAO;gBACX,SAAS,EAAE,iCAAiC;gBAC5C,OAAO,EAAE;oBACR,uBAAuB;oBACvB,2BAA2B,EAAE,gBAAgB,CAAC,uBAAuB;oBACrE,wBAAwB,EAAE,gBAAgB,CAAC,oBAAoB;oBAC/D,iCAAiC,EAAE,iBAAiB,CAAC,uBAAuB;oBAC5E,8BAA8B,EAAE,iBAAiB,CAAC,oBAAoB;oBACtE,8BAA8B,EAAE,sBAAsB,CAAC,uBAAuB;oBAC9E,2BAA2B,EAAE,sBAAsB,CAAC,oBAAoB;iBACxE;aACD,EACD,YAAY,CAAC,KAAK,CAClB,CAAC;QACH,CAAC;QAED,qFAAqF;QACrF,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO;QACR,CAAC;QAED,sFAAsF;QACtF,IAAI,uBAAuB,EAAE,CAAC;YAC7B,OAAO;QACR,CAAC;QAED,MAAM,YAAY,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,MAAM,CAAC,OAA0B;QACvC,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAE9B,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAEM,gBAAgB,CAAC,OAA0B;QACjD,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAE9B,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAEM,kBAAkB,CAAC,OAA0B;QACnD,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAE9B,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAEO,wBAAwB,CAC/B,YAA0B,EAC1B,OAA0B;QAE1B,YAAY,CAAC,IAAI,CAChB,OAAO,EACP,IAAI,CAAC,kBAAkB,EAAE,EACzB,IAAI,CAAC,MAAM,CAAC,yBAAyB,EAAE,CAAC,oBAAoB,CAC5D,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,YAAgC;QAC5C,IAAA,iBAAM,EACL,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAC1B,KAAK,CAAC,yEAAyE,CAC/E,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC7B,CAAC;IAEO,QAAQ,CAAC,YAAgC;QAChD,MAAM,eAAe,GACpB,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QACpF,IAAI,eAAe,EAAE,CAAC;YACrB,mGAAmG;YACnG,kHAAkH;YAClH,6HAA6H;YAC7H,uDAAuD;YACvD,mJAAmJ;YACnJ,IAAI,YAAY,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;gBACzC,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;YACjE,CAAC;YACD,OAAO;QACR,CAAC;QAED,uDAAuD;QACvD,qFAAqF;QACrF,IAAI,CAAC,aAAa,CAAC;YAClB,YAAY,EAAE,IAAI,CAAC,iBAAiB;YACpC,6DAA6D;YAC7D,6GAA6G;SAC7G,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,CAAC;YAClB,YAAY,EAAE,IAAI,CAAC,eAAe;YAClC,sBAAsB,EAAE,IAAI;YAC5B,YAAY;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,CAAC;YAClB,YAAY,EAAE,IAAI,CAAC,SAAS;YAC5B,YAAY;SACZ,CAAC,CAAC;IACJ,CAAC;IAEO,eAAe,CACtB,mBAA4B,EAC5B,uBAAgC;QAEhC,MAAM,uBAAuB,GAC5B,IAAI,CAAC,MAAM,CAAC,yBAAyB,EAAE,CAAC,uBAAuB,CAAC;QACjE,IAAA,iBAAM,EACL,uBAAuB,KAAK,SAAS,EACrC,KAAK,CAAC,iDAAiD,CACvD,CAAC;QACF,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAC1C,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,uBAAuB,CAClD,mBAAmB,EACnB,uBAAuB,CACvB,CAAC;QACH,IAAI,oBAAwC,CAAC;QAC7C,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC1D,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACtD,CAAC;QAED,8DAA8D;QAC9D,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,iBAAiB,CAChD,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,CACvB,CAAC;QACF,OAAO;IACR,CAAC;IAEO,aAAa,CAAC,MAIrB;QACA,MAAM,EAAE,YAAY,EAAE,sBAAsB,GAAG,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;QAC9E,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAE9D,uFAAuF;QACvF,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC;QACxC,IAAA,iBAAM,EACL,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,KAAK,MAAM,EAC5D,KAAK,CAAC,uCAAuC,CAC7C,CAAC;QAEF,MAAM,eAAe,GACpB,CAAC,sBAAsB,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,sBAAsB,EAAE,CAAC;QACjF,IACC,YAAY,CAAC,OAAO,CAAC,SAAS;YAC9B,QAAQ,CAAC,eAAe,KAAK,IAAI;YACjC,qHAAqH;YACrH,yHAAyH;YACzH,eAAe;YACf,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAC3B,CAAC;YACF,IAAA,iBAAM,EAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACpF,yFAAyF;YACzF,qFAAqF;YACrF,6CAA6C;YAC7C,uFAAuF;YACvF,iFAAiF;YACjF,iCAAiC;YACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACpC,OAAO;QACR,CAAC;QAED,IAAI,oBAAwC,CAAC;QAC7C,iDAAiD;QACjD,uFAAuF;QACvF,yGAAyG;QACzG,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,MAAM,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YAEzE,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;YACxD,IAAA,iBAAM,EACL,oBAAoB,KAAK,SAAS,IAAI,oBAAoB,IAAI,CAAC,EAC/D,KAAK,CAAC,mFAAmF,CACzF,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,YAAY,CAC3C,QAAQ,CAAC,QAAQ,EACjB,oBAAoB,EACpB,MAAM,EACN,YAAY,CAAC,OAAO,CAAC,aAAa,CAClC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,QAAoB,EAAE,YAA0B;QAC9D,IAAA,iBAAM,EAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC/C,IAAA,iBAAM,EAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAEzF,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,MAAM,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,QAAQ,CACnB;gBACC,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,UAAU,EAAE,OAAO,CAAC,QAAQ;aAC5B,EACD,MAAM,CACN,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,oBAAoB,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAC7B;gBACC,SAAS,EAAE,aAAa;gBACxB,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM;gBAChC,uBAAuB,EAAE,QAAQ,CAAC,uBAAuB;aACzD,EACD,IAAI,qBAAU,CAAC,aAAa,CAAC,CAC7B,CAAC;YACF,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAEO,kBAAkB;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;IACrD,CAAC;IAED;;;;;;;;;;;;OAYG;IACK,eAAe,CAAC,UAAsB,EAAE,eAAwB;QACvE,8EAA8E;QAC9E,MAAM,aAAa,GAAG,yBAAyB,CAAC,UAAU,CAAC,CAAC;QAE5D,MAAM,sBAAsB,GAAG,eAAe;YAC7C,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,aAAa,CAAC;YACvD,CAAC,CAAC,aAAa,CAAC;QAEjB,IAAI,sBAAsB,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClD,oEAAoE;YACpE,OAAO,sBAAsB,CAAC;QAC/B,CAAC;QAED,sFAAsF;QACtF,iDAAiD;QACjD,MAAM,cAAc,GAAG,sBAAgD,CAAC;QAExE,IACC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,uBAAuB;YAC5D,cAAc,CAAC,kBAAkB;YAClC,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,SAAS,EACtC,CAAC;YACF,wEAAwE;YACxE,OAAO,cAAc,CAAC;QACvB,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAE7E,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,EAAE,CAAC;YACjD,OAAO,eAAe,CAAC,kBAAkB,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB;gBACjF,CAAC,CAAC,eAAe;gBACjB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAC;QACrE,CAAC;QAED,sGAAsG;QACtG,IAAI,eAAe,CAAC,kBAAkB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAClF,MAAM,IAAI,CAAC,sBAAsB,CAAC,eAAe,EAAE,yBAAyB,EAAE;gBAC7E,uBAAuB,EAAE,cAAc,CAAC,kBAAkB;aAC1D,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,eAAe,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACK,SAAS,CAAC,KAAoB;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrC,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YAClB,OAAO,SAAS,CAAC,CAAC,oBAAoB;QACvC,CAAC;QAED,MAAM,UAAU,GAAG,IAAA,0BAAkB,EAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAC1D,MAAM,IAAI,CAAC,sBAAsB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,oBAA4B,CAAC;QACjC,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAC7C,yFAAyF;YACzF,uDAAuD;YACvD,IAAA,iBAAM,EACL,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,EAC3C,KAAK,CAAC,4EAA4E,CAClF,CAAC;YAEF,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACP,IAAA,iBAAM,EAAC,KAAK,CAAC,uBAAuB,KAAK,SAAS,EAAE,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACzF,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAC/C,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAgB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC/C,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,uBAAuB,EAAE,OAAO,CAAC,uBAAuB;aACxD,CAAC,CAAC,EACH,KAAK,CAAC,uBAAuB,CAC7B,CAAC;QACH,CAAC;QAED,2GAA2G;QAC3G,oBAAoB,IAAI,MAAM,GAAG,CAAC,CAAC;QACnC,IAAA,iBAAM,EAAC,oBAAoB,IAAI,CAAC,EAAE,KAAK,CAAC,4CAA4C,CAAC,CAAC;QACtF,OAAO,oBAAoB,CAAC;IAC7B,CAAC;IAEO,sBAAsB,CAC7B,KAAoB,EACpB,QAAgB,EAChB,WAAsC;QAEtC,OAAO,8BAAmB,CAAC,MAAM,CAChC,eAAe,EACf,QAAQ;QACR,sBAAsB,CAAC,SAAS,EAChC;YACC,YAAY,EAAE;gBACb,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;gBAC9B,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;gBAC5C,UAAU,EAAE,IAAA,0BAAkB,EAAC,KAAK,CAAC;gBACrC,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB;gBAC3D,sBAAsB,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,sBAAsB,EAAE;gBAC5E,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC;gBACzE,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB;gBAC5D,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB;gBACvD,GAAG,WAAW;aACd;SACD,CACD,CAAC;IACH,CAAC;IAED;;OAEG;IACI,mBAAmB;QAKzB,iHAAiH;QACjH,8FAA8F;QAC9F,MAAM,SAAS,GAAqB,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QAChE,OAAO;YACN,SAAS;YACT,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE;YACtD,eAAe,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE;SAClD,CAAC;IACH,CAAC;CACD;AA7eD,wBA6eC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport {\n\tITelemetryBaseLogger,\n\ttype ITelemetryBaseProperties,\n} from \"@fluidframework/core-interfaces\";\nimport { assert, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tUsageError,\n\tcreateChildLogger,\n\ttype IFluidErrorBase,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ICompressionRuntimeOptions } from \"../compressionDefinitions.js\";\nimport { PendingMessageResubmitData, PendingStateManager } from \"../pendingStateManager.js\";\n\nimport {\n\tBatchManager,\n\tBatchSequenceNumbers,\n\tsequenceNumbersMatch,\n\ttype BatchId,\n} from \"./batchManager.js\";\nimport {\n\tLocalBatchMessage,\n\tIBatchCheckpoint,\n\ttype OutboundBatchMessage,\n\ttype OutboundSingletonBatch,\n\ttype LocalBatch,\n\ttype OutboundBatch,\n} from \"./definitions.js\";\nimport { OpCompressor } from \"./opCompressor.js\";\nimport { OpGroupingManager } from \"./opGroupingManager.js\";\nimport { serializeOp } from \"./opSerialization.js\";\nimport { OpSplitter } from \"./opSplitter.js\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t/**\n\t * The maximum size of a batch that we can send over the wire.\n\t */\n\treadonly maxBatchSizeInBytes: number;\n\t/**\n\t * If true, maybeFlushPartialBatch will flush the batch if the reference sequence number changed\n\t * since the batch started. Otherwise, it will throw in this case (apart from reentrancy which is handled elsewhere).\n\t * Once the new throw-based flow is proved in a production environment, this option will be removed.\n\t */\n\treadonly flushPartialBatches: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly submitBatchFn:\n\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t| undefined;\n\treadonly legacySendBatchFn: (batch: OutboundBatch) => number;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryBaseLogger;\n\treadonly groupingManager: OpGroupingManager;\n\treadonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;\n\treadonly reSubmit: (message: PendingMessageResubmitData, squash: boolean) => void;\n\treadonly opReentrancy: () => boolean;\n}\n\n/**\n * Info needed to correctly resubmit a batch\n */\nexport interface BatchResubmitInfo {\n\t/**\n\t * If defined, indicates the Batch ID of the batch being resubmitted.\n\t * This must be preserved on the new batch about to be submitted so they can be correlated/deduped in case both are sent.\n\t */\n\tbatchId?: string;\n\t/**\n\t * Indicates whether or not this batch is \"staged\", meaning it should not be sent to the ordering service yet\n\t * This is important on resubmit because we may be in Staging Mode for new changes,\n\t * but resubmitting a non-staged change from before entering Staging Mode\n\t */\n\tstaged: boolean;\n}\n\n/**\n * Temporarily increase the stack limit while executing the provided action.\n * If a negative value is provided for `length`, no stack frames will be collected.\n * If Infinity is provided, all frames will be collected.\n *\n * ADO:4663 - add this to the common packages.\n *\n * @param action - action which returns an error\n * @param length - number of stack frames to collect, 50 if unspecified.\n * @returns the result of the action provided\n */\nexport function getLongStack<T>(action: () => T, length: number = 50): T {\n\t// TODO: better typing here\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n\tconst errorObj = Error as any;\n\tif (\n\t\t/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */\n\t\t// ?? is not logically equivalent when the first clause returns false.\n\t\t(\n\t\t\tObject.getOwnPropertyDescriptor(errorObj, \"stackTraceLimit\") ||\n\t\t\tObject.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), \"stackTraceLimit\")\n\t\t)?.writable !== true\n\t\t/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */\n\t) {\n\t\treturn action();\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\tconst originalStackTraceLimit = errorObj.stackTraceLimit;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\terrorObj.stackTraceLimit = length;\n\t\treturn action();\n\t} finally {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\terrorObj.stackTraceLimit = originalStackTraceLimit;\n\t}\n}\n\n/**\n * Convert from local batch to outbound batch, including computing contentSizeInBytes.\n */\nexport function localBatchToOutboundBatch({\n\tstaged: _staged, // Peel this off the incoming batch, it's irrelevant (see Note below)\n\t...localBatch\n}: LocalBatch): OutboundBatch {\n\t// Note: the staged property might be misleading here, in case a pre-staging batch is resubmitted during staging mode.\n\t// It will be set to true, but the batch was not actually staged.\n\n\t// Shallow copy each message as we switch types\n\tconst outboundMessages = localBatch.messages.map<OutboundBatchMessage>(\n\t\t({ runtimeOp, ...message }) => ({\n\t\t\tcontents: serializeOp(runtimeOp),\n\t\t\t...message,\n\t\t}),\n\t);\n\tconst contentSizeInBytes = outboundMessages.reduce(\n\t\t(acc, message) => acc + (message.contents?.length ?? 0),\n\t\t0,\n\t);\n\n\t// Shallow copy the local batch, updating the messages to be outbound messages and adding contentSizeInBytes\n\tconst outboundBatch: OutboundBatch = {\n\t\t...localBatch,\n\t\tmessages: outboundMessages,\n\t\tcontentSizeInBytes,\n\t};\n\n\treturn outboundBatch;\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 * 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 * @remarks\n * Also content will be stringified, and that adds a lot of overhead due to a lot of escape characters.\n * Not taking it into account, as compression work should help there - compressed payload will be\n * initially stored as base64, and that requires only 2 extra escape characters.\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: OutboundBatch): number => {\n\treturn batch.contentSizeInBytes + opOverhead * batch.messages.length;\n};\n\n/**\n * The Outbox collects messages submitted by the ContainerRuntime into a batch,\n * and then flushes the batch when requested.\n *\n * @remarks There are actually multiple independent batches (some are for a specific message type),\n * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping).\n */\nexport class Outbox {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly blobAttachBatch: BatchManager;\n\tprivate readonly idAllocationBatch: BatchManager;\n\tprivate batchRebasesToReport = 5;\n\tprivate rebasing = false;\n\n\t/**\n\t * Track the number of ops which were detected to have a mismatched\n\t * reference sequence number, in order to self-throttle the telemetry events.\n\t *\n\t * This should be removed as part of ADO:2322\n\t */\n\tprivate readonly maxMismatchedOpsToReport = 3;\n\tprivate mismatchedOpsReported = 0;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tthis.logger = createChildLogger({ logger: params.logger, namespace: \"Outbox\" });\n\n\t\tthis.mainBatch = new BatchManager({ canRebase: true });\n\t\tthis.blobAttachBatch = new BatchManager({ canRebase: true });\n\t\tthis.idAllocationBatch = new BatchManager({\n\t\t\tcanRebase: false,\n\t\t\tignoreBatchId: true,\n\t\t});\n\t}\n\n\tpublic get messageCount(): number {\n\t\treturn this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;\n\t}\n\n\tpublic get mainBatchMessageCount(): number {\n\t\treturn this.mainBatch.length;\n\t}\n\n\tpublic get blobAttachBatchMessageCount(): number {\n\t\treturn this.blobAttachBatch.length;\n\t}\n\n\tpublic get idAllocationBatchMessageCount(): number {\n\t\treturn this.idAllocationBatch.length;\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.messageCount === 0;\n\t}\n\n\tpublic containsUserChanges(): boolean {\n\t\treturn (\n\t\t\tthis.mainBatch.containsUserChanges() || this.blobAttachBatch.containsUserChanges()\n\t\t\t// ID Allocation ops are not user changes\n\t\t);\n\t}\n\n\t/**\n\t * Detect whether batching has been interrupted by an incoming message being processed. In this case,\n\t * we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new\n\t * message as the first message. If flushing partial batch is not enabled, we will throw (except for reentrant ops).\n\t * This would indicate we expected this case to be precluded by logic elsewhere.\n\t *\n\t * @remarks - To detect batch interruption, we compare both the reference sequence number\n\t * (i.e. last message processed by DeltaManager) and the client sequence number of the\n\t * last message processed by the ContainerRuntime. In the absence of op reentrancy, this\n\t * pair will remain stable during a single JS turn during which the batch is being built up.\n\t */\n\tprivate maybeFlushPartialBatch(): void {\n\t\tconst mainBatchSeqNums = this.mainBatch.sequenceNumbers;\n\t\tconst blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;\n\t\tconst idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;\n\t\tassert(\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&\n\t\t\t\tsequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums),\n\t\t\t0x58d /* Reference sequence numbers from both batches must be in sync */,\n\t\t);\n\n\t\tconst currentSequenceNumbers = this.params.getCurrentSequenceNumbers();\n\n\t\tif (\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)\n\t\t) {\n\t\t\t// The reference sequence numbers are stable, there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\t// Reference and/or Client sequence number will be advancing while processing this batch,\n\t\t// so we can't use this check to detect wrongdoing. But we will still log via telemetry.\n\t\t// This is rare, and the reentrancy will be handled during Flush.\n\t\tconst expectedDueToReentrancy = this.isContextReentrant();\n\n\t\tconst errorWrapper = new Lazy(() =>\n\t\t\tgetLongStack(() =>\n\t\t\t\tDataProcessingError.create(\n\t\t\t\t\t\"Sequence numbers advanced as if ops were processed while a batch is accumulating\",\n\t\t\t\t\t\"outboxSequenceNumberCoherencyCheck\",\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tif (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\t// Only log error if this is truly unexpected\n\t\t\t\t\tcategory:\n\t\t\t\t\t\texpectedDueToReentrancy || this.params.config.flushPartialBatches\n\t\t\t\t\t\t\t? \"generic\"\n\t\t\t\t\t\t\t: \"error\",\n\t\t\t\t\teventName: \"ReferenceSequenceNumberMismatch\",\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\texpectedDueToReentrancy,\n\t\t\t\t\t\tmainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tmainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tblobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tblobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tcurrentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,\n\t\t\t\t\t\tcurrentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\terrorWrapper.value,\n\t\t\t);\n\t\t}\n\n\t\t// If we're configured to flush partial batches, do that now and return (don't throw)\n\t\tif (this.params.config.flushPartialBatches) {\n\t\t\tthis.flushAll();\n\t\t\treturn;\n\t\t}\n\n\t\t// If we are in a reentrant context, we know this can happen without causing any harm.\n\t\tif (expectedDueToReentrancy) {\n\t\t\treturn;\n\t\t}\n\n\t\tthrow errorWrapper.value;\n\t}\n\n\tpublic submit(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.mainBatch, message);\n\t}\n\n\tpublic submitBlobAttach(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.blobAttachBatch, message);\n\t}\n\n\tpublic submitIdAllocation(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.idAllocationBatch, message);\n\t}\n\n\tprivate addMessageToBatchManager(\n\t\tbatchManager: BatchManager,\n\t\tmessage: LocalBatchMessage,\n\t): void {\n\t\tbatchManager.push(\n\t\t\tmessage,\n\t\t\tthis.isContextReentrant(),\n\t\t\tthis.params.getCurrentSequenceNumbers().clientSequenceNumber,\n\t\t);\n\t}\n\n\t/**\n\t * Flush all the batches to the ordering service.\n\t * This method is expected to be called at the end of a batch.\n\t *\n\t * @throws If called from a reentrant context, or if the batch being flushed is too large.\n\t * @param resubmitInfo - Key information when flushing a resubmitted batch. Undefined means this is not resubmit.\n\t */\n\tpublic flush(resubmitInfo?: BatchResubmitInfo): void {\n\t\tassert(\n\t\t\t!this.isContextReentrant(),\n\t\t\t0xb7b /* Flushing must not happen while incoming changes are being processed */,\n\t\t);\n\t\tthis.flushAll(resubmitInfo);\n\t}\n\n\tprivate flushAll(resubmitInfo?: BatchResubmitInfo): void {\n\t\tconst allBatchesEmpty =\n\t\t\tthis.idAllocationBatch.empty && this.blobAttachBatch.empty && this.mainBatch.empty;\n\t\tif (allBatchesEmpty) {\n\t\t\t// If we're resubmitting with a batchId and all batches are empty, we need to flush an empty batch.\n\t\t\t// Note that we currently resubmit one batch at a time, so on resubmit, 1 of the 2 batches will *always* be empty.\n\t\t\t// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored\n\t\t\t// by the rest of the system, including remote clients.\n\t\t\t// In some cases we *must* resubmit the empty batch (to match up with a non-empty version tracked locally by a container fork), so we do it always.\n\t\t\tif (resubmitInfo?.batchId !== undefined) {\n\t\t\t\tthis.flushEmptyBatch(resubmitInfo.batchId, resubmitInfo.staged);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't use resubmittingBatchId for idAllocationBatch.\n\t\t// ID Allocation messages are not directly resubmitted so don't pass the resubmitInfo\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.idAllocationBatch,\n\t\t\t// Note: For now, we will never stage ID Allocation messages.\n\t\t\t// They won't contain personal info and no harm in extra allocations in case of discarding the staged changes\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.blobAttachBatch,\n\t\t\tdisableGroupedBatching: true,\n\t\t\tresubmitInfo,\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.mainBatch,\n\t\t\tresubmitInfo,\n\t\t});\n\t}\n\n\tprivate flushEmptyBatch(\n\t\tresubmittingBatchId: BatchId,\n\t\tresubmittingStagedBatch: boolean,\n\t): void {\n\t\tconst referenceSequenceNumber =\n\t\t\tthis.params.getCurrentSequenceNumbers().referenceSequenceNumber;\n\t\tassert(\n\t\t\treferenceSequenceNumber !== undefined,\n\t\t\t0xa01 /* reference sequence number should be defined */,\n\t\t);\n\t\tconst { outboundBatch, placeholderMessage } =\n\t\t\tthis.params.groupingManager.createEmptyGroupedBatch(\n\t\t\t\tresubmittingBatchId,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t);\n\t\tlet clientSequenceNumber: number | undefined;\n\t\tif (this.params.shouldSend() && !resubmittingStagedBatch) {\n\t\t\tclientSequenceNumber = this.sendBatch(outboundBatch);\n\t\t}\n\n\t\t// Push the empty batch placeholder to the PendingStateManager\n\t\tthis.params.pendingStateManager.onFlushEmptyBatch(\n\t\t\tplaceholderMessage,\n\t\t\tclientSequenceNumber,\n\t\t\tresubmittingStagedBatch,\n\t\t);\n\t\treturn;\n\t}\n\n\tprivate flushInternal(params: {\n\t\tbatchManager: BatchManager;\n\t\tdisableGroupedBatching?: boolean;\n\t\tresubmitInfo?: BatchResubmitInfo; // undefined if not resubmitting\n\t}): void {\n\t\tconst { batchManager, disableGroupedBatching = false, resubmitInfo } = params;\n\t\tif (batchManager.empty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rawBatch = batchManager.popBatch(resubmitInfo?.batchId);\n\n\t\t// On resubmit we use the original batch's staged state, so these should match as well.\n\t\tconst staged = rawBatch.staged === true;\n\t\tassert(\n\t\t\tresubmitInfo === undefined || resubmitInfo.staged === staged,\n\t\t\t0xba3 /* Mismatch in staged state tracking */,\n\t\t);\n\n\t\tconst groupingEnabled =\n\t\t\t!disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();\n\t\tif (\n\t\t\tbatchManager.options.canRebase &&\n\t\t\trawBatch.hasReentrantOps === true &&\n\t\t\t// NOTE: This is too restrictive. We should rebase for any reentrant op, not just if it's going to be a grouped batch\n\t\t\t// However there is some test that is depending on this behavior so we haven't removed these conditions yet. See AB#33427\n\t\t\tgroupingEnabled &&\n\t\t\trawBatch.messages.length > 1\n\t\t) {\n\t\t\tassert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);\n\t\t\t// If a batch contains reentrant ops (ops created as a result from processing another op)\n\t\t\t// it needs to be rebased so that we can ensure consistent reference sequence numbers\n\t\t\t// and eventual consistency at the DDS level.\n\t\t\t// Note: Since this is happening in the same turn the ops were originally created with,\n\t\t\t// and they haven't gone to PendingStateManager yet, we can just let them respect\n\t\t\t// ContainerRuntime.inStagingMode\n\t\t\tthis.rebase(rawBatch, batchManager);\n\t\t\treturn;\n\t\t}\n\n\t\tlet clientSequenceNumber: number | undefined;\n\t\t// Did we disconnect? (i.e. is shouldSend false?)\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\t// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.\n\t\tif (this.params.shouldSend() && !staged) {\n\t\t\tconst virtualizedBatch = this.virtualizeBatch(rawBatch, groupingEnabled);\n\n\t\t\tclientSequenceNumber = this.sendBatch(virtualizedBatch);\n\t\t\tassert(\n\t\t\t\tclientSequenceNumber === undefined || clientSequenceNumber >= 0,\n\t\t\t\t0x9d2 /* unexpected negative clientSequenceNumber (empty batch should yield undefined) */,\n\t\t\t);\n\t\t}\n\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\trawBatch.messages,\n\t\t\tclientSequenceNumber,\n\t\t\tstaged,\n\t\t\tbatchManager.options.ignoreBatchId,\n\t\t);\n\t}\n\n\t/**\n\t * Rebases a batch. All the ops in the batch are resubmitted to the runtime and\n\t * they will end up back in the same batch manager they were flushed from and subsequently flushed.\n\t *\n\t * @param rawBatch - the batch to be rebased\n\t */\n\tprivate rebase(rawBatch: LocalBatch, batchManager: BatchManager): void {\n\t\tassert(!this.rebasing, 0x6fb /* Reentrancy */);\n\t\tassert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);\n\n\t\tthis.rebasing = true;\n\t\tconst squash = false;\n\t\tfor (const message of rawBatch.messages) {\n\t\t\tthis.params.reSubmit(\n\t\t\t\t{\n\t\t\t\t\truntimeOp: message.runtimeOp,\n\t\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\t\topMetadata: message.metadata,\n\t\t\t\t},\n\t\t\t\tsquash,\n\t\t\t);\n\t\t}\n\n\t\tif (this.batchRebasesToReport > 0) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"BatchRebase\",\n\t\t\t\t\tlength: rawBatch.messages.length,\n\t\t\t\t\treferenceSequenceNumber: rawBatch.referenceSequenceNumber,\n\t\t\t\t},\n\t\t\t\tnew UsageError(\"BatchRebase\"),\n\t\t\t);\n\t\t\tthis.batchRebasesToReport--;\n\t\t}\n\n\t\tthis.flushInternal({ batchManager });\n\t\tthis.rebasing = false;\n\t}\n\n\tprivate isContextReentrant(): boolean {\n\t\treturn this.params.opReentrancy() && !this.rebasing;\n\t}\n\n\t/**\n\t * As necessary and enabled, groups / compresses / chunks the given batch.\n\t *\n\t * @remarks - If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @param localBatch - Local Batch to be virtualized - i.e. transformed into an Outbound Batch\n\t * @param groupingEnabled - If true, Grouped batching is enabled.\n\t * @returns One of the following:\n\t * - (A) The original batch (Based on what's enabled)\n\t * - (B) A grouped batch (it's a singleton batch)\n\t * - (C) A compressed singleton batch\n\t * - (D) A singleton batch containing the last chunk.\n\t */\n\tprivate virtualizeBatch(localBatch: LocalBatch, groupingEnabled: boolean): OutboundBatch {\n\t\t// Shallow copy the local batch, updating the messages to be outbound messages\n\t\tconst originalBatch = localBatchToOutboundBatch(localBatch);\n\n\t\tconst originalOrGroupedBatch = groupingEnabled\n\t\t\t? this.params.groupingManager.groupBatch(originalBatch)\n\t\t\t: originalBatch;\n\n\t\tif (originalOrGroupedBatch.messages.length !== 1) {\n\t\t\t// Compression requires a single message, so return early otherwise.\n\t\t\treturn originalOrGroupedBatch;\n\t\t}\n\n\t\t// Regardless of whether we grouped or not, we now have a batch with a single message.\n\t\t// Now proceed to compress/chunk it if necessary.\n\t\tconst singletonBatch = originalOrGroupedBatch as OutboundSingletonBatch;\n\n\t\tif (\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes >\n\t\t\t\tsingletonBatch.contentSizeInBytes ||\n\t\t\tthis.params.submitBatchFn === undefined\n\t\t) {\n\t\t\t// Nothing to do if compression is disabled, unnecessary or unsupported.\n\t\t\treturn singletonBatch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(singletonBatch);\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes\n\t\t\t\t? compressedBatch\n\t\t\t\t: this.params.splitter.splitSingletonBatchMessage(compressedBatch);\n\t\t}\n\n\t\t// We want to distinguish this \"BatchTooLarge\" case from the generic \"BatchTooLarge\" case in sendBatch\n\t\tif (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(compressedBatch, \"CompressionInsufficient\", {\n\t\t\t\tuncompressedSizeInBytes: singletonBatch.contentSizeInBytes,\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\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 clientSequenceNumber of the start of the batch, or undefined if nothing was sent\n\t */\n\tprivate sendBatch(batch: OutboundBatch): number | undefined {\n\t\tconst length = batch.messages.length;\n\t\tif (length === 0) {\n\t\t\treturn undefined; // Nothing submitted\n\t\t}\n\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tif (socketSize >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(batch, \"CannotSend\");\n\t\t}\n\n\t\tlet clientSequenceNumber: number;\n\t\tif (this.params.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\tassert(\n\t\t\t\tbatch.messages[0].compression === undefined,\n\t\t\t\t0x5a6 /* Compression should not have happened if the loader does not support it */,\n\t\t\t);\n\n\t\t\tclientSequenceNumber = this.params.legacySendBatchFn(batch);\n\t\t} else {\n\t\t\tassert(batch.referenceSequenceNumber !== undefined, 0x58e /* Batch must not be empty */);\n\t\t\tclientSequenceNumber = this.params.submitBatchFn(\n\t\t\t\tbatch.messages.map<IBatchMessage>((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\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t\t})),\n\t\t\t\tbatch.referenceSequenceNumber,\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 makeBatchTooLargeError(\n\t\tbatch: OutboundBatch,\n\t\tcodepath: string,\n\t\tmoreDetails?: ITelemetryBaseProperties,\n\t): IFluidErrorBase {\n\t\treturn DataProcessingError.create(\n\t\t\t\"BatchTooLarge\",\n\t\t\tcodepath,\n\t\t\t/* sequencedMessage */ undefined,\n\t\t\t{\n\t\t\t\terrorDetails: {\n\t\t\t\t\topCount: batch.messages.length,\n\t\t\t\t\tcontentSizeInBytes: batch.contentSizeInBytes,\n\t\t\t\t\tsocketSize: estimateSocketSize(batch),\n\t\t\t\t\tmaxBatchSizeInBytes: this.params.config.maxBatchSizeInBytes,\n\t\t\t\t\tgroupedBatchingEnabled: this.params.groupingManager.groupedBatchingEnabled(),\n\t\t\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\t\t\tchunkSizeInBytes: this.params.splitter.chunkSizeInBytes,\n\t\t\t\t\t...moreDetails,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back.\n\t */\n\tpublic getBatchCheckpoints(): {\n\t\tmainBatch: IBatchCheckpoint;\n\t\tidAllocationBatch: IBatchCheckpoint;\n\t\tblobAttachBatch: IBatchCheckpoint;\n\t} {\n\t\t// This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type.\n\t\t// When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve.\n\t\tconst mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();\n\t\treturn {\n\t\t\tmainBatch,\n\t\t\tidAllocationBatch: this.idAllocationBatch.checkpoint(),\n\t\t\tblobAttachBatch: this.blobAttachBatch.checkpoint(),\n\t\t};\n\t}\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/container-runtime";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.42.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,sCAAsC,CAAC;AAC3D,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,sCAAsC,CAAC;AAC3D,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/container-runtime";
|
|
11
|
-
exports.pkgVersion = "2.
|
|
11
|
+
exports.pkgVersion = "2.42.0";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.42.0\";\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { IDisposable, type ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
6
6
|
import { type InboundSequencedContainerRuntimeMessage, type LocalContainerRuntimeMessage } from "./messageTypes.js";
|
|
7
|
-
import { LocalBatchMessage, InboundMessageResult, type LocalEmptyBatchPlaceholder, type BatchResubmitInfo } from "./opLifecycle/index.js";
|
|
7
|
+
import { EmptyGroupedBatch, LocalBatchMessage, InboundMessageResult, type LocalEmptyBatchPlaceholder, type BatchResubmitInfo } from "./opLifecycle/index.js";
|
|
8
8
|
/**
|
|
9
9
|
* This represents a message that has been submitted and is added to the pending queue when `submit` is called on the
|
|
10
10
|
* ContainerRuntime. This message has either not been ack'd by the server or has not been submitted to the server yet.
|
|
@@ -22,9 +22,20 @@ export interface IPendingMessage {
|
|
|
22
22
|
* The original runtime op that was submitted to the ContainerRuntime
|
|
23
23
|
* Unless this pending message came from stashed content, in which case this was roundtripped through string
|
|
24
24
|
*/
|
|
25
|
-
runtimeOp?: LocalContainerRuntimeMessage | undefined;
|
|
25
|
+
runtimeOp?: LocalContainerRuntimeMessage | EmptyGroupedBatch | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Local Op Metadata that was passed to the ContainerRuntime when the op was submitted.
|
|
28
|
+
* This contains state needed when processing the ack, or to resubmit or rollback the op.
|
|
29
|
+
*/
|
|
26
30
|
localOpMetadata: unknown;
|
|
31
|
+
/**
|
|
32
|
+
* Metadata that was passed to the ContainerRuntime when the op was submitted.
|
|
33
|
+
* This is rarely used, and may be inspected by the service (as opposed to op contents which is opaque)
|
|
34
|
+
*/
|
|
27
35
|
opMetadata: Record<string, unknown> | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Populated upon processing the op's ack, before moving the pending message to savedOps.
|
|
38
|
+
*/
|
|
28
39
|
sequenceNumber?: number;
|
|
29
40
|
/**
|
|
30
41
|
* Info about the batch this pending message belongs to, for validation and for computing the batchId on reconnect
|
|
@@ -131,6 +142,10 @@ export declare class PendingStateManager implements IDisposable {
|
|
|
131
142
|
* 'hasPendingMessages'.
|
|
132
143
|
*/
|
|
133
144
|
get pendingMessagesCount(): number;
|
|
145
|
+
/**
|
|
146
|
+
* Checks the pending messages to see if any of them represent user changes (aka "dirtyable" messages)
|
|
147
|
+
*/
|
|
148
|
+
hasPendingUserChanges(): boolean;
|
|
134
149
|
/**
|
|
135
150
|
* The minimumPendingMessageSequenceNumber is the minimum of the first pending message and the first initial message.
|
|
136
151
|
*
|
|
@@ -161,7 +176,7 @@ export declare class PendingStateManager implements IDisposable {
|
|
|
161
176
|
* @param staged - Indicates whether batch is staged (not to be submitted while runtime is in Staging Mode)
|
|
162
177
|
* @param ignoreBatchId - Whether to ignore the batchId in the batchStartInfo
|
|
163
178
|
*/
|
|
164
|
-
onFlushBatch(batch: LocalBatchMessage[], clientSequenceNumber: number | undefined, staged: boolean, ignoreBatchId?: boolean): void;
|
|
179
|
+
onFlushBatch(batch: LocalBatchMessage[] | [LocalEmptyBatchPlaceholder], clientSequenceNumber: number | undefined, staged: boolean, ignoreBatchId?: boolean): void;
|
|
165
180
|
/**
|
|
166
181
|
* Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted
|
|
167
182
|
* @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.
|
|
@@ -216,9 +231,11 @@ export declare class PendingStateManager implements IDisposable {
|
|
|
216
231
|
*/
|
|
217
232
|
replayPendingStates(optionsParam?: ReplayPendingStateOptions): void;
|
|
218
233
|
/**
|
|
219
|
-
* Pops all staged batches, invoking the callback on each
|
|
234
|
+
* Pops all staged batches, invoking the callback on each constituent op in order (LIFO)
|
|
220
235
|
*/
|
|
221
|
-
popStagedBatches(callback: (stagedMessage: IPendingMessage
|
|
236
|
+
popStagedBatches(callback: (stagedMessage: IPendingMessage & {
|
|
237
|
+
runtimeOp?: LocalContainerRuntimeMessage;
|
|
238
|
+
}) => void): void;
|
|
222
239
|
}
|
|
223
240
|
export {};
|
|
224
241
|
//# sourceMappingURL=pendingStateManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,12 +12,11 @@ const internal_1 = require("@fluidframework/core-utils/internal");
|
|
|
12
12
|
const internal_2 = require("@fluidframework/telemetry-utils/internal");
|
|
13
13
|
const double_ended_queue_1 = __importDefault(require("double-ended-queue"));
|
|
14
14
|
const uuid_1 = require("uuid");
|
|
15
|
+
const containerRuntime_js_1 = require("./containerRuntime.js");
|
|
15
16
|
const metadata_js_1 = require("./metadata.js");
|
|
16
17
|
const index_js_1 = require("./opLifecycle/index.js");
|
|
17
18
|
function isEmptyBatchPendingMessage(message) {
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
19
19
|
const content = JSON.parse(message.content);
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
21
20
|
return content.type === "groupedBatch" && content.contents?.length === 0;
|
|
22
21
|
}
|
|
23
22
|
function buildPendingMessageContent(message) {
|
|
@@ -102,6 +101,22 @@ class PendingStateManager {
|
|
|
102
101
|
get pendingMessagesCount() {
|
|
103
102
|
return this.pendingMessages.length + this.initialMessages.length;
|
|
104
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Checks the pending messages to see if any of them represent user changes (aka "dirtyable" messages)
|
|
106
|
+
*/
|
|
107
|
+
hasPendingUserChanges() {
|
|
108
|
+
for (let i = 0; i < this.pendingMessages.length; i++) {
|
|
109
|
+
const element = this.pendingMessages.get(i);
|
|
110
|
+
if (element?.runtimeOp !== undefined &&
|
|
111
|
+
isNotEmptyGroupedBatch(element) &&
|
|
112
|
+
(0, containerRuntime_js_1.isContainerMessageDirtyable)(element.runtimeOp)) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Consider any initial messages to be user changes
|
|
117
|
+
// (it's an approximation since we would have to parse them to know for sure)
|
|
118
|
+
return this.initialMessages.length > 0;
|
|
119
|
+
}
|
|
105
120
|
/**
|
|
106
121
|
* The minimumPendingMessageSequenceNumber is the minimum of the first pending message and the first initial message.
|
|
107
122
|
*
|
|
@@ -172,7 +187,6 @@ class PendingStateManager {
|
|
|
172
187
|
* ack is processed, to properly track batch IDs
|
|
173
188
|
*/
|
|
174
189
|
onFlushEmptyBatch(placeholder, clientSequenceNumber, staged) {
|
|
175
|
-
// We have to cast because runtimeOp doesn't apply for empty batches and is missing on LocalEmptyBatchPlaceholder
|
|
176
190
|
this.onFlushBatch([placeholder], clientSequenceNumber, staged);
|
|
177
191
|
}
|
|
178
192
|
/**
|
|
@@ -236,7 +250,9 @@ class PendingStateManager {
|
|
|
236
250
|
// We still need to track it for resubmission.
|
|
237
251
|
try {
|
|
238
252
|
if (isEmptyBatchPendingMessage(nextMessage)) {
|
|
239
|
-
nextMessage.localOpMetadata = {
|
|
253
|
+
nextMessage.localOpMetadata = {
|
|
254
|
+
emptyBatch: true,
|
|
255
|
+
}; // equivalent to applyStashedOp for empty batch
|
|
240
256
|
patchbatchInfo(nextMessage); // Back compat
|
|
241
257
|
this.pendingMessages.push(nextMessage);
|
|
242
258
|
continue;
|
|
@@ -392,7 +408,7 @@ class PendingStateManager {
|
|
|
392
408
|
// Get the next message from the pending queue. Verify a message exists.
|
|
393
409
|
const pendingMessage = this.pendingMessages.peekFront();
|
|
394
410
|
(0, internal_1.assert)(pendingMessage !== undefined, 0xa21 /* No pending message found as we start processing this remote batch */);
|
|
395
|
-
(0, internal_1.assert)(!pendingMessage.batchInfo.staged, 0xb85 /*
|
|
411
|
+
(0, internal_1.assert)(!pendingMessage.batchInfo.staged, 0xb85 /* Pending state mismatch, ack came in but next pending message is staged */);
|
|
396
412
|
// If this batch became empty on resubmit, batch.messages will be empty (but keyMessage is always set)
|
|
397
413
|
// and the next pending message should be an empty batch marker.
|
|
398
414
|
// More Info: We must submit empty batches and track them in case a different fork
|
|
@@ -471,14 +487,16 @@ class PendingStateManager {
|
|
|
471
487
|
const batchMetadataFlag = (0, metadata_js_1.asBatchMetadata)(pendingMessage.opMetadata)?.batch;
|
|
472
488
|
(0, internal_1.assert)(batchMetadataFlag !== false, 0x41b /* We cannot process batches in chunks */);
|
|
473
489
|
// The next message starts a batch (possibly single-message), and we'll need its batchId.
|
|
474
|
-
const batchId =
|
|
490
|
+
const batchId = pendingMessage.batchInfo.ignoreBatchId
|
|
491
|
+
? undefined
|
|
492
|
+
: (0, index_js_1.getEffectiveBatchId)(pendingMessage);
|
|
475
493
|
const staged = pendingMessage.batchInfo.staged;
|
|
476
494
|
if ((0, metadata_js_1.asEmptyBatchLocalOpMetadata)(pendingMessage.localOpMetadata)?.emptyBatch === true) {
|
|
477
495
|
// Resubmit no messages, with the batchId. Will result in another empty batch marker.
|
|
478
496
|
this.stateHandler.reSubmitBatch([], { batchId, staged, squash });
|
|
479
497
|
continue;
|
|
480
498
|
}
|
|
481
|
-
(0, internal_1.assert)(pendingMessage.runtimeOp !== undefined, 0xb87 /* viableOp is only undefined for empty batches */);
|
|
499
|
+
(0, internal_1.assert)(pendingMessage.runtimeOp !== undefined && isNotEmptyGroupedBatch(pendingMessage), 0xb87 /* viableOp is only undefined for empty batches */);
|
|
482
500
|
/**
|
|
483
501
|
* We must preserve the distinct batches on resubmit.
|
|
484
502
|
* Note: It is not possible for the PendingStateManager to receive a partially acked batch. It will
|
|
@@ -500,7 +518,7 @@ class PendingStateManager {
|
|
|
500
518
|
const batch = [];
|
|
501
519
|
// check is >= because batch end may be last pending message
|
|
502
520
|
while (remainingPendingMessagesCount >= 0) {
|
|
503
|
-
(0, internal_1.assert)(pendingMessage.runtimeOp !== undefined, 0xb88 /* viableOp is only undefined for empty batches */);
|
|
521
|
+
(0, internal_1.assert)(pendingMessage.runtimeOp !== undefined && isNotEmptyGroupedBatch(pendingMessage), 0xb88 /* viableOp is only undefined for empty batches */);
|
|
504
522
|
batch.push({
|
|
505
523
|
runtimeOp: pendingMessage.runtimeOp,
|
|
506
524
|
localOpMetadata: pendingMessage.localOpMetadata,
|
|
@@ -532,14 +550,16 @@ class PendingStateManager {
|
|
|
532
550
|
}
|
|
533
551
|
}
|
|
534
552
|
/**
|
|
535
|
-
* Pops all staged batches, invoking the callback on each
|
|
553
|
+
* Pops all staged batches, invoking the callback on each constituent op in order (LIFO)
|
|
536
554
|
*/
|
|
537
555
|
popStagedBatches(callback) {
|
|
538
556
|
while (!this.pendingMessages.isEmpty()) {
|
|
539
557
|
const stagedMessage = this.pendingMessages.peekBack();
|
|
540
558
|
if (stagedMessage?.batchInfo.staged === true) {
|
|
541
|
-
|
|
542
|
-
|
|
559
|
+
if (isNotEmptyGroupedBatch(stagedMessage)) {
|
|
560
|
+
callback(stagedMessage);
|
|
561
|
+
this.pendingMessages.pop();
|
|
562
|
+
}
|
|
543
563
|
}
|
|
544
564
|
else {
|
|
545
565
|
break; // no more staged messages
|
|
@@ -559,4 +579,7 @@ function patchbatchInfo(message) {
|
|
|
559
579
|
message.batchInfo = { clientId: (0, uuid_1.v4)(), batchStartCsn: -1, length: -1, staged: false };
|
|
560
580
|
}
|
|
561
581
|
}
|
|
582
|
+
function isNotEmptyGroupedBatch(message) {
|
|
583
|
+
return message.runtimeOp !== undefined && message.runtimeOp.type !== "groupedBatch";
|
|
584
|
+
}
|
|
562
585
|
//# sourceMappingURL=pendingStateManager.js.map
|