(
self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>,
f: (o: OutElem, i: number) => Effect.Effect<OutElem2, EX, RX>,
options: {
readonly concurrency: number | "unbounded"
readonly unordered?: boolean | undefined
}
)
| 2111 | }) |
| 2112 | |
| 2113 | const mapEffectConcurrent = < |
| 2114 | OutElem, |
| 2115 | OutErr, |
| 2116 | OutDone, |
| 2117 | InElem, |
| 2118 | InErr, |
| 2119 | InDone, |
| 2120 | Env, |
| 2121 | OutElem2, |
| 2122 | EX, |
| 2123 | RX |
| 2124 | >( |
| 2125 | self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, |
| 2126 | f: (o: OutElem, i: number) => Effect.Effect<OutElem2, EX, RX>, |
| 2127 | options: { |
| 2128 | readonly concurrency: number | "unbounded" |
| 2129 | readonly unordered?: boolean | undefined |
| 2130 | } |
| 2131 | ): Channel<OutElem2, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> => |
| 2132 | fromTransformBracket( |
| 2133 | Effect.fnUntraced(function*(upstream, scope, forkedScope) { |
| 2134 | let i = 0 |
| 2135 | const pull = yield* toTransform(self)(upstream, scope) |
| 2136 | const concurrencyN = options.concurrency === "unbounded" |
| 2137 | ? Number.MAX_SAFE_INTEGER |
| 2138 | : options.concurrency |
| 2139 | const queue = yield* Queue.bounded<OutElem2, OutErr | EX | Cause.Done<OutDone>>(0) |
| 2140 | yield* Scope.addFinalizer(forkedScope, Queue.shutdown(queue)) |
| 2141 | |
| 2142 | const runFork = Effect.runForkWith(yield* Effect.context<RX>()) |
| 2143 | const trackFiber = Fiber.runIn(forkedScope) |
| 2144 | |
| 2145 | if (options.unordered) { |
| 2146 | const semaphore = Semaphore.makeUnsafe(concurrencyN) |
| 2147 | const release = constant(semaphore.release(1)) |
| 2148 | const handle = Effect.matchCauseEffect({ |
| 2149 | onFailure: (cause: Cause.Cause<EX>) => Effect.flatMap(Queue.failCause(queue, cause), release), |
| 2150 | onSuccess: (value: OutElem2) => Effect.flatMap(Queue.offer(queue, value), release) |
| 2151 | }) |
| 2152 | yield* semaphore.take(1).pipe( |
| 2153 | Effect.flatMap(() => pull), |
| 2154 | Effect.flatMap((value) => { |
| 2155 | trackFiber(runFork(handle(f(value, i++)))) |
| 2156 | return Effect.void |
| 2157 | }), |
| 2158 | Effect.forever({ disableYield: true }), |
| 2159 | Effect.catchCause((cause) => |
| 2160 | semaphore.withPermits(concurrencyN - 1)( |
| 2161 | Queue.failCause(queue, cause) |
| 2162 | ) |
| 2163 | ), |
| 2164 | Effect.forkIn(forkedScope) |
| 2165 | ) |
| 2166 | } else { |
| 2167 | // capacity is n - 2 because |
| 2168 | // - 1 for the offer *after* starting a fiber |
| 2169 | // - 1 for the current processing fiber |
| 2170 | const effects = yield* Queue.bounded< |
no test coverage detected