/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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_CALL_SETUP = 4; 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 | ChildMessageCallSetup; declare type ChildMessageCall = [ type: typeof CHILD_MESSAGE_CALL, isProcessed: boolean, methodName: string, args: Array, ]; declare type ChildMessageCallSetup = [type: typeof CHILD_MESSAGE_CALL_SETUP]; 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 | URL, options?: WorkerFarmOptions); private _bindExposedWorkerMethods; private _callFunctionWithArgs; getStderr(): NodeJS.ReadableStream; getStdout(): NodeJS.ReadableStream; start(): Promise; 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/jestjs/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; start(): Promise; 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 {};