@thi.ng/rstream
Version:
Reactive streams & subscription primitives for constructing dataflow graphs / pipelines
165 lines • 7.02 kB
TypeScript
import type { ArrayLikeIterable, Fn, Fn3 } from "@thi.ng/api";
import type { CommonOpts, ITransformable, WorkerSource } from "./api.js";
import type { Subscription } from "./subscription.js";
export interface ForkJoinOpts<IN, MSG, RES, OUT> extends Partial<CommonOpts> {
/**
* Input stream to attach to obtain work items from.
*/
src: ITransformable<IN>;
/**
* Transformation function prepare (e.g. chunk) work for a single worker.
* Receives worker `id` `[0,numWorkers)`, `numWorkers` and current input
* value to be processed. Only the results of this function are sent to the
* worker and therefore the function must return a type compatible with the
* configured worker instance.
*
* For example, such a function might extract slices from a large input
* array, one per worker. The given worker ID and worker count can be used
* to create non-overlapping chunks to evenly spread the workload...
*
* Also see: {@link forkBuffer}
*/
fork: Fn3<number, number, IN, MSG>;
/**
* Join function. Receives array of worker results (in worker ID order) and
* is responsible to transform these into the final result / output type.
*/
join: Fn<RES[], OUT>;
/**
* Optional function to extract transferables from `fork` result values
* (i.e. payloads sent to each worker), e.g. ArrayBuffers. See:
* https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage
*/
transferables?: Fn<MSG, any[]>;
/**
* An existing `Worker` instance, a JS source code `Blob` or an URL string.
* In the latter two cases, a worker is created automatically using
* `makeWorker()`.
*/
worker: WorkerSource;
/**
* Optional max number of workers to use. Defaults to
* `navigator.hardwareConcurrency` (or if unavailable, then 4 as fallback).
* If setting this higher, be aware of browser limits and potential
* resulting crashes!
*
* If using multiple `forkJoin`s concurrently, it's the user's
* responsibility to ensure that the total number of workers won't exceed
* the browser limit (Chome/FF ~20).
*/
numWorkers?: number;
/**
* If true, the workers will be terminated and restarted for each new input
* stream value. This is useful to avoid executing extraneous work and
* ensures only the most rececent stream value is being processed.
*
* IMPORTANT: Please note that `forkJoin` does NOT handle backpressure at
* all. If `interrupt` is false, it's the user's responsibility to ensure
* that the input stream does NOT operate on a higher frequency than workers
* can produce results or else undefined behavior WILL occur!
*
* Default: false
*/
interrupt?: boolean;
/**
* If given and greater than zero, all workers will be terminated after
* given period (in millis) after the parent stream is done. If used, this
* value MUST be higher than the expected processing time of the worker
* jobs, in order to guarantee that the last values are processed fully.
*
* Default: 1000
*/
terminate?: number;
/**
* If greater than 0, then each labeled input will cache upto the stated
* number of input values, even if other inputs have not yet produced new
* values. Once the limit is reached, `partitionSync()` will throw an
* `IllegalState` error.
*
* Enabling this option will cause the same behavior as if `reset` is
* enabled (regardless of the actual configured `reset` setting). I.e. new
* results are only produced when ALL required inputs have available
* values...
*/
backPressure?: number;
}
/**
* Returns a {@link StreamSync} instance which creates & attaches multiple
* subscriptions to given `src` input stream, processes each received value in
* parallel via web workers, then recombines partial results and passes the
* resulting transformed value downstream.
*
* @remarks
* See {@link ForkJoinOpts} for further details & behavior options and the
* {@link forkBuffer} and {@link joinBuffer} helpers for array-based value
* processing (most likely use case).
*
* @param src - input stream
* @param opts -
*/
export declare const forkJoin: <IN, MSG, RES, OUT>(opts: ForkJoinOpts<IN, MSG, RES, OUT>) => Subscription<any, OUT>;
export type Sliceable<T> = ArrayLike<T> & {
slice(a: number, b?: number): Sliceable<T>;
};
/**
* Higher-order fork function for scenarios involving the split-parallel
* processing of a large buffer.
*
* @remarks
* The returned function is meant to be used as `fork` function in a
* {@link ForkJoinOpts} config and extracts a workload slice of the original
* buffer for a single worker. The HOF itself takes a minimum chunk size as
* optional parameter (default: 1).
*
* **Note:** Depending on the configured `minChunkSize` and the size of the
* input buffer to be partitioned, the returned fork function might produce
* empty sub-arrays for some workers, iff the configured number of workers
* exceeds the resulting number of chunks / input values. E.g. If the number of
* workers = 8, buffer size = 10 and min chunk size = 2, then the last 3 (i.e. 8
* - 10 / 2) workers will only receive empty workloads.
*
* More generally, if the input buffer size is not equally distributable over
* the given number of workers, the last worker(s) might receive a larger,
* smaller or empty chunk.
*
* Also see {@link forkJoin} and {@link joinBuffer}.
*
* @example
* ```ts
* import { forkBuffer, forkJoin, joinBuffer } from "@thi.ng/rstream";
*
* forkJoin<number[], number[], number[], number[]>({
* src,
* // job definition / split buffer into chunks (min size 256 values)
* fork: forkBuffer(256),
* // re-join partial results
* join: joinBuffer(),
* worker: "./worker.js",
* })
* ```
*
* @param minChunkSize -
*/
export declare const forkBuffer: (minChunkSize?: number) => <T extends Sliceable<any>>(id: number, numWorkers: number, buf: T) => T;
/**
* Higher-order join function for scenarios involving the split-parallel
* processing of a large buffer.
*
* @remarks
* The returned function is meant to be used as `join` function in a
* {@link ForkJoinOpts} config, receives the processed result chunks from all
* workers (ordered by worker ID) and concatenates them back into a single
* result array.
*
* The optional `fn` arg can be used to pick the actual result chunk from each
* worker result. This is useful if the worker result type is not an array and
* includes other data points (e.g. execution metrics etc.). If `fn` is not
* given, it defaults to the identity function (i.e. each worker's result is
* assumed to be an array).
*
* Also see {@link forkJoin} and {@link forkBuffer}.
*
* @param fn -
*/
export declare const joinBuffer: <A, B>(fn?: Fn<A, ArrayLikeIterable<B>>) => (parts: A[]) => B[];
//# sourceMappingURL=forkjoin.d.ts.map