@typed/fx 1.24.0 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/RefSubject.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  import * as C from "@typed/context"
7
7
  import type { Equivalence, FiberId, Runtime } from "effect"
8
- import { Fiber } from "effect"
8
+ import { Fiber, MutableRef } from "effect"
9
9
  import * as Boolean from "effect/Boolean"
10
10
  import * as Cause from "effect/Cause"
11
11
  import * as Effect from "effect/Effect"
@@ -18,7 +18,7 @@ import { sum } from "effect/Number"
18
18
  import * as Option from "effect/Option"
19
19
  import * as ReadonlyArray from "effect/ReadonlyArray"
20
20
  import * as Scope from "effect/Scope"
21
- import type { Fx } from "./Fx.js"
21
+ import { type Fx } from "./Fx.js"
22
22
  import * as core from "./internal/core.js"
23
23
  import * as DeferredRef from "./internal/DeferredRef.js"
24
24
  import { getExitEquivalence, matchEffectPrimitive, withScope } from "./internal/helpers.js"
@@ -41,6 +41,11 @@ export interface Computed<out A, out E = never, out R = never>
41
41
  extends Versioned.Versioned<R, E, A, E, R | Scope.Scope, A, E, R>
42
42
  {
43
43
  readonly [ComputedTypeId]: ComputedTypeId
44
+
45
+ /**
46
+ * @since 1.25.0
47
+ */
48
+ readonly unsafeGet: () => Exit.Exit<A, E>
44
49
  }
45
50
 
46
51
  /**
@@ -70,6 +75,11 @@ export interface Filtered<out A, out E = never, out R = never>
70
75
  * @since 1.20.0
71
76
  */
72
77
  asComputed(): Computed<Option.Option<A>, E, R>
78
+
79
+ /**
80
+ * @since 1.25.0
81
+ */
82
+ readonly unsafeGet: () => Exit.Exit<A, E | Cause.NoSuchElementException>
73
83
  }
74
84
 
75
85
  /**
@@ -101,6 +111,11 @@ export interface RefSubject<in out A, in out E = never, out R = never>
101
111
  readonly runUpdates: <B, E2, R2>(
102
112
  f: (ref: GetSetDelete<A, E, R>) => Effect.Effect<B, E2, R2>
103
113
  ) => Effect.Effect<B, E2, R | R2>
114
+
115
+ /**
116
+ * @since 1.25.0
117
+ */
118
+ readonly unsafeGet: () => Exit.Exit<A, E>
104
119
  }
105
120
 
106
121
  /**
@@ -259,7 +274,9 @@ export function fromRefSubject<A, E, R>(
259
274
 
260
275
  function persistCore<A, E, R, R2>(ref: RefSubject<A, E, R>, core: RefSubjectCore<A, E, R, R2>) {
261
276
  // Log any errors that fail to persist, but don't fail the consumer
262
- return Effect.ignoreLogged(Effect.provide(Effect.flatMap(core.deferredRef, (value) => set(ref, value)), core.context))
277
+ return Effect.ignoreLogged(
278
+ Effect.provide(Effect.flatMap(core.deferredRef, (value) => set(ref, value)), core.runtime)
279
+ )
263
280
  }
264
281
 
265
282
  /**
@@ -317,8 +334,6 @@ const withScopeAndFiberId = <A, E, R>(
317
334
  strategy: ExecutionStrategy.ExecutionStrategy
318
335
  ) => Effect.fiberIdWith((id) => withScope((scope) => f(scope, id), strategy))
319
336
 
320
- const emptyContext = C.empty()
321
-
322
337
  /**
323
338
  * @since 1.20.0
324
339
  */
@@ -332,8 +347,8 @@ export function unsafeMake<E, A>(
332
347
  }
