caminho
Version:
Tool for creating efficient data pipelines in a JavaScript environment
89 lines • 3.78 kB
JavaScript
import { from, lastValueFrom, tap } from 'rxjs';
import { wrapGenerator, wrapGeneratorWithBackPressure } from './operators/generator';
import { pipe } from './operators/pipe';
import { batch } from './operators/batch';
import { parallel } from './operators/parallel';
import { reduce } from './operators/reduce';
import { filter } from './operators/filter';
import { applyOperator, isBatch, } from './operators/helpers/operatorHelpers';
import { PendingDataControlInMemory } from './utils/PendingDataControl';
import { getOnStepFinished } from './utils/onStepFinished';
import { getOnStepStarted } from './utils/onStepStarted';
import { generateId } from './utils/generateId';
export class Caminho {
options;
generator;
operators = [];
pendingDataControl;
constructor(generatorParams, options) {
this.options = options;
this.addOperatorApplier = this.addOperatorApplier.bind(this);
this.getApplierForPipeOrBatch = this.getApplierForPipeOrBatch.bind(this);
this.run = this.run.bind(this);
if (options?.maxItemsFlowing) {
this.pendingDataControl = new PendingDataControlInMemory();
}
this.generator = this.getGenerator(generatorParams);
}
getNumberOfItemsFlowing() {
return this.pendingDataControl?.size;
}
pipe(params) {
const operatorApplier = this.getApplierForPipeOrBatch(params);
this.addOperatorApplier(() => operatorApplier);
return this;
}
parallel(params) {
const operatorAppliers = params.map(this.getApplierForPipeOrBatch);
const operatorApplier = parallel(params, operatorAppliers);
this.addOperatorApplier(() => operatorApplier);
return this;
}
filter(params) {
const loggers = this.getLoggers(params);
this.addOperatorApplier(filter(params.fn, loggers, this.pendingDataControl));
return this;
}
reduce(reduceParams) {
const loggers = this.getLoggers(reduceParams);
this.addOperatorApplier(reduce(reduceParams, loggers, this.pendingDataControl));
return this;
}
async run(initialBag) {
const runId = generateId();
const initial$ = from(this.generator({ ...initialBag }, runId));
const observable$ = this.operators.reduce((acc, operator) => applyOperator(acc, operator, runId), initial$);
const finalObservable$ = this.options?.maxItemsFlowing
? observable$.pipe(tap(() => this.pendingDataControl.decrement(runId)))
: observable$;
try {
return await lastValueFrom(finalObservable$, { defaultValue: initialBag });
}
finally {
this.pendingDataControl?.destroyBucket(runId);
}
}
getGenerator(generatorParams) {
const loggers = this.getLoggers(generatorParams);
if (this.options?.maxItemsFlowing) {
const pendingDataControl = this.pendingDataControl;
return wrapGeneratorWithBackPressure(generatorParams, this.options.maxItemsFlowing, pendingDataControl, loggers);
}
return wrapGenerator(generatorParams, loggers);
}
addOperatorApplier(operatorApplier) {
this.operators.push(operatorApplier);
}
getApplierForPipeOrBatch(params) {
return isBatch(params)
? batch(params, this.getLoggers(params))
: pipe(params, this.getLoggers(params));
}
getLoggers(params) {
const stepName = params.name ?? params.fn.name;
const onStepStarted = getOnStepStarted(stepName, this.options?.onStepStarted);
const onStepFinished = getOnStepFinished(stepName, this.options?.onStepFinished);
return { onStepFinished, onStepStarted };
}
}
//# sourceMappingURL=Caminho.js.map