@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
};