333
348
  ): Effect.Effect<RefSubject<A, E>> {
334
349
  const { id, initial, options, scope } = params
335
- return Effect.suspend(() => {
336
- const core = unsafeMakeCore(initial, id, emptyContext, scope, options)
350
+ return Effect.flatMap(Effect.runtime(), (runtime) => {
351
+ const core = unsafeMakeCore(initial, id, runtime, scope, options)
337
352
 
338
353
  // Sometimes we might be instantiating directly from a known value
339
354
  // Here we seed the value and ensure the subject has it as well for re-broadcasting
@@ -356,16 +371,16 @@ class RefSubjectImpl<A, E, R, R2> extends FxEffectBase<A, E, Exclude<R, R2> | Sc
356
371
  readonly interrupt: Effect.Effect<void, never, Exclude<R, R2>>
357
372
  readonly subscriberCount: Effect.Effect<number, never, Exclude<R, R2>>
358
373
 
359
- private readonly getSetDelete: GetSetDelete<A, E, Exclude<R, R2>>
374
+ readonly getSetDelete: GetSetDelete<A, E, Exclude<R, R2>>
360
375
 
361
376
  constructor(
362
- private readonly core: RefSubjectCore<A, E, R, R2>
377
+ readonly core: RefSubjectCore<A, E, R, R2>
363
378
  ) {
364
379
  super()
365
380
 
366
381
  this.version = Effect.sync(() => core.deferredRef.version)
367
- this.interrupt = Effect.provide(interruptCore(core), core.context)
368
- this.subscriberCount = Effect.provide(core.subject.subscriberCount, core.context)
382
+ this.interrupt = Effect.provide(interruptCore(core), core.runtime)
383
+ this.subscriberCount = Effect.provide(core.subject.subscriberCount, core.runtime)
369
384
  this.getSetDelete = getSetDelete(core)
370
385
 
371
386
  this.runUpdates = this.runUpdates.bind(this)
@@ -376,7 +391,7 @@ class RefSubjectImpl<A, E, R, R2> extends FxEffectBase<A, E, Exclude<R, R2> | Sc
376
391
  run<R3>(sink: Sink.Sink<A, E, R3>): Effect.Effect<unknown, never, Exclude<R, R2> | R3 | Scope.Scope> {
377
392
  return Effect.matchCauseEffect(getOrInitializeCore(this.core, true), {
378
393
  onFailure: (cause) => sink.onFailure(cause),
379
- onSuccess: () => Effect.provide(this.core.subject.run(sink), this.core.context)
394
+ onSuccess: () => Effect.provide(this.core.subject.run(sink), this.core.runtime)
380
395
  })
381
396
  }
382
397
 
@@ -386,6 +401,9 @@ class RefSubjectImpl<A, E, R, R2> extends FxEffectBase<A, E, Exclude<R, R2> | Sc
386
401
  return this.core.semaphore.withPermits(1)(run(this.getSetDelete))
387
402
  }
388
403
 
404
+ unsafeGet: () => Exit.Exit<A, E> = () =>
405
+ Option.getOrThrowWith(this.core.deferredRef.current, () => new Cause.NoSuchElementException())
406
+
389
407
  onSuccess(value: A): Effect.Effect<unknown, never, Exclude<R, R2>> {
390
408
  return setCore(this.core, value)
391
409
  }
@@ -593,7 +611,7 @@ class RefSubjectCore<A, E, R, R2> {
593
611
  constructor(
594
612
  readonly initial: Effect.Effect<A, E, R>,
595
613
  readonly subject: Subject.Subject<A, E, R>,
596
- readonly context: C.Context<R2>,
614
+ readonly runtime: Runtime.Runtime<R2>,
597
615
  readonly scope: Scope.CloseableScope,
598
616
  readonly deferredRef: DeferredRef.DeferredRef<E, A>,
599
617
  readonly semaphore: Effect.Semaphore
@@ -606,12 +624,12 @@ function makeCore<A, E, R>(
606
624
  initial: Effect.Effect<A, E, R>,
607
625
  options?: RefSubjectOptions<A>
608
626
  ) {
609
- return Effect.context<R | Scope.Scope>().pipe(
610
- Effect.bindTo("ctx"),
627
+ return Effect.runtime<R | Scope.Scope>().pipe(
628
+ Effect.bindTo("runtime"),
611
629
  Effect.let("executionStrategy", () => options?.executionStrategy ?? ExecutionStrategy.parallel),
612
630
  Effect.bind(
613
631
  "scope",
614
- ({ ctx, executionStrategy }) => Scope.fork(C.get(ctx, Scope.Scope), executionStrategy)
632
+ ({ executionStrategy, runtime }) => Scope.fork(C.get(runtime.context, Scope.Scope), executionStrategy)
615
633
  ),
616
634
  Effect.bind(
617
635
  "deferredRef",
@@ -619,11 +637,11 @@ function makeCore<A, E, R>(
619
637
  ),
620
638
  Effect.let("subject", () => Subject.unsafeMake<A, E>(Math.max(1, options?.replay ?? 1))),
621
639
  Effect.tap(({ scope, subject }) => Scope.addFinalizer(scope, subject.interrupt)),
622
- Effect.map(({ ctx, deferredRef, scope, subject }) =>
640
+ Effect.map(({ deferredRef, runtime, scope, subject }) =>
623
641
  new RefSubjectCore(
624
642
  initial,
625
643
  subject,
626
- ctx,
644
+ runtime,
627
645
  scope,
628
646
  deferredRef,
629
647
  Effect.unsafeMakeSemaphore(1)
@@ -635,14 +653,14 @@ function makeCore<A, E, R>(
635
653
  function unsafeMakeCore<A, E, R>(
636
654
  initial: Effect.Effect<A, E, R>,
637
655
  id: FiberId.FiberId,
638
- ctx: C.Context<R>,
656
+ runtime: Runtime.Runtime<R>,
639
657
  scope: Scope.CloseableScope,
640
658
  options?: RefSubjectOptions<A>
641
659
  ) {
642
660
  return new RefSubjectCore(
643
661
  initial,
644
662
  Subject.unsafeMake<A, E>(Math.max(1, options?.replay ?? 1)),
645
- ctx,
663
+ runtime,
646
664
  scope,
647
665
  DeferredRef.unsafeMake(id, getExitEquivalence(options?.eq ?? Equal.equals)),
648
666
  Effect.unsafeMakeSemaphore(1)
@@ -667,7 +685,7 @@ function initializeCoreEffect<A, E, R, R2>(
667
685
  lock: boolean
668
686
  ): Effect.Effect<Fiber.Fiber<A, E>, never, Exclude<R, R2>> {
669
687
  const initialize = Effect.onExit(
670
- Effect.provide(core.initial, core.context),
688
+ Effect.provide(core.initial, core.runtime),
671
689
  (exit) =>
672
690
  Effect.sync(() => {
673
691
  core._fiber = undefined
@@ -774,7 +792,7 @@ function deleteCore<A, E, R, R2>(
774
792
  }
775
793
 
776
794
  return core.subject.subscriberCount.pipe(
777
- Effect.provide(core.context),
795
+ Effect.provide(core.runtime),
778
796
  Effect.flatMap(
779
797
  (count: number) => count > 0 && !core._fiber ? initializeCore(core, false) : Effect.unit
780
798
  ),
@@ -799,9 +817,9 @@ function sendEvent<A, E, R, R2>(
799
817
  exit: Exit.Exit<A, E>
800
818
  ): Effect.Effect<unknown, never, Exclude<R, R2>> {
801
819
  if (Exit.isSuccess(exit)) {
802
- return Effect.provide(core.subject.onSuccess(exit.value), core.context)
820
+ return Effect.provide(core.subject.onSuccess(exit.value), core.runtime)
803
821
  } else {
804
- return Effect.provide(core.subject.onFailure(exit.cause), core.context)
822
+ return Effect.provide(core.subject.onFailure(exit.cause), core.runtime)
805
823
  }
806
824
  }
807
825
 
@@ -1035,6 +1053,9 @@ class ComputedImpl<R0, E0, A, E, R, E2, R2, C, E3, R3> extends Versioned.Version
1035
1053
  )
1036
1054
  }
1037
1055
 
1056
+ unsafeGet: () => Exit.Exit<C, E0 | E | E2 | E3> = () =>
1057
+ Option.getOrThrowWith(this._currentValue, () => new Cause.NoSuchElementException())
1058
+
1038
1059
  static make<R0, E0, A, E, R, E2, R2, C, E3, R3>(
1039
1060
  input: Versioned.Versioned<R0, E0, A, E, R, A, E2, R2>,
1040
1061
  f: (a: A) => Effect.Effect<C, E3, R3>
@@ -1086,6 +1107,9 @@ class FilteredImpl<R0, E0, A, E, R, E2, R2, C, E3, R3> extends Versioned.Version
1086
1107
  asComputed(): Computed<Option.Option<C>, E0 | E | E2 | E3, R0 | R2 | R3 | Exclude<R, Scope.Scope>> {
1087
1108
  return ComputedImpl.make(this.input, this.f)
1088
1109
  }
1110
+
1111
+ unsafeGet: () => Exit.Exit<C, Cause.NoSuchElementException | E0 | E | E2 | E3> = () =>
1112
+ Option.getOrThrowWith(this._currentValue, () => new Cause.NoSuchElementException())
1089
1113
  }
1090
1114
 
1091
1115
  /**
@@ -1204,6 +1228,11 @@ class RefSubjectTransform<A, E, R, B> extends FxEffectBase<B, E, R | Scope.Scope
1204
1228
  )
1205
1229
  }
1206
1230
 
1231
+ unsafeGet: () => Exit.Exit<B, E> = () => {
1232
+ const exit = this.ref.unsafeGet()
1233
+ return Exit.map(exit, this.from)
1234
+ }
1235
+
1207
1236
  onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, R> {
1208
1237
  return this.ref.onFailure(cause)
1209
1238
  }
@@ -1227,7 +1256,7 @@ class RefSubjectTransformEffect<A, E, R, B, E2, R2, R3, E3>
1227
1256
  readonly version: Effect.Effect<number, E, R>
1228
1257
  readonly interrupt: Effect.Effect<void, never, R>
1229
1258
  readonly subscriberCount: Effect.Effect<number, never, R>
1230
- readonly subject: Subject.Subject<B, E | E2 | E3>
1259
+ readonly subject: Subject.HoldSubjectImpl<B, E | E2 | E3>
1231
1260
 
1232
1261
  constructor(
1233
1262
  readonly ref: RefSubject<A, E, R>,
@@ -1239,11 +1268,15 @@ class RefSubjectTransformEffect<A, E, R, B, E2, R2, R3, E3>
1239
1268
  this.version = ref.version
1240
1269
  this.interrupt = ref.interrupt
1241
1270
  this.subscriberCount = ref.subscriberCount
1242
- this.subject = Subject.unsafeMake()
1271
+ this.subject = new Subject.HoldSubjectImpl()
1243
1272
  }
1244
1273
 
1245
1274
  run<R4 = never>(sink: Sink.Sink<B, E | E2 | E3, R4>): Effect.Effect<unknown, never, R | R2 | R3 | Scope.Scope | R4> {
1246
- return core.merge(core.mapEffect(this.ref, this.from), this.subject).run(sink)
1275
+ return core.skipRepeats(
1276
+ core.merge(core.tapEffect(core.mapEffect(this.ref, this.from), this.subject.onSuccess), this.subject)
1277
+ ).run(
1278
+ sink
1279
+ )
1247
1280
  }
1248
1281
 
1249
1282
  runUpdates<R4, E4, C>(
@@ -1268,6 +1301,10 @@ class RefSubjectTransformEffect<A, E, R, B, E2, R2, R3, E3>
1268
1301
  )
1269
1302
  }
1270
1303
 
1304
+ unsafeGet: () => Exit.Exit<B, E | E2 | E3> = () => {
1305
+ return Option.getOrThrowWith(MutableRef.get(this.subject.lastValue), () => new Cause.NoSuchElementException())
1306
+ }
1307
+
1271
1308
  onFailure(cause: Cause.Cause<E | E2 | E3>): Effect.Effect<unknown, never, R> {
1272
1309
  return this.subject.onFailure(cause)
1273
1310
  }
@@ -1494,6 +1531,21 @@ class RefSubjectTuple<
1494
1531
  return run(this.getSetDelete)
1495
1532
  }
1496
1533
 
1534
+ unsafeGet: () => Exit.Exit<
1535
+ { readonly [K in keyof Refs]: Effect.Effect.Success<Refs[K]> },
1536
+ Effect.Effect.Error<Refs[number]>
1537
+ > = () => {
1538
+ return Option.getOrThrowWith(
1539
+ Exit.all(this.refs.map((r) => r.unsafeGet())) as Option.Option<
1540
+ Exit.Exit<
1541
+ { readonly [K in keyof Refs]: Effect.Effect.Success<Refs[K]> },
1542
+ Effect.Effect.Error<Refs[number]>
1543
+ >
1544
+ >,
1545
+ () => new Cause.NoSuchElementException()
1546
+ )
1547
+ }
1548
+
1497
1549
  onFailure(
1498
1550
  cause: Cause.Cause<Effect.Effect.Error<Refs[number]>>
1499
1551
  ): Effect.Effect<unknown, never, Effect.Effect.Context<Refs[number]>> {
@@ -1648,6 +1700,24 @@ class RefSubjectStruct<
1648
1700
  return run(this.getSetDelete)
1649
1701
  }
1650
1702
 
1703
+ unsafeGet: () => Exit.Exit<
1704
+ { readonly [K in keyof Refs]: Effect.Effect.Success<Refs[K]> },
1705
+ Effect.Effect.Error<Refs[keyof Refs]>
1706
+ > = () => {
1707
+ const entries = Object.entries(this.refs).map(([k, r]) => Exit.map(r.unsafeGet(), (a) => [k, a] as const))
1708
+ const exit = Option.getOrThrowWith(
1709
+ Exit.all(entries) as Option.Option<
1710
+ Exit.Exit<
1711
+ ReadonlyArray<readonly [string, Effect.Effect.Success<Refs[keyof Refs]>]>,
1712
+ Effect.Effect.Error<Refs[keyof Refs]>
1713
+ >
1714
+ >,
1715
+ () => new Cause.NoSuchElementException()
1716
+ )
1717
+
1718
+ return Exit.map(exit, (entries) => Object.fromEntries(entries)) as any
1719
+ }
1720
+
1651
1721
  onFailure(
1652
1722
  cause: Cause.Cause<Effect.Effect.Error<Refs[keyof Refs]>>
1653
1723
  ): Effect.Effect<unknown, never, Effect.Effect.Context<Refs[keyof Refs]>> {
@@ -1785,6 +1855,10 @@ class RefSubjectTagged<I, E, A> extends FxEffectBase<
1785
1855
  return this.tag.withEffect((ref) => ref.runUpdates(run))
1786
1856
  }
1787
1857
 
1858
+ unsafeGet: () => Exit.Exit<A, E> = () => {
1859
+ throw new Error(`Unable to unsafely get a tagged RefSubject because it requires the Effect context by defnition.`)
1860
+ }
1861
+
1788
1862
  onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, I> {
1789
1863
  return this.tag.withEffect((ref) => ref.onFailure(cause))
1790
1864
  }
@@ -1855,6 +1929,10 @@ class RefSubjectFromTag<I, S, A, E, R> extends FxEffectBase<
1855
1929
  return Effect.flatMap(this._get, (ref) => ref.runUpdates(run))
1856
1930
  }
1857
1931
 
1932
+ unsafeGet: () => Exit.Exit<A, E> = () => {
1933
+ throw new Error(`Unable to unsafely get a tagged RefSubject because it requires the Effect context by defnition.`)
1934
+ }
1935
+
1858
1936
  onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, I | R> {
1859
1937
  return Effect.flatMap(this._get, (ref) => ref.onFailure(cause))
1860
1938
  }
@@ -1949,6 +2027,10 @@ class ComputedFromTag<I, S, A, E, R> extends FxEffectBase<
1949
2027
  toEffect(): Effect.Effect<A, E, I | R> {
1950
2028
  return Effect.flatten(this._get)
1951
2029
  }
2030
+
2031
+ unsafeGet: () => Exit.Exit<A, E> = () => {
2032
+ throw new Error(`Unable to unsafely get a tagged Computed because it requires the Effect context by defnition.`)
2033
+ }
1952
2034
  }
1953
2035
 
1954
2036
  /**
@@ -1996,6 +2078,10 @@ class FilteredFromTag<I, S, A, E, R> extends FxEffectBase<
1996
2078
  asComputed(): Computed<Option.Option<A>, E, R | I> {
1997
2079
  return new ComputedFromTag(this.tag, (s) => this.f(s).asComputed())
1998
2080
  }
2081
+
2082
+ unsafeGet: () => Exit.Exit<A, E> = () => {
2083
+ throw new Error(`Unable to unsafely get a tagged Filtered because it requires the Effect context by defnition.`)
2084
+ }
1999
2085
  }
2000
2086
 
2001
2087
  /**
@@ -2198,6 +2284,8 @@ class RefSubjectSlice<A, E, R> extends FxEffectBase<A, E, R | Scope.Scope, A, E,
2198
2284
  return this.ref.runUpdates(run)
2199
2285
  }
2200
2286
 
2287
+ unsafeGet: () => Exit.Exit<A, E> = () => this.ref.unsafeGet()
2288
+
2201
2289
  onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, R> {
2202
2290
  return this.ref.onFailure(cause)
2203
2291
  }
@@ -2206,3 +2294,33 @@ class RefSubjectSlice<A, E, R> extends FxEffectBase<A, E, R | Scope.Scope, A, E,
2206
2294
  return this.ref.onSuccess(value)
2207
2295
  }
2208
2296
  }
2297
+
2298
+ /**
2299
+ * Get the current value of the RefSubject. If it has not been set yet, a Fiber will be used to wait for the value to be set.
2300
+ *
2301
+ * @since 1.25.0
2302
+ */
2303
+ export const get: {
2304
+ <A, E = never, R = never>(ref: RefSubject<A, E, R>): Effect.Effect<A, E, R>
2305
+ <A, E = never, R = never>(ref: Computed<A, E, R>): Effect.Effect<A, E, R>
2306
+ <A, E = never, R = never>(ref: Filtered<A, E, R>): Effect.Effect<A, E | Cause.NoSuchElementException, R>
2307
+ } = <A, E, R>(
2308
+ ref: RefSubject<A, E, R> | Computed<A, E, R> | Filtered<A, E, R>
2309
+ ): Effect.Effect<A, E | Cause.NoSuchElementException, R> => ref
2310
+
2311
+ /**
2312
+ * Synchronously get the current Exit value of the RefSubject. If it has not been set yet, a Cause.NoSuchElementException will be thrown.
2313
+ *
2314
+ * Note: This is unimplemented for RefSubject.tagged and RefSubject.fromTag because they require the Effect context by definition.
2315
+ * It will throw immediately.
2316
+ *
2317
+ * @since 1.25.0
2318
+ */
2319
+ export const unsafeGetExit = <A, E = never, R = never>(ref: RefSubject<A, E, R>): Exit.Exit<A, E> => ref.unsafeGet()
2320
+
2321
+ /**
2322
+ * Synchronously get the current value of the RefSubject.
2323
+ *
2324
+ * @since 1.25.0
2325
+ */
2326
+ export const unsafeGet = <A, E = never, R = never>(ref: RefSubject<A, E, R>): A => Effect.runSync(unsafeGetExit(ref))
package/src/Subject.ts CHANGED
@@ -159,21 +159,29 @@ export class SubjectImpl<A, E> extends FxBase<A, E, Scope.Scope> implements Subj
159
159
  * @internal
160
160
  */
161
161
  export class HoldSubjectImpl<A, E> extends SubjectImpl<A, E> implements Subject<A, E> {
162
- private lastValue: MutableRef.MutableRef<Option.Option<A>> = MutableRef.make(Option.none())
162
+ readonly lastValue: MutableRef.MutableRef<Option.Option<Exit.Exit<A, E>>> = MutableRef.make(Option.none())
163
163
 
164
164
  // Emit an event to all sinks
165
165
  onSuccess = (a: A) =>
166
166
  Effect.suspend(() => {
167
- MutableRef.set(this.lastValue, Option.some(a))
167
+ MutableRef.set(this.lastValue, Option.some(Exit.succeed(a)))
168
168
 
169
169
  return this.onEvent(a)
170
170
  })
171
171
 
172
+ onFailure = (cause: Cause.Cause<E>): Effect.Effect<void, never, never> => {
173
+ return Effect.suspend(() => {
174
+ MutableRef.set(this.lastValue, Option.some(Exit.failCause(cause)))
175
+
176
+ return this.onCause(cause)
177
+ })
178
+ }
179
+
172
180
  run<R2>(sink: Sink<A, E, R2>): Effect.Effect<unknown, never, R2 | Scope.Scope> {
173
181
  return this.addSink(sink, (scope) =>
174
182
  Option.match(MutableRef.get(this.lastValue), {
175
183
  onNone: () => awaitScopeClose(scope),
176
- onSome: (a) => Effect.zipRight(sink.onSuccess(a), awaitScopeClose(scope))
184
+ onSome: (exit) => Effect.zipRight(Exit.match(exit, sink), awaitScopeClose(scope))
177
185
  }))
178
186
  }
179
187
 
package/src/Versioned.ts CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  import type * as Context from "@typed/context"
9
9
  import type { Layer, Runtime, Scope } from "effect"
10
+ import { Exit } from "effect"
10
11
  import * as Effect from "effect/Effect"
11
12
  import { dual, flow } from "effect/Function"
12
13
  import { sum } from "effect/Number"
@@ -112,9 +113,9 @@ export class VersionedTransform<R0, E0, A, E, R, B, E2, R2, C, E3, R3, D, E4, R4
112
113
  extends FxEffectBase<C, E3, R3, D, E0 | E4, R0 | R4>
113
114
  implements Versioned<never, never, C, E3, R3, D, E0 | E4, R0 | R4>
114
115
  {
115
- protected _version = -1
116
- protected _currentValue: Option.Option<D> = Option.none()
117
- protected _fx: Fx<C, E3, R3>
116
+ public _version = -1
117
+ public _currentValue: Option.Option<Exit.Exit<D, E0 | E4>> = Option.none()
118
+ public _fx: Fx<C, E3, R3>
118
119
 
119
120
  constructor(
120
121
  readonly input: Versioned<R0, E0, A, E, R, B, E2, R2>,
@@ -135,18 +136,25 @@ export class VersionedTransform<R0, E0, A, E, R, B, E2, R2, C, E3, R3, D, E4, R4
135
136
  toEffect(): Effect.Effect<D, E0 | E4, R0 | R4> {
136
137
  const transformed = this._transformEffect(this.input as any as Effect.Effect<B, E2, R2>)
137
138
  const update = (v: number) =>
138
- Effect.tap(
139
- transformed,
140
- (value) =>
139
+ Effect.tapErrorCause(
140
+ Effect.tap(
141
+ transformed,
142
+ (value) =>
143
+ Effect.sync(() => {
144
+ this._currentValue = Option.some(Exit.succeed(value))
145
+ this._version = v
146
+ })
147
+ ),
148
+ (cause) =>
141
149
  Effect.sync(() => {
142
- this._currentValue = Option.some(value)
150
+ this._currentValue = Option.some(Exit.failCause(cause))
143
151
  this._version = v
144
152
  })
145
153
  )
146
154
 
147
155
  return new MulticastEffect(Effect.flatMap(this.input.version, (version) => {
148
156
  if (version === this._version && Option.isSome(this._currentValue)) {
149
- return Effect.succeed(this._currentValue.value)
157
+ return this._currentValue.value
150
158
  }
151
159
 
152
160
  return update(version)
@@ -1266,8 +1266,9 @@ function runOrdered<
1266
1266
  return Effect.suspend(
1267
1267
  () => {
1268
1268
  const buffers = withBuffers(fx.length, sink)
1269
- return Effect.all(
1270
- fx.map((fx, i) =>
1269
+ return Effect.forEach(
1270
+ fx,
1271
+ (fx, i) =>
1271
1272
  Effect.flatMap(
1272
1273
  fx.run(
1273
1274
  Sink.make(
@@ -1276,10 +1277,10 @@ function runOrdered<
1276
1277
  )
1277
1278
  ),
1278
1279
  () => buffers.onEnd(i)
1279
- )
1280
- ),
1280
+ ),
1281
1281
  {
1282
- concurrency
1282
+ concurrency,
1283
+ discard: true
1283
1284
  }
1284
1285
  )
1285
1286
  }