Skip to content

Write support for blob handles with pending payload #24458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
May 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,24 @@ export interface IFluidHandleContext extends IProvideFluidHandleContext {
export interface IFluidHandleErased<T> extends ErasedType<readonly ["IFluidHandle", T]> {
}

// @alpha @legacy
export interface IFluidHandleEvents {
payloadShared: () => void;
}

// @alpha @legacy
export interface IFluidHandleInternal<out T = unknown> extends IFluidHandle<T>, IProvideFluidHandle {
readonly absolutePath: string;
attachGraph(): void;
bind(handle: IFluidHandleInternal): void;
}

// @alpha @legacy
export interface IFluidHandlePayloadPending<T> extends IFluidHandle<T> {
readonly events: Listenable<IFluidHandleEvents>;
readonly payloadState: PayloadState;
}

// @public (undocumented)
export const IFluidLoadable: keyof IProvideFluidLoadable;

Expand All @@ -281,6 +292,17 @@ export interface IFluidLoadable extends IProvideFluidLoadable {
readonly handle: IFluidHandle;
}

// @alpha @legacy
export interface ILocalFluidHandle<T> extends IFluidHandlePayloadPending<T> {
readonly events: Listenable<IFluidHandleEvents & ILocalFluidHandleEvents>;
readonly payloadShareError: unknown;
}

// @alpha @legacy
export interface ILocalFluidHandleEvents extends IFluidHandleEvents {
payloadShareFailed: (error: unknown) => void;
}

// @alpha @legacy
export interface ILoggingError extends Error {
getTelemetryProperties(): ITelemetryBaseProperties;
Expand Down Expand Up @@ -387,6 +409,9 @@ export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
// @public
export type Off = () => void;

// @alpha @legacy
export type PayloadState = "pending" | "shared";

// @public
export type ReplaceIEventThisPlaceHolder<L extends any[], TThis> = L extends any[] ? {
[K in keyof L]: L[K] extends IEventThisPlaceHolder ? TThis : L[K];
Expand Down
72 changes: 72 additions & 0 deletions packages/common/core-interfaces/src/handles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import type { ErasedType } from "./erasedType.js";
import type { IRequest, IResponse } from "./fluidRouter.js";
import type { Listenable } from "./internal.js";

/**
* @legacy
Expand Down Expand Up @@ -117,6 +118,77 @@ export interface IFluidHandleInternalPayloadPending<
readonly payloadPending: boolean;
}

/**
* The state of the handle's payload.
* - "pending" - The payload is not shared to all collaborators
* - "shared" - The payload is available to both the local client and remote collaborators
*
* @remarks
* Clients will see a transition of "pending" to "shared" when the payload has been shared to all collaborators.
* @legacy
* @alpha
*/
export type PayloadState = "pending" | "shared";

/**
* Events which fire from an IFluidHandle.
* @legacy
* @alpha
*/
export interface IFluidHandleEvents {
/**
* Emitted when the payload becomes available to remote collaborators.
*/
payloadShared: () => void;
}

/**
* Observable state on the handle regarding its payload sharing state.
*
* @privateRemarks
* Contents to be merged to IFluidHandle, and then this separate interface should be removed.
* @legacy
* @alpha
*/
export interface IFluidHandlePayloadPending<T> extends IFluidHandle<T> {
/**
* The current state of the handle's payload.
*/
readonly payloadState: PayloadState;
/**
* Event emitter, with events that emit as the payload state transitions.
*/
readonly events: Listenable<IFluidHandleEvents>;
}

/**
* Additional events which fire as a local handle's payload state transitions.
* @legacy
* @alpha
*/
export interface ILocalFluidHandleEvents extends IFluidHandleEvents {
/**
* Emitted for locally created handles when the payload fails sharing to remote collaborators.
*/
payloadShareFailed: (error: unknown) => void;
}

/**
* Additional observable state on a local handle regarding its payload sharing state.
* @legacy
* @alpha
*/
export interface ILocalFluidHandle<T> extends IFluidHandlePayloadPending<T> {
/**
* The error encountered by the handle while sharing the payload, if one has occurred. Undefined if no error has occurred.
*/
readonly payloadShareError: unknown;
/**
* Event emitter, with events that emit as the payload state transitions.
*/
readonly events: Listenable<IFluidHandleEvents & ILocalFluidHandleEvents>;
}

/**
* Symbol which must only be used on an {@link (IFluidHandle:interface)}, and is used to identify such objects.
*
Expand Down
11 changes: 8 additions & 3 deletions packages/common/core-interfaces/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ export { IFluidLoadable, IFluidRunnable } from "./fluidLoadable.js";
export type { IRequest, IRequestHeader, IResponse } from "./fluidRouter.js";

export type {
IProvideFluidHandleContext,
IProvideFluidHandle,
IFluidHandleErased,
IFluidHandleEvents,
IFluidHandleInternal,
IFluidHandleInternalPayloadPending,
IFluidHandleErased,
IFluidHandlePayloadPending,
ILocalFluidHandle,
ILocalFluidHandleEvents,
IProvideFluidHandle,
IProvideFluidHandleContext,
PayloadState,
} from "./handles.js";
export { IFluidHandleContext, IFluidHandle, fluidHandleSymbol } from "./handles.js";

Expand Down
Loading
Loading