4
4
import * as Effect from "effect/Effect"
5
5
import type * as Scope from "effect/Scope"
6
6
import type { NoSuchElementException } from "./Cause.js"
7
+ import * as Cause from "./Cause.js"
8
+ import * as Deferred from "./Deferred.js"
9
+ import * as Exit from "./Exit.js"
7
10
import * as Fiber from "./Fiber.js"
8
11
import * as FiberId from "./FiberId.js"
9
12
import { dual } from "./Function.js"
@@ -30,11 +33,12 @@ export type TypeId = typeof TypeId
30
33
* @since 2.0.0
31
34
* @categories models
32
35
*/
33
- export interface FiberMap < K , A = unknown , E = unknown >
36
+ export interface FiberMap < in out K , out A = unknown , out E = unknown >
34
37
extends Pipeable , Inspectable . Inspectable , Iterable < [ K , Fiber . RuntimeFiber < A , E > ] >
35
38
{
36
39
readonly [ TypeId ] : TypeId
37
40
readonly backing : MutableHashMap . MutableHashMap < K , Fiber . RuntimeFiber < A , E > >
41
+ readonly deferred : Deferred . Deferred < never , unknown >
38
42
}
39
43
40
44
/**
@@ -65,9 +69,13 @@ const Proto = {
65
69
}
66
70
}
67
71
68
- const unsafeMake = < K , A = unknown , E = unknown > ( ) : FiberMap < K , A , E > => {
72
+ const unsafeMake = < K , A = unknown , E = unknown > (
73
+ backing : MutableHashMap . MutableHashMap < K , Fiber . RuntimeFiber < A , E > > ,
74
+ deferred : Deferred . Deferred < never , E >
75
+ ) : FiberMap < K , A , E > => {
69
76
const self = Object . create ( Proto )
70
- self . backing = MutableHashMap . empty ( )
77
+ self . backing = backing
78
+ self . deferred = deferred
71
79
return self
72
80
}
73
81
@@ -97,7 +105,14 @@ const unsafeMake = <K, A = unknown, E = unknown>(): FiberMap<K, A, E> => {
97
105
* @categories constructors
98
106
*/
99
107
export const make = < K , A = unknown , E = unknown > ( ) : Effect . Effect < FiberMap < K , A , E > , never , Scope . Scope > =>
100
- Effect . acquireRelease ( Effect . sync ( ( ) => unsafeMake < K , A , E > ( ) ) , clear )
108
+ Effect . acquireRelease (
109
+ Effect . map ( Deferred . make < never , E > ( ) , ( deferred ) =>
110
+ unsafeMake < K , A , E > (
111
+ MutableHashMap . empty ( ) ,
112
+ deferred
113
+ ) ) ,
114
+ clear
115
+ )
101
116
102
117
/**
103
118
* Create an Effect run function that is backed by a FiberMap.
@@ -159,11 +174,14 @@ export const unsafeSet: {
159
174
previous . value . unsafeInterruptAsFork ( interruptAs ?? FiberId . none )
160
175
}
161
176
MutableHashMap . set ( self . backing , key , fiber )
162
- fiber . addObserver ( ( _ ) => {
177
+ fiber . addObserver ( ( exit ) => {
163
178
const current = MutableHashMap . get ( self . backing , key )
164
179
if ( Option . isSome ( current ) && fiber === current . value ) {
165
180
MutableHashMap . remove ( self . backing , key )
166
181
}
182
+ if ( Exit . isFailure ( exit ) && ! Cause . isInterruptedOnly ( exit . cause ) ) {
183
+ Deferred . unsafeDone ( self . deferred , exit as any )
184
+ }
167
185
} )
168
186
} )
169
187
@@ -372,5 +390,25 @@ export const runtime: <K, A, E>(
372
390
* @since 2.0.0
373
391
* @categories combinators
374
392
*/
375
- export const size = < K , E , A > ( self : FiberMap < K , E , A > ) : Effect . Effect < number > =>
393
+ export const size = < K , A , E > ( self : FiberMap < K , A , E > ) : Effect . Effect < number > =>
376
394
Effect . sync ( ( ) => MutableHashMap . size ( self . backing ) )
395
+
396
+ /**
397
+ * Join all fibers in the FiberMap. If any of the Fiber's in the map terminate with a failure,
398
+ * the returned Effect will terminate with the first failure that occurred.
399
+ *
400
+ * @since 2.0.0
401
+ * @categories combinators
402
+ * @example
403
+ * import { Effect, FiberMap } from "effect";
404
+ *
405
+ * Effect.gen(function* (_) {
406
+ * const map = yield* _(FiberMap.make());
407
+ * yield* _(FiberMap.set(map, "a", Effect.runFork(Effect.fail("error"))));
408
+ *
409
+ * // parent fiber will fail with "error"
410
+ * yield* _(FiberMap.join(map));
411
+ * });
412
+ */
413
+ export const join = < K , A , E > ( self : FiberMap < K , A , E > ) : Effect . Effect < never , E > =>
414
+ Deferred . await ( self . deferred as Deferred . Deferred < never , E > )
0 commit comments