@cadenza.io/core
Version:
This is a framework for building asynchronous graphs and flows of tasks and signals.
1,202 lines (1,183 loc) • 135 kB
TypeScript
type AnyObject = {
[key: string | number]: any;
};
interface ThrottleHandle {
/** Stop the repeating emission */
clear(): void;
}
/**
* Represents a context object used within a graph system.
* Contexts are essentially a container for data that is relevant to a specific task or routine.
* They are passed down the graph and can be used to store and manipulate data during the execution process.
* The context is divided into full context, user data, and metadata.
* Provides methods for accessing, cloning, mutating, combining, and exporting the context data.
*/
declare class GraphContext {
readonly id: string;
readonly fullContext: AnyObject;
readonly userData: AnyObject;
readonly metadata: AnyObject;
constructor(context: AnyObject);
/**
* Gets frozen user data (read-only, no clone).
* @returns Frozen user context.
*/
getContext(): AnyObject;
/**
* Clones the current user context data and returns a deep-cloned copy of it.
*
* @return {AnyObject} A deep-cloned copy of the user context data.
*/
getClonedContext(): AnyObject;
/**
* Gets full raw context (cloned for safety).
* @returns Cloned full context.
*/
getFullContext(): AnyObject;
/**
* Creates and returns a deep-cloned version of the fullContext object.
*
* @return {AnyObject} A deep copy of the fullContext instance, preserving all nested structures and data.
*/
getClonedFullContext(): AnyObject;
/**
* Gets frozen metadata (read-only).
* @returns Frozen metadata object.
*/
getMetadata(): AnyObject;
/**
* Combines the current GraphContext with another GraphContext, merging their user data
* and full context into a new GraphContext instance.
*
* @param {GraphContext} otherContext - The other GraphContext to combine with the current one.
* @return {GraphContext} A new GraphContext instance containing merged data from both contexts.
*/
combine(otherContext: GraphContext): GraphContext;
/**
* Exports the context.
* @returns Exported object.
*/
export(): {
id: string;
context: AnyObject;
};
}
/**
* Abstract class representing an iterator for traversing a collection of elements.
* Subclasses must implement core methods to allow iteration and may optionally implement additional methods for extended functionality.
*/
declare abstract class Iterator {
abstract hasNext(): boolean;
abstract hasPrevious?(): boolean;
abstract next(): any;
abstract previous?(): any;
abstract getFirst?(): any;
abstract getLast?(): any;
}
/**
* Represents an abstract base class for a graph node or task.
* This class provides the foundation for graph-related operations such as traversal,
* exportation, logging, and execution. It must be extended by concrete implementations.
*/
declare abstract class Graph {
/**
* Executes this graph node/task.
* @param args Execution args (e.g., context).
* @returns Result.
*/
abstract execute(...args: any[]): unknown;
/**
* Logs the graph node (debugging).
*/
abstract log(): void;
/**
* Destroys the graph node.
*/
abstract destroy(): void;
/**
* Exports the graph node.
* @returns Exported data.
*/
abstract export(): any;
/**
* Accepts a visitor for traversal (e.g., debugging/exporters).
* @param visitor The visitor.
* @note Non-runtime use; pairs with iterator for data extraction.
*/
abstract accept(visitor: GraphVisitor): void;
/**
* Gets an iterator for graph traversal (e.g., BFS/DFS).
* @returns Iterator.
* @note For debugging/exporters.
*/
abstract getIterator(): Iterator;
}
/**
* Represents an iterator for traversing nodes in a graph structure.
* Implements the Iterator interface and allows traversal of nodes layer by layer.
*/
declare class GraphNodeIterator implements Iterator {
currentNode: GraphNode | undefined;
currentLayer: GraphNode[];
nextLayer: GraphNode[];
index: number;
constructor(node: GraphNode);
hasNext(): boolean;
next(): any;
}
/**
* Represents an abstract chain of execution, where each instance can be
* connected to a succeeding or preceding instance to form a chain of steps.
* Provides methods to manage the links between instances in the chain.
*/
declare abstract class ExecutionChain {
next: ExecutionChain | undefined;
previous: ExecutionChain | undefined;
setNext(next: ExecutionChain): void;
get hasNext(): boolean;
get hasPreceding(): boolean;
getNext(): ExecutionChain | undefined;
getPreceding(): ExecutionChain | undefined;
decouple(): void;
}
/**
* The `GraphLayerIterator` class provides an iterator for traversing through
* layers of a `GraphLayer` data structure. It allows sequential and bi-directional
* iteration, as well as access to the first and last layers in the graph.
*
* @implements {Iterator}
*/
declare class GraphLayerIterator implements Iterator {
graph: GraphLayer;
currentLayer: GraphLayer | undefined;
constructor(graph: GraphLayer);
hasNext(): boolean;
hasPrevious(): boolean;
next(): GraphLayer;
previous(): GraphLayer;
getFirst(): GraphLayer;
getLast(): GraphLayer;
}
/**
* Represents an abstract layer in a graph, handling nodes and their execution.
* A `GraphLayer` can manage execution states, debug states, and relationships with other layers in the graph.
* This class is designed to be extended and requires the implementation of the `execute` method.
*
* @abstract
* @class GraphLayer
* @extends ExecutionChain
* @implements Graph
*/
declare abstract class GraphLayer extends ExecutionChain implements Graph {
readonly index: number;
nodes: GraphNode[];
executionTime: number;
executionStart: number;
debug: boolean;
constructor(index: number);
/**
* Sets the debug mode for the current instance and all associated nodes.
*
* @param {boolean} value - A boolean value to enable (true) or disable (false) debug mode.
* @return {void} No return value.
*/
setDebug(value: boolean): void;
/**
* Abstract method to execute a specific operation given a context.
*
* @param {GraphContext} [context] - Optional parameter representing the execution context, which contains relevant data for performing the operation.
* @return {unknown} - Returns the result of the operation, its type may vary depending on the implementation.
*/
abstract execute(context?: GraphContext): unknown;
/**
* Checks if the current layer has a preceding layer.
*
* @return {boolean} True if the current layer has a preceding layer that is an instance of GraphLayer; otherwise, false.
*/
get hasPreceding(): boolean;
getNumberOfNodes(): number;
/**
* Retrieves a list of nodes that match the given routine execution ID.
*
* @param {string} routineExecId - The ID of the routine execution to filter nodes by.
* @return {Array} An array of nodes that have the specified routine execution ID.
*/
getNodesByRoutineExecId(routineExecId: string): GraphNode[];
/**
* Finds and returns all nodes in the graph that are identical to the given node.
* Two nodes are considered identical if they share the same routine execution ID
* and share a task with each other.
*
* @param {GraphNode} node - The reference node to compare against other nodes in the graph.
* @return {GraphNode[]} An array of nodes that are identical to the given node.
*/
getIdenticalNodes(node: GraphNode): GraphNode[];
/**
* Checks whether all nodes in the collection have been processed.
*
* @return {boolean} Returns true if all nodes are processed, otherwise false.
*/
isProcessed(): boolean;
/**
* Checks whether all layers in the graph have been processed.
*
* @return {boolean} Returns true if all graph layers are processed; otherwise, returns false.
*/
graphDone(): boolean;
/**
* Sets the next GraphLayer in the sequence if it has a higher index than the current layer.
* Updates the previous property if the given next layer has an existing previous layer.
*
* @param {GraphLayer} next - The next GraphLayer to be linked in the sequence.
* @return {void} Does not return a value. Modifies the current layer's state.
*/
setNext(next: GraphLayer): void;
/**
* Adds a node to the graph.
*
* @param {GraphNode} node - The node to be added to the graph.
* @return {void}
*/
add(node: GraphNode): void;
/**
* Starts the execution timer if it has not been started already.
* Records the current timestamp as the start time.
*
* @return {number} The timestamp representing the start time in milliseconds.
*/
start(): number;
/**
* Marks the end of a process by capturing the current timestamp and calculating the execution time if a start time exists.
*
* @return {number} The timestamp at which the process ended, or 0 if the start time is not defined.
*/
end(): number;
/**
* Destroys the current graph layer and its associated resources.
* This method recursively destroys all nodes in the current layer, clears the node list,
* and ensures that any connected subsequent graph layers are also destroyed.
* Additionally, it calls the decoupling logic to disconnect the current layer from its dependencies.
*
* @return {void} Does not return any value.
*/
destroy(): void;
/**
* Returns an iterator for traversing through the graph layers.
*
* @return {GraphLayerIterator} An instance of GraphLayerIterator to traverse graph layers.
*/
getIterator(): GraphLayerIterator;
/**
* Accepts a visitor object to traverse or perform operations on the current graph layer and its nodes.
*
* @param {GraphVisitor} visitor - The visitor instance implementing the visitLayer and visitNode behavior.
* @return {void} Returns nothing.
*/
accept(visitor: GraphVisitor): void;
export(): {
__index: number;
__executionTime: number;
__numberOfNodes: number;
__hasNextLayer: boolean;
__hasPrecedingLayer: boolean;
__nodes: string[];
};
log(): void;
}
/**
* Represents a synchronous graph layer derived from the GraphLayer base class.
* This class is designed to execute graph nodes in a strictly synchronous manner.
* Asynchronous functions are explicitly disallowed, ensuring consistency and predictability.
*/
declare class SyncGraphLayer extends GraphLayer {
/**
* Executes the processing logic of the current set of graph nodes. Iterates through all
* nodes, skipping any that have already been processed, and executes their respective
* logic to generate new nodes. Asynchronous functions are not supported and will
* trigger an error log.
*
* @return {GraphNode[]} An array of newly generated graph nodes after executing the logic of each unprocessed node.
*/
execute(): GraphNode[];
}
/**
* An abstract class representing a GraphExporter.
* This class defines a structure for exporting graph data in different formats,
* depending on the implementations provided by subclasses.
*/
declare abstract class GraphExporter {
abstract exportGraph(graph: SyncGraphLayer): any;
abstract exportStaticGraph(graph: Task[]): any;
}
/**
* GraphBuilder is an abstract base class designed to construct and manage a graph structure
* composed of multiple layers. Subclasses are expected to implement the `compose` method
* based on specific requirements. This class provides methods for adding nodes, managing
* layers, and resetting the graph construction process.
*
* This class supports creating layered graph structures, dynamically adding layers and nodes,
* and debugging graph-building operations.
*/
declare abstract class GraphBuilder {
graph: GraphLayer | undefined;
topLayerIndex: number;
layers: GraphLayer[];
debug: boolean;
setDebug(value: boolean): void;
getResult(): GraphLayer;
/**
* Composes a series of functions or operations.
* This method should be implemented in the child class
* to define custom composition logic.
*
* @return {any} The result of the composed operations or functions
* when implemented in the child class.
*/
compose(): void;
/**
* Adds a node to the appropriate layer of the graph.
*
* @param {GraphNode} node - The node to be added to the graph. The node contains
* layer information that determines which layer it belongs to.
* @return {void} Does not return a value.
*/
addNode(node: GraphNode): void;
/**
* Adds multiple nodes to the graph.
*
* @param {GraphNode[]} nodes - An array of nodes to be added to the graph.
* @return {void} This method does not return a value.
*/
addNodes(nodes: GraphNode[]): void;
/**
* Adds a new layer to the graph at the specified index. If the graph does not exist,
* it creates the graph using the specified index. Updates the graph's top layer index
* and maintains the order of layers.
*
* @param {number} index - The index at which the new layer should be added to the graph.
* @return {void} This method does not return a value.
*/
addLayer(index: number): void;
/**
* Creates a new layer for the graph at the specified index.
*
* @param {number} index - The index of the layer to be created.
* @return {GraphLayer} A new instance of the graph layer corresponding to the provided index.
*/
createLayer(index: number): GraphLayer;
/**
* Retrieves a specific layer from the current set of layers.
*
* @param {number} layerIndex - The index of the layer to retrieve.
* @return {*} The layer corresponding to the given index.
*/
getLayer(layerIndex: number): GraphLayer;
reset(): void;
}
/**
* Abstract class representing a strategy for configuring and executing graph operations.
* Provides a structure for managing graph builders, altering strategies, and updating the execution context.
*
* This class cannot be instantiated directly and must be extended by concrete implementations.
*/
declare abstract class GraphRunStrategy {
graphBuilder: GraphBuilder;
runInstance?: GraphRun;
constructor();
setRunInstance(runInstance: GraphRun): void;
changeStrategy(builder: GraphBuilder): void;
reset(): void;
addNode(node: GraphNode): void;
updateRunInstance(): void;
abstract run(): void;
abstract export(): any;
}
interface RunJson {
__id: string;
__label: string;
__graph: any;
__data: any;
}
/**
* Represents a GraphRun instance which manages the execution of a graph-based workflow.
* It utilizes a specific strategy and export mechanism to manage, execute, and export the graph data.
*/
declare class GraphRun {
readonly id: string;
graph: GraphLayer | undefined;
strategy: GraphRunStrategy;
exporter: GraphExporter | undefined;
constructor(strategy: GraphRunStrategy);
setGraph(graph: GraphLayer): void;
addNode(node: GraphNode): void;
run(): void | Promise<void>;
destroy(): void;
log(): void;
export(): RunJson;
setExporter(exporter: GraphExporter): void;
}
/**
* Represents a routine in a graph structure with tasks and signal observation capabilities.
* Routines are named entrypoint for a sub-graph, describing the purpose for the subsequent flow.
* Since Task names are specific to the task it performs, it doesn't describe the overall flow.
* Routines, therefore are used to assign names to sub-flows that can be referenced using that name instead of the name of the task(s).
* Extends SignalEmitter to emit and handle signals related to the routine's lifecycle and tasks.
*/
declare class GraphRoutine extends SignalEmitter {
readonly name: string;
version: number;
readonly description: string;
readonly isMeta: boolean;
tasks: Set<Task>;
registered: boolean;
registeredTasks: Set<Task>;
observedSignals: Set<string>;
constructor(name: string, tasks: Task[], description: string, isMeta?: boolean);
/**
* Iterates over each task in the `tasks` collection and applies the provided callback function.
* If the callback returns a Promise, resolves all Promises concurrently.
*
* @param {function} callBack - A function to be executed on each task from the `tasks` collection.
* The callback receives the current task as its argument.
* @return {Promise<void>} A Promise that resolves once all callback executions, including asynchronous ones, are complete.
*/
forEachTask(callBack: (task: Task) => any): Promise<void>;
/**
* Sets global Version.
* @param version The Version.
*/
setVersion(version: number): void;
/**
* Subscribes the current instance to the specified signals, enabling it to observe them.
*
* @param {...string} signals - The names of the signals to observe.
* @return {this} Returns the instance to allow for method chaining.
*/
doOn(...signals: string[]): this;
/**
* Unsubscribes from all observed signals and clears the internal collection
* of observed signals. This ensures that the instance is no longer listening
* or reacting to any previously subscribed signals.
*
* @return {this} Returns the current instance for chaining purposes.
*/
unsubscribeAll(): this;
/**
* Unsubscribes the current instance from the specified signals.
*
* @param {...string} signals - The signals to unsubscribe from.
* @return {this} The current instance for method chaining.
*/
unsubscribe(...signals: string[]): this;
/**
* Cleans up resources and emits an event indicating the destruction of the routine.
*
* This method unsubscribes from all events, clears the tasks list,
* and emits a "meta.routine.destroyed" event with details of the destruction.
*
* @return {void}
*/
destroy(): void;
}
/**
* Represents a runner for managing and executing tasks or routines within a graph.
* The `GraphRunner` extends `SignalEmitter` to include signal-based event-driven mechanisms.
*/
declare class GraphRunner extends SignalEmitter {
currentRun: GraphRun;
debug: boolean;
verbose: boolean;
isRunning: boolean;
readonly isMeta: boolean;
strategy: GraphRunStrategy;
/**
* Constructs a runner.
* @param isMeta Meta flag (default false).
* @edge Creates 'Start run' meta-task chained to registry gets.
*/
constructor(isMeta?: boolean);
/**
* Adds tasks or routines to the current execution pipeline. Supports both individual tasks,
* routines, or arrays of tasks and routines. Handles metadata and execution context management.
*
* @param {Task|GraphRoutine|(Task|GraphRoutine)[]} tasks - The task(s) or routine(s) to be added.
* It can be a single task, a single routine, or an array of tasks and routines.
* @param {AnyObject} [context={}] - Optional context object to provide execution trace and metadata.
* Used to propagate information across task or routine executions.
* @return {void} - This method does not return a value.
*/
addTasks(tasks: Task | GraphRoutine | (Task | GraphRoutine)[], context?: AnyObject): void;
/**
* Executes the provided tasks or routines. Maintains the execution state
* and handles synchronous or asynchronous processing.
*
* @param {Task|GraphRoutine|(Task|GraphRoutine)[]} [tasks] - A single task, a single routine, or an array of tasks or routines to execute. Optional.
* @param {AnyObject} [context] - An optional context object to be used during task execution.
* @return {GraphRun|Promise<GraphRun>} - Returns a `GraphRun` instance if the execution is synchronous, or a `Promise` resolving to a `GraphRun` for asynchronous execution.
*/
run(tasks?: Task | GraphRoutine | (Task | GraphRoutine)[], context?: AnyObject): GraphRun | Promise<GraphRun>;
/**
* Executes the provided asynchronous operation and resets the state afterwards.
*
* @param {Promise<void>} run - A promise representing the asynchronous operation to execute.
* @return {Promise<GraphRun>} A promise that resolves to the result of the reset operation after the asynchronous operation completes.
*/
runAsync(run: Promise<void>): Promise<GraphRun>;
/**
* Resets the current state of the graph, creating a new GraphRun instance
* and returning the previous run instance.
* If the debug mode is not enabled, it will destroy the existing resources.
*
* @return {GraphRun} The last GraphRun instance before the reset.
*/
reset(): GraphRun;
setDebug(value: boolean): void;
setVerbose(value: boolean): void;
destroy(): void;
/**
* Sets the strategy to be used for running the graph and initializes
* the current run with the provided strategy if no process is currently running.
*
* @param {GraphRunStrategy} strategy - The strategy to use for running the graph.
* @return {void}
*/
setStrategy(strategy: GraphRunStrategy): void;
}
interface EmitOptions {
squash?: boolean;
squashId?: string | null;
groupId?: string | null;
mergeFunction?: ((oldContext: AnyObject, ...newContext: AnyObject[]) => AnyObject) | null;
debounce?: boolean;
throttle?: boolean;
delayMs?: number;
schedule?: boolean;
exactDateTime?: Date | null;
throttleBatch?: number;
flushStrategy?: string;
}
type SignalDeliveryMode = "single" | "broadcast";
type SignalReceiverFilter = {
serviceNames?: string[];
serviceInstanceIds?: string[];
origins?: string[];
roles?: string[];
protocols?: string[];
runtimeStates?: string[];
};
type SignalMetadata = {
deliveryMode?: SignalDeliveryMode;
broadcastFilter?: SignalReceiverFilter | null;
};
type PassiveSignalListener = (signal: string, context: AnyObject, metadata: SignalMetadata | null) => void;
type SignalDefinitionInput = string | ({
name: string;
} & SignalMetadata);
type FlushStrategyName = string;
interface FlushStrategy {
intervalMs: number;
maxBatchSize: number;
}
/**
* This class manages signals and observers, enabling communication across different parts of an application.
* It follows a singleton design pattern, allowing for centralized signal management.
*/
declare class SignalBroker {
static instance_: SignalBroker;
static get instance(): SignalBroker;
debug: boolean;
verbose: boolean;
setDebug(value: boolean): void;
setVerbose(value: boolean): void;
runner: GraphRunner | undefined;
metaRunner: GraphRunner | undefined;
throttleEmitters: Map<string, any>;
throttleQueues: Map<string, any>;
getSignalsTask: Task | undefined;
registerSignalTask: Task | undefined;
signalObservers: Map<string, {
fn: (runner: GraphRunner, tasks: (Task | GraphRoutine)[], context: AnyObject) => void;
tasks: Set<Task | GraphRoutine>;
registered: boolean;
}>;
emittedSignalsRegistry: Set<string>;
signalMetadataRegistry: Map<string, SignalMetadata>;
passiveSignalListeners: Map<string, PassiveSignalListener>;
private flushStrategies;
private strategyData;
private strategyTimers;
private isStrategyFlushing;
private readonly defaultStrategyName;
constructor();
private resolveSignalMetadataKey;
private normalizeSignalMetadata;
setSignalMetadata(signal: string, metadata?: SignalMetadata | null): void;
getSignalMetadata(signal: string): SignalMetadata | undefined;
logMemoryFootprint(label?: string): void;
/**
* Validates the provided signal name string to ensure it adheres to specific formatting rules.
* Throws an error if any of the validation checks fail.
*
* @param {string} signalName - The signal name to be validated.
* @return {void} - Returns nothing if the signal name is valid.
* @throws {Error} - Throws an error if the signal name is longer than 100 characters, contains spaces,
* contains backslashes, or contains uppercase letters in restricted parts of the name.
*/
validateSignalName(signalName: string): void;
/**
* Initializes with runners.
* @param runner Standard runner for user signals.
* @param metaRunner Meta runner for 'meta.' signals (suppresses further meta-emits).
*/
bootstrap(runner: GraphRunner, metaRunner: GraphRunner): void;
/**
* Initializes and sets up the various tasks for managing and processing signals.
*
* @return {void} This method does not return a value.
*/
init(): void;
setFlushStrategy(name: FlushStrategyName, config: {
intervalMs: number;
maxBatchSize?: number;
}): void;
updateFlushStrategy(name: FlushStrategyName, config: FlushStrategy): void;
removeFlushStrategy(name: FlushStrategyName): void;
getFlushStrategies(): Record<FlushStrategyName, FlushStrategy>;
private readonly MAX_FLUSH_DURATION_MS;
squash(signal: string, context: AnyObject, options?: EmitOptions): void;
private flushGroup;
private flushStrategy;
clearSquashState(): void;
private clearScheduledState;
private scheduledBuckets;
private scheduleTimer;
schedule(signal: string, context: AnyObject, options?: EmitOptions): AbortController;
private flushScheduled;
private debouncedEmitters;
private readonly MAX_DEBOUNCERS;
private clearDebounceState;
private clearThrottleState;
debounce(signal: string, context: any, options?: {
delayMs: number;
}): void;
throttle(signal: string, context: any, options?: EmitOptions): void;
/**
* Emits `signal` repeatedly with a fixed interval.
*
* @param signal
* @param context
* @param intervalMs
* @param leading If true, emits immediately (unless a startDateTime is given and we are before it).
* @param startDateTime Optional absolute Date when the *first* emission after `leading` should occur.
* @returns a handle with `clear()` to stop the loop.
*/
interval(signal: string, context: AnyObject, intervalMs?: number, leading?: boolean, startDateTime?: Date): ThrottleHandle;
/**
* Emits a signal with the specified context, triggering any associated handlers for that signal.
*
* @param {string} signal - The name of the signal to emit.
* @param {AnyObject} [context={}] - An optional context object containing additional information or metadata
* associated with the signal. If the context includes a `__routineExecId`, it will be handled accordingly.
* @param options
* @return {void} This method does not return a value.
*/
emit(signal: string, context?: AnyObject, options?: EmitOptions): void;
/**
* Executes a signal by emitting events, updating context, and invoking listeners.
* Creates a new execution trace if necessary and updates the context with relevant metadata.
* Handles specific, hierarchy-based, and wildcard signals.
*
* @param {string} signal - The signal name to be executed, potentially including namespaces or tags (e.g., "meta.*" or "signal:type").
* @param {AnyObject} context - An object containing relevant metadata and execution details used for handling the signal.
* @return {boolean} Returns true if any listeners were successfully executed, otherwise false.
*/
execute(signal: string, context: AnyObject): boolean;
/**
* Executes the tasks associated with a given signal and context.
* It processes both normal and meta tasks depending on the signal type
* and the availability of the appropriate runner.
*
* @param {string} signal - The signal identifier that determines which tasks to execute.
* @param {AnyObject} context - The context object passed to the task execution function.
* @return {boolean} - Returns true if tasks were executed; otherwise, false.
*/
executeListener(signal: string, context: AnyObject): boolean;
/**
* Adds a signal to the signalObservers for tracking and execution.
* Performs validation on the signal name and emits a meta signal event when added.
* If the signal contains a namespace (denoted by a colon ":"), its base signal is
* also added if it doesn't already exist.
*
* @param {string} signal - The name of the signal to be added.
* @return {void} This method does not return any value.
*/
addSignal(signal: string, metadata?: SignalMetadata | null): void;
/**
* Observes a signal with a routine/task.
* @param signal The signal (e.g., 'domain.action', 'domain.*' for wildcards).
* @param routineOrTask The observer.
* @edge Duplicates ignored; supports wildcards for broad listening.
*/
observe(signal: string, routineOrTask: Task | GraphRoutine, metadata?: SignalMetadata | null): void;
addPassiveSignalListener(listener: PassiveSignalListener): () => void;
private notifyPassiveSignalListeners;
registerEmittedSignal(signal: string, metadata?: SignalMetadata | null): void;
/**
* Unsubscribes a routine/task from a signal.
* @param signal The signal.
* @param routineOrTask The observer.
* @edge Removes all instances if duplicate; deletes if empty.
*/
unsubscribe(signal: string, routineOrTask: Task | GraphRoutine): void;
/**
* Lists all observed signals.
* @returns Array of signals.
*/
listObservedSignals(): string[];
listEmittedSignals(): string[];
reset(): void;
shutdown(): void;
}
/**
* Abstract class representing a signal emitter.
* Allows emitting events or signals, with the option to suppress emissions if desired.
*/
declare abstract class SignalEmitter {
silent: boolean;
/**
* Constructor for signal emitters.
* @param silent If true, suppresses all emissions (e.g., for meta-runners to avoid loops; affects all emits).
*/
constructor(silent?: boolean);
/**
* Emits a signal via the broker.
* @param signal The signal name.
* @param data Optional payload (defaults to empty object).
* @param options
*/
emit(signal: string, data?: AnyObject, options?: EmitOptions): void;
/**
* Emits a signal via the broker if not silent.
* @param signal The signal name.
* @param data Optional payload (defaults to empty object).
* @param options
*/
emitMetrics(signal: string, data?: AnyObject, options?: EmitOptions): void;
}
type SchemaType = "string" | "number" | "boolean" | "array" | "object" | "any";
type SchemaConstraints = {
min?: number;
max?: number;
minLength?: number;
maxLength?: number;
pattern?: string;
enum?: any[];
multipleOf?: number;
format?: "email" | "url" | "date-time" | "uuid" | "custom";
oneOf?: any[];
};
type SchemaDefinition = {
type: SchemaType;
required?: string[];
properties?: {
[key: string]: Schema;
};
items?: Schema;
constraints?: SchemaConstraints;
description?: string;
strict?: boolean;
};
type SchemaMap = Record<string, SchemaDefinition>;
type Schema = SchemaDefinition | SchemaMap;
interface Intent {
name: string;
description?: string;
input?: SchemaDefinition;
output?: SchemaDefinition;
}
interface InquiryOptions {
timeout?: number;
rejectOnTimeout?: boolean;
includePendingTasks?: boolean;
requireComplete?: boolean;
}
declare class InquiryBroker extends SignalEmitter {
static instance_: InquiryBroker;
static get instance(): InquiryBroker;
debug: boolean;
verbose: boolean;
setDebug(value: boolean): void;
setVerbose(value: boolean): void;
validateInquiryName(inquiryName: string): void;
runner: GraphRunner | undefined;
metaRunner: GraphRunner | undefined;
inquiryObservers: Map<string, {
fn: (runner: GraphRunner, tasks: Task[], context: AnyObject) => void;
tasks: Set<Task>;
registered: boolean;
}>;
intents: Map<string, Intent>;
/**
* Initializes with runners.
* @param runner Standard runner for user signals.
* @param metaRunner Meta runner for 'meta.' signals (suppresses further meta-emits).
*/
bootstrap(runner: GraphRunner, metaRunner: GraphRunner): void;
init(): void;
/**
* Observes an inquiry with a routine/task.
* @param inquiry The inquiry (e.g., 'domain.action', 'domain.*' for wildcards).
* @param task The observer.
* @edge Duplicates ignored; supports wildcards for broad listening.
*/
observe(inquiry: string, task: Task): void;
/**
* Unsubscribes a routine/task from an inquiry.
* @param inquiry The inquiry.
* @param task The observer.
* @edge Removes all instances if duplicate; deletes if empty.
*/
unsubscribe(inquiry: string, task: Task): void;
addInquiry(inquiry: string): void;
addIntent(intent: Intent): void;
inquire(inquiry: string, context: AnyObject, options?: InquiryOptions): Promise<AnyObject>;
reset(): void;
}
/**
* Represents a node in a graph structure used for executing tasks.
* A Node is a container for a task and its associated context, providing
* methods for executing the task and managing its lifecycle.
*
* It extends the SignalEmitter class to emit and handle signals related to
* the node's lifecycle, such as "meta.node.started" and "meta.node.completed".
*
* It also implements the Graph interface, allowing it to be used as a part of
* a graph structure, such as a GraphLayer or GraphRoutine.
*
* @extends SignalEmitter
* @implements Graph
*/
declare class GraphNode extends SignalEmitter implements Graph {
id: string;
routineExecId: string;
executionTraceId: string;
task: Task;
context: GraphContext;
layer: GraphLayer | undefined;
divided: boolean;
splitGroupId: string;
processing: boolean;
subgraphComplete: boolean;
graphComplete: boolean;
result: TaskResult;
retryCount: number;
retryDelay: number;
retries: number;
previousNodes: GraphNode[];
nextNodes: GraphNode[];
executionTime: number;
executionStart: number;
failed: boolean;
errored: boolean;
destroyed: boolean;
debug: boolean;
verbose: boolean;
constructor(task: Task, context: GraphContext, routineExecId: string, prevNodes?: GraphNode[], debug?: boolean, verbose?: boolean);
setDebug(value: boolean): void;
isUnique(): boolean;
isMeta(): boolean;
isProcessed(): boolean;
isProcessing(): boolean;
subgraphDone(): boolean;
graphDone(): boolean;
/**
* Compares the current GraphNode instance with another GraphNode to determine if they are considered equal.
*
* @param {GraphNode} node - The GraphNode object to compare with the current instance.
* @return {boolean} Returns true if the nodes share the same task, context, and belong to the same graph; otherwise, false.
*/
isEqualTo(node: GraphNode): boolean;
/**
* Determines if the given node is part of the same graph as the current node.
*
* @param {GraphNode} node - The node to compare with the current node.
* @return {boolean} Returns true if the provided node is part of the same graph
* (i.e., has the same routineExecId), otherwise false.
*/
isPartOfSameGraph(node: GraphNode): boolean;
/**
* Determines whether the current instance shares a task with the provided node.
*
* @param {GraphNode} node - The graph node to compare with the current instance.
* @return {boolean} Returns true if the task names of both nodes match, otherwise false.
*/
sharesTaskWith(node: GraphNode): boolean;
/**
* Determines whether the current node shares the same context as the specified node.
*
* @param {GraphNode} node - The graph node to compare with the current node's context.
* @return {boolean} True if both nodes share the same context; otherwise, false.
*/
sharesContextWith(node: GraphNode): boolean;
getLayerIndex(): number;
getConcurrency(): number;
/**
* Retrieves the tag associated with the current task and context.
*
* @return {string} The tag retrieved from the task within the given context.
*/
getTag(): string;
private classifyBusinessRoutineLifecycle;
private getBusinessRoutineLifecycleDecision;
private rememberBusinessRoutineLifecycleDecision;
/**
* Schedules the current node/task on the specified graph layer if applicable.
*
* This method assesses whether the current node/task should be scheduled
* on the given graph layer. It ensures that tasks are only scheduled
* under certain conditions, such as checking if the task shares
* execution contexts or dependencies with other nodes, and handles
* various metadata emissions and context updates during the scheduling process.
*
* @param {GraphLayer} layer - The graph layer on which the current task should be scheduled.
* @returns {void} Does not return a value.
*/
scheduleOn(layer: GraphLayer): void;
/**
* Starts the execution process by initializing the execution start timestamp,
* emitting relevant metadata, and logging debug information if applicable.
*
* The method performs the following actions:
* 1. Sets the execution start timestamp if it's not already initialized.
* 2. Emits metrics with metadata about the routine execution starting, including additional data if there are no previous nodes.
* 3. Optionally logs debug or verbose information based on the current settings.
* 4. Emits additional metrics to indicate that the execution has started.
*
* @return {number} The timestamp indicating when the execution started.
*/
start(): number;
/**
* Marks the end of an execution process, performs necessary cleanup, emits
* metrics with associated metadata, and signals the completion of execution.
* Also handles specific cases when the graph completes.
*
* @return {number} The timestamp corresponding to the end of execution. If execution
* was not started, it returns 0.
*/
end(): number;
/**
* Executes the main logic of the task, including input validation, processing, and post-processing.
* Handles both synchronous and asynchronous workflows.
*
* @return {Array|Promise|undefined} Returns the next nodes to process if available.
* If asynchronous processing is required, it returns a Promise that resolves to the next nodes.
* Returns undefined in case of an error during input validation or preconditions that prevent processing.
*/
execute(): GraphNode[] | Promise<GraphNode[]>;
/**
* Executes an asynchronous workflow that processes a result and retries on errors.
* The method handles different result states, checks for error properties, and invokes
* error handling when necessary.
*
* @return {Promise<void>} A promise that resolves when the operation completes successfully,
* or rejects if an unhandled error occurs.
*/
workAsync(): Promise<void>;
/**
* Executes an asynchronous operation, processes the result, and determines the next nodes to execute.
* This method will manage asynchronous work, handle post-processing of results, and ensure proper handling of both synchronous and asynchronous next node configurations.
*
* @return {Promise<any>} A promise resolving to the next nodes to be executed. Can be the result of post-processing or a directly resolved next nodes object.
*/
executeAsync(): Promise<GraphNode[]>;
/**
* Executes the task associated with the current instance, using the given context,
* progress callback, and metadata. If the task fails or an error occurs, it attempts
* to retry the execution. If the retry is not successful, it propagates the error and
* returns the result.
*
* @return {TaskResult | Promise<TaskResult>} The result of the task execution, or a
* promise that resolves to the task result. This includes handling for retries on
* failure and error propagation.
*/
work(): TaskResult | Promise<TaskResult>;
inquire(inquiry: string, context: AnyObject, options: InquiryOptions): Promise<any>;
/**
* Emits a signal along with its associated metadata. The metadata includes
* task-specific information such as task name, version, execution ID, and
* additional context metadata like routine execution ID and execution trace ID.
* This method is designed to enrich emitted signals with relevant details
* before broadcasting them.
*
* @param {string} signal - The name of the signal to be emitted.
* @param {AnyObject} data - The data object to be sent along with the signal. Metadata
* will be injected into this object before being emitted.
* @param options
* @return {void} No return value.
*/
emitWithMetadata(signal: string, data: AnyObject, options?: EmitOptions): void;
/**
* Emits metrics with additional metadata describing the task execution and context.
*
* @param {string} signal - The signal name being emitted.
* @param {AnyObject} data - The data associated with the signal emission, enriched with metadata.
* @param options
* @return {void} Emits the signal with enriched data and does not return a value.
*/
emitMetricsWithMetadata(signal: string, data: AnyObject, options?: EmitOptions): void;
/**
* Updates the progress of a task and emits metrics with associated metadata.
*
* @param {number} progress - A number representing the progress value, which will be clamped between 0 and 1.
* @return {void} This method does not return a value.
*/
onProgress(progress: number): void;
/**
* Processes the result of the current operation, validates it, and determines the next set of nodes.
*
* This method ensures that results of certain types such as strings or arrays
* are flagged as errors. It divides the current context into subsequent nodes
* for further processing. If the division returns a promise, it delegates the
* processing to `postProcessAsync`. For synchronous division, it sets the
* `nextNodes` and finalizes the operation.
*
* @return {(Array|undefined)} Returns an array of next nodes for further processing,
* or undefined if no further processing is required.
*/
postProcess(): GraphNode[] | Promise<GraphNode[]>;
/**
* Asynchronously processes and finalizes the provided graph nodes.
*
* @param {Promise<GraphNode[]>} nextNodes A promise that resolves to an array of graph nodes to be processed.
* @return {Promise<GraphNode[]>} A promise that resolves to the processed array of graph nodes.
*/
postProcessAsync(nextNodes: Promise<GraphNode[]>): Promise<GraphNode[]>;
/**
* Finalizes the current task execution by determining if the task is complete, handles any errors or failures,
* emits relevant signals based on the task outcomes, and ensures proper end of the task lifecycle.
*
* @return {void} Does not return a value.
*/
finalize(): void;
/**
* Handles an error event, processes the error, and updates the state accordingly.
*
* @param {unknown} error - The error object or message that occurred.
* @param {AnyObject} [errorData={}] - Additional error data to include in the result.
* @return {void} This method does not return any value.
*/
onError(error: unknown, errorData?: AnyObject): void;
/**
* Retries a task based on the defined retry count and delay time. If the retry count is 0, it immediately resolves with the provided previous result.
*
* @param {any} [prevResult] - The result from a previous attempt, if any, to return when no retries are performed.
* @return {Promise<TaskResult>} - A promise that resolves with the result of the retried task or the previous result if no retries occur.
*/
retry(prevResult?: any): Promise<TaskResult>;
/**
* Retries an asynchronous operation and returns its result.
* If the retry count is zero, the method immediately returns the provided previous result.
*
* @param {any} [prevResult] - The optional result from a previous operation attempt, if applicable.
* @return {Promise<TaskResult>} A promise that resolves to the result of the retried operation.
*/
retryAsync(prevResult?: any): Promise<TaskResult>;
delayRetry(): Promise<void>;
/**
* Processes the result of a task by generating new nodes based on the task output.
* The method handles synchronous and asynchronous generators, validates task output,
* and creates new nodes accordingly. If errors occur, the method attempts to handle them
* by generating alternative task nodes.
*
* @return {GraphNode[] | Promise<GraphNode[]>} Returns an array of generated GraphNode objects
* (synchronously or wrapped in a Promise) based on the task result, or propagates errors if validation fails.
*/
divide(): GraphNode[] | Promise<GraphNode[]>;
/**
* Processes an asynchronous iterator result, validates its output, and generates new graph nodes accordingly.
* Additionally, continues to process and validate results from an asynchronous generator.
*
* @param {Promise<IteratorResult<any>>} current - A promise resolving to the current step result from an asynchronous iterator.
* @return {Promise<GraphNode[]>} A promise resolving to an array of generated GraphNode objects based on validated outputs.
*/
divideAsync(current: Promise<IteratorResult<any>>): Promise<GraphNode[]>;
/**
* Generates new nodes based on the provided result and task configuration.
*
* @param {any} result - The result of the previous operation, which determines the configuration and context for new nodes. It can be a boolean or an object containing details like failure, errors, or metadata.
* @return {GraphNode[]} An array of newly generated graph nodes configured based on the task and context.
*/
generateNewNodes(result: any): GraphNode[];
/**
* Executes the differentiation process based on a given task and updates the instance properties accordingly.
*
* @param {Task} task - The task object containing information such as retry count, retry delay, and metadata status.
* @return {GraphNode} The updated instance after processing the task.
*/
differentiate(task: Task): GraphNode;
/**
* Migrates the current instance to a new context and returns the updated instance.
*
* @param {any} ctx - The context data to be used for migration.
* @return {GraphNode} The updated instance after migration.
*/
migrate(ctx: any): GraphNode;
/**
* Splits the current node into a new group identified by the provided ID.
*
* @param {string} id - The unique identifier for the new split group.
* @return {GraphNode} The current instance of the GraphNode with the updated split group ID.
*/
split(id: string): GraphNode;
/**
* Creates a new instance of the GraphNode with the current node's properties.
* This method allows for duplicating the existing graph node.
*
* @return {GraphNode} A new instance of GraphNode that is a copy of the current node.
*/
clone(): GraphNode;
/**
* Consumes the given graph node by combining contexts, merging previous nodes,
* and performing associated operations on the provided node.
*
* @param {GraphNode} node - The graph node to be consumed.
* @return {void} This method does not return a value.
*/
consume(node: GraphNode): void;
/**
* Changes the identity of the current instance by updating the `id` property.
*
* @param {string} id - The new identity value to be assigned.
* @return {void} Does not return a value.
*/
changeIdentity(id: string): void;
/**
* Completes the subgraph for the current node and recursively for its previous nodes
* once all next nodes have their subgraphs marked as done. If there are no previous nodes,
* it completes the entire graph.
*
* @return {void} Does not return a value.
*/
completeSubgraph(): void;
/**
* Completes the current graph by setting a flag indicating the graph has been completed
* and recursively completes all subsequent nodes in the graph.
*
* @return {void} Does not return a value.
*/
completeGraph(): void;
/**
* Destroys the current instance by releasing resources, breaking references,
* and resetting properties to ensure proper cleanup.
*
* @return {void} No return value.
*/
destroy(): void;
/**
* Retrieves an iterator for traversing through the graph nodes.
*
* @return {GraphNodeIterator} An iterator instance specific to this graph node.
*/
getIterator(): GraphNodeIterator;
/**
* Applies