import { assert, describe, it } from "@effect/vitest" import { assertFalse, assertTrue, strictEqual } from "@effect/vitest/utils" import { Array, Deferred, Effect, Exit, Fiber, FiberSet, pipe, Ref, Scope } from "effect" import { TestClock } from "effect/testing" describe("FiberSet", () => { it.effect("interrupts running fibers when the scope closes", () => Effect.gen(function*() { const ref = yield* Ref.make(0) yield* Effect.scoped( Effect.gen(function*() { const set = yield* FiberSet.make() yield* Effect.onInterrupt( Effect.never, () => Ref.update(ref, (n) => n + 1) ).pipe( FiberSet.run(set), Effect.repeat({ times: 9 }) ) yield* Effect.yieldNow }) ) strictEqual(yield* Ref.get(ref), 10) })) it.effect("runtime", () => Effect.gen(function*() { const ref = yield* Ref.make(0) yield* pipe( Effect.gen(function*() { const set = yield* FiberSet.make() const run = yield* FiberSet.runtime(set)() Array.range(1, 10).forEach(() => run( Effect.onInterrupt( Effect.never, () => Ref.update(ref, (n) => n + 1) ) ) ) yield* Effect.yieldNow }), Effect.scoped ) strictEqual(yield* Ref.get(ref), 10) })) it.effect("runs fibers concurrently and awaitEmpty waits for completion", () => Effect.gen(function*() { const set = yield* FiberSet.make() FiberSet.addUnsafe(set, Effect.runFork(Effect.void)) FiberSet.addUnsafe(set, Effect.runFork(Effect.void)) FiberSet.addUnsafe(set, Effect.runFork(Effect.fail("fail"))) const result = yield* pipe(FiberSet.join(set), Effect.flip) strictEqual(result, "fail") })) it.effect("size", () => Effect.gen(function*() { const scope = yield* Scope.make() const set = yield* pipe(FiberSet.make(), Scope.provide(scope)) FiberSet.addUnsafe(set, Effect.runFork(Effect.never)) FiberSet.addUnsafe(set, Effect.runFork(Effect.never)) strictEqual(yield* FiberSet.size(set), 2) yield* Scope.close(scope, Exit.void) strictEqual(yield* FiberSet.size(set), 0) })) it.effect("propagateInterruption false ignores external interruption", () => Effect.gen(function*() { const set = yield* FiberSet.make() const fiber = yield* FiberSet.run(set, Effect.never, { propagateInterruption: false }) yield* Effect.yieldNow yield* Fiber.interrupt(fiber) assertFalse(yield* Deferred.isDone(set.deferred)) })) it.effect("propagateInterruption true fails join on external interruption", () => Effect.gen(function*() { const set = yield* FiberSet.make() const fiber = yield* FiberSet.run(set, Effect.never, { propagateInterruption: true }) yield* Effect.yieldNow yield* Fiber.interrupt(fiber) assertTrue(Exit.hasInterrupts( yield* FiberSet.join(set).pipe( Effect.exit ) )) })) it.effect("awaitEmpty", () => Effect.gen(function*() { const set = yield* FiberSet.make() yield* FiberSet.run(set, Effect.sleep(1000)) yield* FiberSet.run(set, Effect.sleep(1000)) yield* FiberSet.run(set, Effect.sleep(1000)) yield* FiberSet.run(set, Effect.sleep(1000)) const fiber = yield* Effect.forkChild(FiberSet.awaitEmpty(set)) yield* TestClock.adjust(500) assert.isUndefined(fiber.pollUnsafe()) yield* TestClock.adjust(500) assert.isDefined(fiber.pollUnsafe()) })) it.effect("makeRuntimePromise", () => Effect.gen(function*() { const run = yield* FiberSet.makeRuntimePromise() const result = yield* Effect.promise(() => run(Effect.succeed("done"))) strictEqual(result, "done") })) })