From 59d813aa4973d1115cfc70cc3667508335f49693 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 26 Oct 2024 22:06:42 +1300 Subject: [PATCH] ensure fiber refs are not inherited by ManagedRuntime (#3845) --- .changeset/twelve-seals-move.md | 5 +++ .../effect/src/internal/managedRuntime.ts | 15 +++++--- packages/effect/test/ManagedRuntime.test.ts | 38 +++++++++++-------- 3 files changed, 37 insertions(+), 21 deletions(-) create mode 100644 .changeset/twelve-seals-move.md diff --git a/.changeset/twelve-seals-move.md b/.changeset/twelve-seals-move.md new file mode 100644 index 0000000000..e85d69a7df --- /dev/null +++ b/.changeset/twelve-seals-move.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +ensure fiber refs are not inherited by ManagedRuntime diff --git a/packages/effect/src/internal/managedRuntime.ts b/packages/effect/src/internal/managedRuntime.ts index 4a27cf77f9..ed41588834 100644 --- a/packages/effect/src/internal/managedRuntime.ts +++ b/packages/effect/src/internal/managedRuntime.ts @@ -1,3 +1,4 @@ +import type { Mutable } from "effect/Types" import type * as Effect from "../Effect.js" import * as Effectable from "../Effectable.js" import type { Exit } from "../Exit.js" @@ -8,7 +9,6 @@ import { pipeArguments } from "../Pipeable.js" import { hasProperty } from "../Predicate.js" import type * as Runtime from "../Runtime.js" import * as Scope from "../Scope.js" -import * as effect from "./core-effect.js" import * as core from "./core.js" import * as fiberRuntime from "./fiberRuntime.js" import * as internalLayer from "./layer.js" @@ -56,8 +56,9 @@ export const make = ( ): M.ManagedRuntime => { memoMap = memoMap ?? internalLayer.unsafeMakeMemoMap() const scope = internalRuntime.unsafeRunSyncEffect(fiberRuntime.scopeMake()) - const runtimeEffect = internalRuntime.unsafeRunSyncEffect( - effect.memoize( + let buildFiber: Fiber.RuntimeFiber, ER> | undefined + const runtimeEffect = core.suspend(() => { + buildFiber ??= internalRuntime.unsafeForkEffect( core.tap( Scope.extend( internalLayer.toRuntimeWithMemoMap(layer, memoMap), @@ -66,9 +67,11 @@ export const make = ( (rt) => { self.cachedRuntime = rt } - ) + ), + { scope } ) - ) + return core.flatten(buildFiber.await) + }) const self: ManagedRuntimeImpl = Object.assign(Object.create(ManagedRuntimeProto), { memoMap, scope, @@ -83,7 +86,7 @@ export const make = ( return internalRuntime.unsafeRunPromiseEffect(self.disposeEffect) }, disposeEffect: core.suspend(() => { - ;(self as any).runtime = core.die("ManagedRuntime disposed") + ;(self as Mutable>).runtimeEffect = core.die("ManagedRuntime disposed") self.cachedRuntime = undefined return Scope.close(self.scope, core.exitVoid) }), diff --git a/packages/effect/test/ManagedRuntime.test.ts b/packages/effect/test/ManagedRuntime.test.ts index defe8e4445..07aa4315ff 100644 --- a/packages/effect/test/ManagedRuntime.test.ts +++ b/packages/effect/test/ManagedRuntime.test.ts @@ -1,10 +1,9 @@ -import { ManagedRuntime } from "effect" +import { FiberRefs, List, ManagedRuntime } from "effect" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as FiberRef from "effect/FiberRef" import * as Layer from "effect/Layer" -import * as it from "effect/test/utils/extend" -import { assert, describe, test } from "vitest" +import { assert, describe, it, test } from "effect/test/utils/extend" describe.concurrent("ManagedRuntime", () => { test("memoizes the layer build", async () => { @@ -50,16 +49,25 @@ describe.concurrent("ManagedRuntime", () => { assert.strictEqual(count, 1) }) - it.effect( - "is subtype of effect", - () => - Effect.gen(function*() { - const tag = Context.GenericTag("string") - const layer = Layer.succeed(tag, "test") - const managedRuntime = ManagedRuntime.make(layer) - const runtime = yield* managedRuntime - const result = Context.get(runtime.context, tag) - assert.strictEqual(result, "test") - }) - ) + it.effect("is subtype of effect", () => + Effect.gen(function*() { + const tag = Context.GenericTag("string") + const layer = Layer.succeed(tag, "test") + const managedRuntime = ManagedRuntime.make(layer) + const runtime = yield* managedRuntime + const result = Context.get(runtime.context, tag) + assert.strictEqual(result, "test") + })) + + it.effect("does not inherit fiber refs", () => + Effect.gen(function*() { + const tag = Context.GenericTag("string") + const layer = Layer.succeed(tag, "test") + const managedRuntime = ManagedRuntime.make(layer) + const runtime = yield* managedRuntime.runtimeEffect.pipe( + Effect.withLogSpan("test") + ) + const result = FiberRefs.getOrDefault(runtime.fiberRefs, FiberRef.currentLogSpan) + assert.deepStrictEqual(result, List.empty()) + })) })