@thi.ng/rstream
Version:
Reactive streams & subscription primitives for constructing dataflow graphs / pipelines
49 lines (48 loc) • 1.65 kB
JavaScript
import { assocObj } from "@thi.ng/transducers/assoc-obj";
import { comp } from "@thi.ng/transducers/comp";
import { map } from "@thi.ng/transducers/map";
import { mapcat } from "@thi.ng/transducers/mapcat";
import { range } from "@thi.ng/transducers/range";
import { transduce } from "@thi.ng/transducers/transduce";
import { sync } from "./sync.js";
import { tunnel } from "./tunnel.js";
const forkJoin = (opts) => {
const numWorkers = opts.numWorkers || navigator.hardwareConcurrency || 4;
const workerIDs = range(numWorkers);
return sync({
src: transduce(
map((id) => [
String(id),
opts.src.transform(map((x) => opts.fork(id, numWorkers, x))).subscribe(
tunnel({
src: opts.worker,
transferables: opts.transferables,
interrupt: opts.interrupt === true,
terminate: opts.terminate,
id: String(id)
})
)
]),
assocObj(),
workerIDs
),
xform: comp(
// form result tuple in original order
map((results) => [...map((id) => results[id], workerIDs)]),
// apply user join function
map(opts.join)
),
reset: true,
backPressure: opts.backPressure
});
};
const forkBuffer = (minChunkSize = 1) => (id, numWorkers, buf) => {
const chunkSize = Math.max(minChunkSize, buf.length / numWorkers | 0);
return id < numWorkers - 1 ? buf.slice(id * chunkSize, (id + 1) * chunkSize) : buf.slice(id * chunkSize);
};
const joinBuffer = (fn) => fn ? (parts) => [...mapcat(fn, parts)] : (parts) => Array.prototype.concat.apply([], parts);
export {
forkBuffer,
forkJoin,
joinBuffer
};