UNPKG

@effect-ts/system

Version:

Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.

156 lines (150 loc) 5.04 kB
// ets_tracing: off import { reduce, reduce_ } from "../Collections/Immutable/Chunk/api/reduce.js" import type { Chunk as Chunk_1 } from "../Collections/Immutable/Chunk/index.js" import type { NonEmptyArray } from "../Collections/Immutable/NonEmptyArray/index.js" import * as Tp from "../Collections/Immutable/Tuple/index.js" import * as Exit from "../Exit/index.js" import * as Fiber from "../Fiber/index.js" import { pipe } from "../Function/index.js" import { await as promiseAwait } from "../Promise/await.js" import { halt } from "../Promise/halt.js" import type { Promise } from "../Promise/index.js" import { make } from "../Promise/make.js" import { succeed } from "../Promise/succeed.js" import * as Ref from "../Ref/index.js" import * as as from "./as.js" import * as asUnit from "./asUnit.js" import * as core from "./core.js" import * as Do from "./do.js" import type { Effect, UIO } from "./effect.js" import { forEach_ } from "./excl-forEach.js" import { flatten } from "./flatten.js" import * as interruption from "./interruption.js" import * as map from "./map.js" import * as tap from "./tap.js" function arbiter<E, A>( fibers: Chunk_1<Fiber.Fiber<E, A>>, winner: Fiber.Fiber<E, A>, promise: Promise<E, Tp.Tuple<[A, Fiber.Fiber<E, A>]>>, fails: Ref.Ref<number> ) { return (res: Exit.Exit<E, A>): UIO<void> => pipe( res, Exit.foldM( (e) => flatten( pipe( fails, Ref.modify((c) => Tp.tuple( c === 0 ? pipe(promise, halt(e), asUnit.asUnit) : core.unit, c - 1 ) ) ) ), (a) => pipe( promise, succeed(Tp.tuple(a, winner)), core.chain((set) => set ? pipe( fibers, reduce(core.unit as UIO<void>, (io, f) => f === winner ? io : tap.tap_(io, () => Fiber.interrupt(f)) ) ) : core.unit ) ) ) ) } /** * Returns an effect that races this effect with all the specified effects, * yielding the value of the first effect to succeed with a value. * Losers of the race will be interrupted immediately. * * Note: in case of success eventual interruption errors are ignored */ export function raceAllWithStrategy<R, E, A>( ios: NonEmptyArray<Effect<R, E, A>>, interruptStrategy: "background" | "wait", __trace?: string ): Effect<R, E, A> { return pipe( Do.do, Do.bind("done", () => make<E, Tp.Tuple<[A, Fiber.Fiber<E, A>]>>()), Do.bind("fails", () => Ref.makeRef(ios.length)), Do.bind("c", ({ done, fails }) => interruption.uninterruptibleMask( ({ restore }) => pipe( Do.do, Do.bind("fs", () => forEach_(ios, (x) => pipe(x, interruption.interruptible, core.fork)) ), tap.tap(({ fs }) => reduce_(fs, core.unit as UIO<void>, (io, f) => pipe( io, core.chain(() => pipe(f.await, core.chain(arbiter(fs, f, done, fails)), core.fork) ) ) ) ), Do.let( "inheritRefs", () => (res: Tp.Tuple<[A, Fiber.Fiber<E, A>]>) => pipe(res.get(1).inheritRefs, as.as(res.get(0))) ), Do.bind("c", ({ fs, inheritRefs }) => pipe( restore(pipe(done, promiseAwait, core.chain(inheritRefs))), interruption.onInterrupt(() => reduce_(fs, core.unit as UIO<void>, (io, f) => tap.tap_(io, () => Fiber.interrupt(f)) ) ) ) ), map.map(({ c, fs }) => ({ c, fs })) ), __trace ) ), tap.tap(({ c: { fs } }) => interruptStrategy === "wait" ? forEach_(fs, (f) => f.await) : core.unit ), map.map(({ c: { c } }) => c) ) } /** * Returns an effect that races this effect with all the specified effects, * yielding the value of the first effect to succeed with a value. * Losers of the race will be interrupted immediately. * * Note: in case of success eventual interruption errors are ignored */ export function raceAll<R, E, A>( ios: NonEmptyArray<Effect<R, E, A>>, __trace?: string ): Effect<R, E, A> { return raceAllWithStrategy(ios, "background", __trace) } /** * Returns an effect that races this effect with all the specified effects, * yielding the value of the first effect to succeed with a value. * Losers of the race will be interrupted immediately. * * Note: in case of success eventual interruption errors are ignored */ export function raceAllWait<R, E, A>( ios: NonEmptyArray<Effect<R, E, A>>, __trace?: string ): Effect<R, E, A> { return raceAllWithStrategy(ios, "wait", __trace) }