/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import type { TypedEventEmitter } from "@fluid-internal/client-utils"; import type { IFluidHandle } from "@fluidframework/core-interfaces"; import type { IFluidSerializer } from "@fluidframework/shared-object-base/internal"; import type { ISharedMapEvents } from "./interfaces.js"; import type { IMapClearOperation, IMapDeleteOperation, IMapSetOperation, ISerializableValue, ISerializedValue } from "./internalInterfaces.js"; /** * Union of all possible map operations. */ export type IMapOperation = IMapSetOperation | IMapDeleteOperation | IMapClearOperation; /** * Defines the in-memory object structure to be used for the conversion to/from serialized. * * @remarks Directly used in * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify * | JSON.stringify}, direct result from * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse | JSON.parse}. */ export type IMapDataObjectSerializable = Record; /** * Serialized key/value data. */ export type IMapDataObjectSerialized = Record; /** * A SharedMap is a map-like distributed data structure. */ export declare class MapKernel { private readonly serializer; private readonly handle; private readonly submitMessage; private readonly isAttached; private readonly eventEmitter; /** * The number of key/value pairs stored in the map. */ get size(): number; /** * Mapping of op types to message handlers. */ private readonly messageHandlers; /** * The data the map is storing, but only including sequenced values (no local pending * modifications are included). */ private readonly sequencedData; /** * A data structure containing all local pending modifications, which is used in combination * with the sequencedData to compute optimistic values. * * Pending sets are aggregated into "lifetimes", which permit correct relative iteration order * even across remote operations and rollbacks. */ private readonly pendingData; /** * Create a new shared map kernel. * @param serializer - The serializer to serialize / parse handles * @param handle - The handle of the shared object using the kernel * @param submitMessage - A callback to submit a message through the shared object * @param isAttached - To query whether the shared object should generate ops * @param valueTypes - The value types to register * @param eventEmitter - The object that will emit map events */ constructor(serializer: IFluidSerializer, handle: IFluidHandle, submitMessage: (op: unknown, localOpMetadata: unknown) => void, isAttached: () => boolean, eventEmitter: TypedEventEmitter); /** * Get an iterator over the optimistically observable ILocalValue entries in the map. For example, excluding * sequenced entries that have pending deletes/clears. * * @remarks * There is no perfect solution here, particularly when the iterator is retained over time and the map is * modified or new ack's are received. The pendingData portion of the iteration is the most susceptible to * this problem. The implementation prioritizes (in roughly this order): * 1. Correct immediate iteration (i.e. when the map is not modified before iteration completes) * 2. Consistent iteration order before/after sequencing of pending ops; acks don't change order * 3. Consistent iteration order between synchronized clients, even if they each modified the map concurrently * 4. Remaining as close as possible to the native Map iterator behavior, e.g. live-ish view rather than snapshot * * For this reason, it's important not to internally snapshot the output of the iterator for any purpose that * does not immediately (synchronously) consume that output and dispose of it. */ private readonly internalIterator; /** * Get an iterator over the entries in this map. * @returns The iterator */ entries(): IterableIterator<[string, unknown]>; /** * Get an iterator over the keys in this map. * @returns The iterator */ keys(): IterableIterator; /** * Get an iterator over the values in this map. * @returns The iterator */ values(): IterableIterator; /** * Get an iterator over the entries in this map. * @returns The iterator */ [Symbol.iterator](): IterableIterator<[string, unknown]>; /** * Executes the given callback on each entry in the map. * @param callbackFn - Callback function */ forEach(callbackFn: (value: unknown, key: string, map: Map) => void): void; /** * Compute the optimistic local value for a given key. This combines the sequenced data with * any pending changes that have not yet been sequenced. */ private readonly getOptimisticLocalValue; /** * {@inheritDoc ISharedMap.get} */ get(key: string): T | undefined; /** * Check if a key exists in the map. * @param key - The key to check * @returns True if the key exists, false otherwise */ has(key: string): boolean; /** * {@inheritDoc ISharedMap.set} */ set(key: string, value: unknown): void; /** * Delete a key from the map. * @param key - Key to delete * @returns True if the key existed and was deleted, false if it did not exist */ delete(key: string): boolean; /** * Clear all data from the map. */ clear(): void; /** * Serializes the data stored in the shared map to a JSON string * @param serializer - The serializer to use to serialize handles in its values. * @returns A JSON string containing serialized map data */ getSerializedStorage(serializer: IFluidSerializer): IMapDataObjectSerialized; /** * Populate the kernel with the given map data. * @param data - A JSON string containing serialized map data */ populateFromSerializable(json: IMapDataObjectSerializable): void; /** * Resubmit the given op if a handler is registered. * @param op - The operation to attempt to submit * @param localOpMetadata - The local metadata associated with the op. This is kept locally by the runtime * and not sent to the server. This will be sent back when this message is received back from the server. This is * also sent if we are asked to resubmit the message. * @returns True if the operation was submitted, false otherwise. */ tryResubmitMessage(op: IMapOperation, localOpMetadata: unknown): boolean; tryApplyStashedOp(op: IMapOperation): void; /** * Process the given op if a handler is registered. * @param message - The message to process * @param local - Whether the message originated from the local client * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message. * For messages from a remote client, this will be undefined. * @returns True if the operation was recognized and thus processed, false otherwise. * * @remarks * When this returns false and the caller doesn't handle the op itself, then the op could be from a different version of this code. * In such a case, not applying the op would result in this client becoming out of sync with clients that do handle the op * and could result in data corruption or data loss as well. * Therefore, in such cases the caller should typically throw an error, ensuring that this client treats the situation as data corruption * (since its data no longer matches what other clients think the data should be) and will avoid overriding document content or misleading the users into thinking their current state is accurate. */ tryProcessMessage(op: IMapOperation, local: boolean, localOpMetadata: unknown): boolean; /** * Rollback a local op * @param op - The operation to rollback * @param localOpMetadata - The local metadata associated with the op. */ rollback(op: unknown, localOpMetadata: unknown): void; /** * Get the message handlers for the map. * @returns A map of string op names to IMapMessageHandlers for those ops */ private getMessageHandlers; } //# sourceMappingURL=mapKernel.d.ts.map