grafast
Version:
Cutting edge GraphQL planning and execution engine
192 lines • 7.59 kB
TypeScript
import type { Bucket } from "../bucket.js";
import type { Step } from "../step";
import type { __ValueStep } from "../steps/index.js";
import type { OperationPlan } from "./OperationPlan";
/** Non-branching, non-deferred */
export interface LayerPlanReasonRoot {
type: "root";
}
/** Non-branching, non-deferred */
export interface LayerPlanReasonNullableField {
type: "nullableBoundary";
parentLayerPlan: LayerPlan;
/**
* Can be used such that the same LayerPlan can be used for two selection
* sets for the same parent plan. In this case an additional output plan
* would be added to the LayerPlan.
*
* Also needed for execution (see `executeBucket`).
*/
parentStep: Step;
}
export interface LayerPlanReasonListItemStream {
initialCountStepId?: number;
ifStepId?: number;
labelStepId?: number;
}
/** Non-branching, non-deferred */
export interface LayerPlanReasonListItem {
type: "listItem";
parentLayerPlan: LayerPlan;
/**
* Can be used such that the same LayerPlan can be used for two lists for
* the same parent plan. In this case an additional output plan would be
* added to the LayerPlan.
*
* Also needed for execution (see `executeBucket`).
*/
parentStep: Step;
/**
* If this listItem is to be streamed, the configuration for that streaming.
*/
stream?: LayerPlanReasonListItemStream;
}
/** Non-branching, deferred */
export interface LayerPlanReasonSubscription {
type: "subscription";
parentLayerPlan: LayerPlan;
}
/** Non-branching, deferred */
export interface LayerPlanReasonMutationField {
type: "mutationField";
parentLayerPlan: LayerPlan;
mutationIndex: number;
}
/** Non-branching, deferred */
export interface LayerPlanReasonDefer {
type: "defer";
parentLayerPlan: LayerPlan;
label?: string;
}
/**
* Non-branching, non-deferred
*
* A polymorphic bucket indicates a transition between values of unknown type
* and values of a known polymorphic type. This is predicated based on the
* given typename - before the typename is known, we must run all steps for all
* types, but once the type is known we can be more selective about which steps
* to run.
*
* When a polymorphic type is met, there will always be a polymorphic layer
* plan, even if all steps within it run for all types. This is necessary to
* advance the `polymorphicPathList` index for the relevant indicies.
*/
export interface LayerPlanReasonPolymorphic {
type: "polymorphic";
parentLayerPlan: LayerPlan;
typeNames: string[];
/**
* Stores the __typename, needed for execution (see `executeBucket`).
*/
parentStep: Step<string | null>;
polymorphicPaths: Set<string>;
}
/**
* Branching, non-deferred
*
* A polymorphicPartition bucket accepts a subset of types and contains only
* steps relevant to those types; it's a way to avoid having to do a lot of
* filtering of values being passed into steps' execute methods by
* pre-filtering the values.
*/
export interface LayerPlanReasonPolymorphicPartition {
type: "polymorphicPartition";
parentLayerPlan: LayerPlan<LayerPlanReasonPolymorphic>;
typeNames: string[];
polymorphicPaths: ReadonlySet<string>;
}
/** Non-branching, non-deferred */
export interface LayerPlanReasonSubroutine {
type: "subroutine";
parentLayerPlan: LayerPlan;
parentStep: Step;
}
/**
* Anti-branching, non-deferred
*
* A "combined" layer plan exists to re-combine values from multiple layer
* plans together again, to allow future steps to be more efficient. It's
* typically relevant when polymorphism has occurred and has caused branching,
* the combined layer plan allows the values to be recombined before branching
* again, such that L layers of polymorphism, where there are P different
* polymorphic branches at each layer, results in P*L branches rather than P^L
* branches - i.e. it scales linary with number of layers rather than
* exponentially.
*/
export interface LayerPlanReasonCombined {
type: "combined";
parentLayerPlans: ReadonlyArray<LayerPlan>;
}
export declare function hasParentLayerPlan(reason: LayerPlanReason): reason is Exclude<LayerPlanReason, LayerPlanReasonRoot | LayerPlanReasonCombined>;
export declare function isDeferredLayerPlan(layerPlan: LayerPlan): boolean;
export type LayerPlanReason = LayerPlanReasonRoot | LayerPlanReasonNullableField | LayerPlanReasonListItem | LayerPlanReasonSubscription | LayerPlanReasonMutationField | LayerPlanReasonDefer | LayerPlanReasonPolymorphic | LayerPlanReasonPolymorphicPartition | LayerPlanReasonCombined | LayerPlanReasonSubroutine;
export type HasParent<A extends LayerPlanReason> = A extends any ? A extends {
parentStep: Step;
} ? A : never : never;
export type LayerPlanReasonsWithParentStep = HasParent<LayerPlanReason>;
/**
* A LayerPlan represents (via "reason") either the root (root), when something
* happens at a later time (mutationField, defer), when plurality changes
* (list, stream, subscription, polymorphic), or when a subprocess needs to be
* computed (subroutine).
*
* Layer plans belong to an operation plan.
*
* Every layer plan (except for the root layer plan) has exactly one parent
* layer plan.
*
* Every layer plan is caused by a parent step.
*
* The LayerPlan of a step influences:
*
* 1. how steps are deduplicated
* 2. the order in which the steps are executed
* 3. where the result of executing the step is stored
* 4. when the step execution cache is allowed to be GC'd
*
* NOTE: `__ListTransformStep`'s effectively have a temporary bucket inside
* them (built on the `__Item`) that's thrown away once the transform is
* complete.
*
*/
export declare class LayerPlan<TReason extends LayerPlanReason = LayerPlanReason> {
readonly operationPlan: OperationPlan;
readonly reason: TReason;
id: number;
distributorDependencies: null | {
[distributorStepId: number]: number[];
};
/** How "deep" this layer plan is (how many ancestors it has). The root layer plan has a depth of 0. */
depth: number;
/** The depth at which a "defer boundary" occurs (OperationPlan.getPeers cannot pass a defer boundary), or 0. */
deferBoundaryDepth: number;
/**
* An optimization for OperationPlan.getPeers; this tracks the steps in this
* layer plan, grouped by their step class.
*/
stepsByConstructor: Map<Function, Set<Step>>;
/**
* Populated during `finalize`, this will be empty except for phase
* transition layer plans (defer/stream) wherein it will contain a list of
* "unreachable" layer plan IDs relevant to the "combined" layer plans trying
* to refer to parent layer plans which are outside of this incremental
* boundary (e.g. if two lists both stream, we might combine those, but at
* runtime only one will be populated so we can't wait for the other to
* complete otherwise nothing will happen).
*/
outOfBoundsLayerPlanIds: Set<number>;
private sideEffectRootLayerPlan;
constructor(operationPlan: OperationPlan, reason: TReason);
toString(): string;
print(depth?: number): string;
_hasSetRootStep: boolean;
setRootStep($root: Step): void;
finalize(): void;
newBucket(parentBucket: Bucket): Bucket | null;
newCombinedBucket(finalParentBucket: Pick<Bucket, "sharedState">): Bucket | null;
addCombo(sources: ReadonlyArray<{
layerPlan: LayerPlan;
step: Step;
}>, $target: __ValueStep<any>): void;
}
//# sourceMappingURL=LayerPlan.d.ts.map