/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import type { IBatchMessage } from "@fluidframework/container-definitions/internal"; import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces"; import type { ICompressionRuntimeOptions } from "../compressionDefinitions.js"; import type { PendingMessageResubmitData, PendingStateManager } from "../pendingStateManager.js"; import { type BatchSequenceNumbers } from "./batchManager.js"; import type { LocalBatchMessage, IBatchCheckpoint, LocalBatch, OutboundBatch } from "./definitions.js"; import type { OpCompressor } from "./opCompressor.js"; import type { OpGroupingManager } from "./opGroupingManager.js"; import type { OpSplitter } from "./opSplitter.js"; export interface IOutboxConfig { readonly compressionOptions: ICompressionRuntimeOptions; /** * The maximum size of a batch that we can send over the wire. */ readonly maxBatchSizeInBytes: number; } export interface IOutboxParameters { readonly shouldSend: () => boolean; readonly pendingStateManager: PendingStateManager; readonly submitBatchFn: ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number) | undefined; readonly legacySendBatchFn: (batch: OutboundBatch) => number; readonly config: IOutboxConfig; readonly compressor: OpCompressor; readonly splitter: OpSplitter; readonly logger: ITelemetryBaseLogger; readonly groupingManager: OpGroupingManager; readonly getCurrentSequenceNumbers: () => BatchSequenceNumbers; readonly reSubmit: (message: PendingMessageResubmitData, squash: boolean) => void; readonly opReentrancy: () => boolean; /** * JIT callback to generate an ID allocation op at flush time. * Called after rebase (if any), so the returned message has the correct refSeq. * * @returns A LocalBatchMessage for the ID allocation op, or undefined if no IDs need allocating. */ readonly generateIdAllocationOp: () => LocalBatchMessage | undefined; } /** * Info needed to correctly resubmit a batch */ export interface BatchResubmitInfo { /** * If defined, indicates the Batch ID of the batch being resubmitted. * This must be preserved on the new batch about to be submitted so they can be correlated/deduped in case both are sent. */ batchId?: string; /** * Indicates whether or not this batch is "staged", meaning it should not be sent to the ordering service yet * This is important on resubmit because we may be in Staging Mode for new changes, * but resubmitting a non-staged change from before entering Staging Mode */ staged: boolean; } /** * Temporarily increase the stack limit while executing the provided action. * If a negative value is provided for `length`, no stack frames will be collected. * If Infinity is provided, all frames will be collected. * * ADO:4663 - add this to the common packages. * * @param action - action which returns an error * @param length - number of stack frames to collect, 50 if unspecified. * @returns the result of the action provided */ export declare function getLongStack(action: () => T, length?: number): T; /** * Convert from local batch to outbound batch, including computing contentSizeInBytes. */ export declare function localBatchToOutboundBatch({ staged: _staged, // Peel this off the incoming batch, it's irrelevant (see Note below) ...localBatch }: LocalBatch): OutboundBatch; /** * Estimates the real size in bytes on the socket for a given batch. It assumes that * the envelope size (and the size of an empty op) is 200 bytes, taking into account * extra overhead from stringification. * * @remarks * Also content will be stringified, and that adds a lot of overhead due to a lot of escape characters. * Not taking it into account, as compression work should help there - compressed payload will be * initially stored as base64, and that requires only 2 extra escape characters. * * @param batch - the batch to inspect * @returns An estimate of the payload size in bytes which will be produced when the batch is sent over the wire */ export declare const estimateSocketSize: (batch: OutboundBatch) => number; /** * The Outbox collects messages submitted by the ContainerRuntime into a batch, * and then flushes the batch when requested. * * @remarks There are actually multiple independent batches (some are for a specific message type), * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping). */ export declare class Outbox { private readonly params; private readonly logger; private readonly mainBatch; private readonly blobAttachBatch; private batchRebasesToReport; private rebasing; /** * Track the number of ops which were detected to have a mismatched * reference sequence number, in order to self-throttle the telemetry events. * * This should be removed as part of ADO:2322 */ private readonly maxMismatchedOpsToReport; private mismatchedOpsReported; constructor(params: IOutboxParameters); get messageCount(): number; get mainBatchMessageCount(): number; get blobAttachBatchMessageCount(): number; get isEmpty(): boolean; containsUserChanges(): boolean; /** * Detect whether batching has been interrupted by an incoming message being processed. In this case, * we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new * message as the first message. If flushing partial batch is not enabled, we will throw (except for reentrant ops). * This would indicate we expected this case to be precluded by logic elsewhere. * * @remarks To detect batch interruption, we compare both the reference sequence number * (i.e. last message processed by DeltaManager) and the client sequence number of the * last message processed by the ContainerRuntime. In the absence of op reentrancy, this * pair will remain stable during a single JS turn during which the batch is being built up. */ private outboxSequenceNumberCoherencyCheck; submit(message: LocalBatchMessage): void; submitBlobAttach(message: LocalBatchMessage): void; private addMessageToBatchManager; /** * Flush all the batches to the ordering service. * This method is expected to be called at the end of a batch. * * @throws If called from a reentrant context, or if the batch being flushed is too large. * @param resubmitInfo - Key information when flushing a resubmitted batch. Undefined means this is not resubmit. */ flush(resubmitInfo?: BatchResubmitInfo): void; private flushAll; private flushEmptyBatch; private flushInternal; /** * Rebases a batch. All the ops in the batch are resubmitted to the runtime and * they will end up back in the same batch manager they were flushed from and subsequently flushed. * * @param rawBatch - the batch to be rebased */ private rebase; private isContextReentrant; /** * As necessary and enabled, groups / compresses / chunks the given batch. * * @remarks If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn. * * @param localBatch - Local Batch to be virtualized - i.e. transformed into an Outbound Batch * @param groupingEnabled - If true, Grouped batching is enabled. * @returns One of the following: * - (A) The original batch (Based on what's enabled) * - (B) A grouped batch (it's a singleton batch) * - (C) A compressed singleton batch * - (D) A singleton batch containing the last chunk. */ private virtualizeBatch; /** * Sends the batch object to the container context to be sent over the wire. * * @param batch - batch to be sent * @returns the clientSequenceNumber of the start of the batch, or undefined if nothing was sent */ private sendBatch; private makeBatchTooLargeError; /** * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back. */ getBatchCheckpoints(): { mainBatch: IBatchCheckpoint; blobAttachBatch: IBatchCheckpoint; }; } //# sourceMappingURL=outbox.d.ts.map