Effect CommunityEC
Effect Community13mo ago
21 replies
Aldwin

Managing the Fibers of multiple Effects running at my program's edge (with FiberSet?)

I am making a function that runs my Effects, like this: <R>(runtime: ManagedRuntime<R, never>) => (eff: Effect<unknown, never, R>) => void.

I want the function to immediately run the given effect in the given runtime, and also register an event listener to interrupt all Fibers still running. My first attempt was the following:

const run = <R>(runtime: ManagedRuntime<R, never>) => {
  let fiber: Fiber.Fiber<unknown> = Fiber.succeed(undefined);

  registerCleanupHandler(() => {
    runtime.runFork(Fiber.interrupt(fiber));
  });

  return (eff: Effect<unknown, never, R>) => {
    fiber = runtime.runFork(Effect.zip(Fiber.join(fiber), eff, {concurrent: true}));
  };
}


Here I zip the old fiber into a new fiber, to ensure that when the resulting fiber is interrupted, so is the old one. However, I think this would create a memory leak.

Instead, I should probably be using a FiberSet, so that completed fibers are garbage-collected, or interrupted when the FiberSet's Scope is closed, but I'm having trouble. Is there a higher level API I can use instead? I also tried with a custom Scope and running my effects with Effect.forkIn, but I think that approach leaks memory too (with the finalizers not being garbage collected).
Was this page helpful?