UNPKG

@thi.ng/rstream

Version:

Reactive streams & subscription primitives for constructing dataflow graphs / pipelines

155 lines 6.34 kB
import type { Always, Derefed, IObjectOf } from "@thi.ng/api"; import { type PartitionSync } from "@thi.ng/transducers/partition-sync"; import type { ISubscribable, ISubscription, TransformableOpts } from "./api.js"; import { Subscription } from "./subscription.js"; export type SyncTuple<T extends IObjectOf<ISubscribable<any>>> = { [id in keyof T]: Always<Derefed<T[id]>>; }; export interface StreamSyncOpts<A extends IObjectOf<ISubscribable<any>>, B = SyncTuple<A>> extends TransformableOpts<SyncTuple<A>, B> { /** * An object of input streams / subscribables. The object keys are used to * label the inputs in the result tuple object. */ src: A; /** * If true (default: false) *no* input synchronization (waiting for * values) is applied and `StreamSync` will emit potentially * partially populated tuple objects for each received input value. * However, as with the default behavior, tuples will retain the * most recent consumed value from other inputs. */ mergeOnly: boolean; /** * If true, StreamSync waits for new values from *all* inputs before * a new tuple is produced. If false, that synchronization * only happens for the very first tuple. * * @defaultValue false */ reset: boolean; /** * By default, the last emitted tuple is allowed to be incomplete * (in case all inputs closed). To only allow complete tuples, set * the `all` to false. * * @defaultValue true */ all: boolean; /** * 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; /** * Remove previously received value of an input in result tuple when * input is removed. * * @defaultValue false */ clean: boolean; } /** * Similar to {@link StreamMerge}, but with extra synchronization of inputs. * Before emitting any new values, {@link StreamSync} collects values until at * least one has been received from *all* inputs. Once that's the case, the * collected values are sent as labeled tuple object to downstream subscribers. * * @remarks * Each value in the emitted tuple objects is stored under their input stream's * ID. Only the last value received from each input is passed on. After the * initial tuple has been emitted, you can choose from two possible behaviors: * * 1) Any future change in any input will produce a new result tuple. These * tuples will retain the most recently read values from other inputs. This * behavior is the default and illustrated in the above schematic. * 2) If the `reset` option is `true`, every input will have to provide at least * one new value again until another result tuple is produced. * * Any done inputs are automatically removed. By default, `StreamSync` calls * {@link ISubscriber.done} when the last active input is done, but this * behavior can be overridden via the provided options. * * Input streams can be added and removed dynamically and the emitted tuple size * adjusts to the current number of inputs (the next time a value is received * from any input). After an input is removed (or done) its last received value * can also be removed from the result tuple. This behavior can be configured * via the `clean` option given to `sync()` (disabled by default). * * If the `reset` option is enabled, the last emitted tuple is allowed to be * incomplete, by default. To only allow complete tuples, also set the `all` * option to `false`. * * The synchronization is done via the * [`partitionSync`](https://docs.thi.ng/umbrella/transducers/functions/partitionSync-1.html) * transducer from the [`thi.ng/transducers`](https://thi.ng/transducers) * package. See this function's docs for further details. * * @example * ```ts tangle:../export/sync.ts * import { stream, sync, trace } from "@thi.ng/rstream"; * * const a = stream<number>(); * const b = stream<number>(); * * const main = sync({ src: { a, b } }).subscribe(trace("result: ")); * * a.next(1); * // main received value, but does not yet emit... * * b.next(2); * // now that `b` has delivered a value, `main` will produce its 1st result tuple * // result: { a: 1, b: 2 } * * // any further input changes will trigger new results * // (with cached values from other inputs) * b.next(3); * // result: { a: 1, b: 3 } * ``` * * Also see: {@link StreamSyncOpts} * * @param opts - */ export declare const sync: <A extends IObjectOf<ISubscribable<any>>, B = SyncTuple<A>>(opts: Partial<StreamSyncOpts<A, B>>) => StreamSync<A, B>; /** * See {@link sync} for reference & examples. */ export declare class StreamSync<A extends IObjectOf<ISubscribable<any>>, B = SyncTuple<A>> extends Subscription<any, B> { /** * maps actual inputs to their virtual input subs */ sources: Map<ISubscribable<any>, ISubscription<any, [string, any]>>; /** * maps real source IDs to their actual input */ idSources: Map<string, ISubscribable<any>>; /** * maps (potentially aliased) input IDs to their actual src.id */ realSourceIDs: Map<string, string>; /** * maps real src.id to (potentially aliased) input IDs */ invRealSourceIDs: Map<string, string>; psync: PartitionSync<[string, any]>; clean: boolean; constructor(opts: Partial<StreamSyncOpts<A, B>>); add(src: ISubscribable<any>, id?: string): void; addAll(src: Partial<A>): void; remove(src: ISubscribable<any>): boolean; removeID(id: string): boolean; removeAll(src: Iterable<ISubscribable<any>>): boolean; removeAllIDs(ids: Iterable<string>): boolean; getSourceForID(id: string): ISubscribable<any> | undefined; getSources(): A; unsubscribe(sub?: ISubscription<B, any>): boolean; protected markDone(src: ISubscribable<any>): void; } //# sourceMappingURL=sync.d.ts.map