/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
///
import type {ForkOptions} from 'child_process';
import type {ResourceLimits} from 'worker_threads';
declare const CHILD_MESSAGE_CALL = 1;
declare const CHILD_MESSAGE_END = 2;
declare const CHILD_MESSAGE_INITIALIZE = 0;
declare const CHILD_MESSAGE_MEM_USAGE = 3;
declare type ChildMessage =
| ChildMessageInitialize
| ChildMessageCall
| ChildMessageEnd
| ChildMessageMemUsage;
declare type ChildMessageCall = [
type: typeof CHILD_MESSAGE_CALL,
isProcessed: boolean,
methodName: string,
args: Array,
];
declare type ChildMessageEnd = [
type: typeof CHILD_MESSAGE_END,
isProcessed: boolean,
];
declare type ChildMessageInitialize = [
type: typeof CHILD_MESSAGE_INITIALIZE,
isProcessed: boolean,
fileName: string,
setupArgs: Array,
workerId: string | undefined,
];
declare type ChildMessageMemUsage = [type: typeof CHILD_MESSAGE_MEM_USAGE];
declare type ComputeTaskPriorityCallback = (
method: string,
...args: Array
) => number;
declare type ExcludeReservedKeys = Exclude;
/**
* First-in, First-out task queue that manages a dedicated pool
* for each worker as well as a shared queue. The FIFO ordering is guaranteed
* across the worker specific and shared queue.
*/
export declare class FifoQueue implements TaskQueue {
private _workerQueues;
private readonly _sharedQueue;
enqueue(task: QueueChildMessage, workerId?: number): void;
dequeue(workerId: number): QueueChildMessage | null;
}
declare type FunctionLike = (...args: any) => unknown;
declare type HeapItem = {
priority: number;
};
export declare type JestWorkerFarm> =
Worker_2 & WorkerModule;
export declare function messageParent(
message: unknown,
parentProcess?: NodeJS.Process,
): void;
declare type MethodLikeKeys = {
[K in keyof T]: T[K] extends FunctionLike ? K : never;
}[keyof T];
declare class MinHeap {
private readonly _heap;
peek(): TItem | null;
add(item: TItem): void;
poll(): TItem | null;
}
declare type OnCustomMessage = (message: Array | unknown) => void;
declare type OnEnd = (err: Error | null, result: unknown) => void;
declare type OnStart = (worker: WorkerInterface) => void;
declare type OnStateChangeHandler = (
state: WorkerStates,
oldState: WorkerStates,
) => void;
declare type PoolExitResult = {
forceExited: boolean;
};
/**
* Priority queue that processes tasks in natural ordering (lower priority first)
* according to the priority computed by the function passed in the constructor.
*
* FIFO ordering isn't guaranteed for tasks with the same priority.
*
* Worker specific tasks with the same priority as a non-worker specific task
* are always processed first.
*/
export declare class PriorityQueue implements TaskQueue {
private readonly _computePriority;
private _queue;
private readonly _sharedQueue;
constructor(_computePriority: ComputeTaskPriorityCallback);
enqueue(task: QueueChildMessage, workerId?: number): void;
_enqueue(task: QueueChildMessage, queue: MinHeap): void;
dequeue(workerId: number): QueueChildMessage | null;
_getWorkerQueue(workerId: number): MinHeap;
}
export declare interface PromiseWithCustomMessage extends Promise {
UNSTABLE_onCustomMessage?: (listener: OnCustomMessage) => () => void;
}
declare type Promisify = ReturnType extends Promise<
infer R
>
? (...args: Parameters) => Promise
: (...args: Parameters) => Promise>;
declare type QueueChildMessage = {
request: ChildMessageCall;
onStart: OnStart;
onEnd: OnEnd;
onCustomMessage: OnCustomMessage;
};
declare type QueueItem = {
task: QueueChildMessage;
priority: number;
};
declare type ReservedKeys =
| 'end'
| 'getStderr'
| 'getStdout'
| 'setup'
| 'teardown';
export declare interface TaskQueue {
/**
* Enqueues the task in the queue for the specified worker or adds it to the
* queue shared by all workers
* @param task the task to queue
* @param workerId the id of the worker that should process this task or undefined
* if there's no preference.
*/
enqueue(task: QueueChildMessage, workerId?: number): void;
/**
* Dequeues the next item from the queue for the specified worker
* @param workerId the id of the worker for which the next task should be retrieved
*/
dequeue(workerId: number): QueueChildMessage | null;
}
/**
* The Jest farm (publicly called "Worker") is a class that allows you to queue
* methods across multiple child processes, in order to parallelize work. This
* is done by providing an absolute path to a module that will be loaded on each
* of the child processes, and bridged to the main process.
*
* Bridged methods are specified by using the "exposedMethods" property of the
* "options" object. This is an array of strings, where each of them corresponds
* to the exported name in the loaded module.
*
* You can also control the amount of workers by using the "numWorkers" property
* of the "options" object, and the settings passed to fork the process through
* the "forkOptions" property. The amount of workers defaults to the amount of
* CPUS minus one.
*
* Queueing calls can be done in two ways:
* - Standard method: calls will be redirected to the first available worker,
* so they will get executed as soon as they can.
*
* - Sticky method: if a "computeWorkerKey" method is provided within the
* config, the resulting string of this method will be used as a key.
* Every time this key is returned, it is guaranteed that your job will be
* processed by the same worker. This is specially useful if your workers
* are caching results.
*/
declare class Worker_2 {
private _ending;
private readonly _farm;
private readonly _options;
private readonly _workerPool;
constructor(workerPath: string, options?: WorkerFarmOptions);
private _bindExposedWorkerMethods;
private _callFunctionWithArgs;
getStderr(): NodeJS.ReadableStream;
getStdout(): NodeJS.ReadableStream;
end(): Promise;
}
export {Worker_2 as Worker};
declare type WorkerCallback = (
workerId: number,
request: ChildMessage,
onStart: OnStart,
onEnd: OnEnd,
onCustomMessage: OnCustomMessage,
) => void;
declare enum WorkerEvents {
STATE_CHANGE = 'state-change',
}
export declare type WorkerFarmOptions = {
computeWorkerKey?: (method: string, ...args: Array) => string | null;
enableWorkerThreads?: boolean;
exposedMethods?: ReadonlyArray;
forkOptions?: ForkOptions;
maxRetries?: number;
numWorkers?: number;
resourceLimits?: ResourceLimits;
setupArgs?: Array;
taskQueue?: TaskQueue;
WorkerPool?: new (
workerPath: string,
options?: WorkerPoolOptions,
) => WorkerPoolInterface;
workerSchedulingPolicy?: WorkerSchedulingPolicy;
idleMemoryLimit?: number;
};
declare interface WorkerInterface {
get state(): WorkerStates;
send(
request: ChildMessage,
onProcessStart: OnStart,
onProcessEnd: OnEnd,
onCustomMessage: OnCustomMessage,
): void;
waitForExit(): Promise;
forceExit(): void;
getWorkerId(): number;
getStderr(): NodeJS.ReadableStream | null;
getStdout(): NodeJS.ReadableStream | null;
/**
* Some system level identifier for the worker. IE, process id, thread id, etc.
*/
getWorkerSystemId(): number;
getMemoryUsage(): Promise;
/**
* Checks to see if the child worker is actually running.
*/
isWorkerRunning(): boolean;
/**
* When the worker child is started and ready to start handling requests.
*
* @remarks
* This mostly exists to help with testing so that you don't check the status
* of things like isWorkerRunning before it actually is.
*/
waitForWorkerReady(): Promise;
}
declare type WorkerModule = {
[K in keyof T as Extract<
ExcludeReservedKeys,
MethodLikeKeys
>]: T[K] extends FunctionLike ? Promisify : never;
};
declare type WorkerOptions_2 = {
forkOptions: ForkOptions;
resourceLimits: ResourceLimits;
setupArgs: Array;
maxRetries: number;
workerId: number;
workerData?: unknown;
workerPath: string;
/**
* After a job has executed the memory usage it should return to.
*
* @remarks
* Note this is different from ResourceLimits in that it checks at idle, after
* a job is complete. So you could have a resource limit of 500MB but an idle
* limit of 50MB. The latter will only trigger if after a job has completed the
* memory usage hasn't returned back down under 50MB.
*/
idleMemoryLimit?: number;
/**
* This mainly exists so the path can be changed during testing.
* https://github.com/facebook/jest/issues/9543
*/
childWorkerPath?: string;
/**
* This is useful for debugging individual tests allowing you to see
* the raw output of the worker.
*/
silent?: boolean;
/**
* Used to immediately bind event handlers.
*/
on?: {
[WorkerEvents.STATE_CHANGE]:
| OnStateChangeHandler
| ReadonlyArray;
};
};
export declare interface WorkerPoolInterface {
getStderr(): NodeJS.ReadableStream;
getStdout(): NodeJS.ReadableStream;
getWorkers(): Array;
createWorker(options: WorkerOptions_2): WorkerInterface;
send: WorkerCallback;
end(): Promise;
}
export declare type WorkerPoolOptions = {
setupArgs: Array;
forkOptions: ForkOptions;
resourceLimits: ResourceLimits;
maxRetries: number;
numWorkers: number;
enableWorkerThreads: boolean;
idleMemoryLimit?: number;
};
declare type WorkerSchedulingPolicy = 'round-robin' | 'in-order';
declare enum WorkerStates {
STARTING = 'starting',
OK = 'ok',
OUT_OF_MEMORY = 'oom',
RESTARTING = 'restarting',
SHUTTING_DOWN = 'shutting-down',
SHUT_DOWN = 'shut-down',
}
export {};