/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import { AttachState } from "@fluidframework/container-definitions"; import type { FluidObject, IDisposable, IRequest, IResponse, ITelemetryBaseLogger } from "@fluidframework/core-interfaces"; import type { IFluidHandleInternal, ISignalEnvelope } from "@fluidframework/core-interfaces/internal"; import type { ISnapshot, ISnapshotTree } from "@fluidframework/driver-definitions/internal"; import type { AliasResult, ContainerExtensionProvider, FluidDataStoreMessage, IEnvelope, IFluidDataStoreChannel, IFluidDataStoreContext, IFluidDataStoreContextDetached, IFluidDataStoreFactory, IFluidDataStoreRegistry, IFluidParentContext, IGarbageCollectionData, IInboundSignalMessage, IRuntimeMessageCollection, ISummaryTreeWithStats, ITelemetryContext, MinimumVersionForCollab, NamedFluidDataStoreRegistryEntries } from "@fluidframework/runtime-definitions/internal"; import { type MonitoringContext } from "@fluidframework/telemetry-utils/internal"; import { type RuntimeHeaderData } from "./containerRuntime.js"; import { type IFluidDataStoreContextPrivate, type ILocalDetachedFluidDataStoreContextProps, LocalFluidDataStoreContext } from "./dataStoreContext.js"; import { DataStoreContexts } from "./dataStoreContexts.js"; import { GCNodeType, type IGCNodeUpdatedProps } from "./gc/index.js"; import type { ContainerRuntimeAliasMessage, ContainerRuntimeDataStoreOpMessage, OutboundContainerRuntimeAttachMessage } from "./messageTypes.js"; import { type IContainerRuntimeMetadata } from "./summary/index.js"; /** * True if a tombstoned object should be returned without erroring * @legacy @beta */ export declare const AllowTombstoneRequestHeaderKey = "allowTombstone"; /** * Envelope for signals not intended for the container. * * @privateRemarks * `clientBroadcastSignalSequenceNumber` might be added to the envelope by the container runtime. * But it should not be provided to start with. * * Equivalent to `Required>`. */ export type AddressedUnsequencedSignalEnvelope = IEnvelope; /** * This version of the interface is private to this the package. It should never be exported under any tag. * It is used to manage interactions within the container-runtime package. If something is needed * cross package, it is likely it is also being used cross layer (ContainerRuntime * DataStoreRuntime). * If that is the case, the change likely needs to be staged directly on IFluidParentContext. Changes * being staged on IFluidParentContext can be added here as well, likely with optionality removed, * to ease interactions within this package. */ export interface IFluidParentContextPrivate extends IFluidParentContext, ContainerExtensionProvider { readonly isReadOnly: () => boolean; readonly minVersionForCollab: MinimumVersionForCollab; } /** * Kin of {@link @fluidframework/runtime-definitions#IFluidParentContext} with alternate * `submitMessage` and `submitSignal` methods that are typed specifically for the * root context (aka {@link ContainerRuntime} provided context). * * @privateRemarks * These replacements might be able to get cleaned up if the future suggestions * found in {@link @fluidframework/runtime-definitions#FluidDataStoreMessage} * `@privateRemarks` section are implemented. */ export interface IFluidRootParentContextPrivate extends Omit { /** * Submits the message to be sent to other clients. * @param containerRuntimeMessage - The message. * @param localOpMetadata - The local metadata associated with the message. * This is kept locally 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. */ readonly submitMessage: (containerRuntimeMessage: ContainerRuntimeDataStoreOpMessage | OutboundContainerRuntimeAttachMessage | ContainerRuntimeAliasMessage, localOpMetadata: unknown) => void; /** * Submits the signal to be sent to other clients. * @param envelope - {@link IEnvelope} containing the signal address and contents. * @param targetClientId - When specified, the signal is only sent to the provided client id. */ readonly submitSignal: (envelope: AddressedUnsequencedSignalEnvelope, targetClientId?: string) => void; } type SubmitKeys = "submitMessage" | "submitSignal"; /** * Creates a shallow wrapper of {@link IFluidParentContextPrivate} or * {@link IFluidRootParentContextPrivate} with `submitMessage` and `submitSignal` * methods replaced with the provided overrides. */ export declare function formParentContext(context: Omit, overrides: Pick): Omit & Pick; /** * Returns the type of the given local data store from its package path. */ export declare function getLocalDataStoreType(localDataStore: LocalFluidDataStoreContext): string; /** * This class encapsulates data store handling. Currently it is only used by the container runtime, * but eventually could be hosted on any channel once we formalize the channel api boundary. * @internal */ export declare class ChannelCollection implements Omit, IDisposable { protected readonly baseSnapshot: ISnapshotTree | ISnapshot | undefined; readonly parentContext: IFluidRootParentContextPrivate; private readonly gcNodeUpdated; private readonly isDataStoreDeleted; private readonly aliasMap; private readonly pendingAttach; readonly attachOpFiredForDataStore: Set; protected readonly mc: MonitoringContext; private readonly disposeOnce; readonly containerLoadStats: { readonly containerLoadDataStoreCount: number; readonly referencedDataStoreCount: number; }; private readonly pendingAliasMap; protected readonly contexts: DataStoreContexts; private readonly aliasedDataStores; constructor(baseSnapshot: ISnapshotTree | ISnapshot | undefined, parentContext: IFluidRootParentContextPrivate, baseLogger: ITelemetryBaseLogger, gcNodeUpdated: (props: IGCNodeUpdatedProps) => void, isDataStoreDeleted: (nodePath: string) => boolean, aliasMap: Map); get aliases(): ReadonlyMap; get pendingAliases(): Map>; waitIfPendingAlias(maybeAlias: string): Promise; /** * For sampling. Only log once per container */ private shouldSendAttachLog; protected wrapContextForInnerChannel(id: string): IFluidParentContextPrivate; /** * IFluidDataStoreChannel.makeVisibleAndAttachGraph implementation * Not clear when it would be called and what it should do. * Currently this API is called by context only for root data stores. */ makeVisibleAndAttachGraph(): void; private processAttachMessages; private processAliasMessages; processAliasMessageCore(internalId: string, alias: string, messageTimestampMs?: number): boolean; private alreadyProcessed; /** * Package up the context's attach summary etc into an IAttachMessage */ private generateAttachMessage; /** * Make the data store locally visible in the container graph by moving the data store context from unbound to * bound list and submitting the attach message. This data store can now be reached from the root. * @param id - The id of the data store context to make visible. */ private makeDataStoreLocallyVisible; protected submitAttachChannelOp(localContext: LocalFluidDataStoreContext): void; /** * Generate compact internal DataStore ID. * * A note about namespace and name collisions: * This code assumes that that's the only way to generate internal IDs, and that it's Ok for this namespace to overlap with * user-provided alias names namespace. * There are two scenarios where it could cause trouble: * 1) Old files, where (already removed) CreateRoot*DataStore*() API was used, and thus internal name of data store * was provided by user. Such files may experience name collision with future data stores that receive a name generated * by this function. * 2) Much less likely, but if it happen that internal ID (generated by this function) is exactly the same as alias name * that user might use in the future, them ContainerRuntime.getAliasedDataStoreEntryPoint() or * ContainerRuntime.getDataStoreFromRequest() could return a data store with internalID matching user request, even though * user expected some other data store (that would receive alias later). * Please note that above mentioned functions have the implementation they have (allowing #2) due to #1. */ protected createDataStoreId(): string; createDetachedDataStore(pkg: readonly string[], loadingGroupId?: string): IFluidDataStoreContextDetached; createDataStoreContext(pkg: readonly string[], loadingGroupId?: string): IFluidDataStoreContextPrivate; protected createContext(id: string, pkg: readonly string[], contextCtor: new (props: ILocalDetachedFluidDataStoreContextProps) => T, loadingGroupId?: string): T; get disposed(): boolean; dispose(): void; readonly reSubmitContainerMessage: (message: ContainerRuntimeDataStoreOpMessage | OutboundContainerRuntimeAttachMessage | ContainerRuntimeAliasMessage, localOpMetadata: unknown, squash: boolean) => void; protected readonly resubmitDataStoreOp: (envelope: IEnvelope, localOpMetadata: unknown, squash: boolean) => void; readonly rollbackDataStoreOp: (envelope: IEnvelope, localOpMetadata: unknown) => void; applyStashedOp(content: unknown): Promise; protected applyStashedChannelChannelOp(envelope: IEnvelope): Promise; private applyStashedAttachOp; /** * Process messages for this channel collection. The messages here are contiguous messages in a batch. * @param messageCollection - The collection of messages to process. */ processMessages(messageCollection: IRuntimeMessageCollection): void; /** * Process channel messages. The messages here are contiguous channel type messages in a batch. Bunch * of contiguous messages for a data store should be sent to it together. * @param messageCollection - The collection of messages to process. */ private processChannelMessages; private getDataStore; /** * Returns the data store requested with the given id if available. Otherwise, returns undefined. */ getDataStoreIfAvailable(id: string, requestHeaderData: RuntimeHeaderData): Promise; /** * Checks if the data store has been deleted by GC. If so, log an error. * @param id - The data store's id. * @param context - The data store context. * @param deletedLogSuffix - Whether it was Changed or Requested (will go into the eventName) * @param callSite - The function name this is called from. * @param requestHeaderData - The request header information to log if the data store is deleted. * @param originalRequest - The original request (could be for a child of the DataStore) * @returns true if the data store is deleted. Otherwise, returns false. */ private checkAndLogIfDeleted; processSignal(messageArg: IInboundSignalMessage, local: boolean): void; setConnectionState(canSendOps: boolean, clientId?: string): void; /** * Enumerates the contexts and calls notifyReadOnlyState on them. */ notifyReadOnlyState(readonly: boolean): void; /** * Notifies all data store contexts about the current staging mode state. * * @param staging - A boolean indicating whether the container is in staging mode. */ notifyStagingMode(staging: boolean): void; setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void; get size(): number; /** * Create a summary. Used when attaching or serializing a detached container. */ getAttachSummary(telemetryContext?: ITelemetryContext): ISummaryTreeWithStats; /** * Gets the GC data. Used when attaching or serializing a detached container. */ getAttachGCData(telemetryContext?: ITelemetryContext): IGarbageCollectionData; /** * Helper method for preparing to attach this channel. * Runs the callback for each bound context to incorporate its data however the caller specifies */ private visitLocalBoundContextsDuringAttach; /** * Helper method for preparing to summarize this channel. * Runs the callback for each bound context to incorporate its data however the caller specifies */ private visitContextsDuringSummary; summarize(fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext): Promise; /** * Generates data used for garbage collection. It does the following: * * 1. Calls into each child data store context to get its GC data. * * 2. Prefixes the child context's id to the GC nodes in the child's GC data. This makes sure that the node can be * identified as belonging to the child. * * 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent * the GC data of this channel. * * @param fullGC - true to bypass optimizations and force full generation of GC data. */ getGCData(fullGC?: boolean): Promise; /** * After GC has run, called to notify this Container's data stores of routes that are used in it. * @param usedRoutes - The routes that are used in all data stores in this Container. */ updateUsedRoutes(usedRoutes: readonly string[]): void; deleteChild(dataStoreId: string): void; /** * Delete data stores and its objects that are sweep ready. * @param sweepReadyDataStoreRoutes - The routes of data stores and its objects that are sweep ready and should * be deleted. * @returns The routes of data stores and its objects that were deleted. */ deleteSweepReadyNodes(sweepReadyDataStoreRoutes: readonly string[]): readonly string[]; /** * This is called to update objects whose routes are tombstones. * * A Tombstoned object has been unreferenced long enough that GC knows it won't be referenced again. * Tombstoned objects are eventually deleted by GC. * * @param tombstonedRoutes - The routes that are tombstones in all data stores in this Container. */ updateTombstonedRoutes(tombstonedRoutes: readonly string[]): void; /** * Returns the outbound routes of this channel. Only root data stores are considered referenced and their paths are * part of outbound routes. */ private getOutboundRoutes; /** * Called by GC to retrieve the package path of a data store node with the given path. */ getDataStorePackagePath(nodePath: string): Promise; /** * Called by GC to determine if a node is for a data store or for an object within a data store (for e.g. DDS). * @returns the GC node type if the node belongs to a data store or object within data store, undefined otherwise. */ getGCNodeType(nodePath: string): GCNodeType | undefined; internalId(maybeAlias: string): string; request(request: IRequest): Promise; } export declare function getSummaryForDatastores(snapshot: ISnapshotTree | undefined, metadata?: IContainerRuntimeMetadata): ISnapshotTree | undefined; /** * Traverse this op's contents and detect any outbound routes that were added by this op. * * @internal */ export declare function detectOutboundReferences(address: string, contents: unknown, addedOutboundReference: (fromNodePath: string, toNodePath: string) => void): void; /** * @privateRemarks This class is only used for experimentation/testing. */ export declare class ComposableChannelCollection extends ChannelCollection implements IFluidDataStoreChannel { readonly entryPoint: IFluidHandleInternal; constructor(baseSnapshot: ISnapshotTree | ISnapshot | undefined, parentContext: IFluidParentContextPrivate, baseLogger: ITelemetryBaseLogger, gcNodeUpdated: (props: IGCNodeUpdatedProps) => void, isDataStoreDeleted: (nodePath: string) => boolean, aliasMap: Map, provideEntryPoint: (runtime: ComposableChannelCollection) => Promise); reSubmit(type: string, content: unknown, localOpMetadata: unknown, squash: boolean): void; rollback(type: string, content: unknown, localOpMetadata: unknown): void; } /** * @privateRemarks This factory is only used for experimentation/testing. * * @internal */ export declare class ChannelCollectionFactory implements IFluidDataStoreFactory { private readonly provideEntryPoint; readonly type = "ChannelCollectionChannel"; IFluidDataStoreRegistry: IFluidDataStoreRegistry; constructor(registryEntries: NamedFluidDataStoreRegistryEntries, provideEntryPoint: (runtime: IFluidDataStoreChannel) => Promise); get IFluidDataStoreFactory(): ChannelCollectionFactory; instantiateDataStore(context: IFluidDataStoreContext, _existing: boolean): Promise; } export {}; //# sourceMappingURL=channelCollection.d.ts.map